├── .eslintrc
├── .gitignore
├── .stylelintrc.json
├── README.md
├── doc.js
├── index.html
├── misc
├── comment-parse.js
├── doxxx.js
├── microsoft-tsdoc.js
├── package-lock.json
├── package.json
├── react-parser
│ ├── README.md
│ ├── index.js
│ ├── loader.js
│ ├── package-lock.json
│ ├── package.json
│ └── test.js
└── typescript-parse.js
├── package-lock.json
├── package.json
├── parser-test.js
├── parser.js
├── pnpm-lock.yaml
├── postcss.config.js
├── scripts
└── getdocs.js
├── src
├── 0.1_Button_PropTypes_Function
│ └── index.jsx
├── 0_Button_PropTypes_Class
│ └── index.jsx
├── 0_Button_PropTypes_Function
│ └── index.jsx
├── 1_Button_JSDoc_Simple
│ └── index.jsx
├── 2.1_Button_JSDoc_Function_Extend
│ └── index.jsx
├── 2.2_Button_JSDoc_Function_Ref
│ └── index.jsx
├── 2.2_Button_JSDoc_Hooks
│ └── index.jsx
├── 2_Button_JSDoc_TypeDef_Function
│ └── index.jsx
├── 3_Button_JSDoc_TypeDef_Class
│ └── index.jsx
├── 4_Button_JSDoc_ImportedTypes
│ ├── index.jsx
│ ├── large.ts
│ └── tiny.ts
├── 5_Button_JSDoc_ImportedTypes_React
│ ├── index.jsx
│ └── usefulTypes.ts
├── 6_List_TypeScript
│ └── index.tsx
├── 7_Context
│ └── index.tsx
├── 8_PolymorphicComponent
│ └── index.tsx
├── App.css
├── App.tsx
├── Card
│ └── index.jsx
├── TodoList
│ ├── index.tsx
│ └── xyz.module.css
├── __generated
│ └── .gitkeep
├── __tests__
│ ├── index.test.js
│ ├── misc
│ │ ├── _initJSDom.js
│ │ ├── _setup-tests.js
│ │ └── utils.js
│ ├── simple
│ │ └── x.test.js
│ └── withJsDom
│ │ └── y.test.js
├── favicon.svg
├── index.css
├── logo.svg
├── main.tsx
├── utils
│ ├── 0_@author.js
│ ├── 0_@default.js
│ ├── 0_@deprecated.js
│ ├── 0_@description.js
│ ├── 0_@example.js
│ ├── 0_@extends.js
│ ├── 0_@license.js
│ ├── 0_@link.js
│ ├── 0_@module.js
│ ├── 0_@module2.js
│ ├── 0_@name.js
│ ├── 0_@namespace.js
│ ├── 0_@param.js
│ ├── 0_@remarks.js
│ ├── 0_@schema.js
│ ├── 0_@see.js
│ ├── 0_@summary.js
│ ├── 0_@template.js
│ ├── 0_@this.js
│ ├── 0_@type.js
│ ├── 0_@typedef.js
│ ├── 0__other_tags.js
│ ├── 0_captions.js
│ ├── 0_images.js
│ ├── 0_primatives.js
│ ├── 0_typeof.js
│ ├── 1_array.js
│ ├── 1_class.js
│ ├── 1_enum.js
│ ├── 1_functions.js
│ ├── 1_htmlNodes.js
│ ├── 1_map.js
│ ├── 1_object.js
│ ├── 1_objectz-shorthand.js
│ ├── 1_set.js
│ ├── 2_buffer.js
│ ├── 2_event-listener.js
│ ├── 2_imports-commonJS.js
│ ├── 2_imports-ts.js
│ ├── 2_imports-ts2-refs.js
│ ├── 2_overload.js
│ ├── 2_overload.ts
│ ├── 2_typecasting.js
│ ├── 2_typeof-reference.js
│ ├── 2_union.js
│ ├── asserts.js
│ ├── balena.js
│ ├── calculator.js
│ ├── camel-case.js
│ ├── class-extend.js
│ ├── class-private-func.js
│ ├── class-private-proto.js
│ ├── constants.js
│ ├── contentful-types.ts
│ ├── contentful.js
│ ├── example-three.js
│ ├── examples-two.js
│ ├── examples.js
│ ├── examples
│ │ ├── auth.js
│ │ ├── example-klasa.js
│ │ ├── f-ck.js
│ │ ├── http-headers.ts
│ │ ├── import-defs
│ │ │ ├── api-type-definitions-usage.js
│ │ │ ├── api-type-definitions.js
│ │ │ ├── import-example-usage-five.js
│ │ │ ├── import-example-usage-four.js
│ │ │ ├── import-example-usage-seven.js
│ │ │ ├── import-example-usage-six.js
│ │ │ ├── import-example-usage-three.js
│ │ │ ├── import-example-usage-two.js
│ │ │ ├── import-example-usage.js
│ │ │ ├── import-example-with-export.js
│ │ │ ├── import-example-with-module-exports.js
│ │ │ ├── import-example-with-no-export.js
│ │ │ └── import-example.js
│ │ ├── inferred-param.ts
│ │ ├── inline.js
│ │ ├── json-types.ts
│ │ ├── oauth
│ │ │ ├── oauth.js
│ │ │ └── types.js
│ │ ├── open-api.ts
│ │ ├── rbac
│ │ │ └── index.ts
│ │ ├── react-class.js
│ │ ├── react-render-props.js
│ │ ├── reverse-record.js
│ │ ├── snakecase.js
│ │ ├── split.js
│ │ ├── ts-json.ts
│ │ ├── webapp.js
│ │ └── xyz
│ │ │ ├── types.js
│ │ │ └── xyz.js
│ ├── generics.js
│ ├── ignore-example.js
│ ├── imports
│ │ ├── my-js-file.js
│ │ ├── my.d.ts
│ │ └── ts-types.ts
│ ├── invert.ts
│ ├── jsdoc-module.js
│ ├── simple-jsdoc-generics.js
│ ├── type-examples
│ │ ├── dot-notation.ts
│ │ └── tyoe-utils.ts
│ ├── typedef-div-extend.js
│ ├── typedef-extend.js
│ ├── types.d.ts
│ ├── xyz.js
│ └── zpegasus.js
├── vite-env.d.ts
└── zod
│ ├── autozod.ts
│ ├── example-js.js
│ ├── example.ts
│ └── types.d.ts
├── ts-to-zod.config.js
├── tsconfig.json
├── typedoc.json
└── vite.config.ts
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "parserOptions": {
4 | "ecmaVersion": 2020,
5 | "sourceType": "module",
6 | "ecmaFeatures": {
7 | "jsx": true
8 | }
9 | },
10 | "env": {
11 | "es6": true
12 | },
13 | "plugins": [
14 | "jsdoc"
15 | ],
16 | "extends": [],
17 | "rules": {}
18 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | _misc
9 | misc/structured-types
10 | docs
11 | # Auto generated zod files
12 | src/__generated/**/**
13 | src/**/**/*.validate.js
14 |
15 | # Ignore auto generated json schema files
16 | src/**/**/*.schema.json
17 |
18 | # Ignore Auto generated types, except types.d.ts files
19 | src/**/**/*.d.ts
20 | !src/**/**/types.d.ts
21 | !src/utils/imports/my.d.ts
22 |
23 | # Ignore Auto generated CSS types
24 | src/**/**/*.css.d.ts
25 | src/**/**/*.module.css.d.ts
26 |
27 | coverage-ts
28 | dist
29 |
30 | # Runtime data
31 | pids
32 | *.pid
33 | *.seed
34 | *.pid.lock
35 |
36 | # Directory for instrumented libs generated by jscoverage/JSCover
37 | lib-cov
38 |
39 | # Coverage directory used by tools like istanbul
40 | coverage
41 |
42 | # nyc test coverage
43 | .nyc_output
44 |
45 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
46 | .grunt
47 |
48 | # Bower dependency directory (https://bower.io/)
49 | bower_components
50 |
51 | # node-waf configuration
52 | .lock-wscript
53 |
54 | # Compiled binary addons (https://nodejs.org/api/addons.html)
55 | build/Release
56 |
57 | # Dependency directories
58 | node_modules/
59 | jspm_packages/
60 |
61 | # TypeScript v1 declaration files
62 | typings/
63 |
64 | # Optional npm cache directory
65 | .npm
66 |
67 | # Optional eslint cache
68 | .eslintcache
69 |
70 | # Optional REPL history
71 | .node_repl_history
72 |
73 | # Output of 'npm pack'
74 | *.tgz
75 |
76 | # Yarn Integrity file
77 | .yarn-integrity
78 |
79 | # dotenv environment variables file
80 | .env
81 | .env.test
82 |
83 | # parcel-bundler cache (https://parceljs.org/)
84 | .cache
85 |
86 | # next.js build output
87 | .next
88 |
89 | # nuxt.js build output
90 | .nuxt
91 |
92 | # vuepress build output
93 | .vuepress/dist
94 |
95 | # Serverless directories
96 | .serverless/
97 |
98 | # FuseBox cache
99 | .fusebox/
100 |
101 | # DynamoDB Local files
102 | .dynamodb/
103 |
104 | # General
105 | .DS_Store
106 | .AppleDouble
107 | .LSOverride
108 |
109 | # Icon must end with two \r
110 | Icon
111 |
112 |
113 | # Thumbnails
114 | ._*
115 |
116 | # Files that might appear in the root of a volume
117 | .DocumentRevisions-V100
118 | .fseventsd
119 | .Spotlight-V100
120 | .TemporaryItems
121 | .Trashes
122 | .VolumeIcon.icns
123 | .com.apple.timemachine.donotpresent
124 |
125 | # Directories potentially created on remote AFP share
126 | .AppleDB
127 | .AppleDesktop
128 | Network Trash Folder
129 | Temporary Items
130 | .apdisk
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "stylelint-config-standard",
3 | "plugins": [
4 | "stylelint-no-unused-selectors"
5 | ],
6 | "rules": {
7 | "declaration-no-important": true,
8 | "color-hex-case": "upper",
9 | "indentation": 2,
10 | "plugin/no-unused-selectors": [ true, { "severity": "warning" }],
11 | "no-eol-whitespace": null,
12 | "no-missing-end-of-source-newline": null
13 | }
14 | }
--------------------------------------------------------------------------------
/doc.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const dox = require('doxxx')
4 |
5 |
6 | // const filePath = path.resolve(__dirname, 'src/1_Button_JSDoc_Simple/index.jsx')
7 | // const filePath = path.resolve(__dirname, 'src/2_Button_JSDoc_TypeDef_Function/index.jsx')
8 | // const filePath = path.resolve(__dirname, 'src/2.1_Button_JSDoc_Function_Extend/index.jsx')
9 | // const filePath = path.resolve(__dirname, 'src/3_Button_JSDoc_TypeDef_Class/index.jsx')
10 | // const filePath = path.resolve(__dirname, 'src/4_Button_JSDoc_ImportedTypes/index.jsx')
11 | const filePath = path.resolve(__dirname, 'src/5_Button_JSDoc_ImportedTypes_React/index.jsx')
12 |
13 | const fileCode = fs.readFileSync(filePath, 'utf-8')
14 | const obj = dox.parseComments(fileCode)
15 | const { inspect } = require('util')
16 | console.log('result')
17 | console.log(inspect(obj, {showHidden: false, depth: null}))
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Vite App
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/misc/comment-parse.js:
--------------------------------------------------------------------------------
1 | const { parse, tokenizers } = require('comment-parser/lib')
2 |
3 | // const source = `
4 | // /**
5 | // * Description may go
6 | // * over few lines followed by @tags
7 | // * @param {string} name the name parameter
8 | // * @param {any} value the value of any type
9 | // */`
10 |
11 | const source = `
12 | /**
13 | * Renders a component
14 | * @param {object} [props] - Button props
15 | * @param { import("./types").Pet } p
16 | * @param {string} [props.text] - My button
17 | * @param {string} [props.textColor] - the color of the text in the button
18 | * @param {string} [props.bgColor] - the background color of the button
19 | * @param {object} [props.overrideStyles] - used to set the CSS of the button
20 | * @return {React.ReactElement} - React component
21 | * @example
22 | *
25 | */
26 | export default function Button(props = {}) {
27 | return (
28 |
29 | )
30 | }`
31 |
32 | const parsed = parse(source, {
33 | spacing: 'preserve',
34 | tokenizers: [tokenizers.tag(), tokenizers.description('preserve')],
35 | trim: false
36 | })
37 |
38 | const { inspect } = require('util')
39 | console.log(inspect(parsed, {showHidden: false, depth: null}))
--------------------------------------------------------------------------------
/misc/doxxx.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const dox = require('doxxx')
4 |
5 | var code = `
6 | /**
7 | * tester
8 | * @template T
9 | * @extends {Set}
10 | * @example
11 | * lol()
12 | * console.log('hi')
13 | */
14 | class SortableSet extends Set {
15 | // ...
16 | }
17 |
18 |
19 | /**
20 | * Does xyz
21 | * @returns {Promise<{
22 | * pass: number,
23 | * fail: number
24 | * }>}
25 | */
26 | async function run() {
27 | return Promise.resolve({
28 | pass: 1,
29 | fail: 3
30 | })
31 | }
32 |
33 |
34 | /**
35 | * Renders a component
36 | * @param { import("./types").Pet } p - Pet type
37 | * @param {object} [props] - button props
38 | * @param {string} [props.text] - My button
39 | * @param {string} [props.textColor] - the color of the text in the button
40 | * @param {string} [props.bgColor] - the background color of the button
41 | * @param {object} [props.overrideStyles] - used to set the CSS of the button
42 | * @return {React.ReactElement} - React component
43 | * @example
44 |
47 | */
48 | export default function Button(props = {}) {
49 | return (
50 |
51 | )
52 | }
53 | `;
54 |
55 | var codeTwo = `
56 | interface User {
57 | name: string;
58 | id: number;
59 | }
60 |
61 | /**
62 | * Renders a component
63 | */
64 | class UserAccount {
65 | name: string;
66 | id: number;
67 |
68 | constructor(name: string, id: number) {
69 | this.name = name;
70 | this.id = id;
71 | }
72 | }
73 | `
74 |
75 | var code = `
76 | /**
77 | * Renders a component
78 | * @param {Object} props
79 | * @param {String} props.textColor - the color of the text in the button
80 | * @param {String} props.bgColor - the background color of the button
81 | * @param {React.ReactNode} [props.children] - component children;
82 | * @param {React.CSSProperties} props.overrideStyles - used to set the CSS of the button
83 | * @return {React.ReactElement} - React component
84 | */
85 | export const ButtonTwo = ({ children, textColor, bgColor, overrideStyles = {} }) => (
86 |
95 | )
96 | `
97 |
98 | // const filePath = path.resolve(__dirname, '../src/1_Button_SimpleJSdoc/index.jsx')
99 | // const fileCode = fs.readFileSync(filePath, 'utf-8')
100 | const obj = dox.parseComments(code);
101 | const { inspect } = require('util')
102 | console.log('result')
103 | console.log(inspect(obj, {showHidden: false, depth: null}))
--------------------------------------------------------------------------------
/misc/microsoft-tsdoc.js:
--------------------------------------------------------------------------------
1 | const { TSDocParser, ParserContext, DocComment, DocNode, DocExcerpt } = require('@microsoft/tsdoc');
2 |
3 |
4 | const fs = require('fs')
5 | const path = require('path')
6 | const os = require('os')
7 |
8 | const inputFilename = path.resolve(__dirname, '../src/6_List_TSProps/index.tsx')
9 | const code = fs.readFileSync(inputFilename, 'utf-8')
10 |
11 | const tsdocParser = new TSDocParser();
12 | const parserContext = tsdocParser.parseString(code);
13 |
14 |
15 | /**
16 | * This is a simplistic solution until we implement proper DocNode rendering APIs.
17 | */
18 | class Formatter {
19 | static renderDocNode(docNode) {
20 | let result = '';
21 | if (docNode) {
22 | if (docNode instanceof DocExcerpt) {
23 | result += docNode.content.toString();
24 | }
25 | for (const childNode of docNode.getChildNodes()) {
26 | result += Formatter.renderDocNode(childNode);
27 | }
28 | }
29 | return result;
30 | }
31 |
32 | static renderDocNodes(docNodes){
33 | let result = '';
34 | for (const docNode of docNodes) {
35 | result += Formatter.renderDocNode(docNode);
36 | }
37 | return result;
38 | }
39 | }
40 |
41 | const colors = {
42 | green: (d) => d,
43 | cyan: (d) => d
44 | }
45 |
46 | console.log(os.EOL + colors.green('Extracted Lines:') + os.EOL);
47 | console.log(
48 | JSON.stringify(
49 | parserContext.lines.map((x) => x.toString()),
50 | undefined,
51 | ' '
52 | )
53 | );
54 |
55 | console.log(os.EOL + colors.green('Parser Log Messages:') + os.EOL);
56 |
57 | if (parserContext.log.messages.length === 0) {
58 | console.log('No errors or warnings.');
59 | } else {
60 | for (const message of parserContext.log.messages) {
61 | console.log(inputFilename + message.toString());
62 | }
63 | }
64 |
65 | console.log(os.EOL + colors.green('DocComment parts:') + os.EOL);
66 |
67 | const docComment = parserContext.docComment;
68 |
69 | console.log(colors.cyan('Summary: ') + JSON.stringify(Formatter.renderDocNode(docComment.summarySection)));
70 |
71 | if (docComment.remarksBlock) {
72 | console.log(
73 | colors.cyan('Remarks: ') + JSON.stringify(Formatter.renderDocNode(docComment.remarksBlock.content))
74 | );
75 | }
76 |
77 | for (const paramBlock of docComment.params.blocks) {
78 | console.log(
79 | colors.cyan(`Parameter "${paramBlock.parameterName}": `) +
80 | JSON.stringify(Formatter.renderDocNode(paramBlock.content))
81 | );
82 | }
83 |
84 | if (docComment.returnsBlock) {
85 | console.log(
86 | colors.cyan('Returns: ') + JSON.stringify(Formatter.renderDocNode(docComment.returnsBlock.content))
87 | );
88 | }
89 |
90 | console.log(colors.cyan('Modifiers: ') + docComment.modifierTagSet.nodes.map((x) => x.tagName).join(', '));
91 | const { inspect } = require('util')
92 | // console.log('result')
93 | // console.log(inspect(parserContext, {showHidden: false, depth: null}))
94 |
--------------------------------------------------------------------------------
/misc/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "comment-parser-tests",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@microsoft/tsdoc": {
8 | "version": "0.13.2",
9 | "resolved": "https://registry.npmjs.org/@microsoft/tsdoc/-/tsdoc-0.13.2.tgz",
10 | "integrity": "sha512-WrHvO8PDL8wd8T2+zBGKrMwVL5IyzR3ryWUsl0PXgEV0QHup4mTLi0QcATefGI6Gx9Anu7vthPyyyLpY0EpiQg==",
11 | "dev": true
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/misc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "comment-parser-tests",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [],
11 | "author": "DavidWells",
12 | "license": "ISC",
13 | "devDependencies": {
14 | "@microsoft/tsdoc": "^0.13.2",
15 | "@types/react": "^17.0.9",
16 | "@types/react-dom": "^17.0.6",
17 | "comment-parser": "^1.1.5",
18 | "doxxx": "^1.0.0",
19 | "ts-to-zod": "^1.3.0",
20 | "type-coverage": "^2.17.5",
21 | "type-fest": "^1.2.2",
22 | "typescript": "^4.3.2",
23 | "typescript-coverage-report": "^0.6.0",
24 | "typescript-json-schema": "^0.50.1"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/misc/react-parser/README.md:
--------------------------------------------------------------------------------
1 | Prop type parser.
2 |
3 | - [x] Handles propTypes
4 | - [x] Handles typescript types
5 | - [ ] Doesn't handle JSdocs
6 |
--------------------------------------------------------------------------------
/misc/react-parser/index.js:
--------------------------------------------------------------------------------
1 | // const ts = require('typescript')
2 | const ReactDocGen = require('react-docgen')
3 | const ReactDocGenTS = require('react-docgen-typescript')
4 | const doctrine = require('doctrine')
5 | const fs = require('fs')
6 | const path = require('path')
7 | const deIndent = require('de-indent')
8 |
9 | /**
10 | * Parse JSDoc from prop description.
11 | *
12 | * @param {Prop} prop
13 | * @returns {Prop}
14 | */
15 | function prepareProp(prop) {
16 | if (prop.description) {
17 | const meta = doctrine.parse(prop.description)
18 |
19 | prop.description = meta.description
20 |
21 | meta.tags.forEach(({ title, description, ...tag }) => {
22 | prop[title] = description || true
23 | })
24 | }
25 |
26 | delete prop.parent
27 |
28 | return prop
29 | }
30 |
31 | function parseTS(file, source) {
32 | return ReactDocGenTS.withDefaultConfig({
33 | propFilter: {
34 | skipPropsWithName: ['className'],
35 | },
36 | componentNameResolver(exp, src) {
37 | if (exp.name === 'default') {
38 | return path
39 | .basename(file)
40 | .replace(/\.tsx/, '')
41 | .replace(/(?:^|-)([a-z])/g, (_, c) => c.toUpperCase())
42 | }
43 | },
44 | }).parse(file)[0]
45 | }
46 |
47 | function parseJS(file, source) {
48 | return ReactDocGen.parse(source)
49 | }
50 |
51 | /**
52 | * Parse file to JSDoc Meta
53 | * @argument {string} filename
54 | * @argument {string=} source
55 | * @returns {JSDocMeta}
56 | */
57 | module.exports = function parse(file, source, root = process.cwd()) {
58 | const isTS = /\.tsx$/.test(file)
59 | source = source || fs.readFileSync(file)
60 |
61 | const meta = isTS ? parseTS(file, source) : parseJS(file, source)
62 |
63 | if (!meta) throw new Error('Failed to parse ' + file)
64 |
65 | const docs = doctrine.parse(meta.description)
66 |
67 | meta.description = docs.description
68 |
69 | docs.tags.forEach((tag) => {
70 | if (tag.title === 'example') {
71 | meta[tag.title] = meta[tag.title] || []
72 | meta[tag.title].push(deIndent(tag.description))
73 | } else meta[tag.title] = tag.description
74 | })
75 |
76 | if (meta.methods) {
77 | meta.methods.forEach((method) => {
78 | const doc = doctrine.parse(method.docblock || '')
79 | delete method.docblock
80 | method.private = !doc.tags.some((tag) => tag.title === 'public')
81 | })
82 | }
83 |
84 | meta.props = Object.entries(meta.props || {}).reduce(
85 | (acc, [name, prop]) => acc.concat([{ name, ...prepareProp(prop) }]),
86 | []
87 | )
88 | meta.name =
89 | meta.displayName || meta.name || path.basename(file).replace(/\.jsx?$/, '')
90 | meta.file = path.relative(root, file)
91 |
92 | return meta
93 | }
94 |
95 | /** @typedef {{value: string, computed: boolean}} PropValue */
96 | /** @typedef {{name: string, value?: any, raw?: string}} PropType */
97 | /** @typedef {{name: string, type: PropType, defaultValue?: PropValue, required: boolean, description: string?, private?: boolean}} Prop */
98 | /** @typedef {{name: string, description: string?, version: string, status: string, props: Array}} JSDocMeta */
99 |
--------------------------------------------------------------------------------
/misc/react-parser/loader.js:
--------------------------------------------------------------------------------
1 | const { getOptions } = require('loader-utils')
2 |
3 | const docgen = require('./index')
4 |
5 | const EXPORT = /export\s+default\s+(?:class\s+|function\s*|)([A-Za-z0-9]+)/
6 |
7 | module.exports = async function DocGenLoader(source) {
8 | const callback = this.async()
9 | const { resourcePath } = this
10 | const options = {
11 | test: /./,
12 | root: process.cwd(),
13 | ...getOptions(this),
14 | }
15 |
16 | if (/\.(jsx|tsx)$/.test(resourcePath) && options.test.test(resourcePath)) {
17 | try {
18 | const meta = docgen(resourcePath, source, options.root)
19 | const docs = `\nconst __docs__ = ${JSON.stringify(
20 | meta,
21 | null,
22 | 2
23 | )}`.replace(
24 | /"--\{computed\}-->(.*)<--\{computed\}--"/g,
25 | (_, code) => code
26 | )
27 |
28 | const matches = EXPORT.exec(source)
29 |
30 | if (matches) {
31 | source = source + docs + `\n${matches[1]}.__docs = __docs__\n`
32 | }
33 | } catch (error) {
34 | this.emitError(new Error(resourcePath + ' in ' + error.message))
35 | }
36 | }
37 |
38 | callback(null, source)
39 | }
40 |
--------------------------------------------------------------------------------
/misc/react-parser/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-docgen",
3 | "version": "0.0.1",
4 | "license": "MIT",
5 | "main": "src/index.js",
6 | "module": "dist/docgen.esm.js",
7 | "sideEffects": false,
8 | "types": "dist/index.d.ts",
9 | "dependencies": {
10 | "de-indent": "^1.0.2",
11 | "doctrine": "^2.1.0",
12 | "loader-utils": "^1.2.3",
13 | "lodash.camelcase": "^4.3.0",
14 | "react-docgen": "^2.20.1",
15 | "react-docgen-typescript": "^1.12.3",
16 | "typescript": "^3.3.3333"
17 | },
18 | "files": [
19 | "src/",
20 | "dist/",
21 | "bin/",
22 | "loader.js"
23 | ]
24 | }
25 |
--------------------------------------------------------------------------------
/misc/react-parser/test.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const parse = require('./index')
4 |
5 | let file
6 | file = path.resolve(__dirname, '../../src/0_Button_PropTypes_Class/index.jsx')
7 | file = path.resolve(__dirname, '../../src/0_Button_PropTypes_Function/index.jsx')
8 |
9 |
10 | // file = path.resolve(__dirname, '../../src/1_Button_JSDoc_Simple/index.jsx')
11 | // file = path.resolve(__dirname, '../../src/2_Button_JSDoc_TypeDef_Function/index.jsx')
12 | // file = path.resolve(__dirname, '../../src/2.1_Button_JSDoc_Function_Extend/index.jsx')
13 | // file = path.resolve(__dirname, '../../src/3_Button_JSDoc_TypeDef_Class/index.jsx')
14 | // file = path.resolve(__dirname, '../../src/4_Button_JSDoc_ImportedTypes/index.jsx')
15 | // file = path.resolve(__dirname, '../../src/5_Button_JSDoc_ImportedTypes_React/index.jsx')
16 | // file = path.resolve(__dirname, '../../src/6_List_TypeScript/index.tsx')
17 |
18 | const x = parse(file)
19 | console.log('x', x)
--------------------------------------------------------------------------------
/misc/typescript-parse.js:
--------------------------------------------------------------------------------
1 | const ts = require('typescript');
2 |
3 | const PROPERTY_TYPES = {
4 | any: ts.SyntaxKind.AnyKeyword,
5 | boolean: ts.SyntaxKind.BooleanKeyword,
6 | number: ts.SyntaxKind.NumberKeyword,
7 | string: ts.SyntaxKind.StringKeyword,
8 | };
9 | class TSNode {
10 | constructor(name, type) {
11 | this.children = [];
12 | this.addChildren = (name, type) => {
13 | let node = new TSNode(name, type);
14 | this.children.push(node);
15 | return node;
16 | };
17 | this.getType = () => this.type;
18 | this.getObject = () => {
19 | let map = {};
20 | map[this.name] = this.children.length
21 | ? this.children
22 | .map(child => child.getObject())
23 | .reduce((pv, child) => {
24 | for (let key in child) {
25 | if (pv.hasOwnProperty(key) || key in pv) {
26 | Object.assign(pv[key], child[key]);
27 | } else {
28 | pv[key] = child[key];
29 | }
30 | }
31 | return pv;
32 | }, {})
33 | : this.type;
34 | return map;
35 | };
36 | this.name = name;
37 | this.type = type;
38 | }
39 | }
40 | let visit = parent => node => {
41 | switch (node.kind) {
42 | case ts.SyntaxKind.ModuleDeclaration:
43 | let moduleName = node.name.text;
44 | ts.forEachChild(node, visit(parent.addChildren(moduleName)));
45 | break;
46 | case ts.SyntaxKind.ModuleBlock:
47 | ts.forEachChild(node, visit(parent));
48 | break;
49 | case ts.SyntaxKind.InterfaceDeclaration:
50 | let interfaceName = node.name.text;
51 | parent[interfaceName] = {};
52 | // console.log('interface');
53 | ts.forEachChild(node, visit(parent.addChildren(interfaceName)));
54 | break;
55 | case ts.SyntaxKind.PropertySignature:
56 | let propertyName = node.name;
57 | let propertyType = node.type;
58 | let arrayDeep = 0;
59 | let realPropertyName =
60 | 'string' !== typeof propertyName && 'text' in propertyName
61 | ? propertyName.text
62 | : propertyName;
63 | while (propertyType.kind === ts.SyntaxKind.ArrayType) {
64 | arrayDeep++;
65 | propertyType = propertyType.elementType;
66 | }
67 | if (propertyType.kind === ts.SyntaxKind.TypeReference) {
68 | let realPropertyType = propertyType.typeName;
69 | parent.addChildren(
70 | realPropertyName,
71 | 'Array<'.repeat(arrayDeep) +
72 | (realPropertyType.kind === ts.SyntaxKind.QualifiedName
73 | ? realPropertyType.getText()
74 | : 'text' in realPropertyType
75 | ? realPropertyType.text
76 | : realPropertyType) +
77 | '>'.repeat(arrayDeep)
78 | );
79 | } else {
80 | for (let type in PROPERTY_TYPES) {
81 | if (propertyType.kind === PROPERTY_TYPES[type]) {
82 | parent.addChildren(realPropertyName, type);
83 | break;
84 | }
85 | }
86 | }
87 | break;
88 | default:
89 | }
90 | };
91 |
92 | function tsParse(filename, options) {
93 | const ROOT_NAME = 'root';
94 | const node = new TSNode(ROOT_NAME);
95 |
96 | let program = ts.createProgram([filename], options);
97 | let checker = program.getTypeChecker();
98 | let sourceFile = program.getSourceFiles()[1];
99 |
100 | ts.forEachChild(sourceFile, visit(node));
101 |
102 | return node.getObject()[ROOT_NAME];
103 | };
104 |
105 |
106 | const fs = require('fs')
107 | const path = require('path')
108 |
109 | const inputFilename = path.resolve(__dirname, '../src/6_List_TSProps/index.tsx')
110 |
111 | const x = tsParse(inputFilename, {})
112 | console.log('x', x)
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.0.0",
3 | "scripts": {
4 | "start": "concurrently 'npm:watch:*' 'npm:vite'",
5 | "watch:css": "npm run types:css -- --watch",
6 | "watch:zod": "npm run types:zod -- --watch",
7 | "vite": "vite",
8 | "prebuild": "npm run generate",
9 | "build": "tsc && vite build",
10 | "build-no-types": "vite build",
11 | "build:types": "tcm src --camelCase",
12 | "build:vite": "tsc && vite build",
13 | "serve": "vite preview",
14 | "test": "uvu -r @swc-node/register -r global-jsdom/register -r mock-css-modules --ignore misc src/__tests__",
15 | "test2": "uvu -r @swc-node/register -r mock-css-modules --ignore misc src/__tests__",
16 | "test3": "uvu -r @swc-node/register -r global-jsdom/register -r mock-css-modules --ignore misc src/__tests__/simple",
17 | "test4": "uvu -r @swc-node/register -r mock-css-modules --ignore misc src/__tests__/withJsDom",
18 | "type-coverage": "type-coverage --detail --strict --at-least 90 --ignore-files 'test/*'",
19 | "ts-coverage": "typescript-coverage-report",
20 | "types": "concurrently 'npm:types:*'",
21 | "types:dts": "tsc --noEmit false --emitDeclarationOnly true",
22 | "types:css": "tcm src --camelCase",
23 | "types:zod": "ts-to-zod --all --keepComments",
24 | "types-schema": "typescript-json-schema --ignoreErrors 'src/1_Button_JSDoc_Simple/index.d.ts' '*'",
25 | "emitx": "tsc --noEmit false --outDir dist/components",
26 | "generate": "concurrently 'npm:generate:*'",
27 | "generate:json": "typescript-json-schema --ignoreErrors \"./src/zod/autozod.ts\" '*' -o ./src/zod/autozod.schema.json",
28 | "generate:json-schema": "typescript-json-schema --ignoreErrors \"./src/zod/types.d.ts\" '*' -o ./src/zod/types.schema.json",
29 | "generate:json-dir": "typescript-json-schema --ignoreErrors \"./src/zod/**.ts\" '*' -o ./src/zod/dir.schema.json",
30 | "generate:predicates": "type-predicates-generator -f 'src/utils/types.d.ts' -o src/__generated/predicates.ts -a",
31 | "typedoc": "typedoc"
32 | },
33 | "dependencies": {
34 | "@analytics/listener-utils": "^0.2.4",
35 | "@casl/ability": "^5.4.3",
36 | "@mantine/core": "^2.1.4",
37 | "@mantine/hooks": "^2.1.4",
38 | "@modulz/radix-icons": "^4.0.0",
39 | "analytics": "^0.7.11",
40 | "prop-types": "^15.7.2",
41 | "react": "^17.0.2",
42 | "react-dom": "^17.0.2",
43 | "react-jss": "^10.7.1",
44 | "zod": "^3.5.1"
45 | },
46 | "devDependencies": {
47 | "@davidwells/config-postcss": "0.0.21",
48 | "@structured-types/api": "^3.40.9",
49 | "@structured-types/prop-types-plugin": "^3.40.9",
50 | "@structured-types/react-plugin": "^3.40.9",
51 | "@swc-node/register": "^1.3.3",
52 | "@testing-library/react": "^12.0.0",
53 | "@types/react": "^17.0.15",
54 | "@types/react-dom": "^17.0.9",
55 | "@typescript-eslint/parser": "^4.28.5",
56 | "@vitejs/plugin-react-refresh": "^1.3.6",
57 | "concurrently": "^6.2.0",
58 | "doxxx": "^1.0.0",
59 | "eslint": "^7.31.0",
60 | "eslint-plugin-jsdoc": "^36.0.6",
61 | "getdocs-ts": "^0.1.0",
62 | "global-jsdom": "^8.2.0",
63 | "inspx": "0.0.1-alpha.6",
64 | "jsdom": "^17.0.0",
65 | "mock-css-modules": "^2.0.0",
66 | "stylelint": "^13.13.1",
67 | "stylelint-config-standard": "^22.0.0",
68 | "stylelint-no-unused-selectors": "^1.0.39",
69 | "ts-node": "^10.2.1",
70 | "ts-to-jsdoc": "^1.1.2",
71 | "ts-to-zod": "^1.4.0",
72 | "type-coverage": "^2.18.0",
73 | "type-fest": "^1.2.3",
74 | "type-predicates-generator": "^0.3.1",
75 | "typed-css-modules": "^0.7.0",
76 | "typedoc": "^0.22.11",
77 | "typescript": "^4.5.2",
78 | "typescript-coverage-report": "^0.6.0",
79 | "typescript-json-schema": "^0.50.1",
80 | "uvu": "^0.5.1",
81 | "vite": "^2.4.4"
82 | },
83 | "useful": {
84 | "esm": "^3.2.25",
85 | "jsdom": "^16.7.0"
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/parser-test.js:
--------------------------------------------------------------------------------
1 | /**
2 | * sum api function
3 | * @remarks
4 | * Unlike the summary, the remarks block may contain lengthy documentation content.
5 | * The remarks should not restate information from the summary, since the summary section
6 | * will always be displayed wherever the remarks section appears. Other sections
7 | * (e.g. an `@example` block) will be shown after the remarks section.
8 | *
9 | * @param {number} a first parameter to add
10 | * @param {number} b second parameter to add
11 | * @returns {number} the sum of the two parameters
12 | *
13 | * @example
14 | *
15 | * ```js
16 | * import { sum } from './sum';
17 | *
18 | * expect(sum(1, 2)).toMatchObject({ a: 1, b: 2, result: 3});
19 | * ```
20 | */
21 | export const sum = (a, b = 1) => ({ a, b, result: a + b });
--------------------------------------------------------------------------------
/parser.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const { inspect } = require('util')
4 | const { parseFiles } = require('@structured-types/api');
5 | const propTypesPlugin = require('@structured-types/prop-types-plugin')
6 | const reactPlugin = require('@structured-types/react-plugin');
7 |
8 | let filePath
9 | // filePath = './parser-test.js'
10 | filePath = path.resolve(__dirname, 'src/0_Button_PropTypes_Class/index.jsx')
11 | filePath = path.resolve(__dirname, 'src/0_Button_PropTypes_Function/index.jsx')
12 | // filePath = path.resolve(__dirname, 'src/1_Button_JSDoc_Simple/index.jsx')
13 | // filePath = path.resolve(__dirname, 'src/2_Button_JSDoc_TypeDef_Function/index.jsx')
14 | // filePath = path.resolve(__dirname, 'src/2.1_Button_JSDoc_Function_Extend/index.jsx')
15 | // filePath = path.resolve(__dirname, 'src/3_Button_JSDoc_TypeDef_Class/index.jsx')
16 | // filePath = path.resolve(__dirname, 'src/4_Button_JSDoc_ImportedTypes/index.jsx')
17 | // filePath = path.resolve(__dirname, 'src/5_Button_JSDoc_ImportedTypes_React/index.jsx')
18 |
19 | // https://github.com/ccontrols/structured-types/blob/a65a732f24de298bbde48d27ee9f17c94ba985b5/packages/api/src/types.ts#L34
20 | const PropKind = {
21 | 'String': 1,
22 | 'Number': 2,
23 | 'Boolean': 3,
24 | 'Union': 4,
25 | 'Enum': 5,
26 | 'Tuple': 6,
27 | 'Rest': 7,
28 | 'Undefined': 8,
29 | 'Unknown': 9,
30 | 'Null': 10,
31 | 'Function': 11,
32 | 'Void': 12,
33 | 'Class': 13,
34 | 'Interface': 14,
35 | 'Type': 15,
36 | 'Array': 16,
37 | 'Any': 17,
38 | 'Index': 20,
39 | 'Constructor': 21,
40 | 'Getter': 22,
41 | 'Setter': 23,
42 | 'BigInt': 24,
43 | 'Component': 25,
44 | 'Object': 26,
45 | 'Namespace': 27,
46 | 'RegEx': 28,
47 | }
48 |
49 | const kindMap = Object.keys(PropKind).reduce((acc, key) => {
50 | acc[PropKind[key]] = key
51 | return acc
52 | }, {})
53 | console.log('kindMap', kindMap)
54 |
55 | const kindEntries = Object.entries(PropKind)
56 | console.log('kindEntries', kindEntries)
57 |
58 | function mapper(obj) {
59 | if (obj && typeof obj === 'object' && obj.kind) {
60 | obj.kindType = obj.kind
61 | obj.kind = kindMap[obj.kind]
62 | if (obj.properties) {
63 | obj.properties = obj.properties.map((prop) => {
64 | return mapper(prop)
65 | })
66 | }
67 | if (obj.parameters) {
68 | obj.parameters = obj.parameters.map((prop) => {
69 | return mapper(prop)
70 | })
71 | }
72 | if (obj.returns) {
73 | obj.returns = mapper(obj.returns)
74 | }
75 | }
76 | return obj
77 | }
78 |
79 | console.log(fs.readFileSync(filePath, 'utf-8'))
80 |
81 | const rawDocs = parseFiles([filePath], {
82 | plugins: [
83 | { ...propTypesPlugin, filter: undefined },
84 | reactPlugin
85 | ],
86 | })
87 |
88 | // console.log('rawDocs')
89 | // console.log(inspect(rawDocs, {showHidden: false, depth: null}))
90 |
91 | const docs = Object.keys(rawDocs).map((key) => {
92 | return mapper(rawDocs[key])
93 | })
94 |
95 | console.log('docs')
96 | // console.log(docs[0].parameters[0].properties)
97 | console.log(inspect(docs, {showHidden: false, depth: null}))
98 |
99 | /* Log them */
100 | docs.forEach((doc) => {
101 | console.log(`${doc.name}`)
102 | console.log('doc', doc);
103 | (doc.parameters || doc.properties).forEach((param) => {
104 | console.log(`param "${param.name}" properties`, param.properties)
105 | })
106 | })
107 |
108 |
109 | const getKindByNumber = (kind) => {
110 | return kindMap[kind]
111 | }
112 |
113 | const getKindName = (kind) => {
114 | const strKind = kind ? kind.toString() : 'unknown';
115 | console.log('strKind', strKind)
116 | const found = kindEntries.find(([_, v]) => {
117 | console.log('v', v)
118 | return v.toString() === strKind;
119 | })
120 | return found ? found[0] : undefined;
121 | }
122 |
123 | // console.log(getKindName(1))
124 | // console.log(getKindByNumber(1))
125 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | const { getPostCSSConfig } = require('@davidwells/config-postcss')
2 | // const variable = require('./src/_variables')
3 | // const mixins = require('./src/_mixins')
4 |
5 | const defaultPlugins = getPostCSSConfig({
6 | isNext: true,
7 | variables: {
8 | blue: 'red',
9 | nice: 'yellow',
10 | },
11 | // mixins: mixins
12 | })
13 |
14 | module.exports = {
15 | plugins: {
16 | ...defaultPlugins,
17 | },
18 | }
19 |
--------------------------------------------------------------------------------
/scripts/getdocs.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const {gather} = require("getdocs-ts")
3 |
4 | let items = gather({
5 | filename: path.resolve(__dirname, "../src/utils/examples/rbac/index.ts")
6 | })
7 |
8 | const { inspect } = require('util')
9 | console.log('Extracted types:')
10 | console.log(inspect(items, {showHidden: false, depth: null}))
--------------------------------------------------------------------------------
/src/0.1_Button_PropTypes_Function/index.jsx:
--------------------------------------------------------------------------------
1 | // https://www.inkoop.io/blog/a-guide-to-js-docs-for-react-js/
2 | import React from "react"
3 | import PropTypes from "prop-types"
4 |
5 | /**
6 | * Component for showing details of the user.
7 | * @param {object} props - User props
8 | * @param {string} [props.name] - User's name
9 | * @param {number} [props.age] - User's age
10 | * @component
11 | * @example
12 | * const age = 21
13 | * const name = 'Jitendra Nirnejak'
14 | * return (
15 | *
16 | * )
17 | */
18 | const User = props => {
19 | const { name, age } = props
20 | return (
21 |
22 | {name} is {age} years old.
23 |
24 | )
25 | }
26 |
27 | User.propTypes = {
28 | /**
29 | * User's name
30 | */
31 | name: PropTypes.string.isRequired,
32 | /**
33 | * User's age
34 | */
35 | age: PropTypes.number,
36 | }
37 |
38 | User.defaultProps = {
39 | text: "Jitendra Nirnejak",
40 | age: 21,
41 | }
42 |
43 | export default User
--------------------------------------------------------------------------------
/src/0_Button_PropTypes_Class/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | /**
5 | * General component description in JSDoc format. Markdown is *supported*.
6 | */
7 | export default class ButtonClassWithPropTypes extends React.Component {
8 | static propTypes = {
9 | /** Description of prop "children". */
10 | children: PropTypes.element,
11 | /** Description of prop "foo". */
12 | foo: PropTypes.number,
13 | /** Description of prop "baz". */
14 | baz: PropTypes.oneOfType([
15 | PropTypes.number,
16 | PropTypes.string
17 | ])
18 | }
19 | static defaultProps = {
20 | foo: 42
21 | }
22 |
23 | render() {
24 | const { children, className } = this.props
25 | return (
26 |
27 | {children}
28 |
29 | )
30 | }
31 | }
--------------------------------------------------------------------------------
/src/0_Button_PropTypes_Function/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import PropTypes from 'prop-types'
3 |
4 | const propTypes = {
5 | /** Description of prop "children". */
6 | children: PropTypes.element,
7 | /** Description of prop "foo". */
8 | foo: PropTypes.number,
9 | /** Description of prop "baz". */
10 | baz: PropTypes.oneOfType([
11 | PropTypes.number,
12 | PropTypes.string
13 | ])
14 | }
15 |
16 | const defaultProps = {
17 | foo: 42
18 | }
19 |
20 | export default function ButtonWithPropTypes({ children }) {
21 | return (
22 |
25 | )
26 | }
27 |
28 | ButtonWithPropTypes.propTypes = propTypes
29 | ButtonWithPropTypes.defaultProps = defaultProps
--------------------------------------------------------------------------------
/src/1_Button_JSDoc_Simple/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | /**
4 | * Renders a component
5 | * @param {Object} props - Button props
6 | * @param {String} [props.text] - My button
7 | * @param {Boolean} [props.isActive] - is button active
8 | * @param {String} [props.className] - CSS class name
9 | * @param {React.ReactNode} [props.children] - component children;
10 | * @param {React.CSSProperties} [props.style] - used to set the CSS of the button
11 | * @return {React.ReactElement} - React component
12 | * @example
13 |
16 | */
17 | export default function Button(props = {}) {
18 | return (
19 |
23 | )
24 | }
25 |
26 | /* https://www.javascriptjanuary.com/blog/autocomplete-in-react-using-jsdoc */
27 |
28 | /**
29 | * Renders a component
30 | * @param {Object} props
31 | * @param {String} props.textColor - the color of the text in the button
32 | * @param {String} props.bgColor - the background color of the button
33 | * @param {React.ReactNode} [props.children] - component children;
34 | * @param {React.CSSProperties} props.overrideStyles - used to set the CSS of the button
35 | * @return {React.ReactElement} - React component
36 | */
37 | export const ButtonTwo = ({ children, textColor, bgColor, overrideStyles = {} }) => (
38 |
47 | )
48 |
49 |
50 | /**
51 | * Renders a component
52 | * @param {Object} buttonProps
53 | * @param {String} buttonProps.textColor - the color of the text in the button
54 | * @param {String} buttonProps.bgColor - the background color of the button
55 | * @param {React.ReactNode} [buttonProps.children] - component children;
56 | * @param {React.CSSProperties} buttonProps.overrideStyles - used to set the CSS of the button
57 | * @return {React.ReactElement} - React component
58 | */
59 | export function ButtonThree (buttonProps) {
60 | const { children, textColor, bgColor, overrideStyles = {} } = buttonProps
61 | return (
62 |
71 | )
72 | }
73 |
74 | /**
75 | * Foobar function
76 | * @param {number} a - does thing
77 | * @param {number} b - xyz
78 | * @returns
79 | */
80 | export function fooBar(a, b) {
81 | return a + b
82 | }
--------------------------------------------------------------------------------
/src/2.1_Button_JSDoc_Function_Extend/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | /**
4 | * @typedef CustomProps
5 | * @prop {string} [text] - My button
6 | */
7 |
8 | /**
9 | * HTML div attributes + custom props
10 | * @typedef {React.HTMLAttributes & CustomProps} Props
11 | */
12 |
13 | /**
14 | * Renders a component
15 | * @param {Props} props
16 | * @return {React.ReactElement} - React component
17 | * @example
18 |
19 | Words
20 |
21 | */
22 | export default function MyDivComponent({
23 | text = 'my div',
24 | ...props
25 | }) {
26 | return (
27 |
28 | {text}
29 |
30 | )
31 | }
--------------------------------------------------------------------------------
/src/2.2_Button_JSDoc_Function_Ref/index.jsx:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/66553490/how-do-i-annotate-react-forwardref-with-jsdoc-comments-so-that-intellisense-can
2 | import React, { forwardRef } from 'react';
3 | import PropTypes from 'prop-types';
4 |
5 | /**
6 | * @typedef {Object} ButtonPropTypes
7 | * @property {string} text
8 | * @property {string} icon
9 | */
10 |
11 | /**
12 | * @type React.FC
13 | */
14 | const Button = forwardRef(({ text, icon }, ref) => (
15 |
16 | ))
17 |
18 | const ButtonPropTypes = {
19 | text: PropTypes.string.isRequired,
20 | icon: PropTypes.string.isRequired,
21 | }
22 |
23 | Button.propTypes = ButtonPropTypes
--------------------------------------------------------------------------------
/src/2.2_Button_JSDoc_Hooks/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, Component } from 'react'
2 |
3 | /**
4 | * @typedef {Object} AppUser
5 | * @property {string} given_name
6 | * @property {string} family_name
7 | * @property {string} [favorite_movie]
8 | * @property {string} favorite_book
9 | * @property {Array} [friends]
10 | * @property {Record | null} [stuff]
11 | */
12 |
13 | /**
14 | * @typedef {Boolean} LoadingState — documentation for isLoading
15 | * @description Additional doc
16 | */
17 | /**
18 | * @typedef {Function} LoadingStateSetter — documentation for setIsLoading
19 | */
20 |
21 | export default function MyDivComponent() {
22 | // Inline def
23 | const [state, setState] = useState(/** @type {{name: string?, age: number?}} */({}))
24 |
25 | // Inline def reference to typedefs
26 | const [appUser, setAppUser] = useState(/** @type {AppUser | null} */(null))
27 |
28 | // Reference to typedefs
29 | /** @type {[LoadingState, LoadingStateSetter]} Loading */
30 | const [isLoading, setIsLoading] = React.useState(true);
31 | const isLive = useMyHook({ disabled: true })
32 |
33 | return (
34 |
35 | text
36 |
37 | )
38 | }
39 |
40 | /**
41 | * A hook to do something
42 | *
43 | * @param {object} params
44 | * @param {boolean} [params.disabled] Disable the thing
45 | * @returns {boolean}
46 | */
47 | const useMyHook = (params) => {
48 | const [isUsing, setUsing] = useState(false)
49 | // Some logic here to invoke setUsing()
50 | return isUsing;
51 | };
--------------------------------------------------------------------------------
/src/2_Button_JSDoc_TypeDef_Function/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | /**
4 | * @typedef AdditionalType
5 | * @prop {string} [xyz] - XYZ prop
6 | * @prop {string} [abc] - ABC prop
7 | * @prop {string} bcd - BCD prop
8 | */
9 |
10 | /**
11 | * @typedef Props
12 | * @prop {string} [text] - My button
13 | * @prop {string} [textColor] - the color of the text in the button
14 | * @prop {string} [bgColor] - the background color of the button
15 | * @prop {React.CSSProperties} [overrideStyles] - used to set the CSS of the button
16 | * @prop {() => void} [onLogin] - Login handler
17 | * @prop {AdditionalType} [example] - example ref
18 | */
19 |
20 | /**
21 | * Renders a component
22 | * @param {Props} props
23 | * @return {React.ReactElement} - React component
24 | */
25 | export default function ButtonTwo(props = {}) {
26 | return (
27 |
28 | )
29 | }
--------------------------------------------------------------------------------
/src/3_Button_JSDoc_TypeDef_Class/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | /**
4 | * @typedef Props
5 | * @prop {string} [textColor]
6 | * @prop {React.ReactNode} [desc]
7 | */
8 |
9 | /**
10 | * @typedef State
11 | * @prop {boolean} isDrawerOpen
12 | */
13 |
14 | /**
15 | * @extends Component
16 | */
17 | export default class ButtonClass extends Component {
18 | /** @type {State} */
19 | state = {
20 | isDrawerOpen: false,
21 | }
22 |
23 | constructor(props) {
24 | super(props)
25 | }
26 |
27 | render() {
28 | // This is an error:
29 | // console.log(this.state.lol)
30 | return (
31 |
32 | Button class {this.state.isDrawerOpen}
33 |
34 | )
35 | }
36 | }
--------------------------------------------------------------------------------
/src/4_Button_JSDoc_ImportedTypes/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react'
2 |
3 | /**
4 | * Renders a component with imported types
5 | * @param { import("./tiny").TinyProps } props
6 | * @return {React.ReactElement} - React component
7 | */
8 | export default function ButtonImport(props) {
9 | return (
10 |
13 | )
14 | }
--------------------------------------------------------------------------------
/src/4_Button_JSDoc_ImportedTypes/large.ts:
--------------------------------------------------------------------------------
1 | // Via https://github.com/typescript-cheatsheets/react#basic-prop-types-examples
2 |
3 | export type AppProps = {
4 | message: string;
5 | count: number;
6 | disabled: boolean;
7 | /** array of a type! */
8 | names: string[];
9 | /** string literals to specify exact string values, with a union type to join them together */
10 | status: "waiting" | "success";
11 | /** any object as long as you dont use its properties (NOT COMMON but useful as placeholder) */
12 | obj: object;
13 | obj2: {}; // almost the same as `object`, exactly the same as `Object`
14 | /** an object with any number of properties (PREFERRED) */
15 | obj3: {
16 | id: string;
17 | title: string;
18 | };
19 | /** array of objects! (common) */
20 | objArr: {
21 | id: string;
22 | title: string;
23 | }[];
24 | /** a dict object with any number of properties of the same type */
25 | dict1: {
26 | [key: string]: string;
27 | };
28 | dict2: Record; // equivalent to dict1
29 | /** any function as long as you don't invoke it (not recommended) */
30 | onSomething: Function;
31 | /** function that doesn't take or return anything (VERY COMMON) */
32 | onFakeFunc: () => void;
33 | /** function with named prop (VERY COMMON) */
34 | onChange: (id: number) => void;
35 | /** alternative function type syntax that takes an event (VERY COMMON) */
36 | onClick(event: React.MouseEvent): void;
37 | /** an optional prop (VERY COMMON!) */
38 | optional?: string;
39 | };
--------------------------------------------------------------------------------
/src/4_Button_JSDoc_ImportedTypes/tiny.ts:
--------------------------------------------------------------------------------
1 | export type TinyProps = {
2 | message: string;
3 | count: number;
4 | disabled: boolean;
5 | };
--------------------------------------------------------------------------------
/src/5_Button_JSDoc_ImportedTypes_React/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | /**
4 | * Renders a component with useful react types
5 | * @param { import("./usefulTypes").AppProps } props
6 | * @return {React.ReactElement} - React component
7 | */
8 | export default function ButtonReactTypes(props) {
9 | return (
10 |
13 | )
14 | }
--------------------------------------------------------------------------------
/src/5_Button_JSDoc_ImportedTypes_React/usefulTypes.ts:
--------------------------------------------------------------------------------
1 | // Via https://github.com/typescript-cheatsheets/react#basic-prop-types-examples
2 |
3 | export declare interface AppProps {
4 | children1: JSX.Element; // bad, doesnt account for arrays
5 | children2?: JSX.Element | JSX.Element[]; // meh, doesn't accept strings
6 | children3?: React.ReactChildren; // despite the name, not at all an appropriate type; it is a utility
7 | children4?: React.ReactChild[]; // better, accepts array children
8 | children?: React.ReactNode; // best, accepts everything (see edge case below)
9 | functionChildren?: (name: string) => React.ReactNode; // recommended function as a child render prop type
10 | style?: React.CSSProperties; // to pass through style props
11 | onChange?: React.FormEventHandler; // form events! the generic parameter is the type of event.target
12 | // // more info: https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/#wrappingmirroring
13 | // props: Props & React.ComponentPropsWithoutRef<"button">; // to impersonate all the props of a button element and explicitly not forwarding its ref
14 | // props2: Props & React.ComponentPropsWithRef; // to impersonate all the props of MyButtonForwardedRef and explicitly forwarding its ref
15 | }
--------------------------------------------------------------------------------
/src/6_List_TypeScript/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | type Props = {
4 | message: string;
5 | count?: number;
6 | disabled?: boolean;
7 | /** array of a type! */
8 | names?: string[];
9 | /** string literals to specify exact string values, with a union type to join them together */
10 | status?: "waiting" | "success";
11 | /** any object as long as you dont use its properties (NOT COMMON but useful as placeholder) */
12 | obj?: object;
13 | obj2?: {}; // almost the same as `object`, exactly the same as `Object`
14 | /** an object with any number of properties (PREFERRED) */
15 | obj3?: {
16 | id: string;
17 | title: string;
18 | };
19 | /** array of objects! (common) */
20 | objArr?: {
21 | id: string;
22 | title: string;
23 | }[];
24 | /** any function as long as you don't invoke it (not recommended) */
25 | onSomething?: Function;
26 | /** function with named prop (VERY COMMON) */
27 | onChange?: (id: number) => void;
28 | /** alternative function type syntax that takes an event (VERY COMMON) */
29 | onClick?(event: React.MouseEvent): void;
30 | };
31 |
32 | export default function List(props: Props) {
33 | return (
34 |
35 | List component
36 |
37 | )
38 | }
--------------------------------------------------------------------------------
/src/7_Context/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { Context } from 'react'
2 |
3 | /**
4 | * React context example
5 | * @typedef FooBar
6 | * @property {object} competitionState
7 | * @property {'finished' | 'inprogress'} status
8 | * @property {Array} notificationActions
9 | */
10 |
11 | // Import style
12 |
13 | /** @type {import('react').Context} */
14 | export const MyThemeContext = React.createContext({
15 | competitionState: {},
16 | notificationActions: [],
17 | status: 'finished'
18 | });
19 |
20 |
21 | // Imported type style
22 |
23 | /** @type {Context} */
24 | export const MyThemeContextTwo = React.createContext({
25 | competitionState: {},
26 | notificationActions: [],
27 | status: 'finished'
28 | });
29 |
--------------------------------------------------------------------------------
/src/8_PolymorphicComponent/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import classNames from 'clsx'
3 |
4 | // The `Props` interface becomes a simple interface of the main props
5 | interface Props {
6 | children: React.ReactNode
7 | color?: string
8 | font?: 'thin' | 'regular' | 'heavy'
9 | size?: '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | '10'
10 | }
11 |
12 | // `TextProps` now uses `PolymorphicComponentProps` to add the `as` prop
13 | // and inherit its prop
14 | type TextProps = PolymorphicComponentProps<
15 | C,
16 | Props
17 | >
18 |
19 | export const Text = ({
20 | as,
21 | children,
22 | font = 'regular',
23 | size = '4',
24 | color = 'gray-40',
25 | ...other
26 | }: TextProps) => {
27 | const classes = classNames({ font, size, color })
28 | const Component = as || 'span'
29 |
30 | return (
31 |
32 | {children}
33 |
34 | )
35 | }
36 |
37 | /**
38 | * Usage example
39 | */
40 | export const LOL = () => xyz
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | .App {
2 | text-align: center;
3 | }
4 |
5 | .App-logo {
6 | height: 40vmin;
7 | pointer-events: none;
8 | }
9 |
10 | @media (prefers-reduced-motion: no-preference) {
11 | .App-logo {
12 | animation: App-logo-spin infinite 20s linear;
13 | }
14 | }
15 |
16 | .App-header {
17 | background-color: #282c34;
18 | min-height: 100vh;
19 | display: flex;
20 | flex-direction: column;
21 | align-items: center;
22 | justify-content: center;
23 | font-size: calc(10px + 2vmin);
24 | color: white;
25 | }
26 |
27 | .App-link {
28 | color: #61dafb;
29 | }
30 |
31 | @keyframes App-logo-spin {
32 | from {
33 | transform: rotate(0deg);
34 | }
35 | to {
36 | transform: rotate(360deg);
37 | }
38 | }
39 |
40 | button {
41 | font-size: calc(10px + 2vmin);
42 | }
43 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useRef } from "react"
2 | import TodoList from './TodoList'
3 | import Button from './1_Button_JSDoc_Simple'
4 | import ButtonTwo from './2_Button_JSDoc_TypeDef_Function'
5 | import ButtonClass from './3_Button_JSDoc_TypeDef_Class'
6 | import ButtonImportedTypes from './4_Button_JSDoc_ImportedTypes'
7 | import ButtonReactTypes from './5_Button_JSDoc_ImportedTypes_React'
8 | import List from './6_List_TypeScript'
9 | import Card from './Card'
10 | import Analytics from 'analytics'
11 | import { addListener } from '@analytics/listener-utils'
12 |
13 | const analytics = Analytics({
14 | app: 'xyz',
15 | })
16 |
17 |
18 | console.log('Analytics lib', Analytics)
19 | console.log('analytics instance', analytics)
20 |
21 | export default function App() {
22 | const divRef = useRef(null)
23 | useEffect(() => {
24 | addListener(divRef.current, 'click', () => {
25 | console.log('do thing')
26 | })
27 | })
28 | return (
29 |
30 |
31 |
32 | hi
33 |
34 |
40 |
44 |
47 |
52 |
bold}
54 | >
55 | cool
56 |
57 |
58 |
59 | )
60 | }
61 |
--------------------------------------------------------------------------------
/src/Card/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | /**
4 | * @typedef Props
5 | * @prop {React.ReactNode} [children]
6 | * @prop {React.ReactNode} [desc]
7 | * @prop {React.ReactNode} [selectFlightPrompt]
8 | * @prop {()=>void} [onLogin]
9 | */
10 |
11 | /**
12 | * @param {Props} props
13 | */
14 | export default function Card({ children }) {
15 | return (
16 |
17 | {children}
18 |
19 | )
20 | }
--------------------------------------------------------------------------------
/src/TodoList/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from "react"
2 | import { useListState } from "@mantine/hooks"
3 | import { Cross1Icon, PlusIcon } from "@modulz/radix-icons"
4 | import {
5 | Title,
6 | Text,
7 | Checkbox,
8 | TextInput,
9 | ActionIcon,
10 | Container,
11 | useMantineTheme,
12 | } from "@mantine/core"
13 |
14 | import styles from './xyz.module.css'
15 |
16 | function randomId() {
17 | return Math.random().toString(36).substr(2, 9)
18 | }
19 |
20 | const INITIAL_STATE = [
21 | { value: "Buy 23 RTX 3080 cards", completed: false, key: randomId() },
22 | { value: "Mine Ethereum", completed: false, key: randomId() },
23 | {
24 | value: "Complain about miners on internet to prove innocence",
25 | completed: false,
26 | key: randomId(),
27 | },
28 | {
29 | value: "Sell broken cards on ebay to gamers",
30 | completed: false,
31 | key: randomId(),
32 | },
33 | {
34 | value: "Spend received money on new video cards",
35 | completed: false,
36 | key: randomId(),
37 | },
38 | { value: "Repeat the cycle", completed: false, key: randomId() },
39 | ]
40 |
41 | export default function TodoList() {
42 | const theme = useMantineTheme()
43 | const [newItem, setNewItem] = useState("")
44 | const [state, handlers] = useListState(INITIAL_STATE)
45 |
46 | const items = state.reduce(
47 | (acc, item, index) => {
48 | acc[item.completed ? "completed" : "current"].push(
49 | // @ts-ignore
50 |
59 |
60 | tester
61 |
62 |
{
67 | handlers.setItemProp(
68 | index,
69 | "completed",
70 | event.currentTarget.checked
71 | )
72 | if (event.currentTarget.checked) {
73 | handlers.reorder({ from: index, to: state.length - 1 })
74 | }
75 | }}
76 | />
77 |
78 |
83 | handlers.setItemProp(index, "value", event.currentTarget.value)
84 | }
85 | />
86 |
87 | handlers.remove(index)}
91 | >
92 |
93 |
94 |
95 | )
96 |
97 | return acc
98 | },
99 | { completed: [], current: [] }
100 | )
101 |
102 | return (
103 |
104 |
105 | Business Plan
106 |
107 |
108 | {items.current}
109 |
110 | {items.completed.length > 0 && (
111 |
112 | Completed
113 |
114 | )}
115 | {items.completed}
116 |
117 | setNewItem(event.currentTarget.value)}
122 | icon={}
123 | placeholder="Add business plan task"
124 | onKeyDown={(event) => {
125 | if (
126 | event.nativeEvent.code === "Enter" &&
127 | event.currentTarget.value.trim().length > 0
128 | ) {
129 | handlers.append({
130 | value: event.currentTarget.value,
131 | completed: false,
132 | key: randomId(),
133 | })
134 | setNewItem("")
135 | }
136 | }}
137 | />
138 |
139 | )
140 | }
141 |
--------------------------------------------------------------------------------
/src/TodoList/xyz.module.css:
--------------------------------------------------------------------------------
1 | .test {
2 | background: blue;
3 |
4 | .other {
5 | background: green;
6 | }
7 | }
8 |
9 | .coolBean {
10 | color: purple;
11 | }
12 |
13 | .no {
14 | color: blue;
15 | }
--------------------------------------------------------------------------------
/src/__generated/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/DavidWells/types-with-jsdocs/3c03e4aa9ef5d784305ef2919d461a55a5847a32/src/__generated/.gitkeep
--------------------------------------------------------------------------------
/src/__tests__/index.test.js:
--------------------------------------------------------------------------------
1 | /* initialize JSDOM */
2 | // import './misc/_setup-tests.js' // with jsdom pkh // OR -r global-jsdom/register
3 | // import { setupJSDOM } from './misc/_initJSDom'
4 | import { test } from 'uvu'
5 | import * as assert from 'uvu/assert'
6 | import React from 'react'
7 | import { fireEvent, render } from "@testing-library/react"
8 | import Button from '../0_Button_PropTypes_Class'
9 | /* Ignoring CSS modules https://github.com/avajs/ava/issues/2038#issuecomment-864300925 */
10 | import TodoList from '../TodoList'
11 | import { itSupportsClassName } from './misc/utils'
12 |
13 | /*
14 | https://github.com/modosc/global-jsdom
15 | https://www.npmjs.com/package/mock-css-modules
16 | */
17 |
18 | test('Tests run', async () => {
19 | assert.is(true, true)
20 | })
21 |
22 | test("Renders component in test", async () => {
23 | const MyComponent = () => {
24 | return (
25 | <>
26 |
27 | inside
28 | another
29 |
30 | outside
31 | >
32 | );
33 | };
34 |
35 | const result = render()
36 | assert.ok(result)
37 | // console.log('result.container.innerHTML', result.container.innerHTML)
38 | assert.match(result.container.innerHTML, 'inside')
39 | })
40 |
41 | test("Class component renders", async () => {
42 | // Ensure it supports classes
43 | assert.ok(itSupportsClassName(Button))
44 |
45 | const result = render()
46 | assert.ok(result)
47 | console.log('result.container.innerHTML', result.container.innerHTML)
48 | // assert.match(result.container.innerHTML, 'inside')
49 |
50 | })
51 |
52 | test("component with css modules renders", async () => {
53 | const result = render()
54 | assert.ok(result)
55 | // console.log('result.container.innerHTML', result.container.innerHTML)
56 | assert.match(result.container.innerHTML, 'Complain about miners')
57 | })
58 |
59 | // Needed to exit process once tests finish
60 | // @ts-ignore
61 | test.after(() => setTimeout(() => process.exit(0), 300))
62 |
63 | test.run()
--------------------------------------------------------------------------------
/src/__tests__/misc/_initJSDom.js:
--------------------------------------------------------------------------------
1 | import { JSDOM } from "jsdom"
2 |
3 | const baseUrl = "http://www.example.org";
4 |
5 | // @ts-ignore
6 | export const setupJSDOM = ({ url, ...options } = {}) => {
7 | const dom = new JSDOM("", {
8 | // pretendToBeVisual is enabled so that react works, see
9 | // https://github.com/jsdom/jsdom#pretending-to-be-a-visual-browser
10 | pretendToBeVisual: true,
11 | url: baseUrl + url,
12 | ...options,
13 | });
14 | // @ts-ignore
15 | global.window = dom.window;
16 | // @ts-ignore
17 | global.document = dom.window.document;
18 |
19 | // cleanup func
20 | return () => {
21 | // @ts-ignore
22 | delete global.window;
23 | // @ts-ignore
24 | delete global.document;
25 | };
26 | };
--------------------------------------------------------------------------------
/src/__tests__/misc/_setup-tests.js:
--------------------------------------------------------------------------------
1 | // import { ConstructorOptions, JSDOM } from "jsdom";
2 | const { ConstructorOptions, JSDOM } = require('jsdom')
3 | process.env.NODE_ENV = 'test'
4 |
5 | const jsdom = new JSDOM('')
6 | const {window} = jsdom
7 |
8 | /**
9 | * @param {Object} src
10 | * @param {Object} target
11 | */
12 | function copyProps(src, target) {
13 | Object.defineProperties(target, {
14 | ...Object.getOwnPropertyDescriptors(src),
15 | ...Object.getOwnPropertyDescriptors(target),
16 | })
17 | }
18 |
19 |
20 | global.window = window
21 | global.document = window.document
22 | // @ts-ignore
23 | global.navigator = { userAgent: 'node.js' }
24 | global.requestAnimationFrame = callback => setTimeout(callback, 0)
25 | global.cancelAnimationFrame = id => clearTimeout(id)
26 | copyProps(window, global)
--------------------------------------------------------------------------------
/src/__tests__/misc/utils.js:
--------------------------------------------------------------------------------
1 | // https://github.com/mantinedev/mantine/blob/master/src/mantine-tests/src/it-supports-classname.tsx
2 | import React from 'react'
3 | import { render } from '@testing-library/react'
4 |
5 | /**
6 | * @callback TestUtil
7 | * @param {React.ElementType} Component
8 | * @param {Record} requiredProps
9 | */
10 |
11 | /**
12 | *
13 | * @param {React.ElementType} Component
14 | * @param {Record} requiredProps
15 | */
16 | export function itSupportsClassName(Component, requiredProps = {}) {
17 | const { container } = render()
18 | return container.querySelector('.test-class-name')
19 | }
20 |
21 |
22 | /** @type {TestUtil} */
23 | export function itRendersChildren(Component, requiredProps) {
24 | const { container } = render(
25 |
26 | test-children
27 |
28 | )
29 | return container.querySelector('.test-children')
30 | }
--------------------------------------------------------------------------------
/src/__tests__/simple/x.test.js:
--------------------------------------------------------------------------------
1 | /* initialize JSDOM */
2 | // import './misc/_setup-tests.js' // with jsdom pkh // OR -r global-jsdom/register
3 | // import { setupJSDOM } from './misc/_initJSDom'
4 | import { test } from 'uvu'
5 | import * as assert from 'uvu/assert'
6 | import React from 'react'
7 | import { render } from "@testing-library/react"
8 |
9 | test('Tests run', async () => {
10 | assert.is(true, true)
11 | })
12 |
13 | test("Renders component in test", async () => {
14 | const MyComponent = () => {
15 | return (
16 | <>
17 |
18 | inside
19 | another
20 |
21 | outside
22 | >
23 | );
24 | };
25 |
26 | const result = render()
27 | assert.ok(result)
28 | console.log('result.container.innerHTML', result.container.innerHTML)
29 | assert.match(result.container.innerHTML, 'inside')
30 | })
31 |
32 | // Needed to exit process once tests finish
33 | // @ts-ignore
34 | test.after(() => setTimeout(() => process.exit(0), 300))
35 |
36 | test.run()
--------------------------------------------------------------------------------
/src/__tests__/withJsDom/y.test.js:
--------------------------------------------------------------------------------
1 | /* initialize JSDOM */
2 | import '../misc/_setup-tests.js' // with jsdom pkh // OR -r global-jsdom/register
3 | import { test } from 'uvu'
4 | import * as assert from 'uvu/assert'
5 | import React from 'react'
6 | import { fireEvent, render } from "@testing-library/react"
7 | import Button from '../../0_Button_PropTypes_Class'
8 | /* Ignoring CSS modules https://github.com/avajs/ava/issues/2038#issuecomment-864300925 */
9 | import TodoList from '../../TodoList'
10 | import { itSupportsClassName } from '../misc/utils'
11 |
12 | /*
13 | https://github.com/modosc/global-jsdom
14 | https://www.npmjs.com/package/mock-css-modules
15 | */
16 |
17 |
18 | test('Tests run', async () => {
19 | assert.is(true, true)
20 | })
21 |
22 | test("Renders component in test", async () => {
23 | const MyComponent = () => {
24 | return (
25 | <>
26 |
27 | inside
28 | another
29 |
30 | outside
31 | >
32 | );
33 | };
34 |
35 | const result = render()
36 | assert.ok(result)
37 | // console.log('result.container.innerHTML', result.container.innerHTML)
38 | assert.match(result.container.innerHTML, 'inside')
39 | })
40 |
41 | test("Class component renders", async () => {
42 | // Ensure it supports classes
43 | assert.ok(itSupportsClassName(Button))
44 |
45 | const result = render()
46 | assert.ok(result)
47 | console.log('result.container.innerHTML', result.container.innerHTML)
48 | // assert.match(result.container.innerHTML, 'inside')
49 |
50 | })
51 |
52 | test("component with css modules renders", async () => {
53 | const result = render()
54 | assert.ok(result)
55 | // console.log('result.container.innerHTML', result.container.innerHTML)
56 | assert.match(result.container.innerHTML, 'Complain about miners')
57 | })
58 |
59 | // Needed to exit process once tests finish
60 | // @ts-ignore
61 | test.after(() => setTimeout(() => process.exit(0), 300))
62 |
63 | test.run()
--------------------------------------------------------------------------------
/src/favicon.svg:
--------------------------------------------------------------------------------
1 |
16 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
5 | sans-serif;
6 | -webkit-font-smoothing: antialiased;
7 | -moz-osx-font-smoothing: grayscale;
8 | }
9 |
10 | code {
11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
12 | monospace;
13 | }
14 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/main.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import ReactDOM from 'react-dom'
3 | import Inspect from 'inspx'
4 | import './index.css'
5 | import App from './App'
6 |
7 | ReactDOM.render(
8 |
9 |
10 |
11 |
12 | ,
13 | document.getElementById('root')
14 | )
15 |
--------------------------------------------------------------------------------
/src/utils/0_@author.js:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * @param {Object.} f
4 | * @author David Wells
5 | */
6 | function foo(f) {
7 |
8 | }
9 |
10 |
11 | /**
12 | * @param {Object.} f
13 | * @author David Wells
14 | */
15 | function bar(f) {
16 |
17 | }
18 |
19 |
20 | /**
21 | * Welcome to awesome.ts
22 | * @author Ian Awesome
23 | */
24 | export class Awesome {
25 | constructor() {
26 | console.log('awesome');
27 | }
28 | }
29 |
30 | const awesome = new Awesome();
--------------------------------------------------------------------------------
/src/utils/0_@default.js:
--------------------------------------------------------------------------------
1 | // Mark constant value with default
2 |
3 | /**
4 | * @constant
5 | * @default 'xyz'
6 | */
7 | const MY_VALUE = 'xyz';
--------------------------------------------------------------------------------
/src/utils/0_@deprecated.js:
--------------------------------------------------------------------------------
1 | // Mark function as deprecated
2 |
3 | /**
4 | * @deprecated
5 | */
6 | function brokenFunction() {
7 | throw new Error('this is broken')
8 | }
--------------------------------------------------------------------------------
/src/utils/0_@description.js:
--------------------------------------------------------------------------------
1 | // @description tag
2 |
3 | /**
4 | * Add two numbers.
5 | */
6 | export function add(a, b) {
7 | return a + b;
8 | }
9 |
10 | /**
11 | * @desc Add two numbers.
12 | */
13 | export function addTwo(a, b) {
14 | return a + b;
15 | }
16 |
17 | /**
18 | * @description Add two numbers.
19 | */
20 | export function addThree(a, b) {
21 | return a + b;
22 | }
23 |
--------------------------------------------------------------------------------
/src/utils/0_@example.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Adds two numbers
3 | *
4 | * @param {number} a number one
5 | * @param {number} b number two
6 | * @returns {number} sum of number one and number two
7 | *
8 | * @example Add 1 and 3. If answer is >0, sums result and 5.
9 | * ```
10 | * const answer = sum(1, 3); // returns 4
11 | *
12 | * if (answer > 0) {
13 | * sum(answer, 5)
14 | * }
15 | * ```
16 | */
17 | function sum(a, b) {
18 | return a + b
19 | }
20 |
21 |
22 | // ───────────────────────
23 | // https://github.com/yamadapc/jsdoctest/blob/master/test/test-file-captioned.js
24 |
25 | /**
26 | * @example Integers
27 | * addMoreStuff(1, 2)
28 | * // => 3
29 | * addMoreStuff(3, 2)
30 | * // => 5
31 | *
32 | * @example Doubles
33 | * addMoreStuff(1.5, 2.5)
34 | * // => 4
35 | */
36 |
37 | function addMoreStuff(x, y) {
38 | return x + y;
39 | }
40 |
41 | // ───────────────────────
42 | // https://github.com/jaydenseric/jsdoc-md#example-content
43 |
44 | /**
45 | * Displays a message in a native popup window.
46 | * @kind function
47 | * @name popup
48 | * @param {string} message Message text.
49 | * @example Say `Hello!` to the user.
50 | * This usage:
51 | *
52 | * ```js
53 | * popup('Hello!');
54 | * ```
55 | *
56 | * Displays like this on macOS:
57 | *
58 | * 
59 | */
60 | const popup = (message) => alert(message);
--------------------------------------------------------------------------------
/src/utils/0_@extends.js:
--------------------------------------------------------------------------------
1 | // The @augments or @extends tag indicates that a symbol inherits from, and potentially adds to, a parent symbol.
2 | // You can use this tag to document both class-based and prototype-based inheritance.
3 |
4 | /**
5 | * @constructor
6 | */
7 | function AnimalTwo() {
8 | /** Is this animal alive? */
9 | this.alive = true;
10 | }
11 |
12 | /**
13 | * @constructor
14 | * @augments AnimalTwo
15 | */
16 | class DuckTwo extends AnimalTwo {
17 | quack(stuff) {
18 | console.log(`Doing some pretty crazy stuff with ${stuff}`);
19 | }
20 | }
21 |
22 | /** What do ducks say? */
23 | DuckTwo.prototype.speak = function() {
24 | if (this.alive) {
25 | alert('Quack!');
26 | }
27 | };
28 |
29 | var d = new DuckTwo();
30 | console.log('d', d)
31 | d.speak(); // Quack!
32 | d.alive = false;
33 | d.speak(); // (nothing)
--------------------------------------------------------------------------------
/src/utils/0_@license.js:
--------------------------------------------------------------------------------
1 | // Short license
2 |
3 | /**
4 | * Utility functions for the foo package.
5 | * @module foo/util
6 | * @license Apache-2.0
7 | */
8 | export const util = () => '';
9 |
10 | // Verbose license
11 |
12 | /**
13 | * @license
14 | * Copyright (c) 2015 Example Corporation Inc.
15 | *
16 | * Permission is hereby granted, free of charge, to any person obtaining a copy
17 | * of this software and associated documentation files (the "Software"), to deal
18 | * in the Software without restriction, including without limitation the rights
19 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
20 | * copies of the Software, and to permit persons to whom the Software is
21 | * furnished to do so, subject to the following conditions:
22 | *
23 | * The above copyright notice and this permission notice shall be included in all
24 | * copies or substantial portions of the Software.
25 | *
26 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
29 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
30 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
31 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 | * SOFTWARE.
33 | */
34 |
35 | export const utilTwo = () => '';
36 |
--------------------------------------------------------------------------------
/src/utils/0_@link.js:
--------------------------------------------------------------------------------
1 | /**
2 | * See {@link MyClass} and [MyClass's foo property](MyClass#foo).
3 | * Also, check out {@link http://www.google.com|Google} and
4 | * {@link https://github.com GitHub}.
5 | */
6 | export function myFunction() {}
7 |
--------------------------------------------------------------------------------
/src/utils/0_@module.js:
--------------------------------------------------------------------------------
1 | /** @module User */
2 |
3 | const defaultUserName = "bob";
4 |
5 | /**
6 | * Hello function
7 | * @param {string} name - person name
8 | */
9 | function sayHello(name) {
10 | alert("hello " + name || defaultUserName);
11 | }
--------------------------------------------------------------------------------
/src/utils/0_@module2.js:
--------------------------------------------------------------------------------
1 | // https://github.com/rlwi440/JS-Docs/blob/master/src/calculator.js
2 |
3 | /**
4 | * Calculator module - See {@tutorial calculator-tutorial}
5 | * @module calculator
6 | */
7 |
8 | /**
9 | * Add two numbers
10 | * @param {number} n1 - First number
11 | * @param {number} n2 - Second number
12 | * @returns {number} - Sum of n1 and n2
13 | */
14 | exports.add = (n1, n2) => n1 + n2;
15 |
16 | /**
17 | * Multiply two numbers
18 | * @param {number} n1 - First number
19 | * @param {number} n2 - Second number
20 | * @returns {number} - Product of n1 and n2
21 | */
22 | exports.multiply = (n1, n2) => n1 * n2;
23 |
24 | /**
25 | * Subtract two numbers
26 | * @param {number} n1 - First number
27 | * @param {number} n2 - Second number
28 | * @returns {number} - Difference of n1 and n2
29 | */
30 | exports.subtract = (n1, n2) => n1 - n2;
31 |
32 | /**
33 | * Divide two numbers
34 | * @param {number} n1 - First number
35 | * @param {number} n2 - Second number
36 | * @returns {number} - Quotient of n1 and n2
37 | */
38 | exports.divide = (n1, n2) => n1 / n2;
--------------------------------------------------------------------------------
/src/utils/0_@name.js:
--------------------------------------------------------------------------------
1 | // https://github.com/onury/jsdoc-x/blob/master/test/input-parse/name-test.js
2 |
3 | (function () {
4 | 'use strict';
5 |
6 | // NOTE: symbol descriptions should be unique
7 |
8 | /**
9 | * foo
10 | * @class
11 | */
12 | var foo = {};
13 |
14 | /**
15 | * foo.bar
16 | * @name foo.bar
17 | * @function
18 | */
19 |
20 | /**
21 | * foo.baz
22 | * @name foo.baz
23 | * @alias foo.bazAlias
24 | * @function
25 | */
26 |
27 | /**
28 | * foo.qux
29 | */
30 | foo.qux = function () {};
31 |
32 | foo.ns = {};
33 |
34 | /**
35 | * foo.ns.m1
36 | * @alias m1alias
37 | */
38 | foo.ns.m1 = function () {};
39 |
40 | /**
41 | * foo.ns.m2
42 | * @memberof foo.ns
43 | * @name mx
44 | * @alias ns.m2alias
45 | */
46 | foo.ns.m2 = function () {};
47 |
48 | /**
49 | * foo.ns.m3
50 | * @name m3name
51 | * @function
52 | */
53 | foo.ns.m3 = function () {};
54 |
55 | /**
56 | * foo.ns.m4
57 | * @name ns.m4name
58 | * @function
59 | */
60 | foo.ns.m4 = function () {};
61 |
62 | /**
63 | * m5
64 | * @memberof foo.ns
65 | */
66 | function m5() {}
67 |
68 | /**
69 | * m6
70 | * @memberof foo.ns
71 | * @alias m6alias
72 | */
73 | function m6() {}
74 |
75 | /**
76 | * Some name space.
77 | * @memberof foo
78 | * @type {Object}
79 | */
80 | var o = {};
81 |
82 | /**
83 | * m7
84 | * @memberof foo
85 | * @alias m7alias
86 | */
87 | o.m7 = function () {};
88 |
89 | /**
90 | * m8
91 | * @memberof foo.o
92 | * @alias m8alias
93 | */
94 | o.m8 = function () {};
95 |
96 | /**
97 | * m9
98 | * @memberof foo.o
99 | * @alias m9alias
100 | */
101 | foo.o.m9 = function () {};
102 |
103 | /**
104 | * foo.o.mx
105 | * @memberof foo.o
106 | * @alias m9alias
107 | */
108 | foo.o.mx = function () {};
109 |
110 | })();
--------------------------------------------------------------------------------
/src/utils/0_@namespace.js:
--------------------------------------------------------------------------------
1 | // https://github.com/onury/jsdoc-x/blob/master/test/input-parse/test3.es5.js
2 |
3 | (function () {
4 | 'use strict';
5 |
6 | /**
7 | * Test namespace properties.
8 | * @namespace
9 | * @global
10 | * @name namespace
11 | * @type {Object}
12 | */
13 | var namespace = {};
14 |
15 | /**
16 | * Similar to `window.location` but with differences and additional
17 | * information.
18 | *
19 | * @name namespace.location
20 | * @type {Object}
21 | * @readonly
22 | *
23 | * @property {String} pathname - Gets the path and filename of the current URL, without the base.
24 | * @property {String} query - Gets the querystring part of the current URL, without `?` prefix.
25 | * @property {String} origin - Gets the protocol, hostname and port number of the current URL.
26 | * @property {String} hostname - Gets the domain name of the web host.
27 | * @property {String} host - Gets the host.
28 | * @property {String} href - Gets the href (URL) of the current location.
29 | * @property {String} path - Gets the path, filename and query-string of the current URL, without the base.
30 | * @property {String} hash - Gets the anchor `#` of the current URL, without `#` prefix.
31 | * @property {Function} getQuery() - Gets the value of the given querystring parameter.
32 | * @property {String} protocol - Gets the web protocol used, including `:` suffix.
33 | */
34 | Object.defineProperty(namespace, 'location', {
35 | configurable: false,
36 | get: function () {
37 | return {
38 | host: window.location.host,
39 | hostname: window.location.hostname,
40 | origin: window.location.origin,
41 | port: window.location.port,
42 | protocol: window.location.protocol,
43 | hash: (window.location.hash || '').replace(/^#/, ''),
44 | query: (window.location.search || '').replace(/^\?/, ''),
45 | href: window.location.href,
46 | pathname: window.location.pathname,
47 | path: window.location.pathname + (window.location.search || ''),
48 | getQuery: function () {
49 | return '';
50 | }
51 |
52 | };
53 | }
54 | });
55 |
56 | })();
57 |
58 | // ───────────────────────
59 | // https://jsdoc.app/about-namepaths.html
60 | // IDK why you'd use this .shrug
61 |
62 | /** @namespace */
63 | var chat = {
64 | /**
65 | * Refer to this by chat."#channel"
66 | * @namespace
67 | */
68 | "#channel": {
69 | /**
70 | * Refer to this by chat."#channel".open
71 | * @type {boolean}
72 | * @defaultvalue
73 | */
74 | open: true,
75 | /**
76 | * Internal quotes have to be escaped by backslash. This is
77 | * {@link chat.channel.say-\"hello\"}.
78 | */
79 | 'say-"hello"': function (msg) {}
80 | }
81 | };
--------------------------------------------------------------------------------
/src/utils/0_@param.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Different types of param styles
3 | */
4 |
5 | // default-numeric
6 |
7 | /** @param {number} [x=1] d4 damage */
8 | export function m(x) {}
9 |
10 | // default-string
11 |
12 | /**
13 | * @param {string} [somebody="John Doe"] - Somebody's name.
14 | */
15 | export function sayHello(somebody) {
16 | if (!somebody) {
17 | somebody = 'John Doe';
18 | }
19 | alert('Hello ' + somebody);
20 | }
21 |
22 | // just-param
23 |
24 | /**
25 | * @param somebody
26 | */
27 | export function sayBye(somebody) {
28 | alert('Bye ' + somebody);
29 | }
30 |
31 |
32 | // name-type-description
33 |
34 | /**
35 | * @param {string} somebody Somebody's name.
36 | */
37 | export function sayYo(somebody) {
38 | alert('Yo ' + somebody);
39 | }
40 |
41 | // name-type
42 |
43 | /**
44 | * @param {string} somebody
45 | */
46 | export function sayNo(somebody) {
47 | alert('No ' + somebody);
48 | }
49 |
50 | // optional
51 |
52 | /**
53 | * An optional parameter (using JSDoc syntax)
54 | * @param {string} [somebody] - Somebody's name.
55 | */
56 | export function sayWoo(somebody) {
57 | if (!somebody) {
58 | somebody = 'John Doe';
59 | }
60 | alert('Woo ' + somebody);
61 | }
62 |
63 | // with-hyphen-description
64 |
65 | /**
66 | * @param {string} somebody - Somebody's name.
67 | */
68 | export function sayWhat(somebody) {
69 | alert('What ' + somebody);
70 | }
71 |
--------------------------------------------------------------------------------
/src/utils/0_@remarks.js:
--------------------------------------------------------------------------------
1 | /**
2 | * sum api function
3 | * @remarks
4 | * Unlike the summary, the remarks block may contain lengthy documentation content.
5 | * The remarks should not restate information from the summary, since the summary section
6 | * will always be displayed wherever the remarks section appears. Other sections
7 | * (e.g. an `@example` block) will be shown after the remarks section.
8 | *
9 | * @param {number} a first parameter to add
10 | * @param {number} b second parameter to add
11 | * @returns {number} the sum of the two parameters
12 | *
13 | * @example
14 | *
15 | * ```js
16 | * import { sum } from './sum';
17 | *
18 | * expect(sum(1, 2)).toMatchObject({ a: 1, b: 2, result: 3});
19 | * ```
20 | */
21 | export const sum = (a, b = 1) => {
22 | return a + b
23 | }
--------------------------------------------------------------------------------
/src/utils/0_@schema.js:
--------------------------------------------------------------------------------
1 | // https://github.com/john-doherty/jsdoc-to-json-schema#input-singleton
2 |
3 | /**
4 | * @schema.name Person
5 | * @schema.description This is an example Person object marked up with JSON schema tags to allow schema generation
6 | */
7 | var Person = {
8 |
9 | /**
10 | * @schema.title Name
11 | * @schema.description Please enter your full name
12 | * @schema.type string
13 | * @schema.maxLength 30
14 | * @schema.minLength 1
15 | * @schema.required true
16 | */
17 | name: '',
18 |
19 | /**
20 | * @schema.title Job Title
21 | * @schema.type string
22 | */
23 | jobTitle: '',
24 |
25 | /**
26 | * @schema.title Telephone Number
27 | * @schema.description Please enter telephone number including country code
28 | * @schema.type string
29 | * @schema.required true
30 | */
31 | telephone: '',
32 |
33 | /**
34 | * @schema.type string
35 | * @schema.required true
36 | */
37 | dateOfBirth: ''
38 | };
39 |
40 | /*
41 | Output
42 | {
43 | "name": "Person",
44 | "description": "This is an example Person object marked up with JSON schema tags to allow schema generation",
45 | "properties": {
46 | "name": {
47 | "title": "Name",
48 | "description": "Please enter your full name",
49 | "type": "string",
50 | "maxLength": 30,
51 | "minLength": 1,
52 | "required": true
53 | },
54 | "jobTitle": {
55 | "title": "Job Title",
56 | "type": "string"
57 | },
58 | "telephone": {
59 | "title": "Telephone Number",
60 | "description": "Please enter telephone number including country code",
61 | "type": "string",
62 | "required": true
63 | },
64 | "dateOfBirth": {
65 | "type": "string",
66 | "required": true
67 | },
68 | "address": {
69 | "type": "object"
70 | }
71 | }
72 | }
73 | */
74 |
75 | // ───────────────────────
76 |
77 |
78 | /**
79 | * @schema.name Product
80 | * @schema.description An example product marked up with json schema comments
81 | */
82 | function Product(){
83 |
84 | }
85 |
86 | /**
87 | * @schema.type array
88 | * @schema.minItems 3
89 | * @schema.maxItems 6
90 | * @schema.required true
91 | */
92 | Product.prototype.types = function(){
93 |
94 | }
--------------------------------------------------------------------------------
/src/utils/0_@see.js:
--------------------------------------------------------------------------------
1 | // Inline link
2 |
3 | /**
4 | * @see {@link foo} for further information.
5 | * @see {@link https://github.com|GitHub}
6 | */
7 | export function bar() {}
8 |
9 | // Internal link
10 |
11 | /**
12 | * Both of these will link to the bar function.
13 | * @see {@link bar}
14 | * @see bar
15 | */
16 | export function foo() {}
17 |
18 |
19 | // Pure http link
20 |
21 | /**
22 | * external link documentation
23 | * @see https://reactjs.org/docs/context.html
24 | */
25 |
26 | export const barTwo = () => '';
27 |
--------------------------------------------------------------------------------
/src/utils/0_@summary.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A very long, verbose, wordy, long-winded, tedious, verbacious, tautological,
3 | * profuse, expansive, enthusiastic, redundant, flowery, eloquent, articulate,
4 | * loquacious, garrulous, chatty, extended, babbling description.
5 | * @summary A concise summary.
6 | */
7 | export function bloviate() {}
8 |
--------------------------------------------------------------------------------
/src/utils/0_@template.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 |
3 | // https://github.com/voxpelli/types-in-js/discussions/17
4 |
5 | /** @template [T=undefined] */
6 | class ErrorWithCause extends Error {
7 | /**
8 | * @param {string} message
9 | * @param {{ cause?: T }} [options]
10 | */
11 | constructor (message, { cause } = {}) {
12 | if (cause) {
13 | /** @type {T} */
14 | this.cause = cause;
15 | }
16 | // ...
17 | }
18 | }
19 |
20 |
21 | // ───────────────────────
22 | // https://github.com/microsoft/TypeScript/pull/45483
23 |
24 | /**
25 | * @template {string} [T="hello"]
26 | * @typedef {T} Foo
27 | */
--------------------------------------------------------------------------------
/src/utils/0_@this.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @this {HTMLElement}
3 | * @param {*} e
4 | */
5 | function callbackForLater(e) {
6 | console.log(this.clientHeight, e)
7 | }
--------------------------------------------------------------------------------
/src/utils/0_@type.js:
--------------------------------------------------------------------------------
1 | // Using @type tag
2 |
3 | /** @type {string} */
4 | const myvar = 'string';
5 |
6 | /**
7 | * @type { "small" | "medium" | "large" }
8 | */
9 | const myvarTwo = 'small'
10 |
11 | // See primatives
12 |
13 | // ───────────────────────
14 | // Imported JSON type
15 |
16 | // import importedIcons from './icons.json';
17 |
18 | // /**
19 | // * @type {import('@iconify/types').IconifyJSON}
20 | // */
21 | // const icons = importedIcons;
--------------------------------------------------------------------------------
/src/utils/0_@typedef.js:
--------------------------------------------------------------------------------
1 | /**
2 | * First name & last name
3 | * @typedef {{firstName: string, lastName: string}} BrokenName
4 | */
5 |
6 | /**
7 | * @param {string} name
8 | * @returns {BrokenName}
9 | */
10 | function breakName(name) {
11 | const [first, ...rest] = name.split(' ')
12 |
13 | return {
14 | firstName: first,
15 | lastName: rest.join(' ')
16 | }
17 | }
18 |
19 | // ───────────────────────
20 | // Combining typedefs https://github.com/microsoft/TypeScript/issues/42048
21 |
22 | /** @typedef {{ name: string, age: number }} Bar - A Bar thing of sorts. */ // <-- This is for documentation tooling, and TS understand it.
23 |
24 | /** @typedef {Bar & { color: string }} ExtendBar - A Foo type of thing. */ // <-- This is for documentation tooling, and TS understand it.
25 |
26 | /** @type {ExtendBar} */
27 | const combinedBar = { name: 'bob', age: 21, color: 'purple' }
28 |
29 |
30 | // ───────────────────────
31 | // https://github.com/jsdoc/jsdoc/issues/1890#issuecomment-774715480
32 |
33 | /**
34 | * @typedef {object} Employee
35 | * @property {string} name - The name of an employee.
36 | * @property {string} department - The employee's department.
37 | */
38 | /**
39 | * @typedef {object} Company
40 | * @property {string} name - The name of the company.
41 | * @property {Employee[]} employees - The employees who are responsible for the project.
42 | */
43 | /**
44 | * Assign the project to a list of employees of the given company.
45 | * @param {Company} company - The company this project has been contracted to.
46 | */
47 | function testFunc(company) { }
48 |
49 |
50 | // ───────────────────────
51 |
52 | /**
53 | * @typedef FieldType
54 | * @property {string} Text "text"
55 | * @property {string} Date "date"
56 | * @property {string} DateTime "datetime"
57 | * @property {string} Number "number"
58 | * @property {string} Currency "currency"
59 | * @property {string} CheckBox "checkbox"
60 | * @property {string} ComboBox "combobox"
61 | * @property {string} Dropdownlist "dropdownlist"
62 | * @property {string} Label "label"
63 | * @property {string} TextArea "textarea"
64 | * @property {string} JsonEditor "jsoneditor"
65 | * @property {string} NoteEditor "noteeditor"
66 | * @property {string} ScriptEditor "scripteditor"
67 | * @property {string} SqlEditor "sqleditor"
68 | */
69 |
70 | /** @type {FieldType} */
71 | const fieldtype = {
72 | Text: "text",
73 | Date: "date",
74 | DateTime: "datetime",
75 | Number: "number",
76 | Currency: "currency",
77 | CheckBox: "checkbox",
78 | ComboBox: "combobox",
79 | Dropdownlist: "dropdownlist",
80 | Label: "label",
81 | TextArea: "textarea",
82 | JsonEditor: "jsoneditor",
83 | NoteEditor: "noteeditor",
84 | ScriptEditor: "scripteditor",
85 | SqlEditor: "sqleditor",
86 | }
87 |
88 |
89 | // ───────────────────────
90 | // https://github.com/n3ps/json-schema-to-jsdoc/blob/master/test.js#L803
91 |
92 | /**
93 | * @typedef {object}
94 | * @property {string} [aStringProp]
95 | * @property {object} [anObjectProp]
96 | * @property {boolean} [anObjectProp.aNestedProp] Boolean desc.
97 | * @property {array} [anObjectProp.aNestedArrayProp] Array desc.
98 | * @property {number} anObjectProp.aNestedArrayProp
99 | * @property {?string} [nullableType]
100 | * @property {string|number} [multipleTypes]
101 | * @property {"hello"|"there"|"world"} [enumStringProp]
102 | */
103 |
104 | // ───────────────────────
105 | // https://github.com/artdecocode/typal
106 |
107 | /**
108 | * @typedef {Object} SessionConfig Description of Session Config.
109 | * @prop {string} key The cookie key.
110 | * @prop {number|'session'} [maxAge=86400000] maxAge in ms. Default is 1 day.
111 | * @prop {boolean} [overwrite] Can overwrite or not. Default `true`.
112 | * @prop {boolean} [httpOnly] httpOnly or not or not. Default `true`.
113 | * @prop {boolean} [signed=false] Signed or not. Default `false`.
114 | * @prop {boolean} [rolling] Force a session identifier cookie to be set.
115 | * @prop {boolean} [renew] Renew session when session is nearly expired.
116 | */
117 |
118 |
119 | // ───────────────────────
120 | // https://github.com/homer0/jsdoc-ts-utils/blob/main/src/typedef.js#L26
121 |
122 | /**
123 | * @typedef {Object} TSUtilsOptions
124 | * @property {boolean} typedefImports
125 | * Whether or not to enable the feature that removes `typedef` statements that use
126 | * `import`.
127 | * Default `true`.
128 | * @property {boolean} typeOfTypes
129 | * Whether or not to enable the feature that replaces `{typeof T}` with `{Class.}`.
130 | * Default `true`.
131 | * @property {boolean} extendTypes
132 | * Whether or not to enable the feature that allows intersections to be reformatted.
133 | * Default `true`.
134 | * @property {boolean} modulesOnMemberOf
135 | * Whether or not to enable the feature that fixes modules' paths on `memeberof` so they
136 | * can use dot notation. Default `true`.
137 | * @property {boolean} modulesTypesShortName
138 | * Whether or not to register modules types without the module path too. Default `true`.
139 | * @property {boolean} parentTag
140 | * Whether or not to transform all `parent` tags into `memberof`. Default `true`.
141 | * @property {boolean} typeScriptUtilityTypes
142 | * Whether or not to add the external utility types from TypeScript. Default `true`.
143 | * @property {?Object.} tagsReplacement
144 | * A dictionary of tags to replace, they keys are the tags being used and the values the
145 | * tag that should be used. Default `null`.
146 | */
--------------------------------------------------------------------------------
/src/utils/0__other_tags.js:
--------------------------------------------------------------------------------
1 | // https://www.webdoclabs.com/guides/tags/tags.html
2 |
--------------------------------------------------------------------------------
/src/utils/0_captions.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Some function
3 | * @param {number} a
4 | * @param {number} b
5 | * @param {number} c
6 | *
7 | * @example Add two numbers
8 | * add(2, 4)
9 | * // returns 6
10 | *
11 | * @example Add three numbers
12 | * add(2, 4, 6)
13 | * // returns 12
14 | */
15 | function addThreeNumbers(a, b, c = 0) {
16 | return a + b + c
17 | }
--------------------------------------------------------------------------------
/src/utils/0_images.js:
--------------------------------------------------------------------------------
1 | // Using images in JSdoc
2 |
3 | /**
4 | * this is how it works 
5 | */
6 | class MyClass {
7 |
8 | }
--------------------------------------------------------------------------------
/src/utils/0_primatives.js:
--------------------------------------------------------------------------------
1 | /** @type {string} */
2 | const str = 'string';
3 |
4 | /** @type {number} */
5 | const num = 123;
6 |
7 | /** @type {boolean} */
8 | const bool = true;
9 |
10 | /** @type {null} */
11 | const nul = null;
12 |
13 | /** @type {undefined} */
14 | const und = undefined;
15 |
16 | /** @type {symbol} */
17 | const sym = Symbol('foo');
18 |
19 | /** @type {*} */
20 | const jsDocAny = 'any value';
21 |
22 | /** @type {any} */
23 | const tsAny = 'any value';
24 |
25 | /** @type {unknown} */
26 | const tsUnknown = 'unknown value';
27 |
28 | /** @type {PromiseLike} */
29 | var promisedString = Promise.resolve('hi')
30 |
31 | // Enum into Array
32 | // https://medium.com/@antonkrinitsyn/jsdoc-frequent-patterns-436dad6dbee1
33 | /**
34 | * @typedef {'ally' | 'enemy'} PlayerType
35 | *
36 | * @typedef Player
37 | * @property {PlayerType} type
38 | */
39 |
40 | /** @type {Player[]} */
41 | const players = [
42 | {
43 | type: 'ally',
44 | }
45 | ]
--------------------------------------------------------------------------------
/src/utils/0_typeof.js:
--------------------------------------------------------------------------------
1 | // ----------------------------------------------------- typeof
2 | // https://github.com/chunjin666/jsdoc-learning/blob/master/src/01-types/04-%40type-advanced.js#L19
3 | // When the type of a value is more complicated and cumbersome to write, you can use `typeof` to get its type.
4 |
5 | const userAccountDefault = {
6 | id: 1,
7 | username: 'name1',
8 | account: 'account',
9 | age: 18,
10 | isLogin : false ,
11 | };
12 |
13 | /**
14 | *
15 | * @param {typeof userAccountDefault} account
16 | */
17 | export function setAccount(account) {
18 | console.log(account.id)
19 | }
20 |
21 | setAccount({
22 | id: 2,
23 | username: 'name2',
24 | account: 'account2',
25 | age: 22,
26 | isLogin : true,
27 | })
--------------------------------------------------------------------------------
/src/utils/1_array.js:
--------------------------------------------------------------------------------
1 | /**
2 | * JSDoc style
3 | * @typedef {object} RgbColors
4 | * @property {number} red
5 | * @property {number} green
6 | * @property {number} blue
7 | */
8 |
9 |
10 | /**
11 | * JSDoc style with primative
12 | * @type {Array}
13 | */
14 | const gradesXyz = [98, 97.7, 76, 89];
15 |
16 | /**
17 | * JSDoc style with primative
18 | * @type {Array}
19 | */
20 | const grades = [98, 97.7, 76, 89];
21 |
22 | /**
23 | * JSDoc style
24 | * @type {Array.}
25 | */
26 | const colors1 = [{ red: 0, green: 0, blue: 0 }];
27 |
28 | /**
29 | * TypeScript style
30 | * @type {Array}
31 | */
32 | const color3 = [{ red: 255, green: 255, blue: 255 }];
33 |
34 | /**
35 | * JSDoc type bracket
36 | * @type {String[]}
37 | */
38 | const arrayOfStrings = ['a', 'b'];
39 |
40 | /**
41 | * @type {Number[]}
42 | */
43 | const arrayOfNumbers = [1, 2, 3];
44 |
45 | /**
46 | * @type {Boolean[]}
47 | */
48 | const arrayOfBools = [true, false, true];
49 |
50 | /**
51 | * @type {Array.}
52 | */
53 | const arrayOfStringOrBools = ['true', false, 'true'];
54 |
55 | /**
56 | * TypeScript style
57 | * @type {RgbColors[]}
58 | */
59 | const color2 = [{ red: 111, green: 111, blue: 111 }];
60 |
61 | /**
62 | * TypeScript style array of objects
63 | * @type Array<{localPath:string, fullPath: string}>
64 | */
65 | let filePaths = [{ localPath: 'xyz', fullPath: 'abc' }];
66 |
67 | // Array with any type
68 | /** @type {Array} */
69 | var myArrayOfAnyType = ["children", true, 1, {}];
70 |
71 | /**
72 | * @typedef MyType
73 | * @type {Object}
74 | * @property {string} userId
75 | */
76 | /**
77 | * @typedef MyTypeArray
78 | * @type {Array.}
79 | */
80 | /** @type {MyTypeArray} */
81 | var xyzArray = [{ userId: '123'}, { userId: 'hehehe' }];
82 | // ────── Function returning an array of objects ─────────────────
83 |
84 | /**
85 | * @typedef AwesomeObject
86 | * @type {Object}
87 | * @property {string} name
88 | * @property {boolean} next
89 | * @property {string} test
90 | */
91 |
92 | /**
93 | * @param {Array.} awesomeObjects Awesome objects.
94 | */
95 | function totalAmount(awesomeObjects) {
96 | return awesomeObjects.map((d) => d)
97 | }
98 |
99 | // ────── Function returning an array of objects shorthand ─────────────────
100 |
101 | /**
102 | * @typedef {Object} Article
103 | * @property {number} price
104 | * @property {number} vat
105 | * @property {string} string
106 | * @property {boolean=} sold
107 | */
108 |
109 | /**
110 | * Now we can use Article as a proper type
111 | * @param {[Article]} articles
112 | */
113 | function totalAmount(articles) {
114 | return articles.reduce((total, article) => {
115 | return total + addVAT(article)
116 | }, 0)
117 | }
118 | /**
119 | * @param {Article} article
120 | */
121 | function addVAT(article) {
122 | return article.price + 1
123 | }
124 |
125 | // ───────────────────────
126 | // an array of objects with some known and some unknown properties.
127 | // https://twitter.com/Stegosource/status/1395421390698733570
128 |
129 | /**
130 | * @typedef {Array<{
131 | * known: number
132 | * yep: boolean
133 | * defo: string
134 | * }
135 | * &
136 | * Record
137 | * >
138 | * } MyCustomArray
139 | */
140 |
141 | /** @type {MyCustomArray} */
142 | const myArray = [{ known: 2, yep: true, defo: 'yay', xyz: '123' }]
143 |
144 |
145 | // ───────Array of arrays────────────────
146 | // https://stackoverflow.com/questions/66912667/whats-the-best-way-to-document-an-array-of-arrays-of-arrays-using-jsdoc
147 |
148 | /** @typedef {[string, number, string]} MyTuple */
149 |
150 | /** @type {MyTuple} */
151 | const single = ['aqua-160', 160, 'PreCleaning']
152 |
153 | /** @type {Array>} */
154 | const arrayOfArrays = [[1, 2], [3, 4]];
155 |
156 | /** @type {number[][]} */
157 | const arrayOfArraysDiffSyntax = [[1, 2], [3, 4]];
158 |
159 | /** @type {Array>} */
160 | const nestedArrays = [
161 | [
162 | ['aqua-160', 160, 'PreCleaning'],
163 | ['aqua-260', 260, 'PreCleaning']],
164 | [
165 | ['aqua-360', 360, 'PostCleaning']
166 | ]
167 | ];
168 |
169 | // ────────Conditional pair tuple ───────────────
170 | // https://github.com/jsdoc/jsdoc/issues/1703#issuecomment-898203535
171 |
172 | /**
173 | * @template IType
174 | * @template FnReturnType
175 | * @typedef {[IType, FnReturnType]} ConditionPair
176 | */
177 |
178 | const state = 'foo'
179 | function set_state() {}
180 |
181 | /** @type ConditionPair */
182 | const tuple = [state, set_state]
183 |
184 | /** @type ConditionPair */
185 | const tupleTwo = [state, 1]
186 |
187 |
188 | // ───────────────────────
189 | // Read only array https://discord.com/channels/508357248330760243/813896878058897458/875389849547444265
190 |
191 | /**
192 | * @param {TemplateStringsArray} strings
193 | * @param {...string[]} expr
194 | */
195 | const xyzThing = (strings, ...expr) => {
196 | // strings.push('x') will error
197 | return strings.map((x) => {
198 | return x
199 | })
200 | }
--------------------------------------------------------------------------------
/src/utils/1_class.js:
--------------------------------------------------------------------------------
1 |
2 | // ───────────────────────
3 | // https://github.com/giltayar/jsdoc-typing/blob/master/src/class.js
4 |
5 | class PersonClass {
6 | /**@type {string}*/
7 | firstName
8 | /**@type {string}*/
9 | lastName
10 |
11 | /**
12 | * @param {string} firstName
13 | * @param {string} lastName
14 | */
15 | constructor(firstName, lastName) {
16 | this.firstName = firstName
17 | this.lastName = lastName
18 | }
19 |
20 | /**
21 | * @returns {string}
22 | */
23 | fullName() {
24 | return `${this.firstName} ${this.lastName}`
25 | }
26 | }
27 |
28 | const person = new PersonClass('bob', 'smith')
29 |
30 | // https://fettblog.eu/typescript-jsdoc-superpowers/
31 |
32 | /**
33 | * Creates a new Person.
34 | * @class
35 | */
36 | export function Person() {
37 |
38 | }
39 |
40 | // ───────────────────────
41 | // https://ics.media/entry/6789/
42 |
43 | /**
44 | * Count Manager class
45 | * @constructor
46 | */
47 | function CountManager() {
48 | /**
49 | * Current count
50 | * @type {Number}
51 | */
52 | this._count = 0;
53 |
54 | /**
55 | * Add to count
56 | */
57 | this.addCount = function() {
58 | this._count++;
59 | };
60 |
61 | /**
62 | * Get current count
63 | * @return {Number} current count
64 | */
65 | this.getCount = function() {
66 | return this._count;
67 | };
68 | }
69 |
70 | // ───────────────────────
71 |
72 |
73 | /**
74 | * this is BaseClass.
75 | */
76 | export class BaseClass {
77 | /**
78 | * this is a method of BaseClass.
79 | * @returns {string} a greeting.
80 | */
81 | baseMethod(){
82 | return 'this is base method';
83 | }
84 | }
85 |
86 | /**
87 | * this is MyClass.
88 | */
89 | export default class MyClass extends BaseClass {
90 | /**
91 | * creates a instance of MyClass.
92 | * @param {number} value - initial value.
93 | */
94 | constructor(value){
95 | /**
96 | * this is property of MyClass.
97 | * @type {number}
98 | * @private
99 | */
100 | super()
101 | this._property = value;
102 | }
103 |
104 | /**
105 | * this is method of MyClass.
106 | * @param {number} a - this is a 1st number value.
107 | * @param {number} b - this is a 2nd number value.
108 | * @returns {string} repeated Hello
109 | */
110 | method(a, b){
111 | return 'Hello'.repeat((a + b) * this._property);
112 | }
113 | }
114 |
115 | // ───────────────────────
116 | // https://github.com/joelday/vscode-docthis/blob/master/test/largeFile.ts
117 |
118 | /**
119 | * This description was written from the
120 | *
121 | * @class SomeClass
122 | */
123 | class SomeClass {
124 | /**
125 | * Testing a property.
126 | *
127 | * @memberOf SomeClass
128 | */someProperty = true;
129 |
130 | /**
131 | * This description was written from the Ctrl+Alt+D D shortcut.
132 | *
133 | * @param {string} someParam1
134 | * @param {number} someParam2
135 | * @returns {boolean}
136 | *
137 | * @memberOf SomeClass
138 | */
139 | someFunction1(someParam1, someParam2) {
140 | return true;
141 | }
142 |
143 | /**
144 | * This is a test of the enableJumpToDescriptionLocation setting set to true.
145 | *
146 | * @param {string} someParam1
147 | * @param {number} someParam2
148 | * @returns {boolean}
149 | *
150 | * @memberOf SomeClass
151 | */
152 | someFunction2(someParam1, someParam2) {
153 | return true;
154 | }
155 |
156 | /**
157 | * This one was a successful test with the setting off
158 | *
159 | * @param {string} someParam1
160 | * @param {number} someParam2
161 | * @returns {boolean}
162 | *
163 | * @memberOf SomeClass
164 | */
165 | someFunction3(someParam1, someParam2) {
166 | return true;
167 | }
168 |
169 | /**
170 | * Test with private.
171 | *
172 | * @private
173 | * @param {string} someParam1
174 | * @param {number} someParam2
175 | * @returns {boolean}
176 | *
177 | * @memberOf SomeClass
178 | */
179 | someFunction4(someParam1, someParam2) {
180 | return true;
181 | }
182 |
183 | /**
184 | * Test with public.
185 | *
186 | * @param {string} someParam1
187 | * @param {number} someParam2
188 | * @returns {boolean}
189 | *
190 | * @memberOf SomeClass
191 | */
192 | someFunction5(someParam1, someParam2) {
193 | // Suppress unused function error
194 | this.someFunction4('string', 2);
195 | return true;
196 | }
197 |
198 | /**
199 | * Test with static.
200 | *
201 | * @static
202 | * @param {string} someParam1
203 | * @param {number} someParam2
204 | * @returns {boolean}
205 | *
206 | * @memberOf SomeClass
207 | */
208 | static someFunction6(someParam1, someParam2) {
209 | return true;
210 | }
211 |
212 | /**
213 | * Testing with docthis.includeMemberOfOnClassMembers set to false
214 | *
215 | * @param {string} someParam1
216 | * @param {number} someParam2
217 | * @returns {boolean}
218 | */
219 | someFunction7(someParam1, someParam2) {
220 | return true;
221 | }
222 | }
223 |
224 |
225 | // ───────────────────────
226 | // https://github.com/discordjs/docgen/blob/master/test/src/SomeClass.js
227 |
228 | const EventEmitter = require('events').EventEmitter;
229 |
230 | /**
231 | * A very classy class with lots of class
232 | * @extends EventEmitter
233 | */
234 | class ClassyClass extends EventEmitter {
235 | /**
236 | * Constructs a thing.
237 | */
238 | constructor() {
239 | super();
240 |
241 | /**
242 | * Just some thing
243 | * @type {?number}
244 | */
245 | this.thing = 42;
246 | }
247 |
248 | /**
249 | * Does stuff.
250 | * @param {?string} stuff Stuff to do
251 | * @param {StuffDoer} doer Callback to do the stuff
252 | * @returns {?number} A thing
253 | */
254 | doStuff(stuff, doer) {
255 | console.log(`Doing some pretty crazy stuff with ${stuff}`);
256 | doer(stuff);
257 | return this.thing;
258 | }
259 |
260 | /**
261 | * Who knows what this does.
262 | * @emits ClassyClass#thingDone
263 | */
264 | hmm() {
265 | console.log('Hmmmm..');
266 |
267 | /**
268 | * Emitted when a thing is done
269 | * @event ClassyClass#thingDone
270 | * @param {SomeThing} thingy Thing
271 | */
272 | this.emit('thingDone', 4242424242);
273 | }
274 | }
275 |
276 | /**
277 | * Just some thing
278 | * @typedef {Object} SomeThing
279 | * @property {number} someNumber A really cool number
280 | */
281 |
282 | /**
283 | * Does some stuff with some other stuff.
284 | * @callback StuffDoer
285 | * @param {?string} stuff Stuff to use to do stuff
286 | */
287 |
288 | /**
289 | * @external ClientOptions
290 | * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/typedef/ClientOptions}
291 | */
--------------------------------------------------------------------------------
/src/utils/1_functions.js:
--------------------------------------------------------------------------------
1 | /**
2 | * JSDoc style named function type
3 | * @callback AddStuff
4 | * @param {number} x
5 | * @param {number} y
6 | * @returns {number}
7 | */
8 |
9 | /** @type {AddStuff} */
10 | const addStuff = (x, y) => x + y;
11 |
12 | /**
13 | * TypeScript style inline function type
14 | * @typedef {(x: number, y: number) => number} TsAdd
15 | */
16 |
17 | /** @type {TsAdd} */
18 | const tsAdd = (x, y) => x + y;
19 |
20 | /**
21 | * JSDoc style type function with function declaration
22 | * @param {number} x
23 | * @param {number} y
24 | * @returns {number}
25 | */
26 | function addDec(x, y) {
27 | return x + y;
28 | }
29 |
30 |
31 |
32 | /**
33 | * JSDoc style optional parameter
34 | * @param {number} [x] optional
35 | * @param {number=} y number or undefined
36 | * @param {number} [z=1] optional with default (default not show in type hint)
37 | */
38 | function jsDocOptional(x, y, z = 1) {}
39 |
40 |
41 | /**
42 | * JSDoc style rest parameter
43 | * @param {...number} num
44 | * @returns {number}
45 | */
46 | function sum(...num) {
47 | return num.reduce((s, v) => s + v, 0);
48 | }
49 |
50 | /**
51 | * TypeScript style rest parameter
52 | * @param {number[]} num
53 | */
54 | function tsSum(...num) {
55 | return num.reduce((s, v) => s + v, 0);
56 | }
57 |
58 | /**
59 | * No explicit return value
60 | * @returns {void}
61 | */
62 | function noReturn() {
63 | console.log('no explicit return');
64 | }
65 |
66 | /**
67 | * Function never return
68 | * @returns {never}
69 | */
70 | function neverReturn() {
71 | throw Error('ERRORRRRR');
72 | }
73 |
74 | /**
75 | * @param {string} prefix
76 | * @returns {(baseStr: string) => string}
77 | */
78 | const prependPrefix = (prefix) => (baseStr)=> `${prefix}${baseStr}`;
79 |
80 | /**
81 | * Function no returrn value https://fettblog.eu/typescript-jsdoc-superpowers/
82 | * @param {string} url
83 | * @param {(status: number, response?: string) => void} cb
84 | */
85 | function loadData(url, cb) {
86 | const xhr = new XMLHttpRequest();
87 | xhr.open('GET', url)
88 | xhr.onload = () => {
89 | cb(xhr.status, xhr.responseText)
90 | }
91 | }
92 |
93 |
94 | /**
95 | * Default numeric param
96 | * @param {number} [x=1] d4 damage
97 | */
98 | export function m(x) {
99 | return x
100 | }
101 |
102 | /**
103 | * Default string param
104 | * @param {string} [somebody="John Doe"] - Somebody's name.
105 | */
106 | export function sayHello(somebody) {
107 | if (!somebody) {
108 | somebody = 'John Doe';
109 | }
110 | alert('Hello ' + somebody);
111 | }
112 |
113 | /**
114 | * Just params
115 | * @param somebody
116 | */
117 | export function sayBye(somebody) {
118 | alert('Bye ' + somebody);
119 | }
120 |
121 |
122 | /**
123 | * @typedef {Object} Toast
124 | * @property {string} id
125 | * @property {boolean} closed - Indicates whether user has close the toast.
126 | * @property {Date} generatedOn - Indicates when the toast was generated.
127 | * @property {string} message - toast content.
128 | * @property {"warn" | "info"} type - Indicates type of toast.
129 | * Also useful to show different icons.
130 | */
131 |
132 | /**
133 | * A function for showing toast
134 | * @param {Toast} toast - {@link toast} object
135 | * containing all components of the toast.
136 | */
137 | export function showToast(toast) {}
138 |
139 | // ───────────────────────
140 | // https://twitter.com/jbscript/status/1415553540823535627/photo/1
141 |
142 | /**
143 | * @param {string} selector
144 | * @param {{
145 | * name?: string
146 | * stopIf?: () => boolean
147 | * context?: Document | HTMLElement
148 | * timeout?: number
149 | * }} options
150 | * @returns {Promise}
151 | */
152 | function getElement(selector, {
153 | name = '',
154 | stopIf = () => true,
155 | context = document,
156 | timeout = Infinity,
157 | } = {}) {
158 | return new Promise((resolve) => {
159 |
160 | })
161 | }
162 |
163 |
164 | // ───────────────────────
165 | // https://github.com/aminya/jsdoc2flow/blob/master/test/fixtures/annotated/test2.js#L5
166 |
167 | /**
168 | * Function 1
169 | *
170 | * @param {object} obj
171 | * @param {string} obj.a
172 | * @param {string} obj.b
173 | * @param {object} obj.c
174 | * @param {object=} obj.d
175 | * @param {object=} obj.e
176 | * @returns {number}
177 | */
178 | const fn1 = ({ a, b, c, d, e }) => {
179 | return 1
180 | }
181 |
182 |
183 | // ───────────────────────
184 | // https://github.com/andreidmt/tpl-ts-jsdoc/blob/master/src/hello-world.js#L6
185 |
186 | /**
187 | * @typedef {Object} SayHelloFnReturn
188 | *
189 | * @property {string} beep
190 | * @property {string} boop
191 | */
192 |
193 | /**
194 | * Function with types infered from docs, 2 birds in hand.
195 | *
196 | * @param {Object} [props={}]
197 | * @param {"lorem"|"dolor"} [props.foo="lorem"]
198 | * @param {string} [props.bar="ipsum"]
199 | *
200 | * @returns {SayHelloFnReturn}
201 | */
202 | const sayOy = ({ foo = "lorem", bar = "ipsum" } = {}) => ({
203 | beep: `oy ${foo}`,
204 | boop: `oy ${bar}`,
205 | })
206 |
207 | const robotSays = sayOy({ foo: "dolor" })
208 |
209 |
210 | // ───────────────────────
211 | // https://github.com/homer0/parserror/blob/c12b20e3a321e1e01f41178eceb1d3210991d40f/src/parserror.js#L240
212 |
213 |
214 | /**
215 | * An object with a signature similar to an {@link Error} that {@link Parserror} can
216 | * parse.
217 | *
218 | * @typedef {Object} ParserrorErrorObject
219 | * @property {string} message The error message.
220 | */
221 |
222 | /**
223 | * The options that can be used to customize how {@link Parserror#parse} works.
224 | *
225 | * @typedef {Object} ParserrorParseOptions
226 | * @property {string[]} cases A list of specific cases it should validated against.
227 | * @property {string[]} scopes A list of specific scopes it should use to valdiate the
228 | * error.
229 | * @property {?string} fallback A fallback message in case the error can't be parsed.
230 | * If not specified, the returned error will maintain the
231 | * original message.
232 | */
233 |
234 | /**
235 | * A custom version of `Error` so the Parserror can store the parsing parameters and some
236 | * context information.
237 | *
238 | * @augments Error
239 | */
240 | class FormattedError extends Error {
241 | /**
242 | * @param {string} message
243 | * The error message.
244 | * @param {Object. | string[]} [params={}]
245 | * The parsed parameters Parserror. When parsing a case that uses named groups, the
246 | * parameters are stored on an `object`; otherwise, they'll be an `array`.
247 | * @param {?Object} [context=null]
248 | * Any extra context information for the error.
249 | */
250 | constructor(message, params = {}, context = null) {
251 | super(message);
252 | /**
253 | * The parsed parameters Parserror found. When parsing a case that uses named groups,
254 | * the parameters are stored on an `object`; otherwise, they'll be an `array`.
255 | *
256 | * @type {Object. | string[]}
257 | * @todo Remove `Object.freeze`.
258 | */
259 | this.params = params;
260 | /**
261 | * Any extra context information for the error.
262 | *
263 | * @type {Object}
264 | * @todo Remove `Object.freeze`.
265 | */
266 | this.context = Object.freeze(context || {});
267 |
268 | if (Error.captureStackTrace) {
269 | Error.captureStackTrace(this, this.constructor);
270 | }
271 | }
272 | }
273 |
274 | /**
275 | * Parses and formats an error.
276 | *
277 | * @param {Error | string | ParserrorErrorObject} error
278 | * The error to parse.
279 | * @param {Partial} [options={}]
280 | * Options to customize how the parsing is done.
281 | * @returns {FormattedError}
282 | * @throws {TypeError}
283 | * If `error` is not an {@link Error}, a string or a {@link ParserrorErrorObject}.
284 | */
285 | function parse(error, options = {}) {
286 | const useOptions = {
287 | cases: [],
288 | scopes: [],
289 | fallback: null,
290 | ...options,
291 | };
292 | return new FormattedError('foobar', {}, { original: true });
293 | }
294 |
295 | parse('lol', {
296 | cases: ['cool'],
297 | })
298 |
--------------------------------------------------------------------------------
/src/utils/1_htmlNodes.js:
--------------------------------------------------------------------------------
1 | // https://zenn.dev/asama/articles/0c66573e488b22
2 |
3 | /** @type {HTMLElement|null} */
4 | const myElement = document.querySelector('.my-div');
5 | if (myElement) {
6 | myElement.dataset.myData = "";
7 | }
8 |
9 | /** @type {Window} */
10 | var win;
--------------------------------------------------------------------------------
/src/utils/1_map.js:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/hrdtbs/f7e567c0738725a16a9de7326dc11127
2 |
3 | /** @type Map. */
4 | const elephant = new Map()
5 |
6 | /** @type Map */
7 | const elephantMap = new Map()
8 |
9 | /**
10 | * The child values of this Type
11 | * @since 0.5.0
12 | * @type {Map}
13 | * @private
14 | */
15 | const birdBox = new Map();
--------------------------------------------------------------------------------
/src/utils/1_object.js:
--------------------------------------------------------------------------------
1 | // Object with optional property
2 |
3 | /**
4 | * User type definition
5 | * @typedef {Object} User
6 | * @property {string} email
7 | * @property {string} [nickName]
8 | */
9 | export const user = {
10 | email: 's',
11 | }
12 |
13 | // Object with nested values
14 |
15 | /**
16 | * @typedef Config
17 | * @property {object} defaults - The default values for parties.
18 | * @property {number} defaults.players - The default number of players.
19 | * @property {string} defaults.level - The default level for the party.
20 | * @property {object} defaults.treasure - The default treasure.
21 | * @property {number} defaults.treasure.gold - How much gold the party starts with.
22 | */
23 | export const config = {
24 | defaults: {
25 | players: 1,
26 | level: 'beginner',
27 | treasure: {
28 | gold: 0,
29 | },
30 | },
31 | }
32 |
33 | // Using typedefs
34 |
35 | /**
36 | * JSDoc style
37 | * @typedef {object} Rgb
38 | * @property {number} red
39 | * @property {number} green
40 | * @property {number} blue
41 | */
42 |
43 | /** @type {Rgb} */
44 | const color = { red: 255, green: 255, blue: 255 };
45 |
46 | /**
47 | * TypeScript style
48 | * @typedef {{ brand: string; color: Rgb }} Vehicle
49 | */
50 |
51 | /** @type {Vehicle} */
52 | const car = {
53 | brand: 'Some Brand',
54 | color: { red: 255, green: 255, blue: 255 },
55 | };
56 |
57 | // Object with unknown number of keys
58 |
59 | /**
60 | * Object with unknown keys
61 | * @type {{[key: string]: string}}
62 | */
63 | const obj = {};
64 | obj.a = 'foo';
65 | obj.b = 'bar';
66 |
67 |
68 | // ──────Object with Date────────
69 |
70 | /**
71 | * @typedef Thing
72 | * @property {string} id
73 | * @property {number} index
74 | * @property {Date} expires
75 | * @property {function} callback
76 | */
77 |
78 | /** @type Thing */
79 | let thing = {
80 | id: 'id',
81 | index: 1,
82 | expires: new Date(),
83 | callback: function () {}
84 | }
85 |
86 | // ────────How to define a hashmap / dictionary / plain object───────────────
87 | /**
88 | * @typedef ThingTwo
89 | * @property {Record} stuff
90 | */
91 |
92 | /** @type ThingTwo */
93 | let thingTwo = {
94 | stuff: {
95 | xyz: 'abc',
96 | }
97 | }
98 |
99 | // ───────Object overload───────
100 | // https://github.com/BeyondCodeBootcamp/jsdoc-typescript-starter
101 |
102 | /**
103 | * @typedef Foo
104 | * @property {string} foo
105 | */
106 |
107 | /**
108 | * @typedef Bar
109 | * @property {string} bar
110 | */
111 |
112 | /** @type {Foo & Bar} */
113 | var foobar = { foo: "foo", bar: "bar" };
114 |
115 | /** @typedef {Foo & Bar} FooBar */
116 | /** @type {FooBar} */
117 | var zaz = { foo: "foo", bar: "bar" };
118 |
119 | // ───────────────────────
120 |
121 | // Function with TypeScript style shorthand with optional values
122 |
123 | /**
124 | * @param {string} selector
125 | * @param {{
126 | * name?: string
127 | * stopIf?: () => boolean
128 | * context?: Document | HTMLElement
129 | * timeout?: number
130 | * }} options
131 | * @returns {Promise}
132 | */
133 | function getElement(selector, {
134 | name = '',
135 | stopIf = () => true,
136 | context = document,
137 | timeout = Infinity,
138 | } = {}){
139 | return new Promise((resolve) => {
140 |
141 | })
142 | }
143 |
144 | getElement('test')
145 | /* // type errors
146 | getElement('test', { unexpected: true })
147 | getElement('test', { timeout: '123' })
148 | /** */
149 |
150 |
151 | // ────── Recursive property ────────
152 |
153 | // https://github.com/BeyondCodeBootcamp/jsdoc-typescript-starter/blob/38fb9ff20940f7127724578530e3ae823fd07d5f/types.js#L15
154 |
155 | /**
156 | * @typedef {Object} AppUser
157 | * @property {string} given_name
158 | * @property {string} family_name
159 | * @property {string} [favorite_movie]
160 | * @property {string} favorite_book
161 | * @property {Array} [friends]
162 | * @property {Record | null} [stuff]
163 | */
164 |
165 | /** @type AppUser */
166 | const appUser = {
167 | given_name: 'bob',
168 | family_name: 'smith',
169 | favorite_book: 'harry potter',
170 | stuff: {
171 | hi: 'there'
172 | },
173 | friends: [{
174 | given_name: 'bob',
175 | family_name: 'smith',
176 | favorite_book: 'harry potter',
177 | }],
178 | }
179 |
180 |
181 | // ───────────────────────
182 | // https://gist.github.com/hrdtbs/f7e567c0738725a16a9de7326dc11127
183 |
184 | /**
185 | * @typedef {Object} TestProps
186 | */
187 | /**
188 | * @type {TestProps}
189 | */
190 | const x = {
191 | foobar: 1,
192 | no: 2
193 | }
194 |
195 |
196 | // ───────────────────────
197 | // Partial object with optional keys via {Partial}
198 |
199 | /**
200 | * My object
201 | *
202 | * @typedef {Object} MyObjectWithOptionalParams
203 | * @property {string[]} cases A list of specific cases it should validated against.
204 | * @property {string[]} scopes A list of specific scopes it should use to valdiate the error.
205 | * @property {?string} fallback A fallback message in case the error can't be parsed. If not specified, the returned error will maintain the original message.
206 | */
207 |
208 | /** @type {Partial} */
209 | const objectWithOptionalKeys = {
210 | cases: ['xyz']
211 | }
212 |
213 |
214 | // ───────────────────────
215 | // https://dev.to/samuel-braun/boost-your-javascript-with-jsdoc-typing-3hb3
216 |
217 | // Type aliasing
218 | /** @typedef {number} Age */
219 | /** @typedef {string} Name */
220 | /** @typedef {{ name: Name; age: Age }} MyUser */
221 |
222 | /** @type {MyUser} */
223 | const userThing = { name: 'John Doe', age: 25 };
224 |
--------------------------------------------------------------------------------
/src/utils/1_objectz-shorthand.js:
--------------------------------------------------------------------------------
1 | /*
2 | Example of object shorthand with optional
3 | */
4 |
5 | /**
6 | * @param {string} selector
7 | * @param {{
8 | * name?: string
9 | * stopIf?: () => boolean
10 | * context?: Document | HTMLElement
11 | * timeout?: number
12 | * }} options
13 | * @returns {Promise}
14 | */
15 | function getElement(selector, {
16 | name = '',
17 | stopIf = () => true,
18 | context = document,
19 | timeout = Infinity,
20 | } = {}){
21 | return new Promise((resolve) => {
22 |
23 | })
24 | }
25 |
26 | getElement('test')
27 | /* // type errors
28 | getElement('test', { unexpected: true })
29 | getElement('test', { timeout: '123' })
30 | /** */
--------------------------------------------------------------------------------
/src/utils/1_set.js:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/hrdtbs/f7e567c0738725a16a9de7326dc11127
2 |
3 | /** @type Set. */
4 | /** @type Set */
--------------------------------------------------------------------------------
/src/utils/2_buffer.js:
--------------------------------------------------------------------------------
1 | // https://github.com/Beatso/ScalePixelArt/blob/main/index.js
2 | /**
3 | *
4 | * @param {*} str
5 | * @returns {*}
6 | */
7 | function sharp(str) {}
8 |
9 | /**
10 | * Resizes an image with nearest neighbour interpolation.
11 | * @param {Buffer | Uint8Array | Uint8ClampedArray | Int8Array | Uint16Array | Int16Array | Uint32Array | Int32Array | Float32Array | Float64Array | string} input - The image to resize.
12 | * @param {number} scale - How many times bigger the image should be. Can be negative to shrink the image.
13 | * @returns {Promise} - The resized image.
14 | */
15 | const scaleImage = async (input, scale) => {
16 |
17 | try {
18 | const image = sharp(input)
19 | const metadata = await image.metadata()
20 | const output = await image
21 | .resize ( metadata.width * scale, null, { kernel: "nearest" })
22 | .toBuffer()
23 | return output
24 | }
25 |
26 | catch (error) {
27 | throw error
28 | }
29 |
30 | }
--------------------------------------------------------------------------------
/src/utils/2_event-listener.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * Element selector
5 | * @typedef {(string|Node|NodeList|EventTarget|null)} Selector
6 | */
7 |
8 | /**
9 | * Event to listen to
10 | * @typedef {(string|string[])} EventType
11 | */
12 |
13 | /**
14 | * @typedef {Object} MyOptions
15 | * @prop {boolean} [once]
16 | */
17 |
18 | /**
19 | * Cleanup event listener
20 | * @callback RemoveListener
21 | * @returns {AttachListener}
22 | */
23 |
24 | /**
25 | * ReAttach event listener
26 | * @callback AttachListener
27 | * @returns {RemoveListener}
28 | */
29 |
30 | /**
31 | * Add an event listener
32 | * @callback AddEventListener
33 | * @param {Selector} elements - Element(s) to attach event(s) to.
34 | * @param {EventType} eventType - Event(s) to listen to
35 | * @param {Function} handler - Function to fire
36 | * @param {MyOptions} [options] - Event listener options
37 | * @returns {RemoveListener}
38 | */
39 |
40 | /** @type {AddEventListener} */
41 | function add(elements, eventType, handler, options = {}) {
42 | /** @type RemoveListener */
43 | const remove = () => {
44 | // clean up
45 | return () => {
46 | // reattach
47 | /** @type AttachListener */
48 | return add(elements, eventType, handler, options)
49 | }
50 | }
51 | return remove
52 | }
53 |
54 | const x = add('button', 'click', () => {
55 | console.log('yay')
56 | })
--------------------------------------------------------------------------------
/src/utils/2_imports-commonJS.js:
--------------------------------------------------------------------------------
1 | // via https://docs.joshuatz.com/cheatsheets/js/jsdoc/
2 |
3 | // Use `import(FILE_PATH)['EXPORTED_THING']` instead of `import(FILE_PATH).EXPORTED_THING
4 |
5 | /**
6 | * @typedef {typeof import('./imports/my-js-file')['myExportedFunc']} MyFunc
7 | */
8 |
9 | /**
10 | * Example of common js import ad type
11 | * @param {MyFunc} xyz
12 | * @returns {{total: number, adjustedTotal: number, avgWeight: number}} totals
13 | */
14 | function myFunc(xyz) {
15 | // implementation details omitted
16 | return {
17 | total: 2,
18 | adjustedTotal: 3,
19 | avgWeight: 4,
20 | // @ts-ignore-start
21 | lol: true
22 | }
23 | }
--------------------------------------------------------------------------------
/src/utils/2_imports-ts.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | /**
4 | * Renders a component with imported types
5 | * @param { import("./imports/ts-types").TinyProps } props
6 | * @return {React.ReactElement} - React component
7 | */
8 | export default function ButtonImport(props) {
9 | return (
10 |
13 | )
14 | }
--------------------------------------------------------------------------------
/src/utils/2_imports-ts2-refs.js:
--------------------------------------------------------------------------------
1 | // https://twitter.com/dr_sensor/status/1723468421722210367
2 |
3 | /*
4 | Import a d.ts file and reference exported types
5 |
6 | my.d.ts contains:
7 | export function myFun(a: string, b: string, c: string): number;
8 |
9 | myFun is referenced via @type $["myFun"]
10 | */
11 |
12 | /**
13 | * @typedef {import("./imports/my.d.ts")} $
14 | */
15 |
16 | /** @type $["myFun"] */
17 | export function fun(a, b, c) {
18 | return 1
19 | }
20 |
--------------------------------------------------------------------------------
/src/utils/2_overload.js:
--------------------------------------------------------------------------------
1 | // ───────Object overload───────
2 | // https://github.com/BeyondCodeBootcamp/jsdoc-typescript-starter
3 |
4 | /**
5 | * @typedef Foo
6 | * @property {string} foo
7 | */
8 |
9 | /**
10 | * @typedef Bar
11 | * @property {string} bar
12 | */
13 |
14 | /** @type {Foo & Bar} */
15 | var foobar = { foo: "foo", bar: "bar" };
16 |
17 | /** @typedef {Foo & Bar} FooBar */
18 | /** @type {FooBar} */
19 | var foobar = { foo: "foo", bar: "bar" };
20 |
21 |
22 | // ───────────────────────
23 | // https://austingil.com/typescript-function-overloads-with-jsdoc/
24 |
25 | // A Naive Solution
26 | /**
27 | * @param {string | number} input
28 | * @returns {string | number}
29 | */
30 | function double(input) {
31 | if (typeof input === 'number') {
32 | return input * 2
33 | }
34 | return input + input
35 | }
36 |
37 | // /**
38 | // * @type {{
39 | // * (input: number) => number;
40 | // * (input: string) => string;
41 | // * }}
42 | // */
43 | // const doubleTwo = (input) => {
44 | // if (typeof input === 'number') {
45 | // return input * 2
46 | // }
47 | // return input + input
48 | // }
49 |
50 | // ───────────────────────
51 |
52 | // via https://github.com/microsoft/TypeScript/issues/25590#issuecomment-942782630
53 | /**
54 | * This function takes a number and a string.
55 | * @callback signatureA
56 | * @param {number} num
57 | * @param {string} str
58 | */
59 |
60 | /**
61 | * This function takes a boolean and an object
62 | * @callback signatureB
63 | * @param {boolean} bool
64 | * @param {Object} obj
65 | */
66 |
67 | /**
68 | * This function takes a boolean and an object
69 | * @callback signatureC
70 | * @param {Person} person
71 | * @param {boolean} bool
72 | */
73 |
74 | /**
75 | * @param {Parameters | Parameters | Parameters} args
76 | */
77 | function overloaded(...args) {
78 |
79 | }
80 |
81 | overloaded(1, '2')
82 | overloaded(true, {})
83 | overloaded({ name: 'bob', age: 11 }, true)
84 |
85 |
86 |
87 |
88 |
89 | // https://github.com/microsoft/TypeScript/issues/25590#issuecomment-790713772
90 |
91 | /**
92 | @typedef {{
93 | (s: string): 0 | 1
94 | (b: boolean): 2 | 3
95 | [k:string]: any
96 | }} Gioconda
97 | */
98 |
99 | // /** @type {Gioconda} */
100 | // const monaLisa = (
101 | // /** @param {string|boolean} sb */
102 | // (sb) => {
103 | // return typeof sb === 'string' ? 1 : 2;
104 | // });
105 |
106 | // const obj = {
107 | // /** @type {Gioconda} */
108 | // monaLisa: (
109 | // /** @param {string|boolean} sb */
110 | // (sb) => {
111 | // return typeof sb === 'string' ? 1 : 2;
112 | // })
113 | // };
114 |
115 | // class MonaLisa {
116 | // /** @type {Gioconda} */
117 | // monaLisa = (
118 | // /** @param {string|boolean} sb */
119 | // (sb) => {
120 | // return typeof sb === 'string' ? 1 : 2;
121 | // })
122 | // }
123 |
124 | // /** @type {2 | 3} - call resolve to (b: boolean) => 2 | 3 */
125 | // var twothree = monaLisa(false);
126 | // /** @type {2 | 3} - call resolve to (b: boolean) => 2 | 3 */
127 | // var twothreeObj = obj.monaLisa(false);
128 | // /** @type {2 | 3} - call resolve to (b: boolean) => 2 | 3 */
129 | // var twothreeClass = new MonaLisa().monaLisa(false);
130 |
131 | // // js special property assignment should still be allowed
132 | // monaLisa.overdrive = true;
133 | // obj.monaLisa.overdrive = true;
134 | // MonaLisa.prototype.monaLisa.overdrive = true;
135 |
136 | /**
137 | *
138 | */
139 |
140 | // ───────────────────────
141 | // https://github.com/micromark/micromark/blob/2b1fafb5f3ad0d1c9329ffbc80be1cbd411f5468/packages/micromark/dev/index.js#L12-L30
142 |
143 | /**
144 | * @typedef {'ascii'|'utf8'|'utf-8'|'utf16le'|'ucs2'|'ucs-2'|'base64'|'latin1'|'binary'|'hex'} Encoding
145 | * Encodings supported by the buffer class.
146 | * This is a copy of the typing from Node, copied to prevent Node globals from
147 | * being needed.
148 | * Copied from:
149 | *
150 | * @typedef {string|Uint8Array} Value
151 | * Contents of the file.
152 | * Can either be text, or a `Buffer` like structure.
153 | */
154 |
155 | /**
156 | * @typedef {Record>} Extension
157 | * A syntax extension changes how markdown is tokenized.
158 | * See:
159 | */
160 |
161 | /**
162 | * @typedef ParseOptions
163 | * Parse options.
164 | * @property {Extension[]} [extensions] Array of syntax extensions
165 | */
166 |
167 | /**
168 | * @typedef CompileOptions
169 | * Compile options
170 | * @property {'\r'|'\n'|'\r\n'} [defaultLineEnding]
171 | * Value to use for line endings not in `doc` (`string`, default: first line
172 | * ending or `'\n'`).
173 | * @property {boolean} [allowDangerousHtml=false]
174 | * Whether to allow embedded HTML (`boolean`, default: `false`).
175 | * @property {boolean} [allowDangerousProtocol=false]
176 | */
177 |
178 | /**
179 | * @typedef {ParseOptions & CompileOptions} Options
180 | */
181 |
182 | /**
183 | * @param value Markdown to parse (`string` or `Buffer`).
184 | * @param [encoding] Character encoding to understand `value` as when it’s a `Buffer` (`string`, default: `'utf8'`).
185 | * @param [options] Configuration
186 | */
187 | export const micromark =
188 | /**
189 | * @type {(
190 | * ((value: Value, encoding: Encoding, options?: Options) => string) &
191 | * ((value: Value, options?: Options) => string)
192 | * )}
193 | */
194 | (
195 | /**
196 | * @param {Value} value
197 | * @param {Encoding} [encoding]
198 | * @param {Options} [options]
199 | */
200 | function (value, encoding, options) {
201 | if (typeof encoding !== 'string') {
202 | options = encoding
203 | encoding = undefined
204 | }
205 |
206 | return value
207 | }
208 | )
209 |
210 | // ───────────────────────
211 |
212 | // /**
213 | // * Does something
214 | // * @callback foo_overload1
215 | // * @param {number} arg1 Something
216 | // */
217 |
218 | // /**
219 | // * Does something else
220 | // * @callback foo_overload2
221 | // * @param {string} arg1 Something else
222 | // * @param {number} arg2 Something
223 | // */
224 |
225 | // /** @type { foo_overload1 | foo_overload2 } */
226 | // function fooBarFunc(arg1, arg2) {
227 |
228 | // }
229 |
230 |
231 | // ------------------------------------------------------------------------------
232 | // JSDoc implements function overloading
233 | // https://github.com/microsoft/TypeScript/issues/25590
234 | // ------------------------------------------------------------------------------
235 | // https://github.com/chunjin666/jsdoc-learning/blob/master/src/01-types/07-function-overload.js
236 | // ------------------------------------------------------------------------------
237 | // method one:
238 | // ------------------------------------------------------------------------------
239 | /**
240 | * @param {number} acc
241 | * @param {number} cur
242 | */
243 | const sumReducer = (acc, cur) => acc + cur
244 |
245 | /**
246 | * @type {{
247 | * (nums: number[]): number
248 | * (...nums: number[]): number
249 | * }}
250 | */
251 | const sum = (...nums) => {
252 | if (Array.isArray(nums[0])) {
253 | return nums[0].reduce(sumReducer, 0)
254 | }
255 | return /** @type {number[]} */ (nums).reduce(sumReducer, 0)
256 | };
257 |
258 | sum(1, 2, 3)
259 | sum([1, 2, 3])
--------------------------------------------------------------------------------
/src/utils/2_overload.ts:
--------------------------------------------------------------------------------
1 | // ----Function overload───────
2 | // https://twitter.com/steveruizok/status/1495328409613918210?s=11
3 |
4 | export const greet: {
5 | (name: string): string
6 | (hellos: number): string
7 | (arg: string | number): string
8 | } = (arg) => {
9 | if (typeof arg === 'string') {
10 | return `Hello ${arg}!`
11 | }
12 | return Array.from(Array(arg))
13 | .map(() => `Hello`)
14 | .join(' ')
15 | }
16 |
17 | // greet('c')
18 | // greet(1)
--------------------------------------------------------------------------------
/src/utils/2_typecasting.js:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react'
2 |
3 | // https://gist.github.com/hrdtbs/f7e567c0738725a16a9de7326dc11127
4 | const btn = document.createElement("button");
5 | /** @type {Element} */ (btn).setAttribute("disabled", "true")
6 |
7 |
8 | /**
9 | * First name & last name
10 | * @typedef {{firstName: string, lastName: string}} CoolType
11 | */
12 |
13 | const qwerty = /** @type {CoolType} */({ firstName: 'y', lastName: 'x'})
14 |
15 | // ───────────────────────
16 | // https://twitter.com/karlhorky/status/1409074665209925632
17 | // Inline useState typecast
18 |
19 | /**
20 | * User
21 | * @typedef {{name: string, lastName?: string}} ExampleUser
22 | */
23 |
24 | function C() {
25 | const [u, setU] = useState(/** @type {ExampleUser | null} */ (null))
26 | setU({ name: '' })
27 | }
28 |
29 | // https://github.com/JacobParis/cloudfool/pull/2
30 | // broken
31 | // export default function Component(props) {
32 | // /** @type [ExampleUser, React.Dispatch] */
33 | // const [user, setUser] = useState(null)
34 | // console.log('user', user)
35 | // setUser({ name: 'hi' })
36 | // }
--------------------------------------------------------------------------------
/src/utils/2_typeof-reference.js:
--------------------------------------------------------------------------------
1 |
2 | // https://fettblog.eu/typescript-jsdoc-superpowers/
3 | // Using typeof referrence to defaultCallback
4 |
5 | /**
6 | * @param {number} status The status code as a number
7 | * @param {string} data The data to work with
8 | */
9 | function defaultCallback(status, data) {
10 | if(status === 200) {
11 | document.body.innerHTML = data
12 | }
13 | }
14 |
15 | /**
16 | * @param {string} url the URL to load data from
17 | * @param {typeof defaultCallback} cb what to do afterwards
18 | */
19 | function loadData(url, cb) {
20 | const xhr = new XMLHttpRequest();
21 | xhr.open('GET', url)
22 | xhr.onload = () => {
23 | cb(xhr.status, xhr.responseText)
24 | }
25 | }
--------------------------------------------------------------------------------
/src/utils/2_union.js:
--------------------------------------------------------------------------------
1 | /** @type {(string|Array)} */
2 | export var foo;
3 |
--------------------------------------------------------------------------------
/src/utils/asserts.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * https://github.com/voxpelli/types-in-js/discussions/8
5 | * @param {any} value
6 | * @returns {value is Iterable<*>}
7 | */
8 | const isIterable = (value) => Boolean(value && value[Symbol.iterator]);
--------------------------------------------------------------------------------
/src/utils/balena.js:
--------------------------------------------------------------------------------
1 | // https://www.balena.io/blog/open-source-guide-1-documentation-and-jsdoc/
2 |
3 | // Public Function
4 |
5 | /**
6 | * @summary Sum two numbers
7 | * @function
8 | * @public
9 | *
10 | * @param {Number} x - first number
11 | * @param {Number} y - second number
12 | * @returns {Number} the sum of the two numbers
13 | *
14 | * @example
15 | * const result = math.sum(5, 3);
16 | * console.log(result);
17 | * > 8
18 | */
19 | exports.sum = (x, y) => {
20 | return x + y;
21 | };
22 |
23 | // Private Function
24 |
25 | /**
26 | * @summary Check if a variable is a string
27 | * @function
28 | * @private
29 | *
30 | * @param {*} x - variable
31 | * @returns {Boolean} whether the variable is a string
32 | *
33 | * @example
34 | * if (isString('foo')) {
35 | * console.log('The variable is a string');
36 | * }
37 | */
38 | const isString = (x) => {
39 | return typeof x === 'string' || x instanceof String;
40 | };
41 |
42 | // Constant Variable
43 |
44 | /**
45 | * @summary Default size
46 | * @type Number
47 | * @constant
48 | * @private
49 | */
50 | const DEFAULT_SIZE = 16;
51 |
52 | // Object
53 |
54 | /**
55 | * @summary Exit codes
56 | * @namespace EXIT_CODES
57 | * @private
58 | */
59 | const EXIT_CODES = {
60 |
61 | /**
62 | * @property {Number} SUCCESS
63 | * @memberof EXIT_CODES
64 | *
65 | * @description
66 | * This exit code is used to represent a successful exit status.
67 | */
68 | SUCCESS: 0,
69 |
70 | /**
71 | * @property {Number} ERROR
72 | * @memberof EXIT_CODES
73 | *
74 | * @description
75 | * This exit code is used to represent an erroneous exit status.
76 | */
77 | ERROR: 1
78 |
79 | };
80 |
81 | // Optional Parameter
82 |
83 | /**
84 | * @summary Split a string
85 | * @function
86 | * @public
87 | *
88 | * @param {String} string - input string
89 | * @param {String} [delimiter=' '] - delimiter
90 | * @returns {String[]} splitted string
91 | *
92 | * @example
93 | * const result = utils.split('foo bar baz');
94 | * console.log(result);
95 | * > [ 'foo', 'bar', 'baz' ]
96 | *
97 | * @example
98 | * const result = utils.split('hello_world', '_');
99 | * console.log(result);
100 | * > [ 'hello', 'world' ]
101 | */
102 | exports.split = (string, delimiter = ' ') => {
103 | return string.split(delimiter);
104 | };
105 |
106 | // Object Parameter
107 |
108 | /**
109 | * @summary Tail a string
110 | * @function
111 | * @private
112 | *
113 | * @param {String} string - input string
114 | * @param {Object} [options={}] - options
115 | * @param {String} [options.delimiter='\n'] - string delimiter
116 | * @param {Number} [options.lines=10] - number of lines to show
117 | * @returns {String[]} tailed string
118 | *
119 | * @example
120 | * const result = tail('foo\nbar\nbaz', {
121 | * delimiter: '\n',
122 | * lines: 2
123 | * });
124 | *
125 | * console.log(result);
126 | * > 'bar\nbaz'
127 | */
128 | const tail = (string, options = {}) => {
129 | const delimiter = options.delimiter || '\n';
130 | const lines = options.lines || 10;
131 |
132 | return string
133 | .split(delimiter)
134 | .slice(lines)
135 | };
136 |
137 | // Promise
138 |
139 | /**
140 | * @summary Get a promise that resolves a value
141 | * @function
142 | * @private
143 | *
144 | * @param {*} value - value
145 | * @fulfil {*} - value
146 | * @returns {Promise}
147 | *
148 | * @example
149 | * resolve(5).then((value) => {
150 | * console.log(value);
151 | * });
152 | * > 5
153 | */
154 | const resolve = (value) => {
155 | return Promise.resolve(value);
156 | };
157 |
158 | // Class
159 |
160 |
161 | /**
162 | * @summary Create an instance of Person
163 | * @name Person
164 | * @class
165 | * @public
166 | *
167 | * @param {String} name - person name
168 | * @returns {Person} Person instance
169 | *
170 | * @example
171 | * const person = new Person('Juan Cruz Viotti');
172 | */
173 | export class Person {
174 | constructor(name) {
175 | this.name = name;
176 | }
177 |
178 | /**
179 | * @summary Greet
180 | * @method
181 | * @public
182 | *
183 | * @example
184 | * const person = new Person('Juan Cruz Viotti');
185 | * person.greet();
186 | * // Hi, my name is Juan Cruz Viotti
187 | */
188 | greet() {
189 | console.log(`Hi, my name is ${this.name}`);
190 | }
191 |
192 | }
--------------------------------------------------------------------------------
/src/utils/calculator.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Calculator module - See {@tutorial calculator-tutorial}
3 | * @module calculator
4 | */
5 |
6 | /**
7 | * Add two numbers
8 | * @param {number} n1 - First number
9 | * @param {number} n2 - Second number
10 | * @returns {number} - Sum of n1 and n2
11 | */
12 | exports.add = (n1, n2) => n1 + n2;
13 |
14 | /**
15 | * Multiply two numbers
16 | * @param {number} n1 - First number
17 | * @param {number} n2 - Second number
18 | * @returns {number} - Product of n1 and n2
19 | */
20 | exports.multiply = (n1, n2) => n1 * n2;
21 |
22 | /**
23 | * Subtract two numbers
24 | * @param {number} n1 - First number
25 | * @param {number} n2 - Second number
26 | * @returns {number} - Difference of n1 and n2
27 | */
28 | exports.subtract = (n1, n2) => n1 - n2;
29 |
30 | /**
31 | * Divide two numbers
32 | * @param {number} n1 - First number
33 | * @param {number} n2 - Second number
34 | * @returns {number} - Quotient of n1 and n2
35 | */
36 | exports.divide = (n1, n2) => n1 / n2;
--------------------------------------------------------------------------------
/src/utils/camel-case.js:
--------------------------------------------------------------------------------
1 | import * as TypeFest from 'type-fest'
2 |
3 | /**
4 | * @template T
5 | * @typedef { { [K in keyof T as TypeFest.CamelCase]: T[K] }} CamelCasedProps
6 | */
7 |
8 | /**
9 | * @typedef DbResult
10 | * @property {string} full_name
11 | * @property {string} street_address
12 | * @property {SomethingGlobal} [something]
13 | */
14 |
15 | /** @type {CamelCasedProps} */
16 | const person = {
17 | fullName: 'Bob Bobson',
18 | streetAddress: 'Infinite loop 1',
19 | something: 'value2'
20 | };
21 |
22 |
23 | /** @type {CamelCasedPropsGlobal} */
24 | const personTwo = {
25 | fullName: 'Bob Bobson',
26 | streetAddress: 'Infinite loop 1',
27 | something: 'value'
28 | };
--------------------------------------------------------------------------------
/src/utils/class-extend.js:
--------------------------------------------------------------------------------
1 | // https://fettblog.eu/typescript-jsdoc-superpowers/
2 |
3 | /**
4 | * @template T
5 | * @extends {Set}
6 | */
7 | class SortableSet extends Set {
8 | // ...
9 | }
10 |
11 |
12 | /**
13 | * @augments {Set}
14 | */
15 | class StringSet extends Set {
16 | // ...
17 | }
--------------------------------------------------------------------------------
/src/utils/class-private-func.js:
--------------------------------------------------------------------------------
1 | // https://github.com/microsoft/TypeScript/issues/13206#issuecomment-869194939
2 |
3 | /** The parent object.
4 | * @constructor
5 | * @param {*} arg - A parameter that has to be passed in on construction. */
6 | function Parent(arg) {
7 | /** Public function. In the documentation, this description will carry
8 | * over to the child object. In the IDE, only typechecking will.
9 | * @param {string} name - User's name.
10 | * @returns {string} string **/
11 | this.hello = function(name) {
12 | return "Hello " + name;
13 | }
14 | }
15 |
16 | /** The child object. 'augments' is what jsdocs uses to detect inheritance.
17 | * 'augments' creates an IDE error, which the ts-ignore flag suppresses.
18 | * @constructor
19 | * @param {*} arg - A parameter that has to be passed in on construction.
20 | * @augments Parent
21 | * @ts-ignore */
22 | function Child(arg) {
23 | Parent.call(this, arg);
24 |
25 | // Dummy section to initialize properties from superclass
26 |
27 | // eslint-disable-next-line
28 | if (true) {
29 | // @ts-ignore
30 | var dummy = new Parent(null);
31 | this.hello = dummy.hello;
32 | }
33 |
34 | // New code goes below . . .
35 |
36 | this.hello("abc"); // This will trigger: TS2722: Cannot invoke an object which is possibly 'undefined'
37 |
38 | this.anotherFunction = function() {
39 | this.hello("def"); // This triggers no warning and has correct type/Intellisense comment
40 | }
41 | }
--------------------------------------------------------------------------------
/src/utils/class-private-proto.js:
--------------------------------------------------------------------------------
1 | // https://github.com/englercj/tsd-jsdoc/issues/105#issue-524233914
2 |
3 | /**
4 | * @constructor
5 | * @name Animal
6 | * @classdesc An animal.
7 | * @description Creates a new animal.
8 | */
9 | function Animal() {
10 | this.x = 0;
11 | this.y = 0;
12 | }
13 |
14 | /**
15 | * @function
16 | * @name Animal#move
17 | * @description Move the animal to the specified location.
18 | * @param {Number} x - X-coordinate.
19 | * @param {Number} y - Y-coordinate.
20 | */
21 | Animal.prototype.move = function (x, y) {
22 | this.x = x;
23 | this.y = y;
24 | }
25 |
26 | // /**
27 | // * @private
28 | // * @constructor
29 | // * @name Dog
30 | // * @extends Animal
31 | // * @classdesc A dog.
32 | // * @description Creates a new dog.
33 | // */
34 | // function Dog() {}
35 |
36 | // Dog.prototype = Object.create(Animal.prototype);
37 | // Dog.prototype.constructor = Dog;
38 |
39 | // /**
40 | // * @private
41 | // * @function
42 | // * @name Dog#bark
43 | // * @description The dog barks.
44 | // */
45 | // Dog.prototype.bark = function () {
46 | // console.log('Woof!');
47 | // }
--------------------------------------------------------------------------------
/src/utils/constants.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck til 4.5.0
2 | // https://github.com/microsoft/TypeScript/issues/30445#issuecomment-571422490
3 |
4 | /**
5 | * @constant
6 | * @type {string}
7 | * @default
8 | */
9 | const RED = 'FF0000';
10 |
11 | /** @constant {number} */
12 | var ONE = 1;
13 |
14 | // ONE = 'x' // fails
15 |
16 | const isConst = /** @type {const} */ ({
17 | hello: "world, not string"
18 | })
19 |
20 | var asConst1 = /** @type {const} */(1);
21 | var asConst2 = /** @type {const} */({
22 | x: 1
23 | });
24 |
25 | // ───────────────────────
26 | // https://devblogs.microsoft.com/typescript/announcing-typescript-4-5/#jsdoc-const-and-type-arg-defaults
27 |
28 | // type is { prop: string }
29 | let a = { prop: "hello" };
30 |
31 | // type is { readonly prop: "hello" }
32 | let b = /** @type {const} */ ({ prop: "hello" });
33 |
--------------------------------------------------------------------------------
/src/utils/contentful-types.ts:
--------------------------------------------------------------------------------
1 | export interface AxiosProxyConfig {
2 | host: string;
3 | port?: number;
4 | auth?: {
5 | username: string;
6 | password: string;
7 | };
8 | }
9 |
10 | export type ClientLogLevel = 'error' | 'warning' | 'info';
11 |
12 | export interface CreateClientParams {
13 | space: string;
14 | accessToken: string;
15 | environment?: string;
16 | insecure?: boolean;
17 | host?: string;
18 | basePath?: string;
19 | httpAgent?: any;
20 | httpsAgent?: any;
21 | proxy?: AxiosProxyConfig;
22 | headers?: any;
23 | adapter?: any;
24 | application?: string;
25 | integration?: string;
26 | resolveLinks?: boolean;
27 | removeUnresolved?: boolean;
28 | retryOnError?: boolean;
29 | logHandler?: (level: ClientLogLevel, data?: any) => void;
30 | timeout?: number;
31 | retryLimit?: number;
32 | }
33 |
34 | export interface ContentfulClientApi {
35 | getAsset(id: string, query?: any): Promise;
36 | getAssets(query?: any): Promise;
37 | getContentType(id: string): Promise;
38 | getContentTypes(query?: any): Promise;
39 | getEntries(query?: any): Promise>;
40 | getEntry(id: string, query?: any): Promise>;
41 | getSpace(): Promise;
42 | getLocales(): Promise;
43 | getTag(id: string): Promise;
44 | getTags(query?: any): Promise;
45 | parseEntries(raw: any): Promise>;
46 | sync(query: any): Promise;
47 | }
48 |
49 | export interface Asset {
50 | sys: Sys;
51 | fields: {
52 | title: string;
53 | description: string;
54 | file: {
55 | url: string;
56 | details: {
57 | size: number;
58 | image?: {
59 | width: number;
60 | height: number;
61 | };
62 | };
63 | fileName: string;
64 | contentType: string;
65 | };
66 | };
67 | metadata: Metadata;
68 | toPlainObject(): object;
69 | }
70 |
71 | export interface ContentfulCollection {
72 | total: number;
73 | skip: number;
74 | limit: number;
75 | items: Array;
76 | toPlainObject(): object;
77 | }
78 |
79 | export type AssetCollection = ContentfulCollection
80 |
81 | export interface Entry {
82 | sys: Sys;
83 | fields: T;
84 | metadata: Metadata;
85 | toPlainObject(): object;
86 | update(): Promise>;
87 | }
88 |
89 | export interface EntryCollection extends ContentfulCollection> {
90 | errors?: Array;
91 | includes?: any;
92 | stringifySafe(replacer?: any, space?: any): string;
93 | }
94 |
95 | export interface ContentType {
96 | sys: Sys;
97 | name: string;
98 | description: string;
99 | displayField: string;
100 | fields: Array;
101 | toPlainObject(): object;
102 | }
103 |
104 | export type ContentTypeCollection = ContentfulCollection;
105 |
106 | export interface Space {
107 | sys: Sys;
108 | name: string;
109 | locales: Array;
110 | toPlainObject(): object;
111 | }
112 |
113 | export interface Locale {
114 | code: string
115 | name: string
116 | default: boolean
117 | fallbackCode: string | null
118 | sys: {
119 | id: string
120 | type: 'Locale'
121 | version: number
122 | }
123 | }
124 |
125 | export type LocaleCollection = ContentfulCollection;
126 |
127 | export interface Tag {
128 | name: string
129 | sys: {
130 | id: string
131 | type: 'Tag'
132 | version: number
133 | visibility: 'public'
134 | }
135 | }
136 |
137 | export type TagCollection = ContentfulCollection;
138 |
139 | export interface SyncCollection {
140 | entries: Array>;
141 | assets: Array;
142 | deletedEntries: Array>;
143 | deletedAssets: Array;
144 | nextSyncToken: string;
145 | toPlainObject(): object;
146 | stringifySafe(replacer?: any, space?: any): string;
147 | }
148 |
149 | export interface Sys {
150 | type: string;
151 | id: string;
152 | createdAt: string;
153 | updatedAt: string;
154 | locale: string;
155 | revision?: number;
156 | space?: {
157 | sys: SpaceLink;
158 | };
159 | contentType: {
160 | sys: ContentTypeLink;
161 | };
162 | }
163 |
164 | export interface SpaceLink {
165 | type: 'Link';
166 | linkType: 'Space';
167 | id: string;
168 | }
169 |
170 | export interface ContentTypeLink {
171 | type: 'Link';
172 | linkType: 'ContentType';
173 | id: string;
174 | }
175 |
176 | export interface Field {
177 | disabled: boolean;
178 | id: string;
179 | linkType?: string;
180 | localized: boolean;
181 | name: string;
182 | omitted: boolean;
183 | required: boolean;
184 | type: FieldType;
185 | validations: FieldValidation[];
186 | items?: FieldItem;
187 | }
188 |
189 | export type FieldType = 'Symbol' | 'Text' | 'Integer' | 'Number' | 'Date' | 'Boolean' | 'Location' | 'Link' | 'Array' | 'Object' | 'RichText';
190 |
191 | export interface FieldValidation {
192 | unique?: boolean;
193 | size?: {
194 | min?: number;
195 | max?: number;
196 | };
197 | regexp?: {
198 | pattern: string;
199 | };
200 | linkMimetypeGroup?: string[];
201 | in?: string[];
202 | linkContentType?: string[];
203 | message?: string;
204 | nodes?: {
205 | 'entry-hyperlink'?: FieldValidation[];
206 | 'embedded-entry-block'?: FieldValidation[];
207 | 'embedded-entry-inline'?: FieldValidation[];
208 | };
209 | enabledNodeTypes?: string[];
210 | }
211 |
212 | export interface FieldItem {
213 | type: 'Link' | 'Symbol';
214 | validations: FieldValidation[];
215 | linkType?: 'Entry' | 'Asset';
216 | }
217 |
218 | // @ts-ignore
219 | export function createClient(params: CreateClientParams): ContentfulClientApi;
220 |
221 | /**
222 | * Types of fields found in an Entry
223 | */
224 | export namespace EntryFields {
225 | export type Symbol = string;
226 | export type Text = string;
227 | export type Integer = number;
228 | export type Number = number;
229 | export type Date = string;
230 | export type Boolean = boolean;
231 | export interface Location {
232 | lat: string;
233 | lon: string;
234 | }
235 | export type Link = Asset | Entry;
236 | export type Array = Symbol[] | Entry[] | Asset[];
237 | export type Object = T;
238 | export interface RichText {
239 | data:{};
240 | content: RichTextContent[];
241 | nodeType: 'document';
242 | }
243 | }
244 |
245 | interface RichTextDataTarget {
246 | sys: {
247 | id: string;
248 | type: "Link";
249 | "linkType": 'Entry' | 'Asset';
250 | };
251 | }
252 |
253 | interface RichTextData {
254 | uri?: string;
255 | target?: RichTextDataTarget;
256 | }
257 |
258 | type RichTextNodeType = 'text' | 'heading-1' | 'heading-2' | 'heading-3' | 'heading-4' | 'heading-5'
259 | | 'heading-6' | 'paragraph' | 'hyperlink' | 'entry-hyperlink' | 'asset-hyperlink'
260 | | 'unordered-list' | 'ordered-list' | 'list-item' | 'blockquote' | 'hr' | 'embedded-entry-block'
261 | | 'embedded-entry-inline';
262 |
263 | interface RichTextContent {
264 | data: RichTextData;
265 | content?: RichTextContent[]
266 | marks: {type: ('bold' | 'underline' | 'code' | 'italic')}[];
267 | value?: string;
268 | nodeType: RichTextNodeType;
269 | }
270 |
271 | interface TagLink {
272 | sys: {
273 | type: 'Link';
274 | linkType: 'Tag';
275 | id: string;
276 | }
277 | }
278 |
279 | interface Metadata {
280 | tags: TagLink[];
281 | }
--------------------------------------------------------------------------------
/src/utils/contentful.js:
--------------------------------------------------------------------------------
1 | // https://github.com/contentful/contentful.js/blob/2276d9381387be0fb68943d6231b528385244c7c/lib/contentful.js
2 |
3 | /**
4 | * Contentful Delivery API SDK. Allows you to create instances of a client
5 | * with access to the Contentful Content Delivery API.
6 | * @namespace contentful
7 | * @see ContentfulClientAPI
8 | */
9 |
10 | /**
11 | * Create a client instance
12 | * @func
13 | * @name createClient
14 | * @memberof contentful
15 | * @param {Object} params - Client initialization parameters
16 | * @prop {string} params.space - Space ID
17 | * @prop {string} params.accessToken - Contentful CDA Access Token
18 | * @prop {string} [params.environment="master"] - Contentful Environment ID
19 | * @prop {boolean=} params.insecure - Requests will be made over http instead of the default https (default: true)
20 | * @prop {string=} params.host - API host (default: cdn.contentful.com). Also usable with preview.contentful.com.
21 | * @prop {string=} params.basePath - Path appended to the host to support gateways/proxies with custom urls.
22 | * @prop {Object=} params.httpAgent - Optional Node.js HTTP agent for proxying (see Node.js docs and https-proxy-agent)
23 | * @prop {Object=} params.httpsAgent - Optional Node.js HTTP agent for proxying (see Node.js docs and https-proxy-agent)
24 | * @prop {Object=} params.proxy - Optional Axios proxy (see axios docs )
25 | * @prop {Object=} params.headers - Optional additional headers
26 | * @prop {function=} params.adapter - Optional axios request adapter (see axios docs )
27 | * @prop {boolean=?} params.resolveLinks - If we should resolve links between entries (default: true)
28 | * @prop {boolean=?} params.removeUnresolved - If we should remove links to entries which could not be resolved (default: false)
29 | * @prop {boolean=?} params.retryOnError - If we should retry on errors and 429 rate limit exceptions (default: true)
30 | * @prop {function=} params.logHandler - A log handler function to process given log messages & errors. Receives the log level (error, warning & info) and the actual log data (Error object or string). (The default can be found at: https://github.com/contentful/contentful-sdk-core/blob/master/src/create-http-client.ts)
31 | * @prop {string=?} params.application - Application name and version e.g myApp/version
32 | * @prop {string=?} params.integration - Integration name and version e.g react/version
33 | * @prop {number=} params.timeout in milliseconds - connection timeout (default:30000)
34 | * @prop {number=} params.retryLimit - Optional number of retries before failure. Default is 5
35 | * @returns { import("./contentful-types").ContentfulClientApi }
36 | * @example
37 | * const contentful = require('contentful')
38 | * const client = contentful.createClient({
39 | * accessToken: 'myAccessToken',
40 | * space: 'mySpaceId'
41 | * })
42 | */
43 |
44 | export function createClient (params) {
45 | return {
46 | // @ts-ignore
47 | getAsset: (id, query) => {},
48 | // @ts-ignore
49 | getAssets: (query) => {},
50 | // @ts-ignore
51 | getContentType: (id) => {},
52 | // @ts-ignore
53 | getContentTypes: (query) => {},
54 | // @ts-ignore
55 | getEntries: (query) => {},
56 | // @ts-ignore
57 | getEntry: (id, query) => {},
58 | // @ts-ignore
59 | getSpace: () => {},
60 | // @ts-ignore
61 | getLocales: () => {},
62 | // @ts-ignore
63 | getTag: (id) => {},
64 | // @ts-ignore
65 | getTags: (query) => {},
66 | // @ts-ignore
67 | parseEntries: (raw) => {},
68 | // @ts-ignore
69 | sync: (query) => {}
70 | }
71 | }
--------------------------------------------------------------------------------
/src/utils/example-three.js:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | const { add, subtract, divide, multiply } = require('./calculator');
3 |
4 | /**
5 | * @file index.js is the root file for this example app
6 | * @author Brad Traversy
7 | * @link Traversy Media
8 | */
9 |
10 | /**
11 | * Student Name
12 | * @type {string}
13 | */
14 | const studentName = 'John Doe';
15 |
16 | /**
17 | * Array of grades
18 | * @type {Array}
19 | */
20 | const grades = [98, 97.7, 76, 89];
21 |
22 | /**
23 | * Todo object
24 | * @type {{id: number|string, text: string}}
25 | */
26 | const todo = {
27 | id: '1',
28 | text: 'Hello'
29 | };
30 |
31 | /**
32 | * Calculate tax
33 | * @param {number} amount - Total amount
34 | * @param {number} tax - Tax percentage
35 | * @returns {string} - Total with a dollar sign
36 | */
37 | const calculateTax = (amount, tax) => {
38 | return `$${amount + tax * amount}`;
39 | };
40 |
41 | /**
42 | * A student
43 | * @typedef {Object} Student
44 | * @property {number} id - Student ID
45 | * @property {string} name - Student name
46 | * @property {string|number} [age] - Student age (optional)
47 | * @property {boolean} isActive - Student is active
48 | */
49 |
50 | /**
51 | * @type {Student}
52 | */
53 | const student = {
54 | id: 1,
55 | name: 'John Doe',
56 | age: 20,
57 | isActive: true
58 | };
59 |
60 | /**
61 | * Class to create a person object
62 | */
63 | class Person {
64 | /**
65 | *
66 | * @param {Object} personInfo Information about the person
67 | */
68 | constructor(personInfo) {
69 | /**
70 | * @property {string} name Persons name
71 | */
72 | this.name = personInfo.name;
73 | /**
74 | * @property {string} age Persons age
75 | */
76 | this.age = personInfo.age;
77 | }
78 |
79 | /**
80 | * @property {Function} greet A greeting with the name and age
81 | * @returns void
82 | */
83 | greet() {
84 | console.log(`Hello, my name is ${this.name} and I am ${this.age}`);
85 | }
86 | }
87 |
88 | /**
89 | * See {@link Person}
90 | */
91 | const person1 = new Person({
92 | name: 'John Doe',
93 | age: 30
94 | });
95 |
96 | console.log(add(20, 30));
--------------------------------------------------------------------------------
/src/utils/examples-two.js:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | function xyz(pred, actual, expected, msg, msgtwo) {
6 |
7 | }
8 |
9 | /**
10 | * @param {unknown} actual
11 | * @param {unknown} expected
12 | * @param {string} [msg]
13 | * @returns {void}
14 | */
15 | function notEqual(actual, expected, msg) {
16 | xyz(actual !== expected, actual, expected, msg || 'should not be equal', 'notEqual')
17 | }
18 |
19 | notEqual(false, 'whatever', 'woowowow')
20 |
21 | /**
22 | * Does xyz
23 | * @returns {Promise<{
24 | * pass: number,
25 | * fail: number
26 | * }>}
27 | */
28 | async function run() {
29 | return Promise.resolve({
30 | pass: 1,
31 | fail: 3
32 | })
33 | }
34 |
35 | /**
36 | * @param {Error} e
37 | * @returns {string}
38 | */
39 | function findAtLineFromError (e) {
40 | return 'lol'
41 | }
42 |
43 | /**
44 | * @param {Error | null} err
45 | * @param {string} [msg]
46 | * @returns {void}
47 | */
48 | function ifError(err, msg) {
49 | xyz(!err, err, 'no error', msg || String(err), 'ifError')
50 | }
51 |
52 |
53 | /**
54 | * Description about the function
55 | * @param {string[]} a - description about a
56 | * @return {Promise} n - Promise fulfilled by array of strings
57 | */
58 | function example(a) {
59 | return Promise.resolve(a.map((x) => `_${x}`))
60 | }
61 | example(['one', 'two', 'three']).then((newArray) => {
62 | console.log(newArray)
63 | })
--------------------------------------------------------------------------------
/src/utils/examples/auth.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef Auth
3 | * @property {string} username
4 | * @property {string} password
5 | */
6 | /**
7 | * @typedef Token
8 | * @property {String} access_token
9 | */
10 | /**
11 | * @param {Auth} auth
12 | *
13 | * @returns {Promise}
14 | */
15 | async function login(auth) {
16 | return authenticateWithThirdPartyService(auth)
17 | }
18 |
19 | async function authenticateWithThirdPartyService(auth) {
20 | return {
21 | access_token: 'hi'
22 | }
23 | }
--------------------------------------------------------------------------------
/src/utils/examples/f-ck.js:
--------------------------------------------------------------------------------
1 | // https://github.com/wooorm/f-ck/blob/main/index.js
2 | // https://github.com/wooorm/f-ck/blob/main/package.json
3 | /*
4 | "scripts": {
5 | "prepublishOnly": "npm run build && npm run format",
6 | "build": "rimraf \"*.d.ts\" && tsc && type-coverage",
7 | "format": "remark . -qfo && prettier . -w --loglevel warn && xo --fix",
8 | "test-api": "node --conditions development test.js",
9 | "test-coverage": "c8 --check-coverage --branches 100 --functions 100 --lines 100 --statements 100 --reporter lcov npm run test-api",
10 | "test": "npm run build && npm run format && npm run test-coverage"
11 | },
12 | */
13 | /**
14 | * `butt` > `b*tt`
15 | *
16 | * @param {string} value
17 | * @param {string} [character='*']
18 | * @returns {string}
19 | */
20 | export function vowel(value, character) {
21 | return value.replace(/[aeiouy]/g, character || '*')
22 | }
23 |
24 | /**
25 | * `butt` > `b**t`
26 | *
27 | * @param {string} value
28 | * @param {string} [character='*']
29 | * @returns {string}
30 | */
31 | export function inner(value, character) {
32 | if (value.length <= 2) {
33 | return value
34 | }
35 |
36 | return (
37 | value.charAt(0) +
38 | (character || '*').repeat(value.length - 2) +
39 | value.charAt(value.length - 1)
40 | )
41 | }
42 |
43 | /**
44 | * `butt` > `@#$%`
45 | *
46 | * @param {number|string} value
47 | * @param {string} [pattern='@#$%!&?']
48 | * @returns {string}
49 | */
50 | export function grawlix(value, pattern = '@#$%!&?') {
51 | const length = typeof value === 'number' ? value : value.length
52 | return (
53 | pattern.repeat(Math.floor(length / pattern.length)) +
54 | pattern.slice(0, length % pattern.length)
55 | )
56 | }
--------------------------------------------------------------------------------
/src/utils/examples/http-headers.ts:
--------------------------------------------------------------------------------
1 | export interface HTTPRequest {
2 | headers?: { [k: string]: any };
3 | params?: { [k: string]: any };
4 | query?: { [k: string]: any };
5 | body?: any;
6 | }
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/api-type-definitions-usage.js:
--------------------------------------------------------------------------------
1 | const { OPTIONS } = require('./api-type-definitions.js')
2 |
3 | /**
4 | * Creates OS based shortcuts for files, folders, urls, and applications.
5 | *
6 | * @param {OPTIONS} options Options object for each OS, and global options
7 | * @return {boolean} True = success, false = failed to create the icon or set its permissions (Linux).
8 | */
9 | function createDesktopShortcut (options) {
10 | console.log(options)
11 | // the library code
12 | return false
13 | }
14 |
15 | createDesktopShortcut({
16 | verbose: true,
17 | uglify: true,
18 | input: 'body { color: red; }'
19 | })
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/api-type-definitions.js:
--------------------------------------------------------------------------------
1 | // https://github.com/red-perfume/red-perfume-css/blob/main/api-type-definitions.js
2 | // https://stackoverflow.com/questions/49836644/how-to-import-a-typedef-from-one-file-to-another-in-jsdoc-using-vs-code
3 |
4 | /**
5 | * @file Type definitions for the API and reusable functions/objects
6 | * @author TheJaredWilcurt
7 | */
8 |
9 | /**
10 | * OPTIONAL: console.error is called by default if verbose: true.
11 | *
12 | * Your own custom logging function called with helpful warning/error
13 | * messages from the internal validators. Only used if verbose: true.
14 | *
15 | * @callback {Function} CUSTOMLOGGER
16 | * @param {string} message The human readable warning/error message
17 | * @param {object} [error] Sometimes an error or options object is passed
18 | * @return {void}
19 | */
20 |
21 | /**
22 | * @typedef {object} OPTIONS
23 | * @property {boolean} [verbose=true] Logs out helpful warnings/errors using `customLogger` or console.error.
24 | * @property {boolean} [uglify=false] If `false` atomized classes are long (`.rp__padding__--COLOR12px`). If `true` they are short (`.rp__b5p`).
25 | * @property {string} [input=''] A string of any valid CSS to be atomized
26 | */
27 |
28 | /**
29 | * @typedef {object} CLASSMAP
30 | * @property {{[key: string]: string[]}} classMapEntry The key is the original classname, the value is an array of strings of atomized classes
31 | */
32 |
33 | /**
34 | * @typedef {object} SELECTORCHUNK
35 | * @property {string} type The type of selector ('tag', 'attribute', 'pseudo')
36 | * @property {string} name Selector name ('class', 'hover')
37 | * @property {string} [action] Action ('element')
38 | * @property {string} [value] Actual selector value ('cow')
39 | * @property {boolean} [ignoreCase] If casing should be ignored (false)
40 | * @property {string} [namespace] Not sure what this is (null)
41 | * @property {string} [data] Not sure what this is (null)
42 | * @property {string} [original] The original value for this selector ('.cow')
43 | */
44 |
45 | /**
46 | * @typedef {SELECTORCHUNK[]} SELECTOR
47 | */
48 |
49 | /**
50 | * @typedef {SELECTOR[]} SELECTORS
51 | */
52 |
53 | /**
54 | * @typedef {object} DECLARATION
55 | * @property {string} type The type of AST ('declaration')
56 | * @property {string} property The CSS property name ('background', 'width')
57 | * @property {string} value The CSS value ('#F00', '100px')
58 | */
59 |
60 | /**
61 | * @typedef {DECLARATION[]} DECLARATIONS
62 | */
63 |
64 | /**
65 | * @typedef {object} RULE
66 | * @property {string} type The type of the AST ('rule')
67 | * @property {SELECTORS} selectors Array of arrays containing AST objects for each part of the CSS Selector
68 | * @property {DECLARATIONS} declarations Array of declaration objects for each property/value pair
69 | */
70 |
71 | /**
72 | * @typedef {object} STYLESHEET
73 | * @property {string} [source] Not sure what this is (undefined)
74 | * @property {RULE[]} rules Array of all rules in the the stylesheet
75 | * @property {Array} parsingErrors Not sure what this is (empty array)
76 | */
77 |
78 | /**
79 | * @typedef {object} STYLESHEETAST
80 | * @property {string} type The type of the AST ('stylesheet')
81 | * @property {STYLESHEET} stylesheet Object containing the Rules AST
82 | */
83 |
84 | /**
85 | * @typedef {object} UGLIFYRESULT
86 | * @property {string} name An uglified class name ('.rp__b5z2')
87 | * @property {number} index The index number used (520958)
88 | */
89 |
90 | /**
91 | * @typedef {object} OUTPUT
92 | * @property {CLASSMAP} classMap Example: { '.cow': ['.rp__0', '.rp__1'], '.moo': ['.rp__2', '.rp__1'] }
93 | * @property {string} atomizedCss A string of atomized CSS styles
94 | * @property {string[]} styleErrors Array of strings of errors that occurred, or empty array if no errors occurred
95 | */
96 |
97 | /**
98 | * @type {OPTIONS}
99 | */
100 | let OPTIONS;
101 |
102 | /**
103 | * @type {CLASSMAP}
104 | */
105 | let CLASSMAP;
106 |
107 | /**
108 | * @type {SELECTORCHUNK}
109 | */
110 | let SELECTORCHUNK;
111 |
112 | /**
113 | * @type {SELECTOR}
114 | */
115 | let SELECTOR;
116 |
117 | /**
118 | * @type {SELECTORS}
119 | */
120 | let SELECTORS;
121 |
122 | /**
123 | * @type {DECLARATION}
124 | */
125 | let DECLARATION;
126 |
127 | /**
128 | * @type {DECLARATIONS}
129 | */
130 | let DECLARATIONS;
131 |
132 | /**
133 | * @type {RULE}
134 | */
135 | let RULE;
136 |
137 | /**
138 | * @type {STYLESHEET}
139 | */
140 | let STYLESHEET;
141 |
142 | /**
143 | * @type {STYLESHEETAST}
144 | */
145 | let STYLESHEETAST;
146 |
147 | /**
148 | * @type {UGLIFYRESULT}
149 | */
150 | let UGLIFYRESULT;
151 |
152 | /**
153 | * @type {OUTPUT}
154 | */
155 | let OUTPUT;
156 |
157 | module.exports = {
158 | OPTIONS,
159 | CLASSMAP,
160 | SELECTORCHUNK,
161 | SELECTOR,
162 | SELECTORS,
163 | DECLARATION,
164 | DECLARATIONS,
165 | RULE,
166 | STYLESHEET,
167 | STYLESHEETAST,
168 | UGLIFYRESULT,
169 | OUTPUT
170 | };
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-five.js:
--------------------------------------------------------------------------------
1 | import Types from "./import-example-with-export.js"
2 |
3 | /** @type {typeof Types.MyType} */
4 | const myVar = {
5 | name : 'Roy',
6 | description : 'abc123',
7 | // age: 25,
8 | }
9 | console.log(myVar)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-four.js:
--------------------------------------------------------------------------------
1 |
2 | /** @type {import('./import-example.js').MyType} */
3 | const myVarY = {
4 | name : 'Roy',
5 | description : 'abc123',
6 | // age: 25,
7 | }
8 | console.log(myVarY)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-seven.js:
--------------------------------------------------------------------------------
1 |
2 | /** @type {MyTypeFromNoExport} */
3 | const myVar = {
4 | name : 'Roy',
5 | description : 'abc123',
6 | // age: 25,
7 | }
8 | console.log(myVar)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-six.js:
--------------------------------------------------------------------------------
1 | const { MyTypeHere } = require('./import-example-with-module-exports.js')
2 |
3 | /** @type {MyTypeHere} */
4 | const myVar = {
5 | name : 'Roy',
6 | description : 'abc123',
7 | // age: 25,
8 | }
9 | console.log(myVar)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-three.js:
--------------------------------------------------------------------------------
1 | const Types = require('./import-example.js')
2 |
3 | /** @type {Types.MyType} */
4 | const myVar = {
5 | name : 'Roy',
6 | description : 'abc123',
7 | // age: 25,
8 | }
9 | console.log(myVar)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage-two.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef {import('./import-example.js').MyType} XYZ
3 | */
4 |
5 | /** @type {XYZ} */
6 | const myVarX = {
7 | name : 'Roy',
8 | description : 'abc123',
9 | // age: 25,
10 | }
11 | console.log(myVarX)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-usage.js:
--------------------------------------------------------------------------------
1 | import * as Types from "./import-example"
2 |
3 | /** @type {Types.MyType} */
4 | const myVar = {
5 | name : 'Roy',
6 | description : 'abc123',
7 | // age: 25,
8 | }
9 | console.log(myVar)
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-with-export.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/49836644/how-to-import-a-typedef-from-one-file-to-another-in-jsdoc-using-vs-code
2 |
3 | /**
4 | * @typedef MyType
5 | * @prop {string} name
6 | * @prop {string} description
7 | */
8 |
9 | /** @type {MyType} */
10 | let MyType
11 |
12 | export default {
13 | MyType
14 | }
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-with-module-exports.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/49836644/how-to-import-a-typedef-from-one-file-to-another-in-jsdoc-using-vs-code
2 |
3 | /**
4 | * @typedef MyTypeHere
5 | * @prop {string} name
6 | * @prop {string} description
7 | */
8 |
9 | /**
10 | * @type {MyTypeHere}
11 | */
12 | let MyTypeHere;
13 |
14 | module.exports = {
15 | MyTypeHere,
16 | }
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example-with-no-export.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/49836644/how-to-import-a-typedef-from-one-file-to-another-in-jsdoc-using-vs-code
2 |
3 | /**
4 | * @typedef MyTypeFromNoExport
5 | * @prop {string} name
6 | * @prop {string} description
7 | */
8 |
--------------------------------------------------------------------------------
/src/utils/examples/import-defs/import-example.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/49836644/how-to-import-a-typedef-from-one-file-to-another-in-jsdoc-using-vs-code
2 |
3 | /**
4 | * @typedef MyType
5 | * @prop {string} name
6 | * @prop {string} description
7 | */
8 |
9 | export const Types = {}
--------------------------------------------------------------------------------
/src/utils/examples/inferred-param.ts:
--------------------------------------------------------------------------------
1 | // https://www.typescriptlang.org/play?#code/C4TwDgpgBA0hIHkBGArAPAFQHxQLxQG8AoKKAbRigEsA7KAa3gHsAzKDAXQC4oAKGgIYBbCDxgBKPDgBuTKgBMiAXwDcRIiwCuNAMbAqTOkIGM4iVJigQAHsAg15AZ1jxk6bFl5NUPDON+EJFAAThDAmsF03ihQAs4CNCDK6jqGjsBQ0XhQxqauqLzEpAI8-MIQkrg4RaRQAPR1UAB6APxBpKk0jkwANhAAdD1MAOZlIuJBSgA0QUilguNSgbX1ja3tUJ3dfYMjYxWTM0riQA
2 | // https://twitter.com/PettengillAaron/status/1608208857867632641
3 | type KeyObj = {
4 | [K in keyof T]: (name: K) => void
5 | };
6 |
7 | function makeKeyObj>(obj: T): T {
8 | return obj as any
9 | }
10 |
11 | const obj = makeKeyObj({
12 | a: (name) => {
13 | // ^?
14 | console.log(name)
15 | },
16 | b: (name) => {
17 | // ^?
18 | console.log(name)
19 | },
20 | })
--------------------------------------------------------------------------------
/src/utils/examples/inline.js:
--------------------------------------------------------------------------------
1 | // https://whistlr.info/2021/check-js-with-ts/
2 |
3 | /** @type {number[]} */
4 | const x2 = []; // otherwise TS thinks this is 'any[]'
5 |
6 | /**
7 | * @param {Element} bar
8 | * @param {?Element} barOrNull
9 | * @return {Promise}
10 | */
11 | async function fooMethod(bar, barOrNull) {
12 | // do something with bar/barOrNull
13 | }
14 |
15 | /** @type {(arg: number) => string} */
16 | const fn = (arg) => {
17 | /* ... */
18 | return 'done';
19 | };
20 |
21 | // this is a _cast_, not a declaration: you need to wrap in parens ()
22 | const nowIsNumberType = /** @type {number} */ (window['someExternalAny']);
--------------------------------------------------------------------------------
/src/utils/examples/json-types.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * A type representing all allowed JSON primitive values.
3 | *
4 | * @public
5 | */
6 | export type JsonPrimitive = number | string | boolean | null;
7 |
8 | /**
9 | * A type representing all allowed JSON object values.
10 | *
11 | * @public
12 | */
13 | export type JsonObject = { [key in string]?: JsonValue };
14 |
15 | /**
16 | * A type representing all allowed JSON array values.
17 | *
18 | * @public
19 | */
20 | export interface JsonArray extends Array {}
21 |
22 | /**
23 | * A type representing all allowed JSON values.
24 | *
25 | * @public
26 | */
27 | export type JsonValue = JsonObject | JsonArray | JsonPrimitive;
--------------------------------------------------------------------------------
/src/utils/examples/oauth/oauth.js:
--------------------------------------------------------------------------------
1 | // https://www.codejam.info/2021/10/jsdoc-typescript-inside-javascript.html
2 | const crypto = require('crypto')
3 |
4 | /**
5 | * @typedef {Object} SyncOAuthChallengeImpl
6 | * @property {crypto.KeyPairKeyObjectResult} keyPair
7 | * @typedef {SyncOAuthChallengeImpl} SyncOAuthChallenge
8 | */
9 |
10 | /**
11 | * @param {SyncOAuthChallenge} challenge
12 | * @param {Object} [options]
13 | * @param {string} [options.clientId] - OAuth client ID.
14 | * @param {string} [options.scope] - OAuth scope.
15 | * @param {string} [options.tokenEndpoint] - OAuth token endpoint.
16 | * @param {string} [options.tokenServerUrl] - TokenServer URL.
17 | * @returns {Promise}
18 | */
19 | async function complete (challenge, result, options) {
20 | // Actual code.
21 | return {
22 | oauthToken: {
23 | access_token: 'string',
24 | scope: 'string',
25 | expires_in: 1,
26 | },
27 | syncKeyBundle: {
28 | encryptionKey: 'string',
29 | hmacKey: 'string',
30 | kid: 'string',
31 | },
32 | token: {
33 | id: 'string',
34 | key: 'string',
35 | },
36 | tokenIssuedAt: 1,
37 | }
38 | }
39 |
40 | module.exports = { complete }
--------------------------------------------------------------------------------
/src/utils/examples/oauth/types.js:
--------------------------------------------------------------------------------
1 | // https://www.codejam.info/2021/10/jsdoc-typescript-inside-javascript.html
2 |
3 | /**
4 | * @typedef {Object} SyncOptions
5 | * @property {string} [authServerUrl]
6 | * @property {string} [authorizationUrl]
7 | * @property {string} [tokenEndpoint]
8 | * @property {string} [tokenServerUrl]
9 | * @property {Object} [oauthOptions]
10 | *
11 | * @typedef {Object} OAuthToken
12 | * @property {string} access_token
13 | * @property {string} scope
14 | * @property {number} expires_in
15 | *
16 | * @typedef {Object} SyncToken
17 | * @property {string} id
18 | * @property {string} key
19 | *
20 | * @typedef {Object} SyncKeyBundle
21 | * @property {string} encryptionKey
22 | * @property {string} hmacKey
23 | * @property {string} kid
24 | *
25 | * @typedef {Object} SyncCredentials
26 | * @property {OAuthToken} oauthToken - The OAuth token required to authenticate to the TokenServer.
27 | * @property {SyncKeyBundle} syncKeyBundle - The Sync key bundle required to decrypt the collection keys.
28 | * @property {SyncToken} token - The token object required to call the Firefox Sync API.
29 | * @property {number} tokenIssuedAt - Timestamp in milliseconds of when the token was issued to preemptively refresh it.
30 | */
31 |
32 | // Does nothing but required for TypeScript to import this file.
33 | module.exports = {}
--------------------------------------------------------------------------------
/src/utils/examples/rbac/index.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/stalniy/casl-examples/blob/19c2dbd1c3dc9fb855ed24108b4481a4eafca5ba/packages/react-blog/src/services/ability.ts
2 | import { Ability, AbilityClass } from '@casl/ability'
3 |
4 | export interface User {
5 | email: string
6 | }
7 |
8 | interface Article {
9 | id: string
10 | title: string
11 | body: string
12 | published: boolean
13 | createdAt: string
14 | author: string
15 | createdBy: User
16 | }
17 |
18 | type Actions = 'manage' | 'create' | 'read' | 'update' | 'delete' | 'publish';
19 | type Subjects = 'article' | Article | 'all' | 'release';
20 |
21 | export type AppAbility = Ability<[Actions, Subjects]>;
22 | export const AppAbility = Ability as AbilityClass;
23 |
24 | function createAbility() {
25 | const ability = new AppAbility()
26 | ability.can = ability.can.bind(ability)
27 | ability.cannot = ability.cannot.bind(ability)
28 |
29 | return ability;
30 | }
31 |
32 | const xyz = createAbility()
33 | xyz
34 | xyz.can('create', 'article')
35 |
36 | const art: Article = {
37 | id: 'string',
38 | title: 'string',
39 | body: 'string',
40 | published: false,
41 | createdAt: 'string',
42 | author: 'string',
43 | createdBy: {
44 | email: 'foo'
45 | },
46 | }
--------------------------------------------------------------------------------
/src/utils/examples/react-class.js:
--------------------------------------------------------------------------------
1 | // https://stackoverflow.com/questions/43768915/how-to-use-typescript-jsdoc-annotations-for-react-proptypes
2 | import React, { Component } from "react";
3 |
4 | /**
5 | * @typedef {object} Props
6 | * @prop {string} className
7 | * @prop {number} numberProp
8 | *
9 | * @extends {Component}
10 | */
11 | export default class SomeComponent extends Component {
12 | render() {
13 | return (
14 |
15 | {this.props.numberProp}
16 |
17 | );
18 | }
19 | }
--------------------------------------------------------------------------------
/src/utils/examples/react-render-props.js:
--------------------------------------------------------------------------------
1 | // https://medium.com/geekculture/using-jsdoc-to-enable-intellisense-for-render-props-in-vscode-e655ae4e64c1
2 | // https://forums.expo.dev/t/registerrootcomponent-typescript-whats-the-correct-parameter-type/52799
3 |
4 | import React, { useState } from "react";
5 | import PropTypes from "prop-types";
6 |
7 | /**
8 | * @callback ChildrenFn
9 | * @param {{ open: boolean }} props - whether the toggle is open or not
10 | * @returns {React.ReactNode}
11 | */
12 |
13 | /**
14 | * @param {Object} props
15 | * @param {ChildrenFn} props.children
16 | * @returns {React.ReactElement}
17 | */
18 | function Toggle(props) {
19 | const [open, setOpen] = useState(false);
20 | return (
21 |
22 |
25 | {props.children({ open })}
26 |
27 | )
28 | }
29 |
30 | Toggle.propTypes = {
31 | children: PropTypes.func.isRequired
32 | }
33 |
34 |
35 | function usage() {
36 | return (
37 |
38 | {({ open }) => {
39 | return open ? xyz
: null
40 | }}
41 |
42 | )
43 | }
44 |
45 | export default Toggle;
--------------------------------------------------------------------------------
/src/utils/examples/reverse-record.js:
--------------------------------------------------------------------------------
1 | // https://www.jacobparis.com/blog/jsdoc-cheatsheet#type-parameters
2 | /**
3 | * @template {PropertyKey} T
4 | * @template {PropertyKey} U
5 | *
6 | * @param {Record} input
7 | * @returns {Record}
8 | */
9 | function reverseRecord(input) {
10 | const entries = Object.entries(
11 | input,
12 | ).map(([key, value]) => [value, key])
13 | return Object.fromEntries(entries)
14 | }
15 |
16 | reverseRecord({ foo: 'bar'})
--------------------------------------------------------------------------------
/src/utils/examples/snakecase.js:
--------------------------------------------------------------------------------
1 | // https://twitter.com/anuraghazru/status/1444712390759575556
2 | /**
3 | * @typedef {object} CardColors
4 | * @property {string} titleColor
5 | * @property {string} textColor
6 | * @property {string} iconColor
7 | */
8 |
9 | /**
10 | * CamelToSnakeCase
11 | * @template S {string}
12 | * @typedef {S extends `${infer T}${infer U}`
13 | * ? `${T extends Capitalize ? "_" : ""}${Lowercase}${CamelToSnakeCase}`
14 | * : S
15 | * } CamelToSnakeCase
16 | */
17 |
18 | /**
19 | * Snakifies object properties
20 | * @template T
21 | * @typedef {{[K in keyof T as CamelToSnakeCase]: T[K]}} Snakify
22 | */
23 |
24 | /**
25 | * returns theme based colors with proper overrides and defaults
26 | * @param {Snakify & { fallbackTheme: string; theme: string }} options
27 | * @returns {CardColors}
28 | */
29 | function getCardColors(options) {
30 | console.log(options);
31 |
32 | return {
33 | titleColor: "",
34 | iconColor: "",
35 | textColor: "",
36 | };
37 | }
38 |
39 | getCardColors({
40 | title_color: 'cool',
41 | text_color: 'nice',
42 | icon_color: 'red',
43 | fallbackTheme: 'blue',
44 | theme: 'custom'
45 | });
46 |
--------------------------------------------------------------------------------
/src/utils/examples/split.js:
--------------------------------------------------------------------------------
1 | // https://twitter.com/anuraghazru/status/1444712396673613824
2 |
3 | /**
4 | * @template T {string}
5 | * @template K {string}
6 | * @typedef {T extends `${infer P1}${K & string}${infer P2}`
7 | * ? [P1, ...Split]
8 | * : [T]
9 | * } Split
10 | */
11 |
12 |
13 | /**
14 | * Hover over `prop`
15 | * @typedef {Split<'Hello World', ' '>} prop
16 | */
--------------------------------------------------------------------------------
/src/utils/examples/ts-json.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/samchon/typescript-json/tree/master#json-schema-generation
2 | // https://github.com/samchon/typescript-json/tree/master#comment-tags
3 | export interface TagExample {
4 | /* -----------------------------------------------------------
5 | ARRAYS
6 | ----------------------------------------------------------- */
7 | /**
8 | * You can limit array length like below.
9 | *
10 | * @minItems 3
11 | * @maxItems 10
12 | *
13 | * Also, you can use `@items` tag instead.
14 | *
15 | * @items (5, 10] --> 5 < length <= 10
16 | * @items [7 --> 7 <= length
17 | * @items 12) --> length < 12
18 | *
19 | * Furthermore, you can use additional tags for each item.
20 | *
21 | * @type uint
22 | * @format uuid
23 | */
24 | array: Array;
25 |
26 | /**
27 | * If two-dimensional array comes, length limit would work for
28 | * both 1st and 2nd level arraies. Also using additional tags
29 | * for each item (string) would still work.
30 | *
31 | * @items (5, 10)
32 | * @format url
33 | */
34 | matrix: string[][];
35 |
36 | /* -----------------------------------------------------------
37 | NUMBERS
38 | ----------------------------------------------------------- */
39 | /**
40 | * Type of number.
41 | *
42 | * It must be one of integer or unsigned integer.
43 | *
44 | * @type int
45 | * @type uint
46 | */
47 | type: number;
48 |
49 | /**
50 | * You can limit range of numeric value like below.
51 | *
52 | * @minimum 5
53 | * @maximum 10
54 | *
55 | * Also, you can use `@range` tag instead.
56 | *
57 | * @range (5, 10] --> 5 < x <= 10
58 | * @range [7 --> 7 <= x
59 | * @range 12) --> x < 12
60 | */
61 | range: number;
62 |
63 | /**
64 | * Step tag requires minimum or exclusiveMinimum tag.
65 | *
66 | * 3, 13, 23, 33, ...
67 | *
68 | * @step 10
69 | * @exclusiveMinimum 3
70 | * @range [3
71 | */
72 | step: number;
73 |
74 | /**
75 | * Value must be multiple of the given number.
76 | *
77 | * -5, 0, 5, 10, 15, ...
78 | *
79 | * @multipleOf 5
80 | */
81 | multipleOf: number;
82 |
83 | /* -----------------------------------------------------------
84 | STRINGS
85 | ----------------------------------------------------------- */
86 | /**
87 | * You can limit string length like below.
88 | *
89 | * @minLength 3
90 | * @maxLength 10
91 | *
92 | * Also, you can use `@length` tag instead.
93 | *
94 | * @length 10 --> length = 10
95 | * @length [3, 7] --> 3 <= length && length <= 7
96 | * @length (5, 10) --> 5 < length && length < 10
97 | * @length [4 --> 4 < length
98 | * @length 7) --> length < 7
99 | */
100 | length: string;
101 |
102 | /**
103 | * Mobile number composed by only numbers.
104 | *
105 | * Note that, `typescript-json` does not support flag of regex,
106 | * because JSON schema definition does not support it either.
107 | * Therefore, write regex pattern without `/` characters and flag.
108 | *
109 | * @pattern ^0[0-9]{7,16}
110 | * -> RegExp(/[0-9]{7,16}/).test("01012345678")
111 | */
112 | mobile: string;
113 |
114 | /**
115 | * E-mail address.
116 | *
117 | * @format email
118 | */
119 | email: string;
120 |
121 | /**
122 | * UUID value.
123 | *
124 | * @format uuid
125 | */
126 | uuid: string;
127 |
128 | /**
129 | * URL address.
130 | *
131 | * @format url
132 | */
133 | url: string;
134 |
135 | /**
136 | * IPv4 address.
137 | *
138 | * @format ipv4
139 | */
140 | ipv4: string;
141 |
142 | /**
143 | * IPv6 address.
144 | *
145 | * @format ipv6
146 | */
147 | ipv6: string;
148 | }
--------------------------------------------------------------------------------
/src/utils/examples/webapp.js:
--------------------------------------------------------------------------------
1 | // https://gist.github.com/Meshida/22096d72ccfbc03998c7f5f5caf02f24
2 |
3 | /**
4 | * @typedef {Object} PostData
5 | * @prop {Object} postData
6 | * An object of data for the received POST requests.
7 | * @prop {number} postData.length
8 | * The same as contentLength of ReqParams
9 | * @prop {string} postData.type
10 | * The MIME type of the POST body
11 | * @prop {string} postData.contents
12 | * The content text of the POST body
13 | * @prop {string} postData.name
14 | * Always the value "postData"
15 | */
16 |
17 | /**
18 | * @typedef {Object} ReqParams
19 | * @prop {string} queryString
20 | * The value of the query string portion of the URL, or null if no query string is specified
21 | * @prop {Object.} parameter
22 | * An object of key/value pairs that correspond to the request parameters. Only the first value is returned for parameters that have multiple values.
23 | * @prop {Object.>} parameters
24 | * An object of key/value pairs that correspond to the request parameters. All the values of each key are in an array.
25 | * @prop {number} contentLength
26 | * The length of the request body for POST requests, or -1 for GET requests.
27 | */
28 |
29 | /**
30 | * @param {ReqParams} e An data of the GET request
31 | */
32 | function doGet(e) {
33 | }
34 |
35 | /**
36 | * @param {ReqParams & PostData} e An data of the POST request
37 | */
38 | function doPost(e) {
39 | }
--------------------------------------------------------------------------------
/src/utils/examples/xyz/types.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef FeaturedObject
3 | * @property {number} id
4 | * @property {string} title
5 | * @property {string} description
6 | * @property {string} image
7 | * @property {object} [button]
8 | * @property {string} button.name
9 | * @property {string} button.href
10 | */
11 |
12 | // Does nothing but required for TypeScript to import this file.
13 | module.exports = {}
--------------------------------------------------------------------------------
/src/utils/examples/xyz/xyz.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @param {object} props
3 | * @param {import('./types').FeaturedObject[]} props.items
4 | * @param {boolean} [props.breadcrumb]
5 | * @returns
6 | */
7 | export default function FeaturedSlideshow(props) {
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/utils/generics.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 | // https://fettblog.eu/typescript-jsdoc-superpowers/
3 |
4 | /**
5 | * @template T
6 | * @param {T} obj
7 | * @param {(keyof T)[]} params
8 | */
9 | function pluck(obj, ...params) {
10 | return params.map(el => obj[el])
11 | }
12 |
13 | /** @type { (obj: T, params: K[]) => Array} */
14 | function values(obj, ...params) {
15 | return params.map(el => obj[el])
16 | }
17 |
18 | const article = {}
19 |
20 | const numbers = values(article, 'price', 'vat')
21 | const strings = values(article, 'title')
22 | const mixed = values(article, 'title', 'vat')
23 |
24 | // ───────────────────────
25 | // https://github.com/homer0/packages/blob/main/packages/public/prettier-plugin-jsdoc/src/fns/utils.js#L8
26 |
27 | /**
28 | * Ensures a given object is an array.
29 | *
30 | * @param {T | T[]} obj The object to validate.
31 | * @returns {T[]}
32 | * @template T
33 | */
34 | const ensureArray = (obj) => {
35 | if (Array.isArray(obj)) return obj
36 | return [obj]
37 | }
38 |
39 | const arr1 = ensureArray('foo')
40 | const arr2 = ensureArray(true)
41 |
42 |
43 | // ───────────────────────
44 | // https://zenn.dev/asama/articles/0c66573e488b22
45 |
46 | /**
47 | * @template T
48 | * @param {T} x - 戻り値に流用するジェネリクスパラメータ
49 | * @return {T}
50 | */
51 | function id(x) {
52 | return x;
53 | }
54 |
55 | const a = id("string");
56 | const b = id(123);
57 | const c = id({});
58 |
59 |
60 |
61 | // ───────────────────────
62 | // https://github.com/giltayar/jsdoc-typing/blob/master/src/map-values.js
63 |
64 | /**
65 | * @template {string|number|symbol} K
66 | * @template T
67 | * @template W
68 | * @param {Record} object
69 | * @param {(t: T) => W} mapFunction
70 | *
71 | * @returns {Record}
72 | */
73 | function mapValues(object, mapFunction) {
74 | return Object.fromEntries(Object.entries(object).map(([key, value]) => [key, mapFunction(value)]))
75 | }
76 |
77 |
78 | // ───────────────────────
79 | // https://twitter.com/techytacos/status/1419767168305033232
80 |
81 |
82 | /**
83 | * @typedef {{
84 | * data : {
85 | * foo: string
86 | * }
87 | * }} Foo
88 | */
89 |
90 | /**
91 | * @param {CustomEvent} e
92 | */
93 | function coolio(e) {
94 | console.log(e.detail.data.foo)
95 | }
96 |
97 | // ───────────────────────
98 | // https://stackoverflow.com/questions/59243543/jsdoc-type-variables/59253145#59253145
99 |
100 | /**
101 | * @template A
102 | * @param {A} x
103 | * @return {A}
104 | */
105 | const idTwo = (x) => x;
106 |
107 | /** @type {string} */
108 | let strtwo = '';
109 |
110 | /** @type {number} */
111 | let numtwo = 1;
112 |
113 | strtwo = idTwo(true); // Type warning.
114 |
115 | strtwo = idTwo('string'); // Type safe.
116 |
117 | strtwo = idTwo(1234); // Type warning.
118 |
119 | numtwo = idTwo(true); // Type warning.
120 |
121 | numtwo = idTwo('string'); // Type warning.
122 |
123 | numtwo = idTwo(1234); // Type safe.
124 |
125 | // https://twitter.com/DerekNguyen10/status/1404307885635477507/photo/1
126 |
127 |
128 | // ───────────────────────
129 | // https://github.com/chunjin666/jsdoc-learning/blob/master/src/01-types/06-%40template.js
130 |
131 | // You can use the @template tag to declare a type parameter, which can make the function, class, and type generic
132 |
133 | /**
134 | * @template T
135 | * @param { T } x-a generic parameter that flows to the return type
136 | * @return {T}
137 | */
138 | function id(x) {
139 | return x;
140 | }
141 |
142 | const ta = id('string');
143 | const tb = id(123);
144 | const tc = id({});
145 |
146 | // You can use multiple tags to declare multiple type parameters
147 |
148 | /**
149 | * @template T,U,V
150 | * @template W,X
151 | */
152 |
153 | // You can specify a type restriction before the type parameter name
154 |
155 | /**
156 | * @template {string} K - must be a string or character literal
157 | * @template {{ execute(s: string): string }} Executable - there must be an execute function, the parameters and return values are strings
158 | * @param { K } key
159 | * @param {Executable} executable
160 | */
161 | function execute(key, executable) {
162 | executable.execute(key);
163 | }
164 |
165 | // Another example of specifying type restrictions.
166 | /**
167 | * @typedef {{a: string, b: number}} BaseOption
168 | */
169 | /**
170 | * @template {{c: boolean}} T
171 | * @typedef {BaseOption & T} MergeOption
172 | */
173 |
174 | /**
175 | * @type {MergeOption<{c: boolean, d: number}>}
176 | */
177 | const option = { };
178 | option.c
179 | option.d
180 |
181 | // You can assign a default value to the type parameter in this way, which is not supported by the editor. . .
182 |
183 | /** @template [T=object] */
184 | class CustomCache {
185 | /** @param {T} initial */
186 | constructor(T) {}
187 | }
188 | let c = new CustomCache();
--------------------------------------------------------------------------------
/src/utils/ignore-example.js:
--------------------------------------------------------------------------------
1 | // @ts-nocheck
2 |
3 | class Baz {}
4 | // @ts-ignore
5 | const foo = {}
6 | // without block ignore
7 | // @ts-ignore
8 | foo.bar = new Baz({ someUntypedParameter: true })
9 | // @ts-ignore
10 | foo.bar2 = new Baz({ someUntypedParameter: true })
11 | // @ts-ignore
12 | foo.bar3 = new Baz({ someUntypedParameter: true })
13 | // @ts-ignore
14 | foo.bar4 = new Baz({ someUntypedParameter: true })
15 |
16 | // @ts-ignore
17 | foo.bar = new Baz({ someUntypedParameter: true })
18 | // @ts-ignore
19 | foo.bar2 = new Baz({ someUntypedParameter: true })
20 | // @ts-ignore
21 | foo.bar3 = new Baz({ someUntypedParameter: true })
22 | foo.bar4 = new Baz({ someUntypedParameter: true })
23 |
24 |
25 | /**
26 | * Example of @ts-ignore-start + @ts-ignore-end
27 | * @param {MyFunc} xyz
28 | * @returns {{total: number, adjustedTotal: number, avgWeight: number}} totals
29 | */
30 | function myFunc(xyz) {
31 | // implementation details omitted
32 | return {
33 | total: 2,
34 | adjustedTotal: 3,
35 | avgWeight: 4,
36 | // @ts-ignore-start
37 | lol: true,
38 | haha: true
39 | // @ts-ignore-end
40 | // what: 'no' <- broken
41 | }
42 | }
--------------------------------------------------------------------------------
/src/utils/imports/my-js-file.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | /**
4 | * myExportedFunc from common js
5 | * @param {number} [x] optional
6 | * @param {number=} y number or undefined
7 | * @param {number} [z=1] optional with default (default not show in type hint)
8 | */
9 | function myExportedFunc(x, y, z = 1) {
10 |
11 | }
12 |
13 | module.exports = {
14 | myExportedFunc
15 | }
--------------------------------------------------------------------------------
/src/utils/imports/my.d.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | export function myFun(a: string, b: string, c: string): number;
5 |
--------------------------------------------------------------------------------
/src/utils/imports/ts-types.ts:
--------------------------------------------------------------------------------
1 | export type TinyProps = {
2 | message: string;
3 | count: number;
4 | disabled: boolean;
5 | };
--------------------------------------------------------------------------------
/src/utils/invert.ts:
--------------------------------------------------------------------------------
1 | // https://twitter.com/buildsghost/status/1498540615658721283/photo/1
2 | /*
3 | export type InvertObject = {
4 | [K in keyof T as T[K]]: K
5 | }
6 |
7 | const fooToBar = {
8 | foo1 : 'bar1',
9 | foo2: 'bar2',
10 | } as const
11 |
12 | const barToFoo: InvertObject = {
13 | boo1: 'foo1', // Object literal may only specify known properties..
14 | bar2: 'foo2', // Type '"boo2"‘ is not assignable to type '"foo2"'.
15 | }
16 | */
--------------------------------------------------------------------------------
/src/utils/jsdoc-module.js:
--------------------------------------------------------------------------------
1 | // Links are incorrect
2 |
3 | /** @module Example */
4 |
5 | /**
6 | * @class module:Example.Car
7 | * @property {Function} start {@link module:Example.Car#start}
8 | * @property {Function} stop {@link module:Example.Car#stop}
9 | *
10 | */
11 | class Car {
12 | /**
13 | * @method module:Example.Car#start
14 | *
15 | */
16 | start () { /* function body */ }
17 |
18 | /**
19 | * @description You could use various other tags here,
20 | * and JSDoc will still auto-assign the following namepath
21 | * "module:Example.Car#stop" to this method
22 | *
23 | */
24 | stop () {
25 |
26 | }
27 | }
--------------------------------------------------------------------------------
/src/utils/simple-jsdoc-generics.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @function
3 | * @template A
4 | * @param {A} val
5 | * @returns {Promise}
6 | */
7 | function selfResolved(val) {
8 | return Promise.resolve(val)
9 | }
--------------------------------------------------------------------------------
/src/utils/type-examples/dot-notation.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/ghoullier/awesome-template-literal-types#dot-notation-string-type-safe
2 |
3 | type PathImpl =
4 | Key extends string
5 | ? T[Key] extends Record
6 | ? | `${Key}.${PathImpl> & string}`
7 | | `${Key}.${Exclude & string}`
8 | : never
9 | : never;
10 |
11 | type PathImpl2 = PathImpl | keyof T;
12 |
13 | type Path = PathImpl2 extends string | keyof T ? PathImpl2 : keyof T;
14 |
15 | type PathValue> =
16 | P extends `${infer Key}.${infer Rest}`
17 | ? Key extends keyof T
18 | ? Rest extends Path
19 | ? PathValue
20 | : never
21 | : never
22 | : P extends keyof T
23 | ? T[P]
24 | : never;
25 |
26 | declare function get>(obj: T, path: P): PathValue;
27 |
28 | const object = {
29 | firstName: "Diego",
30 | lastName: "Haz",
31 | age: 30,
32 | cool: { thing: { wow: 'nice' }},
33 |
34 | projects: [
35 | { name: "Reakit", contributors: 68 },
36 | { name: "Constate", contributors: 12 },
37 | ]
38 | } as const;
39 |
40 | get(object, "cool.thing.wow");
41 |
42 | export {}
--------------------------------------------------------------------------------
/src/utils/type-examples/tyoe-utils.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/shm-open/utilities/blob/master/src/types.ts
2 |
3 | /**
4 | * Make a Partial type with all its field types as partial - recursively
5 | */
6 | export type RecursivePartial = {
7 | [P in keyof T]?: T[P] extends (infer U)[]
8 | ? RecursivePartial[]
9 | :
10 | T[P] extends object
11 | ? RecursivePartial
12 | : T[P];
13 | };
14 |
15 | /**
16 | * Nullable could be T or undefined or null
17 | */
18 | export type Nullable = T | undefined | null;
19 |
20 | /**
21 | * Extract the type of object property
22 | */
23 | export type PropertyType = T[K];
24 |
25 | /**
26 | * Extract the type of array item
27 | */
28 | export type ArrayItemType = T[number];
29 |
30 | /**
31 | * Extract the types array of function parameters
32 | * @deprecated please use ts built-in Parameters instead.
33 | */
34 | export type ParametersTypes = T extends (...args: infer P) => unknown ? P : [];
35 |
36 | /**
37 | * Convert interface to type, so it can be used to work with Record
38 | * check out this thread for details
39 | * https://github.com/microsoft/TypeScript/issues/15300#issuecomment-760165845
40 | * @example foo as Typify
41 | */
42 | export type Typify = { [K in keyof T]: T[K] };
43 |
44 | /**
45 | * convert object into typified instance, it's nothing more than `as Typify`
46 | * just works as an shorthand of explicit cast.
47 | * @param target interface type object
48 | * @returns the target itself, typified
49 | */
50 | export function typify(target: T): Typify {
51 | return target;
52 | }
53 |
54 | /**
55 | * Covert type T to Promise except for Promises
56 | */
57 | export type Promisify = T extends Promise
58 | ? T
59 | : T extends boolean
60 | ? Promise
61 | : Promise;
--------------------------------------------------------------------------------
/src/utils/typedef-div-extend.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @typedef {React.HTMLAttributes} DOMDiv
3 | */
4 |
5 | /**
6 | * @typedef {Object} Props
7 | * @prop {string} [myprop]
8 | */
9 |
10 | /**
11 | * @typedef {DOMDiv & Props} Thing
12 | */
13 |
14 | /**
15 | * @type {Thing}
16 | */
17 | const bozo = {
18 | myprop: 'clown',
19 | }
20 |
21 | /**
22 | * @type {DOMDiv & Props}
23 | */
24 | const bozoz = {
25 | myprop: 'Bozo the Clown',
26 | id: 'xyxyx',
27 | }
--------------------------------------------------------------------------------
/src/utils/typedef-extend.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Person object
3 | * @typedef {Object} Person
4 | * @prop {string} name
5 | * @prop {number} age
6 | */
7 |
8 | /**
9 | * @typedef {Object} Job
10 | * @prop {string} [job]
11 | */
12 |
13 | /**
14 | * Person with optional job
15 | * @typedef {Person & Job} Bozo
16 | */
17 |
18 | /**
19 | * @type {Person}
20 | */
21 | const personNoJob = {
22 | name: 'Bozo the Clown',
23 | age: 50,
24 | }
25 |
26 | /**
27 | * @type {Bozo}
28 | */
29 | const bozo1 = {
30 | name: 'Bozo the Clown',
31 | age: 50,
32 | job: 'clown'
33 | }
34 |
35 | /**
36 | * @type {Bozo}
37 | */
38 | const bozo2 = {
39 | name: 'Bozo the Clown',
40 | age: 50,
41 | }
42 |
--------------------------------------------------------------------------------
/src/utils/types.d.ts:
--------------------------------------------------------------------------------
1 | import * as TypeFest from 'type-fest'
2 |
3 | export type Pet = {
4 | name: string,
5 | };
6 |
7 | /* Export global types to avoid imports */
8 | declare global {
9 | type SomethingGlobal = 'value' | 'value2'
10 | type CamelCasedPropsGlobal = { [K in keyof T as TypeFest.CamelCase]: T[K] };
11 | // ────────────see enumns───────────
12 | type Values = T[keyof T];
13 | type RuneTierE = {
14 | COMMON: 1;
15 | SEMIRARE: 2;
16 | RARE: 3;
17 | };
18 | type RuneTier = Values;
19 | // https://gist.github.com/nicolashery/b30d0464dbd016aa3978129652aa1385
20 | namespace Models {
21 | type ProductTag = "popular" | "featured" | "sale";
22 | interface ProductTagEnum {
23 | Popular: "popular";
24 | Featured: "featured";
25 | Sale: "sale";
26 | }
27 |
28 | interface Product {
29 | id: string;
30 | name: string;
31 | tags: Array;
32 | }
33 | }
34 | /* https://www.benmvp.com/blog/polymorphic-react-components-typescript/ */
35 | // Source: https://github.com/emotion-js/emotion/blob/master/packages/styled-base/types/helper.d.ts
36 | // A more precise version of just React.ComponentPropsWithoutRef on its own
37 | type PropsOf<
38 | C extends keyof JSX.IntrinsicElements | React.JSXElementConstructor
39 | > = JSX.LibraryManagedAttributes>
40 |
41 | type AsProp = {
42 | /**
43 | * An override of the default HTML tag.
44 | * Can also be another React component.
45 | */
46 | as?: C
47 | }
48 | /**
49 | * Allows for extending a set of props (`ExtendedProps`) by an overriding set of props
50 | * (`OverrideProps`), ensuring that any duplicates are overridden by the overriding
51 | * set of props.
52 | */
53 | type ExtendableProps<
54 | ExtendedProps = {},
55 | OverrideProps = {}
56 | > = OverrideProps & Omit
57 | /**
58 | * Allows for inheriting the props from the specified element type so that
59 | * props like children, className & style work, as well as element-specific
60 | * attributes like aria roles. The component (`C`) must be passed in.
61 | */
62 | type InheritableElementProps<
63 | C extends React.ElementType,
64 | Props = {}
65 | > = ExtendableProps, Props>
66 | /**
67 | * A more sophisticated version of `InheritableElementProps` where
68 | * the passed in `as` prop will determine which props can be included
69 | */
70 | type PolymorphicComponentProps<
71 | C extends React.ElementType,
72 | Props = {}
73 | > = InheritableElementProps>
74 | }
75 |
--------------------------------------------------------------------------------
/src/utils/xyz.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line spaced-comment
2 |
3 | // https://github.com/Agoric/agoric-sdk/blob/20c4ff00adbffff067858c3c5702ae7a9e0522b8/packages/pegasus/package.json#L53
4 |
5 | /**
6 | * @typedef {string} DenomUri
7 | * @typedef {string} Denom
8 | * @typedef {string} DepositAddress
9 | * @typedef {string} TransferProtocol
10 | * @typedef {string} Brand
11 | * @typedef {string} ZCFSeat
12 |
13 | *
14 | * @typedef {Object} Peg
15 | * @property {() => string} getAllegedName get the debug name
16 | * @property {() => Brand} getLocalBrand get the brand associated with the peg
17 | * @property {() => DenomUri} getDenomUri get the denomination identifier
18 | */
19 |
20 | /**
21 | * @typedef {Object} BoardDepositFacet a registry for depositAddresses
22 | * @property {(id: string) => any} getValue return the corresponding DepositFacet
23 | */
24 |
25 | /**
26 | * @typedef {Object} FungibleTransferPacket
27 | * @property {string} amount The extent of the amount
28 | * @property {Denom} denom The denomination of the amount
29 | * @property {string} [sender] The sender address
30 | * @property {DepositAddress} receiver The receiver deposit address
31 | */
32 |
33 | /**
34 | * @typedef {(zcfSeat: ZCFSeat, depositAddress: DepositAddress) => Promise} Sender
35 | * Successive transfers are not guaranteed to be processed in the order in which they were sent.
36 | * @typedef {(packet: FungibleTransferPacket) => Promise} Receiver
37 | * @typedef {Object} Courier
38 | * @property {Sender} send
39 | * @property {Receiver} receive
40 | */
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/zod/autozod.ts:
--------------------------------------------------------------------------------
1 | export interface Enemy {
2 | name: string;
3 | powers: string[];
4 | inPrison: boolean;
5 | }
6 | export interface Superman {
7 | name: "superman" | "clark kent" | "kal-l";
8 | enemies: Record;
9 | age: number;
10 | underKryptonite?: boolean;
11 | }
12 | export interface Villain {
13 | name: string;
14 | powers: string[];
15 | friends: Villain[];
16 | }
17 | export interface EvilPlan {
18 | owner: Villain;
19 | description: string;
20 | details: EvilPlanDetails;
21 | }
22 | export interface EvilPlanDetails {
23 | parent: EvilPlan;
24 | steps: string[];
25 | }
26 | export declare type Story = [subject: string, problems: string[]];
27 | export declare type KrytonResponse = Promise;
28 | export declare type KillSuperman = (withKryptonite: boolean, method: string) => Promise;
29 | export interface WithDefaults {
30 | /**
31 | * @default 42
32 | */
33 | theAnswerToTheUltimateQuestionOfLife: number;
34 | /**
35 | * @default false
36 | */
37 | isVulnerable: boolean;
38 | /**
39 | * @default clark
40 | */
41 | name: "clark" | "superman" | "kal-l";
42 | /**
43 | * @default The Answer to the Ultimate Question of Life
44 | */
45 | theMeaningOf42: string;
46 | /**
47 | * @default ""
48 | */
49 | emptyString?: string;
50 | /**
51 | * @default "true"
52 | */
53 | booleanAsString: string;
54 | }
55 | interface NonExported {
56 | name: string;
57 | }
58 | export interface Exported {
59 | a: NonExported;
60 | b: string;
61 | }
62 | export {};
63 |
--------------------------------------------------------------------------------
/src/zod/example-js.js:
--------------------------------------------------------------------------------
1 | import { supermanSchema } from './autozod.validate'
2 |
3 | /**
4 | * @type { import("./autozod").Superman } Superman
5 | */
6 | const superman = {
7 | name: 'superman',
8 | age: 12,
9 | underKryptonite: false,
10 | enemies: {
11 | bill: {
12 | name: 'bill',
13 | powers: ['flys'],
14 | inPrison: false
15 | }
16 | }
17 | }
18 |
19 | supermanSchema.parse(superman)
20 |
--------------------------------------------------------------------------------
/src/zod/example.ts:
--------------------------------------------------------------------------------
1 | import { Superman } from './autozod'
2 | import { supermanSchema } from './autozod.validate'
3 |
4 | const superman: Superman = {
5 | name: 'superman',
6 | age: 12,
7 | underKryptonite: false,
8 | enemies: {
9 | bill: {
10 | name: 'bill',
11 | powers: ['flys'],
12 | inPrison: false
13 | }
14 | }
15 | }
16 |
17 | supermanSchema.parse(superman)
18 |
--------------------------------------------------------------------------------
/src/zod/types.d.ts:
--------------------------------------------------------------------------------
1 | export interface Funky {
2 | name: string;
3 | powers: string[];
4 | inPrison: boolean;
5 | }
6 |
7 | export interface Fancy {
8 | name: "superman" | "clark kent" | "kal-l";
9 | age: number;
10 | underKryptonite?: boolean;
11 | }
--------------------------------------------------------------------------------
/ts-to-zod.config.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | name: "example",
4 | input: "./src/zod/autozod.ts",
5 | output: "./src/zod/autozod.validate.js",
6 | },
7 | // {
8 | // name: "config",
9 | // input: "src/config.ts",
10 | // output: "src/config.zod.ts"
11 | // },
12 | ];
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "lib": ["DOM", "DOM.Iterable", "ESNext"],
5 | "allowJs": true,
6 | "checkJs": true,
7 | "skipLibCheck": false,
8 | "noImplicitAny": false,
9 | "esModuleInterop": true,
10 | "allowSyntheticDefaultImports": true,
11 | "strict": true,
12 | "forceConsistentCasingInFileNames": true,
13 | "strictNullChecks": false,
14 | "module": "ESNext",
15 | "moduleResolution": "Node",
16 | "resolveJsonModule": true,
17 | "isolatedModules": true,
18 | "noEmit": true,
19 | "declaration": true,
20 | "jsx": "react"
21 | },
22 | "include": ["./src"],
23 | "exclude": [
24 | "**/*.d.ts",
25 | "dist",
26 | "node_modules"
27 | ]
28 | }
29 |
--------------------------------------------------------------------------------
/typedoc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://typedoc.org/schema.json",
3 | "entryPoints": ["./src/utils/examples.js"],
4 | "sort": ["source-order"],
5 | "media": "media"
6 | }
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import reactRefresh from '@vitejs/plugin-react-refresh'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [reactRefresh()],
7 | css: {
8 | modules: {
9 | localsConvention: 'camelCaseOnly',
10 | },
11 | }
12 | })
13 |
--------------------------------------------------------------------------------