diff --git a/.config/.prettierignore b/.config/.prettierignore index 6eb33261f..dc6fe88db 100644 --- a/.config/.prettierignore +++ b/.config/.prettierignore @@ -1,13 +1,17 @@ ../.nyc_output ../coverage ../dist +../docs **/package-lock.json ../src/test/**/specs*.json ../src/test/packages/**/*.js ../src/test/renderer/specs ../src/test/renderer/testProject +../src/test/utils/options/readers/data/invalid2.json ../static/main.js ../example/docs/ +**/tmp +**/.vs # Turn this back on once supported by Prettier ../src/test/converter2/behavior/instantiationExpressions.ts diff --git a/.config/typedoc.json b/.config/typedoc.json index c66f52536..8c5fa9b53 100644 --- a/.config/typedoc.json +++ b/.config/typedoc.json @@ -6,14 +6,27 @@ "ConverterComponent", "RendererComponent", "SORT_STRATEGIES", - "_ModelToObject" + "_ModelToObject", + "EventHooksMomento", + "MarkedPlugin" ], "entryPoints": ["../src"], "entryPointStrategy": "Resolve", "excludeExternals": true, + "excludeInternal": false, "excludePrivate": true, - "excludeInternal": true, "treatWarningsAsErrors": false, - "validation": true, + "validation": { + "notExported": true, + "invalidLink": true, + "notDocumented": false + }, + "visibilityFilters": { + "protected": false, + "private": false, + "inherited": true, + "external": false, + "@internal": false + }, "logLevel": "Verbose" } diff --git a/.eslintrc b/.eslintrc index 09bdeba12..021c00e0e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -17,6 +17,7 @@ "ignorePatterns": [ "src/test/renderer/specs", "dist", + "docs", "coverage", "static/main.js", "src/lib/output/themes/default/assets", @@ -37,6 +38,9 @@ "rules": { "@typescript-eslint/no-floating-promises": 1, + // This one is just annoying since it complains at incomplete code + "no-empty": 0, + // This rule is factually incorrect. Interfaces which extend some type alias can be used to introduce // new type names. This is useful particularly when dealing with mixins. "@typescript-eslint/no-empty-interface": 0, @@ -45,15 +49,28 @@ "@typescript-eslint/ban-types": 0, "@typescript-eslint/no-explicit-any": 0, + // Really annoying, doesn't provide any value. + "@typescript-eslint/no-empty-function": 0, + // Declaration merging with a namespace is a necessary tool when working with enums. "@typescript-eslint/no-namespace": 0, // Reported by TypeScript "@typescript-eslint/no-unused-vars": 0, + "no-console": 1, + // Feel free to turn one of these back on and submit a PR! "@typescript-eslint/no-non-null-assertion": 0, - "@typescript-eslint/explicit-module-boundary-types": 0 + "@typescript-eslint/explicit-module-boundary-types": 0, + + "no-restricted-syntax": [ + "warn", + { + "selector": "ImportDeclaration[source.value=/.*perf$/]", + "message": "Benchmark calls must be removed before committing." + } + ] }, "overrides": [ { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e12d3479a..d02348cb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,9 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - # ESLint doesn't support Node 12.10 anymore. Test on the oldest available - # node that our tools support. - node: ["12.22", "12", "14", "16"] + node: ["14.14", "14", "16", "18"] name: Node ${{ matrix.node }} steps: - name: Checkout repository @@ -29,7 +27,7 @@ jobs: # For other test runs, skip so we don't have to go build the regression screenshots. SKIP_VISUAL_TEST: true - name: Lint - run: npm run lint + run: npm run lint -- --max-warnings 0 - name: Circular dependency check uses: gerrit0/circular-dependency-check@v1 with: diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index a93249fac..435d8231f 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -28,4 +28,9 @@ jobs: npm run build node dist/test/capture-screenshots.js - name: Test - run: npx reg-suit run --test + run: npx reg-suit run -c .config/regconfig.json --test + - name: Upload Results + uses: actions/upload-artifact@v3 + with: + name: visual-regression + path: dist/tmp/.reg diff --git a/.gitignore b/.gitignore index c925ecfbc..e781780c5 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ yarn-error.log **/node_modules/ /coverage/ /dist/ +/docs typedoc*.tgz tmp diff --git a/.vscode/launch.json b/.vscode/launch.json index e781de55e..683024248 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,6 +4,22 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { + "args": [ + "--timeout", + "0", + "--config", + "${workspaceFolder}/.config/mocha.fast.json", + "-g", + "1734" + ], + "internalConsoleOptions": "openOnSessionStart", + "name": "Debug Tests", + "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", + "request": "launch", + "skipFiles": ["/**"], + "type": "pwa-node" + }, { "name": "Attach", "port": 9229, diff --git a/.vscode/settings.json b/.vscode/settings.json index 07873a75b..bb69beb90 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,5 +10,6 @@ "prettier.configPath": ".config/.prettierrc.json", "prettier.ignorePath": ".config/.prettierignore", "eslint.workingDirectories": [".", "./example"], - "mochaExplorer.configFile": ".config/mocha.test-explorer.json" + "mochaExplorer.configFile": ".config/mocha.test-explorer.json", + "cSpell.words": ["cname", "tsbuildinfo", "tsdoc"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index c1166b9a3..64a6ecbb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,91 @@ # Unreleased +### Breaking Changes + +- Node 12 is no longer officially supported as it has gone end of life as of 2022-04-30. It might still work, but may stop working at any time. +- Dropped support for TypeScript before 4.6. +- `{@link}` tags in comments will now be resolved as declaration references similar to TSDoc's declaration references. + For most cases, this will just work. See [the documentation](https://typedoc.org/guides/link-resolution/) for details on how link resolution works. +- TypeDoc will now produce warnings for bracketed links (`[[ target ]]`). Use `{@link target}` instead. The `{@link}` syntax will be recognized by [TypeScript 4.3](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-3.html#editor-support-for-link-tags) and later and used to provide better intellisense. TypeDoc version 0.24.0 will remove support for `[[ target ]]` style links. +- `extends` in typedoc.json is now resolved using NodeJS module resolution, so a local path must begin with `./`. +- In the JSON output for `DeclarationReflection`s, `getSignature` is no longer a one-tuple. +- In the JSON output for `DeclarationReflection`s, `setSignature` is no longer a one-tuple. +- In the JSON output for `DeclarationReflection`s, `typeParameter` has been renamed to `typeParameters` +- The `searchGroupBoosts` option must now be given the rendered group name rather than reflection kind names, and can be given custom group names. +- `@inheritDoc` now follows the behavior specified by TSDoc when copying comments with a reference. +- The `gaSite` option has been removed since Google Analytics now infers the site automatically, updated Google Analytics script to latest version, #1846. +- Comments on export declarations will only overrides comments for references and namespaces, #1901. +- The deprecated `listInvalidSymbolLinks` option has been removed. Use `validation.invalidLink` instead. +- The deprecated `true` and `false` values have been removed from `--emit`, to migrate replace `true` with `"both"` and `false` with `"docs"` (the default). +- Links are no longer be resolved against a global list of all symbols. See [the documentation](https://typedoc.org/guides/link-resolution/) for details on link resolution. +- The `validation.invalidLink` option is now on by default. +- `reflection.decorates`, `reflection.decorators`, and their corresponding interfaces have been removed as no code in TypeDoc used them. +- The shape of the `Comment` class has changed significantly to support multiple tag kinds. +- Listeners to `Converter.EVENT_CREATE_TYPE_PARAMETER` and `Converter.EVENT_CREATE_DECLARATION` will now never be passed a `ts.Node` as their third argument. +- Constant variables which are interpreted as functions will no longer have the `ReflectionFlag.Const` flag set. +- `reflection.defaultValue` is no longer set for enum members. The same information is available on `reflection.type` with more precision. +- Removed deprecated `removeReaderByName`, `addDeclarations` and `removeDeclarationByName` methods on `Options`. +- Removed `ProjectReflection.directory`, it was unused by TypeDoc and not properly tested. +- Removed `ProjectReflection.files`, this was an internal cache that should not have been exposed, and shouldn't have existed in the first place, since removing it made TypeDoc faster. +- Removed `ReflectionGroup.kind` since groups can now be created with the `@group` tag. +- Removed `ReflectionKind.Event`, the `@event` tag is now an alias for `@group Events`. Note: This changes the value of `ReflectionKind.Reference` from `16777216` to `8388608`. +- Themes are now set on the document element rather than on body, #1706. + +### Features + +- TypeDoc now supports the `@group` tag to group reflections in a page. If no `@group` tag is specified, reflections will be grouped according to their kind, #1652. +- TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. +- Entry point strategies `Resolve` and `Expand` may now specify globs, #1926. +- `typedoc.json` now supports comments like `tsconfig.json`. +- TypeDoc will now read the `blockTags`, `inlineTags`, and `modifierTags` out of `tsdoc.json` in the same directory as `tsconfig.json` if it exists. + It is recommended to add `"extends": ["typedoc/tsdoc.json"]`, which defines TypeDoc specific tags to your `tsdoc.json` if you create one. +- If an exported symbol has multiple declarations, TypeDoc will now check all appropriate declarations for comments, and warn if more than one declaration contains a comment, #1855. +- Improved support for JSDoc style `@example` tags. If the tag content does not include a code block, TypeDoc now follows VSCode's behavior of treating the entire block as a code block, #135. +- TypeDoc will now render members marked with `@deprecated` with a line through their name, #1381. +- Added new `commentStyle` option which can be used to control what comments TypeDoc will parse. + + | Value | Behavior | + | ----- | -------------------------------------- | + | JSDoc | Use block comments starting with `/**` | + | Block | Use all block comments | + | Line | Use `//` comments | + | All | Use both block and line comments | + +- TypeDoc will now warn if part of a comment will be overwritten due to use of `@inheritDoc` instead of silently dropping part of the comment. +- Added support for inline `@inheritDoc` tags, #1480. +- It is now possible to link directly to a specific overload, #1326. +- The JSON output will now include URLs to the file on the remote repository if possible. +- Added a new `visibilityFilters` option which controls the available filters on a page. +- TypeDoc will now try to place block elements on a new line in HTML output, resulting in less overwhelming diffs when rebuilding docs, #1923. +- Added `blockTags`, `inlineTags`, `modifierTags` to control which tags TypeDoc will allow when parsing comments. + If a tag not in in one of these options is encountered, TypeDoc will produce a warning and use context clues to determine how to parse the tag. + +### Bug Fixes + +- Fixed off by one error in warnings for types referenced but not included in the documentation. +- TypeDoc will no longer render a `Type Parameters` heading if there are no type parameters in some cases. +- Improved source location detection for constructors. +- Improved comment discovery on destructured exported functions, #1770. +- Links which refer to members within a reference reflection will now correctly resolve to the referenced reflection's member, #1770. +- Correctly detect optional parameters in JavaScript projects using JSDoc, #1804. +- Fixed identical anchor links for reflections with the same name, #1845. +- TypeDoc will now automatically inherit documentation from classes `implements` by other interfaces/classes. +- Fixed `@inheritDoc` on accessors, #1927. +- JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. +- `searchCategoryBoosts` are now correctly computed for all categories, #1960. +- The `excludeNotDocumented` option will no longer hide a module if it has a documentation comment, #1948. +- Prevent `--excludeNotDocumented` from hiding properties of type literals (`a` in `function fn(p: { a: string })`), #1752. +- Allow `cts` and `mts` extensions in packages resolution mode, #1952. +- Corrected schema generation for https://typedoc.org/schema.json + +### Thanks! + +- @aqumus +- @fb55 +- @futurGH +- @Shane4368 +- @shmax + ## v0.22.18 (2022-06-25) ### Features @@ -864,7 +950,7 @@ - Missing comments on variable functions, closes #1421 - Resolve type parameters in concrete subclasses - Use entryPoints to search for readme -- Only create extra programs when dealing with solution style tsconfigs +- Only create extra programs when dealing with solution style tsconfig.json files - A typo in description of DefaultTheme.getMapping (#1416) - Correct handling of arrays in generic constraints, closes #1408 - Type converters threw on older TS versions diff --git a/README.md b/README.md index e8d36e74e..90ba34bc2 100644 --- a/README.md +++ b/README.md @@ -79,23 +79,17 @@ For a complete list of the command line arguments run `typedoc --help` or visit Specifies the location the documentation should be written to. Defaults to `./docs` - `--json `
Specifies the location and file name a json file describing the project is - written to. When specified no documentation will be generated. + written to. When specified no documentation will be generated unless `--out` is also + specified. - `--options`
Specify a json option file that should be loaded. If not specified TypeDoc will look for 'typedoc.json' in the current directory. - `--tsconfig `
Specify a typescript config file that should be loaded. If not specified TypeDoc will look for 'tsconfig.json' in the current directory. - -#### Source file handling - - `--exclude `
Exclude files by the given pattern when a path is provided as source. Supports standard minimatch patterns. -- `--excludeNotDocumented`
- Only document items which have a doc comment. This option is useful, if you - want to document only small part of your symbols and do not show the - remaining ones in the documentation. #### Theming @@ -109,8 +103,6 @@ For a complete list of the command line arguments run `typedoc --help` or visit #### Miscellaneous -- `--listInvalidSymbolLinks`
- Display the list of links that don't point to actual code symbols. - `--version`
Display the version number of TypeDoc. - `--help`
@@ -123,9 +115,3 @@ You can find TypeDoc on GitHub; feel free to open an issue or create a pull requ https://github.com/TypeStrong/typedoc For more information, read the [contribution guide](https://github.com/TypeStrong/typedoc/blob/master/.github/CONTRIBUTING.md). - -## License - -Copyright (c) 2015 [Sebastian Lenz](https://typedoc.org).
-Copyright (c) 2016-2021 [TypeDoc Contributors](https://github.com/TypeStrong/typedoc/graphs/contributors).
-Licensed under the Apache License 2.0. diff --git a/example/typedoc.json b/example/typedoc.json index 5c68ffca2..6ebbe1921 100644 --- a/example/typedoc.json +++ b/example/typedoc.json @@ -9,6 +9,6 @@ "Model": 1.2 }, "searchGroupBoosts": { - "Class": 1.5 + "Classes": 1.5 } } diff --git a/internal-docs/custom-themes.md b/internal-docs/custom-themes.md index ab5bb545f..6ef538072 100644 --- a/internal-docs/custom-themes.md +++ b/internal-docs/custom-themes.md @@ -26,9 +26,9 @@ class MyThemeContext extends DefaultThemeRenderContext { // to destructure the context object to only grab what they care about. override analytics = () => { // Reusing existing option rather than declaring our own for brevity - if (!this.options.isSet("gaSite")) return; + if (!this.options.isSet("gaId")) return; - const site = this.options.getValue("gaSite"); + const site = this.options.getValue("gaId"); const script = ` (function() { diff --git a/package-lock.json b/package-lock.json index 4fdcf0723..d3fca28b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,14 @@ { "name": "typedoc", - "version": "0.22.18", + "version": "0.23.0-beta.7", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.22.18", + "version": "0.23.0-beta.7", "license": "Apache-2.0", "dependencies": { - "glob": "^8.0.3", "lunr": "^2.3.9", "marked": "^4.0.16", "minimatch": "^5.1.0", @@ -19,7 +18,6 @@ "typedoc": "bin/typedoc" }, "devDependencies": { - "@types/glob": "^7.2.0", "@types/lunr": "^2.3.4", "@types/marked": "^4.0.3", "@types/minimatch": "3.0.5", @@ -27,10 +25,11 @@ "@types/node": "^17.0.35", "@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/parser": "^5.26.0", + "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de", + "c8": "^7.11.3", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", - "nyc": "^15.1.0", "prettier": "2.6.2", "puppeteer": "^13.5.2", "reg-notify-github-plugin": "^0.11.1", @@ -41,262 +40,18 @@ "typescript": "^4.7.2" }, "engines": { - "node": ">= 12.10.0" + "node": ">= 14.14" }, "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" + "typescript": "4.6.x || 4.7.x" } }, - "node_modules/@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.10.4" - } - }, - "node_modules/@babel/core": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", - "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.1", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/@babel/core/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/generator": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", - "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "node_modules/@babel/generator/node_modules/source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "dependencies": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "dependencies": { - "@babel/types": "^7.11.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "dependencies": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.11.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, - "node_modules/@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "dependencies": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.11.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", - "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", - "dev": true, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "node_modules/@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - } - }, - "node_modules/@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -438,26 +193,10 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true, "engines": { "node": ">=8" @@ -565,12 +304,6 @@ "@types/node": "*" } }, - "node_modules/@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -591,6 +324,12 @@ "rxjs": "^7.2.0" } }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -937,6 +676,12 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@typestrong/fs-fixture-builder": { + "version": "0.0.0", + "resolved": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#b88cd06fe814614a0d924af9d10d04ff95a551de", + "integrity": "sha512-pPa8hDfxdpjyoKMlYlORl7yQTz6JwPUdTmZGBzsxeU7dJSTVGRXalGhSnKeCQSaUeenf0IAHW4PSuDwv/dXY1Q==", + "dev": true + }, "node_modules/@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -1059,18 +804,6 @@ "node": ">=8" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -1084,39 +817,12 @@ "node": ">= 8" } }, - "node_modules/append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "dependencies": { - "default-require-extensions": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, "node_modules/arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -1332,16 +1038,6 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -1418,6 +1114,102 @@ "node": "*" } }, + "node_modules/c8": { + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.3.tgz", + "integrity": "sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/c8/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/c8/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -1447,21 +1239,6 @@ "node": ">=0.10.0" } }, - "node_modules/caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "dependencies": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -1484,15 +1261,6 @@ "node": ">=6" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", @@ -1521,32 +1289,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -1766,21 +1508,6 @@ "node": ">=0.10.0" } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -1802,12 +1529,6 @@ "node": ">= 0.8" } }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "node_modules/component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -1997,25 +1718,6 @@ "node": ">=0.10.0" } }, - "node_modules/cpx/node_modules/fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - }, - "engines": { - "node": ">= 4.0" - } - }, "node_modules/cpx/node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -2526,18 +2228,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "node_modules/default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", - "dev": true, - "dependencies": { - "strip-bom": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -2763,12 +2453,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, "node_modules/esbuild": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", @@ -2804,294 +2488,6 @@ "esbuild-windows-arm64": "0.14.39" } }, - "node_modules/esbuild-android-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", - "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", - "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", - "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", - "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", - "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", - "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", - "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", - "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", - "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", - "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", - "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", - "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", - "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", - "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", - "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", - "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", - "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", - "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/esbuild-windows-64": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", @@ -3108,22 +2504,6 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", - "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -3419,19 +2799,6 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -3718,13 +3085,6 @@ "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "node_modules/filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -3746,23 +3106,6 @@ "node": ">=8" } }, - "node_modules/find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "dependencies": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/avajs/find-cache-dir?sponsor=1" - } - }, "node_modules/find-index": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", @@ -3888,26 +3231,6 @@ "node": ">=0.10.0" } }, - "node_modules/fromentries": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", - "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -3917,21 +3240,8 @@ "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "node_modules/function-bind": { "version": "1.1.1", @@ -3945,15 +3255,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "node_modules/gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -3977,15 +3278,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, "node_modules/get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -4028,24 +3320,6 @@ "assert-plus": "^1.0.0" } }, - "node_modules/glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", @@ -4113,15 +3387,6 @@ "node": ">= 0.10" } }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -4201,15 +3466,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -4309,19 +3565,6 @@ "node": ">=0.10.0" } }, - "node_modules/hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", - "dev": true, - "dependencies": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -4494,6 +3737,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -4502,7 +3746,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/inquirer": { "version": "8.1.5", @@ -4950,15 +4195,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -5065,64 +4301,10 @@ "dev": true }, "node_modules/istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "dependencies": { - "append-transform": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true, - "dependencies": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" - }, "engines": { "node": ">=8" } @@ -5141,24 +4323,10 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", "dev": true, "dependencies": { "html-escaper": "^2.0.0", @@ -5174,43 +4342,12 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "node_modules/jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -5235,21 +4372,6 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "node_modules/json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", @@ -5341,12 +4463,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "node_modules/lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -5897,13 +5013,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, "node_modules/nanoid": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", @@ -5997,229 +5106,34 @@ } } }, - "node_modules/node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "dependencies": { - "process-on-spawn": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/normalize-package-data": { "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "dependencies": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "bin": { - "nyc": "bin/nyc.js" - }, - "engines": { - "node": ">=8.9" - } - }, - "node_modules/nyc/node_modules/ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "dependencies": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/nyc/node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/nyc/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/nyc/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/nyc/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/nyc/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/nyc/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/nyc/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", "dev": true, "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, - "node_modules/nyc/node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "node_modules/nyc/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "node_modules/normalize-package-data/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", "dev": true, - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" + "bin": { + "semver": "bin/semver" } }, - "node_modules/nyc/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/oauth-sign": { @@ -6425,6 +5339,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "dependencies": { "wrappy": "1" } @@ -6610,18 +5525,6 @@ "node": ">=8" } }, - "node_modules/p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/p-timeout": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", @@ -6643,21 +5546,6 @@ "node": ">=6" } }, - "node_modules/package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6913,18 +5801,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "node_modules/process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "dependencies": { - "fromentries": "^1.2.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -7580,18 +6456,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "dependencies": { - "es6-error": "^4.0.1" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -7703,12 +6567,6 @@ "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "node_modules/resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", @@ -7721,15 +6579,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -7926,12 +6775,6 @@ "randombytes": "^2.1.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "node_modules/set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -8186,15 +7029,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", @@ -8216,23 +7050,6 @@ "deprecated": "See https://github.com/lydell/source-map-url#deprecated", "dev": true }, - "node_modules/spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "dependencies": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -8277,12 +7094,6 @@ "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -8450,15 +7261,6 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -8650,15 +7452,6 @@ "node": ">=0.6.0" } }, - "node_modules/to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -8835,24 +7628,6 @@ "node": ">= 0.8.0" } }, - "node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "dependencies": { - "is-typedarray": "^1.0.0" - } - }, "node_modules/typescript": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", @@ -9032,6 +7807,20 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "node_modules/v8-to-istanbul": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz", + "integrity": "sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.7", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -9122,12 +7911,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "node_modules/word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -9196,19 +7979,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "node_modules/ws": { "version": "8.5.0", @@ -9320,268 +8092,42 @@ }, "node_modules/yauzl": { "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.11", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz", - "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/core": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz", - "integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.1", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.0", - "@babel/types": "^7.11.0", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz", - "integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz", - "integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==", - "dev": true - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" } }, - "@babel/traverse": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", - "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.0", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.0", - "@babel/types": "^7.11.0", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" + "engines": { + "node": ">=6" } }, - "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } + } + }, + "dependencies": { + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true }, "@cspotcode/source-map-support": { "version": "0.8.1", @@ -9698,23 +8244,10 @@ "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "dev": true }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - } - }, "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", "dev": true }, "@jridgewell/resolve-uri": { @@ -9807,12 +8340,6 @@ "@types/node": "*" } }, - "@types/color-name": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", - "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", - "dev": true - }, "@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", @@ -9833,6 +8360,12 @@ "rxjs": "^7.2.0" } }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, "@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -10066,6 +8599,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@typestrong/fs-fixture-builder": { + "version": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#b88cd06fe814614a0d924af9d10d04ff95a551de", + "integrity": "sha512-pPa8hDfxdpjyoKMlYlORl7yQTz6JwPUdTmZGBzsxeU7dJSTVGRXalGhSnKeCQSaUeenf0IAHW4PSuDwv/dXY1Q==", + "dev": true, + "from": "@typestrong/fs-fixture-builder@github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de" + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", @@ -10151,15 +8690,6 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -10170,36 +8700,12 @@ "picomatch": "^2.0.4" } }, - "append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "requires": { - "default-require-extensions": "^3.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, "arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, "arr-diff": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", @@ -10358,16 +8864,6 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, "bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -10424,6 +8920,71 @@ "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", "dev": true }, + "c8": { + "version": "7.11.3", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.11.3.tgz", + "integrity": "sha512-6YBmsaNmqRm9OS3ZbIiL2EZgi1+Xc4O24jL3vMYGE6idixYuGdy76rIfIdltSKDj9DpLNrcXSonUTR1miBD0wA==", + "dev": true, + "requires": { + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^2.0.0", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-reports": "^3.1.4", + "rimraf": "^3.0.2", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9" + }, + "dependencies": { + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + } + } + }, "cache-base": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", @@ -10449,18 +9010,6 @@ } } }, - "caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - } - }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -10477,12 +9026,6 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "camelcase-keys": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", @@ -10507,28 +9050,6 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -10693,21 +9214,6 @@ "object-visit": "^1.0.0" } }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, "colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", @@ -10723,12 +9229,6 @@ "delayed-stream": "~1.0.0" } }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", @@ -10893,17 +9393,6 @@ } } }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, "glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -11317,15 +9806,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", - "dev": true, - "requires": { - "strip-bom": "^4.0.0" - } - }, "defaults": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", @@ -11507,12 +9987,6 @@ "is-symbol": "^1.0.2" } }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, "esbuild": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.14.39.tgz", @@ -11541,132 +10015,6 @@ "esbuild-windows-arm64": "0.14.39" } }, - "esbuild-android-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.14.39.tgz", - "integrity": "sha512-EJOu04p9WgZk0UoKTqLId9VnIsotmI/Z98EXrKURGb3LPNunkeffqQIkjS2cAvidh+OK5uVrXaIP229zK6GvhQ==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.14.39.tgz", - "integrity": "sha512-+twajJqO7n3MrCz9e+2lVOnFplRsaGRwsq1KL/uOy7xK7QdRSprRQcObGDeDZUZsacD5gUkk6OiHiYp6RzU3CA==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.14.39.tgz", - "integrity": "sha512-ImT6eUw3kcGcHoUxEcdBpi6LfTRWaV6+qf32iYYAfwOeV+XaQ/Xp5XQIBiijLeo+LpGci9M0FVec09nUw41a5g==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.14.39.tgz", - "integrity": "sha512-/fcQ5UhE05OiT+bW5v7/up1bDsnvaRZPJxXwzXsMRrr7rZqPa85vayrD723oWMT64dhrgWeA3FIneF8yER0XTw==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.14.39.tgz", - "integrity": "sha512-oMNH8lJI4wtgN5oxuFP7BQ22vgB/e3Tl5Woehcd6i2r6F3TszpCnNl8wo2d/KvyQ4zvLvCWAlRciumhQg88+kQ==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.14.39.tgz", - "integrity": "sha512-1GHK7kwk57ukY2yI4ILWKJXaxfr+8HcM/r/JKCGCPziIVlL+Wi7RbJ2OzMcTKZ1HpvEqCTBT/J6cO4ZEwW4Ypg==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.14.39.tgz", - "integrity": "sha512-g97Sbb6g4zfRLIxHgW2pc393DjnkTRMeq3N1rmjDUABxpx8SjocK4jLen+/mq55G46eE2TA0MkJ4R3SpKMu7dg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.14.39.tgz", - "integrity": "sha512-4tcgFDYWdI+UbNMGlua9u1Zhu0N5R6u9tl5WOM8aVnNX143JZoBZLpCuUr5lCKhnD0SCO+5gUyMfupGrHtfggQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.14.39.tgz", - "integrity": "sha512-t0Hn1kWVx5UpCzAJkKRfHeYOLyFnXwYynIkK54/h3tbMweGI7dj400D1k0Vvtj2u1P+JTRT9tx3AjtLEMmfVBQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.14.39.tgz", - "integrity": "sha512-23pc8MlD2D6Px1mV8GMglZlKgwgNKAO8gsgsLLcXWSs9lQsCYkIlMo/2Ycfo5JrDIbLdwgP8D2vpfH2KcBqrDQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.14.39.tgz", - "integrity": "sha512-epwlYgVdbmkuRr5n4es3B+yDI0I2e/nxhKejT9H0OLxFAlMkeQZxSpxATpDc9m8NqRci6Kwyb/SfmD1koG2Zuw==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.14.39.tgz", - "integrity": "sha512-W/5ezaq+rQiQBThIjLMNjsuhPHg+ApVAdTz2LvcuesZFMsJoQAW2hutoyg47XxpWi7aEjJGrkS26qCJKhRn3QQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.14.39.tgz", - "integrity": "sha512-IS48xeokcCTKeQIOke2O0t9t14HPvwnZcy+5baG13Z1wxs9ZrC5ig5ypEQQh4QMKxURD5TpCLHw2W42CLuVZaA==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.14.39.tgz", - "integrity": "sha512-zEfunpqR8sMomqXhNTFEKDs+ik7HC01m3M60MsEjZOqaywHu5e5682fMsqOlZbesEAAaO9aAtRBsU7CHnSZWyA==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.14.39.tgz", - "integrity": "sha512-Uo2suJBSIlrZCe4E0k75VDIFJWfZy+bOV6ih3T4MVMRJh1lHJ2UyGoaX4bOxomYN3t+IakHPyEoln1+qJ1qYaA==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.14.39.tgz", - "integrity": "sha512-secQU+EpgUPpYjJe3OecoeGKVvRMLeKUxSMGHnK+aK5uQM3n1FPXNJzyz1LHFOo0WOyw+uoCxBYdM4O10oaCAA==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.14.39.tgz", - "integrity": "sha512-qHq0t5gePEDm2nqZLb+35p/qkaXVS7oIe32R0ECh2HOdiXXkj/1uQI9IRogGqKkK+QjDG+DhwiUw7QoHur/Rwg==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.14.39.tgz", - "integrity": "sha512-XPjwp2OgtEX0JnOlTgT6E5txbRp6Uw54Isorm3CwOtloJazeIWXuiwK0ONJBVb/CGbiCpS7iP2UahGgd2p1x+Q==", - "dev": true, - "optional": true - }, "esbuild-windows-64": { "version": "0.14.39", "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.14.39.tgz", @@ -11674,13 +10022,6 @@ "dev": true, "optional": true }, - "esbuild-windows-arm64": { - "version": "0.14.39", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.14.39.tgz", - "integrity": "sha512-sBZQz5D+Gd0EQ09tZRnz/PpVdLwvp/ufMtJ1iDFYddDaPpZXKqPyaxfYBLs3ueiaksQ26GGa7sci0OqFzNs7KA==", - "dev": true, - "optional": true - }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -11896,12 +10237,6 @@ "eslint-visitor-keys": "^3.3.0" } }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, "esquery": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", @@ -12130,13 +10465,6 @@ "flat-cache": "^3.0.4" } }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", @@ -12152,17 +10480,6 @@ "to-regex-range": "^5.0.1" } }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - } - }, "find-index": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", @@ -12261,12 +10578,6 @@ "map-cache": "^0.2.2" } }, - "fromentries": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", - "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", - "dev": true - }, "fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", @@ -12276,14 +10587,8 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true }, "function-bind": { "version": "1.1.1", @@ -12297,12 +10602,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -12320,12 +10619,6 @@ "has-symbols": "^1.0.1" } }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, "get-stdin": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", @@ -12356,18 +10649,6 @@ "assert-plus": "^1.0.0" } }, - "glob": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", - "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, "glob-base": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", @@ -12422,12 +10703,6 @@ "find-index": "^0.1.1" } }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, "globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -12485,12 +10760,6 @@ "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", "dev": true }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, "has-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", @@ -12566,16 +10835,6 @@ } } }, - "hasha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.0.tgz", - "integrity": "sha512-2W+jKdQbAdSIrggA8Q35Br8qKadTrqCTC8+XZvBWepKDK6m9XkX6Iz1a2yh2KP01kzAR/dpuMeUnocoLYDcskw==", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - } - }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -12701,6 +10960,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, "requires": { "once": "^1.3.0", "wrappy": "1" @@ -12709,7 +10969,8 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "inquirer": { "version": "8.1.5", @@ -13026,12 +11287,6 @@ "has-tostringtag": "^1.0.0" } }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, "is-string": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", @@ -13111,55 +11366,11 @@ "dev": true }, "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", "dev": true }, - "istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "requires": { - "append-transform": "^2.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" - } - }, "istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", @@ -13171,21 +11382,10 @@ "supports-color": "^7.1.0" } }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - } - }, "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.4.tgz", + "integrity": "sha512-r1/DshN4KSE7xWEknZLLLLDn5CJybV3nw01VTkp6D5jzLuELlcbudfj/eSQFvrKsJuTVCGnePO7ho82Nw9zzfw==", "dev": true, "requires": { "html-escaper": "^2.0.0", @@ -13198,34 +11398,12 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, "json-schema": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", @@ -13250,15 +11428,6 @@ "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, - "json5": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", - "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, "jsonc-parser": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz", @@ -13334,12 +11503,6 @@ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -13746,13 +11909,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "nan": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", - "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", - "dev": true, - "optional": true - }, "nanoid": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", @@ -13819,15 +11975,6 @@ "whatwg-url": "^5.0.0" } }, - "node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "requires": { - "process-on-spawn": "^1.0.0" - } - }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -13854,158 +12001,6 @@ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true }, - "nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -14160,6 +12155,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, "requires": { "wrappy": "1" } @@ -14290,15 +12286,6 @@ "p-limit": "^2.2.0" } }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, "p-timeout": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", @@ -14314,18 +12301,6 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, - "package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -14510,15 +12485,6 @@ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", "dev": true }, - "process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "requires": { - "fromentries": "^1.2.0" - } - }, "progress": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", @@ -15035,15 +13001,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, "remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -15126,12 +13083,6 @@ "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", "dev": true }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "resolve": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.15.1.tgz", @@ -15141,12 +13092,6 @@ "path-parse": "^1.0.6" } }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, "resolve-url": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", @@ -15282,12 +13227,6 @@ "randombytes": "^2.1.0" } }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -15496,12 +13435,6 @@ "kind-of": "^3.2.0" } }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, "source-map-resolve": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", @@ -15521,20 +13454,6 @@ "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", "dev": true }, - "spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - } - }, "spdx-correct": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", @@ -15576,12 +13495,6 @@ "extend-shallow": "^3.0.0" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -15712,12 +13625,6 @@ "ansi-regex": "^5.0.1" } }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", @@ -15879,12 +13786,6 @@ "os-tmpdir": "~1.0.2" } }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", @@ -16013,21 +13914,6 @@ "prelude-ls": "^1.2.1" } }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, "typescript": { "version": "4.7.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.2.tgz", @@ -16172,6 +14058,17 @@ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", "dev": true }, + "v8-to-istanbul": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.0.tgz", + "integrity": "sha512-HcvgY/xaRm7isYmyx+lFKA4uQmfUbN0J4M0nNItvzTvH/iQ9kW5j/t4YSR+Ge323/lrgDAWJoF46tzGQHwBHFw==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.7", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + } + }, "validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -16250,12 +14147,6 @@ "is-symbol": "^1.0.3" } }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, "word-wrap": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", @@ -16308,19 +14199,8 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true }, "ws": { "version": "8.5.0", diff --git a/package.json b/package.json index 89b8a2114..5dc8e27e1 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,12 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.22.18", + "version": "0.23.0-beta.7", "homepage": "https://typedoc.org", "main": "./dist/index.js", - "exports": "./dist/index.js", + "exports": { + ".": "./dist/index.js" + }, "types": "./dist/index.d.ts", "bin": { "typedoc": "bin/typedoc" @@ -18,20 +20,18 @@ "url": "https://github.com/TypeStrong/TypeDoc/issues" }, "engines": { - "node": ">= 12.10.0" + "node": ">= 14.14" }, "dependencies": { - "glob": "^8.0.3", "lunr": "^2.3.9", "marked": "^4.0.16", "minimatch": "^5.1.0", "shiki": "^0.10.1" }, "peerDependencies": { - "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x || 4.7.x" + "typescript": "4.6.x || 4.7.x" }, "devDependencies": { - "@types/glob": "^7.2.0", "@types/lunr": "^2.3.4", "@types/marked": "^4.0.3", "@types/minimatch": "3.0.5", @@ -39,10 +39,11 @@ "@types/node": "^17.0.35", "@typescript-eslint/eslint-plugin": "^5.26.0", "@typescript-eslint/parser": "^5.26.0", + "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de", + "c8": "^7.11.3", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", - "nyc": "^15.1.0", "prettier": "2.6.2", "puppeteer": "^13.5.2", "reg-notify-github-plugin": "^0.11.1", @@ -57,22 +58,22 @@ "!*.map", "/dist", "!/dist/tmp", + "!/dist/.tsbuildinfo", "!/dist/test", "/LICENSE", - "/static" + "/static", + "/tsdoc.json" ], "scripts": { - "pretest": "node scripts/copy_test_files.js", - "test": "mocha -r ts-node/register --config .config/mocha.fast.json", - "pretest:full": "npm run pretest", - "test:full": "nyc mocha -r ts-node/register --config .config/mocha.full.json", + "test": "c8 mocha -r ts-node/register --config .config/mocha.fast.json", + "build:c2": "node bin/typedoc --tsconfig src/test/converter2/tsconfig.json", + "test:full": "c8 mocha -r ts-node/register --config .config/mocha.full.json", "test:visual": "node ./dist/test/capture-screenshots.js && reg-suit -c .config/regconfig.json compare", "test:visual:accept": "node scripts/accept_visual_regression.js", - "prerebuild_specs": "npm run pretest", "rebuild_specs": "node scripts/rebuild_specs.js", "build": "npm run build:tsc && npm run build:themes", "build:tsc": "tsc --project .", - "build:themes": "esbuild src/lib/output/themes/default/assets/bootstrap.ts --bundle --minify --outfile=static/main.js", + "build:themes": "node scripts/build_themes.js", "build:prod": "npm run build:prod:tsc && npm run build:themes", "build:prod:tsc": "tsc --project . --sourceMap false", "lint": "eslint . && npm run prettier -- --check .", @@ -85,18 +86,19 @@ "documentation", "generator" ], - "nyc": { + "c8": { "extension": [ ".ts", ".tsx" ], "reporter": [ - "html", + "html-spa", "text-summary" ], "exclude": [ "**/*.d.ts", - "src/test" + "src/test", + "tmp" ] } } diff --git a/scripts/build_themes.js b/scripts/build_themes.js new file mode 100644 index 000000000..39ad2d9ad --- /dev/null +++ b/scripts/build_themes.js @@ -0,0 +1,12 @@ +const esbuild = require("esbuild"); + +esbuild.buildSync({ + entryPoints: ["src/lib/output/themes/default/assets/bootstrap.ts"], + bundle: true, + minify: true, + outfile: "static/main.js", + banner: { + js: '"use strict";', + }, + logLevel: "info", +}); diff --git a/scripts/copy_test_files.js b/scripts/copy_test_files.js deleted file mode 100644 index 5dd1bcd63..000000000 --- a/scripts/copy_test_files.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check - -const { remove, copy } = require("../dist/lib/utils/fs"); -const { join } = require("path"); - -const toCopy = [ - "test/converter", - "test/converter2", - "test/module", - "test/packages", - "test/utils/options/readers/data", - "test/slow/entry-points", -]; - -const copies = toCopy.map(async (dir) => { - const source = join(__dirname, "../src", dir); - const target = join(__dirname, "../dist", dir); - await remove(target); - await copy(source, target); -}); - -Promise.all(copies).catch((reason) => { - console.error(reason); - process.exit(1); -}); diff --git a/scripts/generate_options_schema.js b/scripts/generate_options_schema.js index 460ef817d..6929bf8eb 100644 --- a/scripts/generate_options_schema.js +++ b/scripts/generate_options_schema.js @@ -24,8 +24,12 @@ addTypeDocOptions({ description: option.help, }; - switch (option.type ?? ParameterType.String) { + const type = option.type ?? ParameterType.String; + switch (type) { case ParameterType.Array: + case ParameterType.GlobArray: + case ParameterType.PathArray: + case ParameterType.ModuleArray: data.type = "array"; data.items = { type: "string" }; data.default = @@ -34,6 +38,7 @@ addTypeDocOptions({ ).defaultValue ?? []; break; case ParameterType.String: + case ParameterType.Path: data.type = "string"; if (!IGNORED_DEFAULT_OPTIONS.has(option.name)) { data.default = @@ -105,7 +110,15 @@ addTypeDocOptions({ data.default = defaults; } case ParameterType.Mixed: - break; // Nothing to do... TypeDoc really shouldn't have any of these. + data.default = + /** @type {import("../dist").MixedDeclarationOption} */ ( + option + ).defaultValue; + break; + + default: + /** @type {never} */ + let _unused = type; } schema.properties[option.name] = data; @@ -115,6 +128,26 @@ addTypeDocOptions({ schema.properties.logger.enum = ["console", "none"]; schema.properties.logger.default = "console"; +schema.properties.visibilityFilters.type = "object"; +schema.properties.visibilityFilters.properties = Object.fromEntries( + Object.keys(schema.properties.visibilityFilters.default).map((x) => [ + x, + { type: "boolean" }, + ]) +); +schema.properties.visibilityFilters.patternProperties = { + "^@": { type: "boolean" }, +}; +schema.properties.visibilityFilters.additionalProperties = false; + +schema.properties.compilerOptions.type = "object"; +schema.properties.compilerOptions.markedOptions = "object"; + +schema.properties.extends = { + type: "array", + items: { type: "string" }, +}; + const output = JSON.stringify(schema, null, "\t"); if (process.argv.length > 2) { diff --git a/scripts/rebuild_specs.js b/scripts/rebuild_specs.js index 6f5e20066..2ac03a852 100644 --- a/scripts/rebuild_specs.js +++ b/scripts/rebuild_specs.js @@ -7,28 +7,21 @@ const path = require("path"); const TypeDoc = require(".."); const { getExpandedEntryPointsForPaths } = require("../dist/lib/utils"); +const base = path.join(__dirname, "../src/test/converter"); + const app = new TypeDoc.Application(); app.options.addReader(new TypeDoc.TSConfigReader()); app.bootstrap({ name: "typedoc", excludeExternals: true, - disableSources: true, - tsconfig: path.join( - __dirname, - "..", - "dist", - "test", - "converter", - "tsconfig.json" - ), + disableSources: false, + tsconfig: path.join(base, "tsconfig.json"), externalPattern: ["**/node_modules/**"], entryPointStrategy: TypeDoc.EntryPointStrategy.Expand, + logLevel: TypeDoc.LogLevel.Warn, + gitRevision: "fake", }); -// Note that this uses the test files in dist, not in src, this is important since -// when running the tests we copy the tests to dist and then convert them. -const base = path.join(__dirname, "../dist/test/converter"); - /** @type {[string, () => void, () => void][]} */ const conversions = [ [ @@ -90,29 +83,23 @@ function rebuildConverterTests(dirs) { .split(TypeDoc.normalizePath(base)) .join("%BASE%") + "\n"; after(); - fs.writeFileSync(out.replace("dist", "src"), data); + fs.writeFileSync(out, data); } } } } async function main(filter = "") { - const dirs = await Promise.all( - ( - await fs.promises.readdir(base) - ).map((dir) => { - const dirPath = path.join(base, dir); - return Promise.all([dirPath, fs.promises.stat(dirPath)]); - }) - ); + console.log("Base directory is", base); + const dirs = await fs.promises.readdir(base, { withFileTypes: true }); await rebuildConverterTests( dirs - .filter(([fullPath, stat]) => { - if (!stat.isDirectory()) return false; - return fullPath.endsWith(filter); + .filter((dir) => { + if (!dir.isDirectory()) return false; + return dir.name.endsWith(filter); }) - .map(([path]) => path) + .map((dir) => path.join(base, dir.name)) ); } diff --git a/src/index.ts b/src/index.ts index fb6dc1db4..f75b8748d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ export { EventDispatcher, Event } from "./lib/utils/events"; export { resetReflectionID } from "./lib/models/reflections/abstract"; export { normalizePath } from "./lib/utils/fs"; export * from "./lib/models"; -export { Converter, Context } from "./lib/converter"; +export { Converter, Context, type CommentParserConfig } from "./lib/converter"; export { Renderer, @@ -21,6 +21,7 @@ export type { RenderTemplate, RendererHooks } from "./lib/output"; export { ArgumentsReader, BindOption, + CommentStyle, JSX, LogLevel, Logger, @@ -53,6 +54,7 @@ export type { SortStrategy, ParameterTypeToOptionTypeMap, DocumentationEntryPoint, + ManuallyValidatedOption, } from "./lib/utils"; export type { EventMap, EventCallback } from "./lib/utils/events"; @@ -60,7 +62,7 @@ export type { EventMap, EventCallback } from "./lib/utils/events"; export { JSONOutput, Serializer, - SerializerComponent, + type SerializerComponent, SerializeEvent, } from "./lib/serialization"; export type { SerializeEventData } from "./lib/serialization"; diff --git a/src/lib/application.ts b/src/lib/application.ts index f9bc913ea..d4d7282d2 100644 --- a/src/lib/application.ts +++ b/src/lib/application.ts @@ -12,7 +12,6 @@ import { loadPlugins, writeFile, discoverPlugins, - NeverIfInternal, TSConfigReader, } from "./utils/index"; @@ -23,8 +22,7 @@ import { } from "./utils/component"; import { Options, BindOption } from "./utils"; import type { TypeDocOptions } from "./utils/options/declaration"; -import { flatMap, unique } from "./utils/array"; -import { validateExports } from "./validation/exports"; +import { unique } from "./utils/array"; import { ok } from "assert"; import { DocumentationEntryPoint, @@ -34,7 +32,9 @@ import { } from "./utils/entry-point"; import { nicePath } from "./utils/paths"; import { hasBeenLoadedMultipleTimes } from "./utils/general"; +import { validateExports } from "./validation/exports"; import { validateDocumentation } from "./validation/documentation"; +import { validateLinks } from "./validation/links"; // eslint-disable-next-line @typescript-eslint/no-var-requires const packageInfo = require("../../package.json") as { @@ -157,16 +157,6 @@ export class Application extends ChildableComponent< } } - /** - * Return the application / root component instance. - */ - override get application(): NeverIfInternal { - this.logger.deprecated( - "Application.application is deprecated. Plugins are now passed the application instance when loaded." - ); - return this as never; - } - /** * Return the path to the TypeScript compiler. */ @@ -224,16 +214,15 @@ export class Application extends ChildableComponent< `Converting with ${programs.length} programs ${entryPoints.length} entry points` ); - const errors = flatMap([...programs], ts.getPreEmitDiagnostics); + const errors = programs.flatMap((program) => + ts.getPreEmitDiagnostics(program) + ); if (errors.length) { this.logger.diagnostics(errors); return; } - if ( - this.options.getValue("emit") === "both" || - this.options.getValue("emit") === true - ) { + if (this.options.getValue("emit") === "both") { for (const program of programs) { program.emit(); } @@ -343,10 +332,7 @@ export class Application extends ChildableComponent< } if (successFinished) { - if ( - this.options.getValue("emit") === "both" || - this.options.getValue("emit") === true - ) { + if (this.options.getValue("emit") === "both") { currentProgram.emit(); } @@ -408,6 +394,7 @@ export class Application extends ChildableComponent< validate(project: ProjectReflection) { const checks = this.options.getValue("validation"); + const start = Date.now(); if (checks.notExported) { validateExports( @@ -425,9 +412,11 @@ export class Application extends ChildableComponent< ); } - // checks.invalidLink is currently handled when rendering by the MarkedLinksPlugin. - // It should really move here, but I'm putting that off until done refactoring the comment - // parsing so that we don't have duplicate parse logic all over the place. + if (checks.invalidLink) { + validateLinks(project, this.logger); + } + + this.logger.verbose(`Validation took ${Date.now() - start}ms`); } /** diff --git a/src/lib/converter/comments/blockLexer.ts b/src/lib/converter/comments/blockLexer.ts new file mode 100644 index 000000000..80f33e365 --- /dev/null +++ b/src/lib/converter/comments/blockLexer.ts @@ -0,0 +1,380 @@ +import { Token, TokenSyntaxKind } from "./lexer"; + +export function* lexBlockComment( + file: string, + pos = 0, + end = file.length +): Generator { + // Wrapper around our real lex function to collapse adjacent text tokens. + let textToken: Token | undefined; + for (const token of lexBlockComment2(file, pos, end)) { + if (token.kind === TokenSyntaxKind.Text) { + if (textToken) { + textToken.text += token.text; + } else { + textToken = token; + } + } else { + if (textToken) { + yield textToken; + textToken = void 0; + } + yield token; + } + } + + if (textToken) { + yield textToken; + } + return; +} + +function* lexBlockComment2( + file: string, + pos: number, + end: number +): Generator { + pos += 2; // Leading '/*' + end -= 2; // Trailing '*/' + + if (pos < end && file[pos] === "*") { + // Might start with '/**' + pos++; + } + + // Before skipping whitespace, figure out the comment indent size + const [commentHasStars, indent] = discoverIndent(file, pos, end); + + // Skip leading whitespace + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + + // Trailing whitespace + while (pos < end && /\s/.test(file[end - 1])) { + end--; + } + + let lineStart = true; + let braceStartsType = false; + + for (;;) { + if (pos >= end) { + return; + } + + if (lineStart) { + pos = skipIndent(pos); + if (commentHasStars && file[pos] === "*") { + pos++; + if (file[pos] === " ") { + pos++; + } + } + lineStart = false; + } + + switch (file[pos]) { + case "\n": + yield makeToken(TokenSyntaxKind.NewLine, 1); + lineStart = true; + break; + + case "{": + if (braceStartsType && nextNonWs(pos + 1) !== "@") { + yield makeToken( + TokenSyntaxKind.TypeAnnotation, + findEndOfType(pos) - pos + ); + braceStartsType = false; + } else { + yield makeToken(TokenSyntaxKind.OpenBrace, 1); + } + break; + + case "}": + yield makeToken(TokenSyntaxKind.CloseBrace, 1); + braceStartsType = false; + break; + + case "`": { + // Markdown's code rules are a royal pain. This could be one of several things. + // 1. Inline code: <1-n ticks> + // 2. Code block: <3 ticks>\n\n<3 ticks>\n + // 3. Unmatched tick(s), not code, but part of some text. + // We don't quite handle #2 correctly yet. PR welcome! + braceStartsType = false; + let tickCount = 1; + let lookahead = pos; + + while (lookahead + 1 < end && file[lookahead + 1] === "`") { + tickCount++; + lookahead++; + } + let lookaheadStart = pos; + const codeText: string[] = []; + + lookahead++; + while (lookahead < end) { + if (lookaheadExactlyNTicks(lookahead, tickCount)) { + lookahead += tickCount; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + break; + } else if (file[lookahead] === "`") { + while (lookahead < end && file[lookahead] === "`") { + lookahead++; + } + } else if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + file[lookahead + 1] === "/" + ) { + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + lookaheadStart = lookahead + 1; + lookahead += 2; + } else if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + file[lookahead + 1] !== "\n" + ) { + lookahead += 2; + } else if (file[lookahead] === "\n") { + lookahead++; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + lookahead = skipIndent(lookahead); + if (commentHasStars && file[lookahead] === "*") { + lookahead++; + if (file[lookahead] === " ") { + lookahead++; + } + } + lookaheadStart = lookahead; + } else { + lookahead++; + } + } + + if (lookahead >= end && pos !== lookahead) { + if ( + tickCount === 3 && + file.substring(pos, end).includes("\n") + ) { + codeText.push(file.substring(lookaheadStart, end)); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + } else { + yield makeToken(TokenSyntaxKind.Text, tickCount); + } + } + + break; + } + + case "@": { + let lookahead = pos + 1; + while (lookahead < end && /[a-z]/i.test(file[lookahead])) { + lookahead++; + } + + if (lookahead !== pos + 1) { + while ( + lookahead < end && + /[a-z0-9]/i.test(file[lookahead]) + ) { + lookahead++; + } + } + + if (lookahead !== pos + 1) { + braceStartsType = true; + yield makeToken(TokenSyntaxKind.Tag, lookahead - pos); + break; + } + } + // fall through if we didn't find something that looks like a tag + + default: { + const textParts: string[] = []; + + let lookaheadStart = pos; + let lookahead = pos; + while (lookahead < end) { + if ("{}\n`".includes(file[lookahead])) break; + + if ( + lookahead !== pos && + file[lookahead] === "@" && + /\s/.test(file[lookahead - 1]) + ) { + // Probably the start of a modifier tag + break; + } + + if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + "{}@/`".includes(file[lookahead + 1]) + ) { + textParts.push( + file.substring(lookaheadStart, lookahead), + file[lookahead + 1] + ); + lookahead++; + lookaheadStart = lookahead + 1; + } + + lookahead++; + } + + textParts.push(file.substring(lookaheadStart, lookahead)); + + if (textParts.some((part) => /\S/.test(part))) { + braceStartsType = false; + } + + pos = lookahead; + // This piece of text had line continuations or escaped text + yield { + kind: TokenSyntaxKind.Text, + text: textParts.join(""), + }; + break; + } + } + } + + function makeToken(kind: TokenSyntaxKind, size: number): Token { + const start = pos; + pos += size; + + return { + kind, + text: file.substring(start, pos), + }; + } + + function skipIndent(pos: number) { + let taken = indent; + let lookahead = pos; + while ( + taken > 0 && + lookahead < end && + file[lookahead] !== "\n" && + /\s/.test(file[lookahead]) + ) { + taken--; + lookahead++; + } + return lookahead; + } + + function lookaheadExactlyNTicks(pos: number, n: number) { + if (pos + n > end) { + return false; + } + + return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`"; + } + + function findEndOfType(pos: number): number { + let openBraces = 0; + + while (pos < end) { + if (file[pos] === "{") { + openBraces++; + } else if (file[pos] === "}") { + if (--openBraces === 0) { + break; + } + } else if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos); + } + + pos++; + } + + if (pos < end && file[pos] === "}") { + pos++; + } + + return pos; + } + + function findEndOfString(pos: number): number { + const endOfString = file[pos]; + pos++; + while (pos < end) { + if (file[pos] === endOfString) { + break; + } else if (file[pos] === "\\") { + pos++; // Skip escaped character + } else if ( + endOfString === "`" && + file[pos] === "$" && + file[pos + 1] === "{" + ) { + // Template literal with data inside a ${} + while (pos < end && file[pos] !== "}") { + if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos) + 1; + } else { + pos++; + } + } + } + + pos++; + } + + return pos; + } + + function nextNonWs(pos: number): string | undefined { + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + return file[pos]; + } +} + +function discoverIndent( + file: string, + pos: number, + end: number +): [boolean, number] { + let indent = 0; + + while (pos < end && file[pos] !== "\n") { + pos++; + } + + outer: while (pos < end) { + pos++; + const lineStart = pos; + while (pos < end && file[pos] !== "\n") { + if (/\S/.test(file[pos])) { + indent = pos - lineStart; + break outer; + } + pos++; + } + } + + const commentHasStars = pos < end && file[pos] === "*"; + + return [commentHasStars, indent]; +} diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts new file mode 100644 index 000000000..29c126e49 --- /dev/null +++ b/src/lib/converter/comments/declarationReference.ts @@ -0,0 +1,449 @@ +/** + * Parser for declaration references, see the [TSDoc grammar](https://github.com/microsoft/tsdoc/blob/main/tsdoc/src/beta/DeclarationReference.grammarkdown) + * for reference. TypeDoc **does not** support the full grammar today. This is intentional, since the TSDoc + * specified grammar allows the user to construct nonsensical declaration references such as `abc![def!ghi]` + * + * @module + */ + +import type { Chars } from "../../utils"; + +export const MeaningKeywords = [ + "class", // SymbolFlags.Class + "interface", // SymbolFlags.Interface + "type", // SymbolFlags.TypeAlias + "enum", // SymbolFlags.Enum + "namespace", // SymbolFlags.Module + "function", // SymbolFlags.Function + "var", // SymbolFlags.Variable + "constructor", // SymbolFlags.Constructor + "member", // SymbolFlags.ClassMember | SymbolFlags.EnumMember + "event", // + "call", // SymbolFlags.Signature (for __call) + "new", // SymbolFlags.Signature (for __new) + "index", // SymbolFlags.Signature (for __index) + "complex", // Any complex type +] as const; +export type MeaningKeyword = typeof MeaningKeywords[number]; + +export interface DeclarationReference { + resolutionStart: "global" | "local"; + moduleSource?: string; + symbolReference?: SymbolReference; +} + +export interface Meaning { + keyword?: MeaningKeyword; + label?: string; + index?: number; +} + +export interface SymbolReference { + path?: ComponentPath[]; + meaning?: Meaning; +} + +export interface ComponentPath { + /** + * How to resolve the `path` + * - `.` - Navigate via `exports` of symbol + * - `#` - Navigate via `members` of symbol + * - `~` - Navigate via `locals` of symbol + */ + navigation: "." | "#" | "~"; + path: string; +} + +// +const WhiteSpace = /[\t\u2B7F\u240C \u00A0\uFEFF\p{White_Space}]/u; +const LineTerminator = "\r\n\u2028\u2029"; +const Punctuators = "{}()[]!.#~:,"; +const FutureReservedPunctuator = "{}@"; +const NavigationPunctuator = ".#~"; +const DecimalDigit = "0123456789"; +const HexDigit = DecimalDigit + "abcdefABCDEF"; +const SingleEscapeCharacter = `'"\\bfnrtv`; +const EscapeCharacter = SingleEscapeCharacter + DecimalDigit + "xu"; +const UserLabelStart = "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"; +const UserLabelCharacter = UserLabelStart + DecimalDigit; + +const SingleEscapeChars: Record, string> = { + "'": "'", + '"': '"', + "\\": "\\", + b: "\b", + f: "\f", + n: "\n", + r: "\r", + t: "\t", + v: "\v", +}; + +// EscapeSequence:: +// SingleEscapeCharacter +// NonEscapeCharacter +// `0` [lookahead != DecimalDigit] +// HexEscapeSequence +// UnicodeEscapeSequence +function parseEscapeSequence( + source: string, + pos: number, + end: number +): [string, number] | undefined { + // SingleEscapeCharacter + if (SingleEscapeCharacter.includes(source[pos])) { + return [SingleEscapeChars[source[pos] as "b"], pos + 1]; + } + + // NonEscapeCharacter:: SourceCharacter but not one of EscapeCharacter or LineTerminator + if (!(EscapeCharacter + LineTerminator).includes(source[pos])) { + return [source[pos], pos + 1]; + } + + // `0` [lookahead != DecimalDigit] + if ( + source[pos] === "0" && + pos + 1 < end && + !DecimalDigit.includes(source[pos + 1]) + ) { + return ["\x00", pos + 1]; + } + + // HexEscapeSequence:: x HexDigit HexDigit + if ( + source[pos] === "x" && + pos + 2 < end && + HexDigit.includes(source[pos + 1]) && + HexDigit.includes(source[pos + 2]) + ) { + return [ + String.fromCharCode( + parseInt(source.substring(pos + 1, pos + 3), 16) + ), + pos + 3, + ]; + } + + return parseUnicodeEscapeSequence(source, pos, end); +} + +// UnicodeEscapeSequence:: +// `u` HexDigit HexDigit HexDigit HexDigit +// `u` `{` CodePoint `}` +// CodePoint:: > |HexDigits| but only if MV of |HexDigits| ≤ 0x10FFFF +function parseUnicodeEscapeSequence( + source: string, + pos: number, + end: number +): [string, number] | undefined { + if (source[pos] !== "u" || pos + 1 >= end) { + return; + } + + if (HexDigit.includes(source[pos + 1])) { + if ( + pos + 4 >= end || + !HexDigit.includes(source[pos + 2]) || + !HexDigit.includes(source[pos + 3]) || + !HexDigit.includes(source[pos + 4]) + ) { + return; + } + + return [ + String.fromCharCode( + parseInt(source.substring(pos + 1, pos + 5), 16) + ), + pos + 5, + ]; + } + + if ( + source[pos + 1] === "{" && + pos + 2 < end && + HexDigit.includes(source[pos + 2]) + ) { + let lookahead = pos + 3; + + while (lookahead < end && HexDigit.includes(source[lookahead])) { + lookahead++; + } + + if (lookahead >= end || source[lookahead] !== "}") return; + + const codePoint = parseInt(source.substring(pos + 2, lookahead), 16); + if (codePoint <= 0x10ffff) { + return [String.fromCodePoint(codePoint), lookahead + 1]; + } + } +} + +// String:: `"` StringCharacters? `"` +// StringCharacters:: StringCharacter StringCharacters? +// StringCharacter:: +// SourceCharacter but not one of `"` or `\` or LineTerminator +// `\` EscapeSequence +export function parseString( + source: string, + pos: number, + end: number +): [string, number] | undefined { + let result = ""; + + if (source[pos++] !== '"') return; + + while (pos < end) { + if (source[pos] === '"') { + return [result, pos + 1]; + } + + if (LineTerminator.includes(source[pos])) return; + + if (source[pos] === "\\") { + const esc = parseEscapeSequence(source, pos + 1, end); + if (!esc) return; + + result += esc[0]; + pos = esc[1]; + continue; + } + + result += source[pos++]; + } +} + +// ModuleSource:: String | ModuleSourceCharacters +export function parseModuleSource( + source: string, + pos: number, + end: number +): [string, number] | undefined { + if (pos >= end) return; + + if (source[pos] === '"') { + return parseString(source, pos, end); + } + + let lookahead = pos; + while ( + lookahead < end && + !('"!' + LineTerminator).includes(source[lookahead]) + ) { + lookahead++; + } + + if (lookahead === pos) return; + + return [source.substring(pos, lookahead), lookahead]; +} + +// SymbolReference: +// ComponentPath Meaning? +// Meaning +export function parseSymbolReference( + source: string, + pos: number, + end: number +): [SymbolReference, number] | undefined { + const path = parseComponentPath(source, pos, end); + pos = path?.[1] ?? pos; + + const meaning = parseMeaning(source, pos, end); + pos = meaning?.[1] ?? pos; + + if (path || meaning) { + return [{ path: path?.[0], meaning: meaning?.[0] }, pos]; + } +} + +// Component:: +// String +// ComponentCharacters +// `[` DeclarationReference `]` <--- THIS ONE IS NOT IMPLEMENTED. +export function parseComponent( + source: string, + pos: number, + end: number +): [string, number] | undefined { + if (pos < end && source[pos] === '"') { + return parseString(source, pos, end); + } + + let lookahead = pos; + while ( + lookahead < end && + !( + '"' + + Punctuators + + FutureReservedPunctuator + + LineTerminator + ).includes(source[lookahead]) && + !WhiteSpace.test(source[lookahead]) + ) { + lookahead++; + } + + if (lookahead === pos) return; + + return [source.substring(pos, lookahead), lookahead]; +} + +// ComponentPath: +// Component +// ComponentPath `.` Component // Navigate via 'exports' of |ComponentPath| +// ComponentPath `#` Component // Navigate via 'members' of |ComponentPath| +// ComponentPath `~` Component // Navigate via 'locals' of |ComponentPath| +export function parseComponentPath(source: string, pos: number, end: number) { + const components: ComponentPath[] = []; + let component = parseComponent(source, pos, end); + + if (!component) return; + pos = component[1]; + components.push({ navigation: ".", path: component[0] }); + + while (pos < end && NavigationPunctuator.includes(source[pos])) { + const navigation = source[pos] as "." | "#" | "~"; + pos++; + component = parseComponent(source, pos, end); + if (!component) { + return; + } + + pos = component[1]; + components.push({ navigation, path: component[0] }); + } + + return [components, pos] as const; +} + +// The TSDoc specification permits the first four branches of Meaning. TypeDoc adds the UserLabel +// branch so that the @label tag can be used with this form of declaration references. +// Meaning: +// `:` MeaningKeyword // Indicates the meaning of a symbol (i.e. ':class') +// `:` MeaningKeyword `(` DecimalDigits `)` // Indicates an overloaded meaning (i.e. ':function(1)') +// `:` `(` DecimalDigits `)` // Shorthand for an overloaded meaning (i.e. `:(1)`) +// `:` DecimalDigits // Shorthand for an overloaded meaning (i.e. ':1') +// `:` UserLabel // Indicates a user defined label via {@label CUSTOM_LABEL} +// +// UserLabel: +// UserLabelStart UserLabelCharacter* +export function parseMeaning( + source: string, + pos: number, + end: number +): [Meaning, number] | undefined { + if (source[pos++] !== ":") return; + + const keyword = MeaningKeywords.find( + (kw) => pos + kw.length <= end && source.startsWith(kw, pos) + ); + + if (keyword) { + pos += keyword.length; + } + + if (!keyword && UserLabelStart.includes(source[pos])) { + let lookahead = pos + 1; + + while ( + lookahead < end && + UserLabelCharacter.includes(source[lookahead]) + ) { + lookahead++; + } + + return [{ label: source.substring(pos, lookahead) }, lookahead]; + } + + if ( + pos + 1 < end && + source[pos] === "(" && + DecimalDigit.includes(source[pos + 1]) + ) { + let lookahead = pos + 1; + + while (lookahead < end && DecimalDigit.includes(source[lookahead])) { + lookahead++; + } + + if (lookahead < end && source[lookahead] === ")") { + return [ + { + keyword, + index: parseInt(source.substring(pos + 1, lookahead)), + }, + lookahead + 1, + ]; + } + } + + if (!keyword && pos < end && DecimalDigit.includes(source[pos])) { + let lookahead = pos; + + while (lookahead < end && DecimalDigit.includes(source[lookahead])) { + lookahead++; + } + + return [ + { + index: parseInt(source.substring(pos, lookahead)), + }, + lookahead, + ]; + } + + if (keyword) { + return [{ keyword }, pos]; + } +} + +// // NOTE: The following grammar is incorrect as |SymbolReference| and |ModuleSource| have an +// // ambiguous parse. The correct solution is to use a cover grammar to parse +// // |SymbolReference| until we hit a `!` and then reinterpret the grammar. +// DeclarationReference: +// [empty] +// SymbolReference // Shorthand reference to symbol +// ModuleSource `!` // Reference to a module +// ModuleSource `!` SymbolReference // Reference to an export of a module +// ModuleSource `!` `~` SymbolReference // Reference to a local of a module +// `!` SymbolReference // Reference to global symbol +export function parseDeclarationReference( + source: string, + pos: number, + end: number +): [DeclarationReference, number] | undefined { + let moduleSource: string | undefined; + let symbolReference: SymbolReference | undefined; + let resolutionStart: "global" | "local" = "local"; + + const moduleSourceOrSymbolRef = parseModuleSource(source, pos, end); + if (moduleSourceOrSymbolRef) { + if ( + moduleSourceOrSymbolRef[1] < end && + source[moduleSourceOrSymbolRef[1]] === "!" + ) { + // We had a module source! + pos = moduleSourceOrSymbolRef[1] + 1; + resolutionStart = "global"; + moduleSource = moduleSourceOrSymbolRef[0]; + } + } else if (source[pos] === "!") { + pos++; + resolutionStart = "global"; + } + + const ref = parseSymbolReference(source, pos, end); + if (ref) { + symbolReference = ref[0]; + pos = ref[1]; + } + + return [ + { + moduleSource, + resolutionStart, + symbolReference, + }, + pos, + ]; +} diff --git a/src/lib/converter/comments/declarationReferenceResolver.ts b/src/lib/converter/comments/declarationReferenceResolver.ts new file mode 100644 index 000000000..c30b9fd04 --- /dev/null +++ b/src/lib/converter/comments/declarationReferenceResolver.ts @@ -0,0 +1,225 @@ +import { ok } from "assert"; +import { + ContainerReflection, + DeclarationReflection, + Reflection, + ReflectionKind, +} from "../../models"; +import { filterMap } from "../../utils"; +import type { + ComponentPath, + DeclarationReference, + Meaning, + MeaningKeyword, +} from "./declarationReference"; + +export function resolveDeclarationReference( + reflection: Reflection, + ref: DeclarationReference +): Reflection | undefined { + let high: Reflection[] = []; + let low: Reflection[] = []; + + if (ref.moduleSource) { + high = + reflection.project.children?.filter( + (c) => + c.kindOf(ReflectionKind.SomeModule) && + c.name === ref.moduleSource + ) || []; + } else if (ref.resolutionStart === "global") { + high.push(reflection.project); + } else { + ok(ref.resolutionStart === "local"); + // TypeScript's behavior is to first try to resolve links via variable scope, and then + // if the link still hasn't been found, check either siblings (if comment belongs to a member) + // or otherwise children. + let refl: Reflection | undefined = reflection; + if (refl.kindOf(ReflectionKind.ExportContainer)) { + high.push(refl); + } + while (refl.parent) { + refl = refl.parent; + if (refl.kindOf(ReflectionKind.ExportContainer)) { + high.push(refl); + } + } + + if (reflection.kindOf(ReflectionKind.SomeMember)) { + high.push(reflection.parent!); + } else if ( + reflection.kindOf(ReflectionKind.SomeSignature) && + reflection.parent!.kindOf(ReflectionKind.SomeMember) + ) { + high.push(reflection.parent!.parent!); + } else if (high[0] !== reflection) { + high.push(reflection); + } + } + + if (ref.symbolReference) { + for (const part of ref.symbolReference.path || []) { + const high2 = high; + high = []; + const low2 = low; + low = []; + + for (const refl of high2) { + const resolved = resolveSymbolReferencePart(refl, part); + high.push(...resolved.high); + low.push(...resolved.low); + } + + for (const refl of low2) { + const resolved = resolveSymbolReferencePart(refl, part); + low.push(...resolved.high); + low.push(...resolved.low); + } + } + + if (ref.symbolReference.meaning) { + high = filterMapByMeaning(high, ref.symbolReference.meaning); + low = filterMapByMeaning(low, ref.symbolReference.meaning); + } + } + + return high[0] || low[0]; +} + +function filterMapByMeaning( + reflections: Reflection[], + meaning: Meaning +): Reflection[] { + return filterMap(reflections, (refl): Reflection | undefined => { + const kwResolved = resolveKeyword(refl, meaning.keyword) || []; + if (meaning.label) { + return kwResolved.find((r) => r.label === meaning.label); + } + return kwResolved[meaning.index || 0]; + }); +} + +function resolveKeyword( + refl: Reflection, + kw: MeaningKeyword | undefined +): Reflection[] | undefined { + switch (kw) { + case undefined: + return refl instanceof DeclarationReflection && refl.signatures + ? refl.signatures + : [refl]; + case "class": + if (refl.kindOf(ReflectionKind.Class)) return [refl]; + break; + case "interface": + if (refl.kindOf(ReflectionKind.Interface)) return [refl]; + break; + case "type": + if (refl.kindOf(ReflectionKind.SomeType)) return [refl]; + break; + case "enum": + if (refl.kindOf(ReflectionKind.Enum)) return [refl]; + break; + case "namespace": + if (refl.kindOf(ReflectionKind.SomeModule)) return [refl]; + break; + case "function": + if (refl.kindOf(ReflectionKind.FunctionOrMethod)) { + return (refl as DeclarationReflection).signatures; + } + break; + case "var": + if (refl.kindOf(ReflectionKind.Variable)) return [refl]; + break; + + case "new": + case "constructor": + if ( + refl.kindOf( + ReflectionKind.ClassOrInterface | ReflectionKind.TypeLiteral + ) + ) { + const ctor = (refl as ContainerReflection).children?.find((c) => + c.kindOf(ReflectionKind.Constructor) + ); + return (ctor as DeclarationReflection)?.signatures; + } + break; + + case "member": + if (refl.kindOf(ReflectionKind.SomeMember)) return [refl]; + break; + case "event": + // Never resolve. Nobody should use this. + // It's required by the grammar, but is not documented by TypeDoc + // nor by the comments in the grammar. + break; + case "call": + return (refl as DeclarationReflection).signatures; + + case "index": + if ((refl as DeclarationReflection).indexSignature) { + return [(refl as DeclarationReflection).indexSignature!]; + } + break; + + case "complex": + if (refl.kindOf(ReflectionKind.SomeType)) return [refl]; + break; + } +} + +function resolveSymbolReferencePart( + refl: Reflection, + path: ComponentPath +): { high: Reflection[]; low: Reflection[] } { + let high: Reflection[] = []; + let low: Reflection[] = []; + + if (!(refl instanceof ContainerReflection) || !refl.children) { + return { high, low }; + } + + switch (path.navigation) { + // Grammar says resolve via "exports"... as always, reality is more complicated. + // Check exports first, but also allow this as a general purpose "some child" operator + // so that resolution doesn't behave very poorly with projects using JSDoc style resolution. + // Also is more consistent with how TypeScript resolves link tags. + case ".": + high = refl.children.filter( + (r) => + r.name === path.path && + (r.kindOf(ReflectionKind.SomeExport) || r.flags.isStatic) + ); + low = refl.children.filter( + (r) => + r.name === path.path && + (!r.kindOf(ReflectionKind.SomeExport) || !r.flags.isStatic) + ); + break; + + // Resolve via "members", interface children, class instance properties/accessors/methods, + // enum members, type literal properties + case "#": + high = refl.children.filter((r) => { + return ( + r.name === path.path && + r.kindOf(ReflectionKind.SomeMember) && + !r.flags.isStatic + ); + }); + break; + + // Resolve via "locals"... treat this as a stricter `.` which only supports traversing + // module/namespace exports since TypeDoc doesn't support documenting locals. + case "~": + if ( + refl.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project) + ) { + high = refl.children.filter((r) => r.name === path.path); + } + break; + } + + return { high, low }; +} diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts new file mode 100644 index 000000000..facd7dcbe --- /dev/null +++ b/src/lib/converter/comments/discovery.ts @@ -0,0 +1,313 @@ +import * as ts from "typescript"; +import { ReflectionKind } from "../../models"; +import { assertNever, Logger } from "../../utils"; +import { CommentStyle } from "../../utils/options/declaration"; +import { nicePath } from "../../utils/paths"; + +// Note: This does NOT include JSDoc syntax kinds. This is important! +// Comments from @typedef and @callback tags are handled specially by +// the JSDoc converter because we only want part of the comment when +// getting them. +const wantedKinds: Record = { + [ReflectionKind.Project]: [ts.SyntaxKind.SourceFile], + [ReflectionKind.Module]: [ts.SyntaxKind.SourceFile], + [ReflectionKind.Namespace]: [ + ts.SyntaxKind.ModuleDeclaration, + ts.SyntaxKind.SourceFile, + ts.SyntaxKind.BindingElement, + ts.SyntaxKind.ExportSpecifier, + ], + [ReflectionKind.Enum]: [ + ts.SyntaxKind.EnumDeclaration, + ts.SyntaxKind.VariableDeclaration, + ], + [ReflectionKind.EnumMember]: [ + ts.SyntaxKind.EnumMember, + // These here so that @enum gets comments + ts.SyntaxKind.PropertyAssignment, + ts.SyntaxKind.PropertySignature, + ], + [ReflectionKind.Variable]: [ + ts.SyntaxKind.VariableDeclaration, + ts.SyntaxKind.BindingElement, + ts.SyntaxKind.ExportAssignment, + ], + [ReflectionKind.Function]: [ + ts.SyntaxKind.FunctionDeclaration, + ts.SyntaxKind.BindingElement, + ], + [ReflectionKind.Class]: [ + ts.SyntaxKind.ClassDeclaration, + ts.SyntaxKind.BindingElement, + ], + [ReflectionKind.Interface]: [ts.SyntaxKind.InterfaceDeclaration], + [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor], + [ReflectionKind.Property]: [ + ts.SyntaxKind.PropertyDeclaration, + ts.SyntaxKind.PropertySignature, + ts.SyntaxKind.BinaryExpression, + ts.SyntaxKind.PropertyAssignment, + ], + [ReflectionKind.Method]: [ + ts.SyntaxKind.FunctionDeclaration, + ts.SyntaxKind.MethodDeclaration, + ], + [ReflectionKind.CallSignature]: [ + ts.SyntaxKind.FunctionDeclaration, + ts.SyntaxKind.VariableDeclaration, + ts.SyntaxKind.MethodDeclaration, + ts.SyntaxKind.MethodDeclaration, + ts.SyntaxKind.PropertyDeclaration, + ts.SyntaxKind.PropertySignature, + ts.SyntaxKind.CallSignature, + ], + [ReflectionKind.IndexSignature]: [ts.SyntaxKind.IndexSignature], + [ReflectionKind.ConstructorSignature]: [ts.SyntaxKind.ConstructSignature], + [ReflectionKind.Parameter]: [ts.SyntaxKind.Parameter], + [ReflectionKind.TypeLiteral]: [ts.SyntaxKind.TypeLiteral], + [ReflectionKind.TypeParameter]: [ts.SyntaxKind.TypeParameter], + [ReflectionKind.Accessor]: [ + ts.SyntaxKind.GetAccessor, + ts.SyntaxKind.SetAccessor, + ], + [ReflectionKind.GetSignature]: [ts.SyntaxKind.GetAccessor], + [ReflectionKind.SetSignature]: [ts.SyntaxKind.SetAccessor], + [ReflectionKind.ObjectLiteral]: [ts.SyntaxKind.ObjectLiteralExpression], + [ReflectionKind.TypeAlias]: [ts.SyntaxKind.TypeAliasDeclaration], + [ReflectionKind.Reference]: [ + ts.SyntaxKind.NamespaceExport, + ts.SyntaxKind.ExportSpecifier, + ], +}; + +export function discoverComment( + symbol: ts.Symbol, + kind: ReflectionKind, + logger: Logger, + commentStyle: CommentStyle +): [ts.SourceFile, ts.CommentRange[]] | undefined { + // For a module comment, we want the first one defined in the file, + // not the last one, since that will apply to the import or declaration. + const reverse = symbol.declarations?.some(ts.isSourceFile); + + const discovered: [ts.SourceFile, ts.CommentRange[]][] = []; + + for (const decl of symbol.declarations || []) { + const text = decl.getSourceFile().text; + if (wantedKinds[kind].includes(decl.kind)) { + const node = declarationToCommentNode(decl); + if (!node) { + continue; + } + + // Special behavior here! We temporarily put the implementation comment + // on the reflection which contains all the signatures. This lets us pull + // the comment on the implementation if some signature does not have a comment. + // However, we don't want to skip the node if it is a reference to something. + // See the gh1770 test for an example. + if ( + kind & ReflectionKind.ContainsCallSignatures && + !(node as ts.FunctionDeclaration).body && + node.kind !== ts.SyntaxKind.BindingElement + ) { + continue; + } + + const comments = collectCommentRanges( + ts.getLeadingCommentRanges(text, node.pos) + ); + + if (reverse) { + comments?.reverse(); + } + + const selectedDocComment = comments.find((ranges) => + permittedRange(text, ranges, commentStyle) + ); + + if (selectedDocComment) { + discovered.push([decl.getSourceFile(), selectedDocComment]); + } + } + } + + switch (discovered.length) { + case 0: + return undefined; + case 1: + return discovered[0]; + default: { + logger.warn( + `${symbol.name} has multiple declarations with a comment. An arbitrary comment will be used.` + ); + const locations = discovered.map(([sf, [{ pos }]]) => { + const path = nicePath(sf.fileName); + const line = ts.getLineAndCharacterOfPosition(sf, pos).line + 1; + return `${path}:${line}`; + }); + logger.info( + `The comments for ${ + symbol.name + } are declared at:\n\t${locations.join("\n\t")}` + ); + return discovered[0]; + } + } +} + +export function discoverSignatureComment( + declaration: ts.SignatureDeclaration | ts.JSDocSignature, + commentStyle: CommentStyle +): [ts.SourceFile, ts.CommentRange[]] | undefined { + const node = declarationToCommentNode(declaration); + if (!node) { + return; + } + + const text = node.getSourceFile().text; + + const comments = collectCommentRanges( + ts.getLeadingCommentRanges(text, node.pos) + ); + + const comment = comments.find((ranges) => + permittedRange(text, ranges, commentStyle) + ); + if (comment) { + return [node.getSourceFile(), comment]; + } +} + +/** + * Check whether the given module declaration is the topmost. + * + * This function returns TRUE if there is no trailing module defined, in + * the following example this would be the case only for module `C`. + * + * ``` + * module A.B.C { } + * ``` + * + * @param node The module definition that should be tested. + * @return TRUE if the given node is the topmost module declaration, FALSE otherwise. + */ +function isTopmostModuleDeclaration(node: ts.ModuleDeclaration): boolean { + return node.getChildren().some(ts.isModuleBlock); +} + +/** + * Return the root module declaration of the given module declaration. + * + * In the following example this function would always return module + * `A` no matter which of the modules was passed in. + * + * ``` + * module A.B.C { } + * ``` + */ +function getRootModuleDeclaration(node: ts.ModuleDeclaration): ts.Node { + while ( + node.parent && + node.parent.kind === ts.SyntaxKind.ModuleDeclaration + ) { + const parent = node.parent; + if (node.name.pos === parent.name.end + 1) { + node = parent; + } else { + break; + } + } + + return node; +} + +function declarationToCommentNode(node: ts.Declaration): ts.Node | undefined { + if (node.parent?.kind === ts.SyntaxKind.VariableDeclarationList) { + return node.parent.parent; + } + + if (node.kind === ts.SyntaxKind.ModuleDeclaration) { + if (!isTopmostModuleDeclaration(node)) { + return; + } else { + return getRootModuleDeclaration(node); + } + } + + if (node.kind === ts.SyntaxKind.ExportSpecifier) { + return node.parent.parent; + } + + if ( + [ + ts.SyntaxKind.NamespaceExport, + ts.SyntaxKind.FunctionExpression, + ts.SyntaxKind.FunctionType, + ts.SyntaxKind.FunctionType, + ts.SyntaxKind.ArrowFunction, + ].includes(node.kind) + ) { + return node.parent; + } + + return node; +} + +/** + * Separate comment ranges into arrays so that multiple line comments are kept together + * and each block comment is left on its own. + */ +function collectCommentRanges( + ranges: ts.CommentRange[] | undefined +): ts.CommentRange[][] { + const result: ts.CommentRange[][] = []; + + let collect: ts.CommentRange[] = []; + for (const range of ranges || []) { + collect.push(range); + + switch (range.kind) { + case ts.SyntaxKind.MultiLineCommentTrivia: + if (collect.length) { + result.push(collect); + collect = []; + } + result.push([range]); + break; + case ts.SyntaxKind.SingleLineCommentTrivia: + collect.push(range); + break; + /* istanbul ignore next */ + default: + assertNever(range.kind); + } + } + + if (collect.length) { + result.push(collect); + } + + return result; +} + +function permittedRange( + text: string, + ranges: ts.CommentRange[], + commentStyle: CommentStyle +): boolean { + switch (commentStyle) { + case CommentStyle.All: + return true; + case CommentStyle.Block: + return ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia; + case CommentStyle.Line: + return ranges[0].kind === ts.SyntaxKind.SingleLineCommentTrivia; + case CommentStyle.JSDoc: + return ( + ranges[0].kind === ts.SyntaxKind.MultiLineCommentTrivia && + text[ranges[0].pos] === "/" && + text[ranges[0].pos + 1] === "*" && + text[ranges[0].pos + 2] === "*" + ); + } +} diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts new file mode 100644 index 000000000..86e2aca4d --- /dev/null +++ b/src/lib/converter/comments/index.ts @@ -0,0 +1,190 @@ +import * as ts from "typescript"; +import { Comment, ReflectionKind } from "../../models"; +import { assertNever, Logger } from "../../utils"; +import type { CommentStyle } from "../../utils/options/declaration"; +import { nicePath } from "../../utils/paths"; +import { lexBlockComment } from "./blockLexer"; +import { discoverComment, discoverSignatureComment } from "./discovery"; +import { lexLineComments } from "./lineLexer"; +import { parseComment } from "./parser"; + +export interface CommentParserConfig { + blockTags: Set; + inlineTags: Set; + modifierTags: Set; +} + +const commentCache = new WeakMap>(); + +function getCommentWithCache( + discovered: [ts.SourceFile, ts.CommentRange[]] | undefined, + config: CommentParserConfig, + logger: Logger +) { + if (!discovered) return; + + const [file, ranges] = discovered; + const cache = commentCache.get(file) || new Map(); + if (cache?.has(ranges[0].pos)) { + return cache.get(ranges[0].pos)!.clone(); + } + + const line = ts.getLineAndCharacterOfPosition(file, ranges[0].pos).line + 1; + const warning = (warning: string) => + logger.warn( + `${warning} in comment at ${nicePath(file.fileName)}:${line}.` + ); + + let comment: Comment; + switch (ranges[0].kind) { + case ts.SyntaxKind.MultiLineCommentTrivia: + comment = parseComment( + lexBlockComment(file.text, ranges[0].pos, ranges[0].end), + config, + warning + ); + break; + case ts.SyntaxKind.SingleLineCommentTrivia: + comment = parseComment( + lexLineComments(file.text, ranges), + config, + warning + ); + break; + default: + assertNever(ranges[0].kind); + } + + cache.set(ranges[0].pos, comment); + commentCache.set(file, cache); + + return comment.clone(); +} + +export function getComment( + symbol: ts.Symbol, + kind: ReflectionKind, + config: CommentParserConfig, + logger: Logger, + commentStyle: CommentStyle +): Comment | undefined { + const comment = getCommentWithCache( + discoverComment(symbol, kind, logger, commentStyle), + config, + logger + ); + + if (symbol.declarations?.some(ts.isSourceFile) && comment) { + // Module comment, make sure it is tagged with @packageDocumentation or @module. + // If it isn't then the comment applies to the first statement in the file, so throw it away. + if ( + !comment.hasModifier("@packageDocumentation") && + !comment.getTag("@module") + ) { + return; + } + } + + if (!symbol.declarations?.some(ts.isSourceFile) && comment) { + // Ensure module comments are not attached to non-module reflections. + if ( + comment.hasModifier("@packageDocumentation") || + comment.getTag("@module") + ) { + return; + } + } + + return comment; +} + +export function getSignatureComment( + declaration: ts.SignatureDeclaration | ts.JSDocSignature, + config: CommentParserConfig, + logger: Logger, + commentStyle: CommentStyle +): Comment | undefined { + return getCommentWithCache( + discoverSignatureComment(declaration, commentStyle), + config, + logger + ); +} + +export function getJsDocComment( + declaration: + | ts.JSDocPropertyLikeTag + | ts.JSDocCallbackTag + | ts.JSDocTypedefTag + | ts.JSDocTemplateTag + | ts.JSDocEnumTag, + config: CommentParserConfig, + logger: Logger +): Comment | undefined { + const file = declaration.getSourceFile(); + + // First, get the whole comment. We know we'll need all of it. + let parent: ts.Node = declaration.parent; + while (!ts.isJSDoc(parent)) { + parent = parent.parent; + } + + // Then parse it. + const comment = getCommentWithCache( + [ + file, + [ + { + kind: ts.SyntaxKind.MultiLineCommentTrivia, + pos: parent.pos, + end: parent.end, + }, + ], + ], + config, + logger + )!; + + // And pull out the tag we actually care about. + if (ts.isJSDocEnumTag(declaration)) { + return new Comment(comment.getTag("@enum")?.content); + } + + if ( + ts.isJSDocTemplateTag(declaration) && + declaration.comment && + declaration.typeParameters.length > 1 + ) { + // We could just put the same comment on everything, but due to how comment parsing works, + // we'd have to search for any @template with a name starting with the first type parameter's name + // which feels horribly hacky. + logger.warn( + `TypeDoc does not support multiple type parameters defined in a single @template tag with a comment.`, + declaration + ); + return; + } + + let name: string | undefined; + if (ts.isJSDocTemplateTag(declaration)) { + // This isn't really ideal. + name = declaration.typeParameters[0].name.text; + } else { + name = declaration.name?.getText(); + } + + if (!name) { + return; + } + + const tag = comment.getIdentifiedTag(name, `@${declaration.tagName.text}`); + + if (!tag) { + logger.error( + `Failed to find JSDoc tag for ${name} after parsing comment, please file a bug report.`, + declaration + ); + } else { + return new Comment(tag.content.slice()); + } +} diff --git a/src/lib/converter/comments/lexer.ts b/src/lib/converter/comments/lexer.ts new file mode 100644 index 000000000..f7d8dcf4d --- /dev/null +++ b/src/lib/converter/comments/lexer.ts @@ -0,0 +1,14 @@ +export enum TokenSyntaxKind { + Text = "text", + NewLine = "new_line", + OpenBrace = "open_brace", + CloseBrace = "close_brace", + Tag = "tag", + Code = "code", + TypeAnnotation = "type", +} + +export interface Token { + kind: TokenSyntaxKind; + text: string; +} diff --git a/src/lib/converter/comments/lineLexer.ts b/src/lib/converter/comments/lineLexer.ts new file mode 100644 index 000000000..f0fb023fa --- /dev/null +++ b/src/lib/converter/comments/lineLexer.ts @@ -0,0 +1,317 @@ +import type * as ts from "typescript"; +import { Token, TokenSyntaxKind } from "./lexer"; + +export function* lexLineComments( + file: string, + ranges: ts.CommentRange[] +): Generator { + // Wrapper around our real lex function to collapse adjacent text tokens. + let textToken: Token | undefined; + for (const token of lexBlockComment2( + file, + ranges[0].pos, + ranges[ranges.length - 1].end + )) { + if (token.kind === TokenSyntaxKind.Text) { + if (textToken) { + textToken.text += token.text; + } else { + textToken = token; + } + } else { + if (textToken) { + yield textToken; + textToken = void 0; + } + yield token; + } + } + + if (textToken) { + yield textToken; + } + return; +} + +function* lexBlockComment2( + file: string, + pos: number, + end: number +): Generator { + // Trailing whitespace + while (pos < end && /\s/.test(file[end - 1])) { + end--; + } + + let lineStart = true; + let braceStartsType = false; + + for (;;) { + if (lineStart) { + pos = skipLeadingLineTrivia(pos); + lineStart = false; + } + + if (pos >= end) { + return; + } + + switch (file[pos]) { + case "\n": + yield makeToken(TokenSyntaxKind.NewLine, 1); + lineStart = true; + break; + + case "{": + if (braceStartsType && nextNonWs(pos + 1) !== "@") { + yield makeToken( + TokenSyntaxKind.TypeAnnotation, + findEndOfType(pos) - pos + ); + braceStartsType = false; + } else { + yield makeToken(TokenSyntaxKind.OpenBrace, 1); + } + break; + + case "}": + yield makeToken(TokenSyntaxKind.CloseBrace, 1); + braceStartsType = false; + break; + + case "`": { + // Markdown's code rules are a royal pain. This could be one of several things. + // 1. Inline code: <1-n ticks> + // 2. Code block: <3 ticks>\n\n<3 ticks>\n + // 3. Unmatched tick(s), not code, but part of some text. + // We don't quite handle #2 correctly yet. PR welcome! + braceStartsType = false; + let tickCount = 1; + let lookahead = pos; + + while (lookahead + 1 < end && file[lookahead + 1] === "`") { + tickCount++; + lookahead++; + } + let lookaheadStart = pos; + const codeText: string[] = []; + + lookahead++; + while (lookahead < end) { + if (lookaheadExactlyNTicks(lookahead, tickCount)) { + lookahead += tickCount; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + break; + } else if (file[lookahead] === "`") { + while (lookahead < end && file[lookahead] === "`") { + lookahead++; + } + } else if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + file[lookahead + 1] !== "\n" + ) { + lookahead += 2; + } else if (file[lookahead] === "\n") { + lookahead++; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + lookahead = skipLeadingLineTrivia(lookahead); + lookaheadStart = lookahead; + } else { + lookahead++; + } + } + + if (lookahead >= end && pos !== lookahead) { + if ( + tickCount === 3 && + file.substring(pos, end).includes("\n") + ) { + codeText.push(file.substring(lookaheadStart, end)); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + } else { + yield makeToken(TokenSyntaxKind.Text, tickCount); + } + } + + break; + } + + case "@": { + let lookahead = pos + 1; + while (lookahead < end && /[a-z]/i.test(file[lookahead])) { + lookahead++; + } + + if (lookahead !== pos + 1) { + while ( + lookahead < end && + /[a-z0-9]/i.test(file[lookahead]) + ) { + lookahead++; + } + } + + if (lookahead !== pos + 1) { + braceStartsType = true; + yield makeToken(TokenSyntaxKind.Tag, lookahead - pos); + break; + } + } + // fall through if we didn't find something that looks like a tag + + default: { + const textParts: string[] = []; + + let lookaheadStart = pos; + let lookahead = pos; + while (lookahead < end) { + if ("{}\n`".includes(file[lookahead])) break; + + if ( + lookahead !== pos && + file[lookahead] === "@" && + /\s/.test(file[lookahead - 1]) + ) { + // Probably the start of a modifier tag + break; + } + + if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + "{}@`".includes(file[lookahead + 1]) + ) { + textParts.push( + file.substring(lookaheadStart, lookahead), + file[lookahead + 1] + ); + lookahead++; + lookaheadStart = lookahead + 1; + } + + lookahead++; + } + + textParts.push(file.substring(lookaheadStart, lookahead)); + + if (textParts.some((part) => /\S/.test(part))) { + braceStartsType = false; + } + + pos = lookahead; + // This piece of text had line continuations or escaped text + yield { + kind: TokenSyntaxKind.Text, + text: textParts.join(""), + }; + break; + } + } + } + + function makeToken(kind: TokenSyntaxKind, size: number): Token { + const start = pos; + pos += size; + + return { + kind, + text: file.substring(start, pos), + }; + } + + function skipLeadingLineTrivia(pos: number) { + let lookahead = pos; + while (lookahead < end && /\s/.test(file[lookahead])) { + lookahead++; + } + while (lookahead < end && file[lookahead] === "/") { + lookahead++; + } + if (lookahead < end && file[lookahead] === " ") { + lookahead++; + } + return lookahead; + } + + function lookaheadExactlyNTicks(pos: number, n: number) { + if (pos + n > end) { + return false; + } + + return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`"; + } + + function findEndOfType(pos: number): number { + let openBraces = 0; + + while (pos < end) { + if (file[pos] === "{") { + openBraces++; + } else if (file[pos] === "}") { + if (--openBraces === 0) { + break; + } + } else if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos); + } + + pos++; + } + + if (pos < end && file[pos] === "}") { + pos++; + } + + return pos; + } + + function findEndOfString(pos: number): number { + const endOfString = file[pos]; + pos++; + while (pos < end) { + if (file[pos] === endOfString) { + break; + } else if (file[pos] === "\\") { + pos++; // Skip escaped character + } else if ( + endOfString === "`" && + file[pos] === "$" && + file[pos + 1] === "{" + ) { + // Template literal with data inside a ${} + while (pos < end && file[pos] !== "}") { + if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos) + 1; + } else { + pos++; + } + } + } + + pos++; + } + + return pos; + } + + function nextNonWs(pos: number): string | undefined { + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + return file[pos]; + } +} diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts new file mode 100644 index 000000000..582083b4c --- /dev/null +++ b/src/lib/converter/comments/parser.ts @@ -0,0 +1,373 @@ +import { ok } from "assert"; +import type { CommentParserConfig } from "."; +import { Comment, CommentDisplayPart, CommentTag } from "../../models"; +import { assertNever, removeIf } from "../../utils"; +import { Token, TokenSyntaxKind } from "./lexer"; + +interface LookaheadGenerator { + done(): boolean; + peek(): T; + take(): T; +} + +function makeLookaheadGenerator( + gen: Generator +): LookaheadGenerator { + let nextItem = gen.next(); + + return { + done() { + return !!nextItem.done; + }, + peek() { + ok(!nextItem.done); + return nextItem.value; + }, + take() { + const thisItem = nextItem; + ok(!thisItem.done); + nextItem = gen.next(); + return thisItem.value; + }, + }; +} + +export function parseComment( + tokens: Generator, + config: CommentParserConfig, + warning: (message: string) => void +): Comment { + const lexer = makeLookaheadGenerator(tokens); + + const comment = new Comment(); + comment.summary = blockContent(comment, lexer, config, warning); + + while (!lexer.done()) { + comment.blockTags.push(blockTag(comment, lexer, config, warning)); + } + + postProcessComment(comment, warning); + + return comment; +} + +const HAS_USER_IDENTIFIER: `@${string}`[] = [ + "@callback", + "@param", + "@prop", + "@property", + "@template", + "@typedef", + "@typeParam", + "@inheritDoc", +]; + +function makeCodeBlock(text: string) { + return "```ts\n" + text + "\n```"; +} + +/** + * Loop over comment, produce lint warnings, and set tag names for tags + * which have them. + */ +function postProcessComment(comment: Comment, warning: (msg: string) => void) { + for (const tag of comment.blockTags) { + if (HAS_USER_IDENTIFIER.includes(tag.tag) && tag.content.length) { + const first = tag.content[0]; + if (first.kind === "text") { + let end = first.text.search(/\s/); + if (end === -1) end = first.text.length; + + tag.name = first.text.substring(0, end); + if (tag.name.startsWith("[") && tag.name.endsWith("]")) { + tag.name = tag.name.slice(1, tag.name.indexOf("=")); + } + + first.text = first.text.substring(end); + const endOfTrivia = first.text.search(/[^\-\s]/); + if (endOfTrivia !== -1) { + first.text = first.text.substring(endOfTrivia); + } else { + // Remove this token, no real text in it. + tag.content.shift(); + } + } + } + + if ( + tag.content.some( + (part) => + part.kind === "inline-tag" && part.tag === "@inheritDoc" + ) + ) { + warning( + "An inline @inheritDoc tag should not appear within a block tag as it will not be processed" + ); + } + + if ( + tag.tag === "@example" && + !tag.content.some((part) => part.kind === "code") + ) { + const caption = tag.content[0].text.match( + /^\s*(.*?)<\/caption>\s*(\n|$)/ + ); + if (caption) { + const code = Comment.combineDisplayParts([ + { + kind: "text", + text: tag.content[0].text.slice(caption[0].length), + }, + ...tag.content.slice(1), + ]); + tag.content = [ + { + kind: "text", + text: caption[1] + "\n", + }, + { + kind: "code", + text: makeCodeBlock(code), + }, + ]; + } else { + tag.content = [ + { + kind: "code", + text: makeCodeBlock( + Comment.combineDisplayParts(tag.content) + ), + }, + ]; + } + } + } + + const remarks = comment.blockTags.filter((tag) => tag.tag === "@remarks"); + if (remarks.length > 1) { + warning( + "At most one @remarks tag is expected in a comment, ignoring all but the first" + ); + removeIf(comment.blockTags, (tag) => remarks.indexOf(tag) > 0); + } + + const inheritDoc = comment.blockTags.filter( + (tag) => tag.tag === "@inheritDoc" + ); + const inlineInheritDoc = comment.summary.filter( + (part) => part.kind === "inline-tag" && part.tag === "@inheritDoc" + ); + + if (inlineInheritDoc.length + inheritDoc.length > 1) { + warning( + "At most one @inheritDoc tag is expected in a comment, ignoring all but the first" + ); + const allInheritTags = [...inlineInheritDoc, ...inheritDoc]; + removeIf(comment.summary, (part) => allInheritTags.indexOf(part) > 0); + removeIf(comment.blockTags, (tag) => allInheritTags.indexOf(tag) > 0); + } + + if ( + (inlineInheritDoc.length || inheritDoc.length) && + comment.summary.some( + (part) => part.kind !== "inline-tag" && /\S/.test(part.text) + ) + ) { + warning( + "Content in the summary section will be overwritten by the @inheritDoc tag" + ); + } + + if ((inlineInheritDoc.length || inheritDoc.length) && remarks.length) { + warning( + "Content in the @remarks block will be overwritten by the @inheritDoc tag" + ); + } +} + +const aliasedTags = new Map([["@return", "@returns"]]); + +function blockTag( + comment: Comment, + lexer: LookaheadGenerator, + config: CommentParserConfig, + warning: (msg: string) => void +): CommentTag { + const blockTag = lexer.take(); + ok(blockTag.kind === TokenSyntaxKind.Tag); // blockContent is broken if this fails. + + const tagName = aliasedTags.get(blockTag.text) || blockTag.text; + + return new CommentTag( + tagName as `@${string}`, + blockContent(comment, lexer, config, warning) + ); +} + +function blockContent( + comment: Comment, + lexer: LookaheadGenerator, + config: CommentParserConfig, + warning: (msg: string) => void +): CommentDisplayPart[] { + const content: CommentDisplayPart[] = []; + let atNewLine = true; + + loop: while (!lexer.done()) { + const next = lexer.peek(); + let consume = true; + + switch (next.kind) { + case TokenSyntaxKind.NewLine: + case TokenSyntaxKind.Text: + content.push({ kind: "text", text: next.text }); + break; + + case TokenSyntaxKind.Code: + content.push({ kind: "code", text: next.text }); + break; + + case TokenSyntaxKind.Tag: + if (next.text === "@inheritdoc") { + warning( + "The @inheritDoc tag should be properly capitalized" + ); + next.text = "@inheritDoc"; + } + if (config.modifierTags.has(next.text)) { + comment.modifierTags.add(next.text); + break; + } else if (!atNewLine && !config.blockTags.has(next.text)) { + // Treat unknown tag as a modifier, but warn about it. + comment.modifierTags.add(next.text); + warning( + `Treating unrecognized tag "${next.text}" as a modifier tag` + ); + break; + } else { + // Block tag or unknown tag, handled by our caller. + break loop; + } + + case TokenSyntaxKind.TypeAnnotation: + // We always ignore these. In TS files they are redundant, in JS files + // they are required. + break; + + case TokenSyntaxKind.CloseBrace: + // Unmatched closing brace, generate a warning, and treat it as text. + warning(`Unmatched closing brace in comment`); + content.push({ kind: "text", text: next.text }); + break; + + case TokenSyntaxKind.OpenBrace: + inlineTag(lexer, content, config, warning); + consume = false; + break; + + default: + assertNever(next.kind); + } + + if (consume && lexer.take().kind === TokenSyntaxKind.NewLine) { + atNewLine = true; + } + } + + // Collapse adjacent text parts + for (let i = 0; i < content.length - 1 /* inside loop */; ) { + if (content[i].kind === "text" && content[i + 1].kind === "text") { + content[i].text += content[i + 1].text; + content.splice(i + 1, 1); + } else { + i++; + } + } + + // Now get rid of extra whitespace, and any empty parts + for (let i = 0; i < content.length /* inside loop */; ) { + if (i === 0 || content[i].kind === "inline-tag") { + content[i].text = content[i].text.trimStart(); + } + if (i === content.length - 1 || content[i].kind === "inline-tag") { + content[i].text = content[i].text.trimEnd(); + } + + if (!content[i].text && content[i].kind === "text") { + content.splice(i, 1); + } else { + i++; + } + } + + return content; +} + +function inlineTag( + lexer: LookaheadGenerator, + block: CommentDisplayPart[], + config: CommentParserConfig, + warning: (msg: string) => void +) { + const openBrace = lexer.take(); + + // Now skip whitespace to grab the tag name. + // If the first non-whitespace text after the brace isn't a tag, + // then produce a warning and treat what we've consumed as plain text. + if ( + lexer.done() || + ![TokenSyntaxKind.Text, TokenSyntaxKind.Tag].includes(lexer.peek().kind) + ) { + warning("Encountered an unescaped open brace without an inline tag"); + block.push({ kind: "text", text: openBrace.text }); + return; + } + + let tagName = lexer.take(); + + if ( + lexer.done() || + (tagName.kind === TokenSyntaxKind.Text && + (!/^\s+$/.test(tagName.text) || + lexer.peek().kind != TokenSyntaxKind.Tag)) + ) { + warning("Encountered an unescaped open brace without an inline tag"); + block.push({ kind: "text", text: openBrace.text + tagName.text }); + return; + } + + if (tagName.kind !== TokenSyntaxKind.Tag) { + tagName = lexer.take(); + } + + if (!config.inlineTags.has(tagName.text)) { + warning(`Encountered an unknown inline tag "${tagName.text}"`); + } + + const content: string[] = []; + + // At this point, we know we have an inline tag. Treat everything following as plain text, + // until we get to the closing brace. + while (!lexer.done() && lexer.peek().kind !== TokenSyntaxKind.CloseBrace) { + const token = lexer.take(); + if (token.kind === TokenSyntaxKind.OpenBrace) { + warning( + "Encountered an open brace within an inline tag, this is likely a mistake" + ); + } + + content.push(token.kind === TokenSyntaxKind.NewLine ? " " : token.text); + } + + if (lexer.done()) { + warning("Inline tag is not closed"); + } else { + lexer.take(); // Close brace + } + + block.push({ + kind: "inline-tag", + tag: tagName.text as `@${string}`, + text: content.join(""), + }); +} diff --git a/src/lib/converter/comments/rawLexer.ts b/src/lib/converter/comments/rawLexer.ts new file mode 100644 index 000000000..f2dcc4751 --- /dev/null +++ b/src/lib/converter/comments/rawLexer.ts @@ -0,0 +1,301 @@ +import { Token, TokenSyntaxKind } from "./lexer"; + +export function* lexCommentString( + file: string +): Generator { + // Wrapper around our real lex function to collapse adjacent text tokens. + let textToken: Token | undefined; + for (const token of lexCommentString2(file)) { + if (token.kind === TokenSyntaxKind.Text) { + if (textToken) { + textToken.text += token.text; + } else { + textToken = token; + } + } else { + if (textToken) { + yield textToken; + textToken = void 0; + } + yield token; + } + } + + if (textToken) { + yield textToken; + } + return; +} + +function* lexCommentString2( + file: string +): Generator { + let pos = 0; + let end = file.length; + + // Skip leading whitespace + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + + // Trailing whitespace + while (pos < end && /\s/.test(file[end - 1])) { + end--; + } + + let lineStart = true; + let braceStartsType = false; + + for (;;) { + if (pos >= end) { + return; + } + + if (lineStart) { + lineStart = false; + } + + switch (file[pos]) { + case "\n": + yield makeToken(TokenSyntaxKind.NewLine, 1); + lineStart = true; + break; + + case "{": + if (braceStartsType && nextNonWs(pos + 1) !== "@") { + yield makeToken( + TokenSyntaxKind.TypeAnnotation, + findEndOfType(pos) - pos + ); + braceStartsType = false; + } else { + yield makeToken(TokenSyntaxKind.OpenBrace, 1); + } + break; + + case "}": + yield makeToken(TokenSyntaxKind.CloseBrace, 1); + braceStartsType = false; + break; + + case "`": { + // Markdown's code rules are a royal pain. This could be one of several things. + // 1. Inline code: <1-n ticks> + // 2. Code block: <3 ticks>\n\n<3 ticks>\n + // 3. Unmatched tick(s), not code, but part of some text. + // We don't quite handle #2 correctly yet. PR welcome! + braceStartsType = false; + let tickCount = 1; + let lookahead = pos; + + while (lookahead + 1 < end && file[lookahead + 1] === "`") { + tickCount++; + lookahead++; + } + let lookaheadStart = pos; + const codeText: string[] = []; + + lookahead++; + while (lookahead < end) { + if (lookaheadExactlyNTicks(lookahead, tickCount)) { + lookahead += tickCount; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + break; + } else if (file[lookahead] === "`") { + while (lookahead < end && file[lookahead] === "`") { + lookahead++; + } + } else if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + file[lookahead + 1] !== "\n" + ) { + lookahead += 2; + } else if (file[lookahead] === "\n") { + lookahead++; + codeText.push( + file.substring(lookaheadStart, lookahead) + ); + lookaheadStart = lookahead; + } else { + lookahead++; + } + } + + if (lookahead >= end && pos !== lookahead) { + if ( + tickCount === 3 && + file.substring(pos, end).includes("\n") + ) { + codeText.push(file.substring(lookaheadStart, end)); + yield { + kind: TokenSyntaxKind.Code, + text: codeText.join(""), + }; + pos = lookahead; + } else { + yield makeToken(TokenSyntaxKind.Text, tickCount); + } + } + + break; + } + + case "@": { + let lookahead = pos + 1; + while (lookahead < end && /[a-z]/i.test(file[lookahead])) { + lookahead++; + } + + if (lookahead !== pos + 1) { + while ( + lookahead < end && + /[a-z0-9]/i.test(file[lookahead]) + ) { + lookahead++; + } + } + + if (lookahead !== pos + 1) { + braceStartsType = true; + yield makeToken(TokenSyntaxKind.Tag, lookahead - pos); + break; + } + } + // fall through if we didn't find something that looks like a tag + + default: { + const textParts: string[] = []; + + let lookaheadStart = pos; + let lookahead = pos; + while (lookahead < end) { + if ("{}\n`".includes(file[lookahead])) break; + + if ( + lookahead !== pos && + file[lookahead] === "@" && + /\s/.test(file[lookahead - 1]) + ) { + // Probably the start of a modifier tag + break; + } + + if ( + file[lookahead] === "\\" && + lookahead + 1 < end && + "{}@`".includes(file[lookahead + 1]) + ) { + textParts.push( + file.substring(lookaheadStart, lookahead), + file[lookahead + 1] + ); + lookahead++; + lookaheadStart = lookahead + 1; + } + + lookahead++; + } + + textParts.push(file.substring(lookaheadStart, lookahead)); + + if (textParts.some((part) => /\S/.test(part))) { + braceStartsType = false; + } + + pos = lookahead; + // This piece of text had line continuations or escaped text + yield { + kind: TokenSyntaxKind.Text, + text: textParts.join(""), + }; + break; + } + } + } + + function makeToken(kind: TokenSyntaxKind, size: number): Token { + const start = pos; + pos += size; + + return { + kind, + text: file.substring(start, pos), + }; + } + + function lookaheadExactlyNTicks(pos: number, n: number) { + if (pos + n > end) { + return false; + } + + return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`"; + } + + function findEndOfType(pos: number): number { + let openBraces = 0; + + while (pos < end) { + if (file[pos] === "{") { + openBraces++; + } else if (file[pos] === "}") { + if (--openBraces === 0) { + break; + } + } else if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos); + } + + pos++; + } + + if (pos < end && file[pos] === "}") { + pos++; + } + + return pos; + } + + function findEndOfString(pos: number): number { + const endOfString = file[pos]; + pos++; + while (pos < end) { + if (file[pos] === endOfString) { + break; + } else if (file[pos] === "\\") { + pos++; // Skip escaped character + } else if ( + endOfString === "`" && + file[pos] === "$" && + file[pos + 1] === "{" + ) { + // Template literal with data inside a ${} + while (pos < end && file[pos] !== "}") { + if ("`'\"".includes(file[pos])) { + pos = findEndOfString(pos) + 1; + } else { + pos++; + } + } + } + + pos++; + } + + return pos; + } + + function nextNonWs(pos: number): string | undefined { + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + return file[pos]; + } +} diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 22db86884..f27187ea2 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -14,7 +14,7 @@ import type { Converter } from "./converter"; import { isNamedNode } from "./utils/nodes"; import { ConverterEvents } from "./converter-events"; import { resolveAliasedSymbol } from "./utils/symbols"; -import type { SearchConfig } from "../utils/options/declaration"; +import { getComment } from "./comments"; /** * The context describes the current state the converter is in. @@ -70,19 +70,6 @@ export class Context { this.convertingTypeNode = true; } - /** - * This is a horrible hack to avoid breaking backwards compatibility for plugins - * that use EVENT_CREATE_DECLARATION. The comment plugin needs to be able to check - * this to properly get the comment for module re-exports: - * ```ts - * /** We should use this comment */ - * export * as Mod from "./mod" - * ``` - * Will be removed in 0.23. - * @internal - */ - exportSymbol?: ts.Symbol; - /** @internal */ shouldBeStatic = false; @@ -119,17 +106,6 @@ export class Context { return this.converter.application.options.getCompilerOptions(); } - getSearchOptions(): SearchConfig { - return { - searchCategoryBoosts: this.converter.application.options.getValue( - "searchCategoryBoosts" - ) as SearchConfig["searchCategoryBoosts"], - searchGroupBoosts: this.converter.application.options.getValue( - "searchGroupBoosts" - ) as SearchConfig["searchGroupBoosts"], - }; - } - /** * Return the type declaration of the given node. * @@ -146,15 +122,11 @@ export class Context { if (!nodeType) { if (node.symbol) { nodeType = this.checker.getDeclaredTypeOfSymbol(node.symbol); - } else if (node.parent && node.parent.symbol) { + } else if (node.parent?.symbol) { nodeType = this.checker.getDeclaredTypeOfSymbol( node.parent.symbol ); - } else if ( - node.parent && - node.parent.parent && - node.parent.parent.symbol - ) { + } else if (node.parent?.parent?.symbol) { nodeType = this.checker.getDeclaredTypeOfSymbol( node.parent.parent.symbol ); @@ -201,13 +173,50 @@ export class Context { const name = getHumanName( nameOverride ?? exportSymbol?.name ?? symbol?.name ?? "unknown" ); + const reflection = new DeclarationReflection(name, kind, this.scope); + this.postReflectionCreation(reflection, symbol, exportSymbol); + + return reflection; + } + + postReflectionCreation( + reflection: Reflection, + symbol: ts.Symbol | undefined, + exportSymbol: ts.Symbol | undefined + ) { + if ( + exportSymbol && + reflection.kind & + (ReflectionKind.SomeModule | ReflectionKind.Reference) + ) { + reflection.comment = getComment( + exportSymbol, + reflection.kind, + this.converter.config, + this.logger, + this.converter.commentStyle + ); + } + if (symbol && !reflection.comment) { + reflection.comment = getComment( + symbol, + reflection.kind, + this.converter.config, + this.logger, + this.converter.commentStyle + ); + } + if (this.shouldBeStatic) { reflection.setFlag(ReflectionFlag.Static); } - reflection.escapedName = symbol?.escapedName; - this.addChild(reflection); + if (reflection instanceof DeclarationReflection) { + reflection.escapedName = symbol?.escapedName; + this.addChild(reflection); + } + if (symbol && this.converter.isExternal(symbol)) { reflection.setFlag(ReflectionFlag.External); } @@ -215,26 +224,14 @@ export class Context { this.registerReflection(reflection, exportSymbol); } this.registerReflection(reflection, symbol); - - return reflection; } - finalizeDeclarationReflection( - reflection: DeclarationReflection, - symbol: ts.Symbol | undefined, - exportSymbol?: ts.Symbol, - commentNode?: ts.Node - ) { - this.exportSymbol = exportSymbol; + finalizeDeclarationReflection(reflection: DeclarationReflection) { this.converter.trigger( ConverterEvents.CREATE_DECLARATION, this, - reflection, - (symbol && - this.converter.getNodesForSymbol(symbol, reflection.kind)[0]) ?? - commentNode + reflection ); - this.exportSymbol = undefined; } addChild(reflection: DeclarationReflection) { @@ -245,7 +242,7 @@ export class Context { } shouldIgnore(symbol: ts.Symbol) { - return this.converter.shouldIgnore(symbol, this.checker); + return this.converter.shouldIgnore(symbol); } /** @@ -293,17 +290,10 @@ export class Context { } } -const builtInSymbolRegExp = /^__@(\w+)$/; const uniqueSymbolRegExp = /^__@(.*)@\d+$/; function getHumanName(name: string) { - // TS 4.0, 4.1, 4.2 - well known symbols are treated specially. - let match = builtInSymbolRegExp.exec(name); - if (match) { - return `[Symbol.${match[1]}]`; - } - - match = uniqueSymbolRegExp.exec(name); + const match = uniqueSymbolRegExp.exec(name); if (match) { return `[${match[1]}]`; } diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index 0b740d2bf..1c8c889c3 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -12,8 +12,9 @@ import { convertSymbol } from "./symbols"; import { createMinimatch, matchesAny } from "../utils/paths"; import type { IMinimatch } from "minimatch"; import { hasAllFlags, hasAnyFlag } from "../utils/enum"; -import { resolveAliasedSymbol } from "./utils/symbols"; import type { DocumentationEntryPoint } from "../utils/entry-point"; +import type { CommentParserConfig } from "./comments"; +import type { CommentStyle } from "../utils/options/declaration"; /** * Compiles source files using TypeScript and converts compiler symbols to reflections. @@ -50,6 +51,15 @@ export class Converter extends ChildableComponent< @BindOption("excludeProtected") excludeProtected!: boolean; + @BindOption("commentStyle") + commentStyle!: CommentStyle; + + private _config?: CommentParserConfig; + + get config(): CommentParserConfig { + return this._config || this._buildCommentParserConfig(); + } + /** * General events */ @@ -74,7 +84,7 @@ export class Converter extends ChildableComponent< /** * Triggered when the converter has created a declaration reflection. - * The listener will be given {@link Context}, {@link Reflection} and a `ts.Node?`. + * The listener will be given {@link Context} and a {@link DeclarationReflection}. * @event */ static readonly EVENT_CREATE_DECLARATION = @@ -82,7 +92,7 @@ export class Converter extends ChildableComponent< /** * Triggered when the converter has created a signature reflection. - * The listener will be given {@link Context}, {@link SignatureReflection} and a `ts.Node?` + * The listener will be given {@link Context}, {@link SignatureReflection} | {@link ProjectReflection} and a `ts.Node?` * @event */ static readonly EVENT_CREATE_SIGNATURE = ConverterEvents.CREATE_SIGNATURE; @@ -96,7 +106,7 @@ export class Converter extends ChildableComponent< /** * Triggered when the converter has created a type parameter reflection. - * The listener will be given {@link Context}, {@link TypeParameterReflection} and a `ts.Node?` + * The listener will be given {@link Context} and a {@link TypeParameterReflection} * @event */ static readonly EVENT_CREATE_TYPE_PARAMETER = @@ -171,90 +181,6 @@ export class Converter extends ChildableComponent< return convertType(context, node); } - /** @internal */ - getNodesForSymbol(symbol: ts.Symbol, kind: ReflectionKind) { - const wantedKinds: ts.SyntaxKind[] = { - [ReflectionKind.Project]: [ts.SyntaxKind.SourceFile], - [ReflectionKind.Module]: [ts.SyntaxKind.SourceFile], - [ReflectionKind.Namespace]: [ - ts.SyntaxKind.ModuleDeclaration, - ts.SyntaxKind.SourceFile, - ], - [ReflectionKind.Enum]: [ - ts.SyntaxKind.EnumDeclaration, - ts.SyntaxKind.VariableDeclaration, - ], - [ReflectionKind.EnumMember]: [ - ts.SyntaxKind.EnumMember, - ts.SyntaxKind.PropertyAssignment, - ts.SyntaxKind.PropertySignature, - ], - [ReflectionKind.Variable]: [ - ts.SyntaxKind.VariableDeclaration, - ts.SyntaxKind.ExportAssignment, - ], - [ReflectionKind.Function]: [ - ts.SyntaxKind.FunctionDeclaration, - ts.SyntaxKind.VariableDeclaration, - ], - [ReflectionKind.Class]: [ts.SyntaxKind.ClassDeclaration], - [ReflectionKind.Interface]: [ - ts.SyntaxKind.InterfaceDeclaration, - ts.SyntaxKind.JSDocTypedefTag, - ], - [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor], - [ReflectionKind.Property]: [ - ts.SyntaxKind.PropertyDeclaration, - ts.SyntaxKind.PropertyAssignment, - ts.SyntaxKind.PropertySignature, - ts.SyntaxKind.JSDocPropertyTag, - ts.SyntaxKind.BinaryExpression, - ], - [ReflectionKind.Method]: [ - ts.SyntaxKind.MethodDeclaration, - ts.SyntaxKind.PropertyDeclaration, - ts.SyntaxKind.PropertySignature, - ], - [ReflectionKind.CallSignature]: [ - ts.SyntaxKind.FunctionDeclaration, - ts.SyntaxKind.VariableDeclaration, - ts.SyntaxKind.MethodDeclaration, - ts.SyntaxKind.MethodDeclaration, - ts.SyntaxKind.PropertyDeclaration, - ts.SyntaxKind.PropertySignature, - ts.SyntaxKind.CallSignature, - ], - [ReflectionKind.IndexSignature]: [ts.SyntaxKind.IndexSignature], - [ReflectionKind.ConstructorSignature]: [ - ts.SyntaxKind.ConstructSignature, - ], - [ReflectionKind.Parameter]: [ts.SyntaxKind.Parameter], - [ReflectionKind.TypeLiteral]: [ts.SyntaxKind.TypeLiteral], - [ReflectionKind.TypeParameter]: [ts.SyntaxKind.TypeParameter], - [ReflectionKind.Accessor]: [ - ts.SyntaxKind.GetAccessor, - ts.SyntaxKind.SetAccessor, - ], - [ReflectionKind.GetSignature]: [ts.SyntaxKind.GetAccessor], - [ReflectionKind.SetSignature]: [ts.SyntaxKind.SetAccessor], - [ReflectionKind.ObjectLiteral]: [ - ts.SyntaxKind.ObjectLiteralExpression, - ], - [ReflectionKind.TypeAlias]: [ - ts.SyntaxKind.TypeAliasDeclaration, - ts.SyntaxKind.JSDocTypedefTag, - ], - [ReflectionKind.Event]: [], /// this needs to go away - [ReflectionKind.Reference]: [ - ts.SyntaxKind.NamespaceExport, - ts.SyntaxKind.ExportSpecifier, - ], - }[kind]; - - const declarations = symbol.getDeclarations() ?? []; - return declarations.filter((d) => wantedKinds.includes(d.kind)); - } - /** * Compile the files within the given context and convert the compiler symbols to reflections. * @@ -301,11 +227,9 @@ export class Converter extends ChildableComponent< const allExports = getExports(context, node, symbol); - if ( - allExports.every((exp) => this.shouldIgnore(exp, context.checker)) - ) { + if (allExports.every((exp) => this.shouldIgnore(exp))) { this.owner.logger.verbose( - `Ignoring entry point ${entryName} since all members will be ignored.` + `All members of ${entryName} are excluded, ignoring entry point.` ); return; } @@ -316,8 +240,7 @@ export class Converter extends ChildableComponent< context.project.registerReflection(context.project, symbol); context.trigger( Converter.EVENT_CREATE_DECLARATION, - context.project, - node + context.project ); moduleContext = context; } else { @@ -327,12 +250,7 @@ export class Converter extends ChildableComponent< void 0, entryName ); - context.finalizeDeclarationReflection( - reflection, - symbol, - void 0, - node - ); + context.finalizeDeclarationReflection(reflection); moduleContext = context.withScope(reflection); } @@ -375,59 +293,52 @@ export class Converter extends ChildableComponent< this.trigger(Converter.EVENT_RESOLVE_END, context); } - /** @internal */ - shouldIgnore(symbol: ts.Symbol, checker: ts.TypeChecker) { - if ( - this.excludeNotDocumented && - // If the enum is included, we should include members even if not documented. - !hasAllFlags(symbol.flags, ts.SymbolFlags.EnumMember) && - resolveAliasedSymbol(symbol, checker).getDocumentationComment( - checker - ).length === 0 - ) { - return true; - } - + /** + * Used to determine if we should immediately bail when creating a reflection. + * Note: This should not be used for excludeNotDocumented because we don't have enough + * information at this point since comment discovery hasn't happened. + * @internal + */ + shouldIgnore(symbol: ts.Symbol) { if (this.isExcluded(symbol)) { return true; } - if (!this.excludeExternals) { - return false; - } - - return this.isExternal(symbol); + return this.excludeExternals && this.isExternal(symbol); } private isExcluded(symbol: ts.Symbol) { this.excludeCache ??= createMinimatch( this.application.options.getValue("exclude") ); + const cache = this.excludeCache; - for (const node of symbol.getDeclarations() ?? []) { - if (matchesAny(this.excludeCache, node.getSourceFile().fileName)) { - return true; - } - } - - return false; + return (symbol.getDeclarations() ?? []).some((node) => + matchesAny(cache, node.getSourceFile().fileName) + ); } /** @internal */ isExternal(symbol: ts.Symbol) { this.externalPatternCache ??= createMinimatch(this.externalPattern); - for (const node of symbol.getDeclarations() ?? []) { - if ( - matchesAny( - this.externalPatternCache, - node.getSourceFile().fileName - ) - ) { - return true; - } - } + const cache = this.externalPatternCache; + + return (symbol.getDeclarations() ?? []).some((node) => + matchesAny(cache, node.getSourceFile().fileName) + ); + } - return false; + private _buildCommentParserConfig() { + this._config = { + blockTags: new Set(this.application.options.getValue("blockTags")), + inlineTags: new Set( + this.application.options.getValue("inlineTags") + ), + modifierTags: new Set( + this.application.options.getValue("modifierTags") + ), + }; + return this._config; } } diff --git a/src/lib/converter/factories/comment.ts b/src/lib/converter/factories/comment.ts deleted file mode 100644 index e832ad55f..000000000 --- a/src/lib/converter/factories/comment.ts +++ /dev/null @@ -1,283 +0,0 @@ -import * as ts from "typescript"; - -import { Comment, CommentTag } from "../../models/comments/index"; -import type { Logger } from "../../utils"; - -/** - * Check whether the given module declaration is the topmost. - * - * This function returns TRUE if there is no trailing module defined, in - * the following example this would be the case only for module C. - * - * ``` - * module A.B.C { } - * ``` - * - * @param node The module definition that should be tested. - * @return TRUE if the given node is the topmost module declaration, FALSE otherwise. - */ -function isTopmostModuleDeclaration(node: ts.ModuleDeclaration): boolean { - return node.getChildren().some(ts.isModuleBlock); -} - -/** - * Return the root module declaration of the given module declaration. - * - * In the following example this function would always return module - * A no matter which of the modules was passed in. - * - * ``` - * module A.B.C { } - * ``` - */ -function getRootModuleDeclaration(node: ts.ModuleDeclaration): ts.Node { - while ( - node.parent && - node.parent.kind === ts.SyntaxKind.ModuleDeclaration - ) { - const parent = node.parent; - if (node.name.pos === parent.name.end + 1) { - node = parent; - } else { - break; - } - } - - return node; -} - -/** - * Derived from the internal ts utility - * https://github.com/Microsoft/TypeScript/blob/v3.2.2/src/compiler/utilities.ts#L954 - * @param node - * @param text - */ -function getJSDocCommentRanges(node: ts.Node, text: string): ts.CommentRange[] { - const hasTrailingCommentRanges = [ - ts.SyntaxKind.Parameter, - ts.SyntaxKind.FunctionExpression, - ts.SyntaxKind.ArrowFunction, - ts.SyntaxKind.ParenthesizedExpression, - ].includes(node.kind); - - let commentRanges = ts.getLeadingCommentRanges(text, node.pos) ?? []; - if (hasTrailingCommentRanges) { - commentRanges = ( - ts.getTrailingCommentRanges(text, node.pos) ?? [] - ).concat(commentRanges); - } - - // True if the comment starts with '/**' but not if it is '/**/' - return commentRanges.filter( - ({ pos }) => text.substr(pos, 3) === "/**" && text[pos + 4] !== "/" - ); -} - -export function getJsDocCommentText(comment: ts.JSDocTag["comment"]) { - if (typeof comment === "string") { - return comment; - } - - return comment?.map((val) => val.text).join(""); -} - -/** - * Return the raw comment string for the given node. - * - * @param node The node whose comment should be resolved. - * @returns The raw comment string or undefined if no comment could be found. - */ -export function getRawComment( - node: ts.Node, - logger: Logger -): string | undefined { - // This happens if we are converting a JS project that has @typedef "interfaces" - // with an @property tag, a @typedef type alias, a callback with parameters, etc. - if ( - ts.isJSDocTypedefTag(node) || - ts.isJSDocPropertyTag(node) || - ts.isJSDocParameterTag(node) || - ts.isJSDocCallbackTag(node) - ) { - // Also strip off leading dashes: - // @property {string} name - docs - return getJsDocCommentText(node.comment)?.replace(/^\s*-\s*/, ""); - } - - if ( - node.parent && - node.parent.kind === ts.SyntaxKind.VariableDeclarationList - ) { - node = node.parent.parent; - } else if (node.kind === ts.SyntaxKind.ModuleDeclaration) { - if (!isTopmostModuleDeclaration(node)) { - return; - } else { - node = getRootModuleDeclaration(node); - } - } else if (node.kind === ts.SyntaxKind.NamespaceExport) { - node = node.parent; - } else if (node.kind === ts.SyntaxKind.ExportSpecifier) { - node = node.parent.parent; - } else if (node.kind === ts.SyntaxKind.FunctionType) { - node = node.parent; - } - - const sourceFile = node.getSourceFile(); - const comments = getJSDocCommentRanges(node, sourceFile.text); - if (comments.length) { - let comment: ts.CommentRange; - - if (node.kind === ts.SyntaxKind.SourceFile) { - const explicitPackageComment = - comments.find((comment) => - sourceFile.text - .substring(comment.pos, comment.end) - .includes("@module") - ) ?? - comments.find((comment) => - sourceFile.text - .substring(comment.pos, comment.end) - .includes("@packageDocumentation") - ); - - if (explicitPackageComment) { - comment = explicitPackageComment; - } else if (comments.length > 1) { - // Legacy behavior, require more than one comment and use the first comment. - comment = comments[0]; - - logger.deprecated( - `Specifying multiple comments at the start of a file to use the first comment as the comment for the module has been deprecated. Use @module or @packageDocumentation instead.\n\t${sourceFile.fileName}`, - false - ); - } else { - // Single comment that may be a license comment, or no comments, bail. - return; - } - } else { - comment = comments[comments.length - 1]; - - // If a non-SourceFile node comment has this tag, it should not be attached to the node - // as it documents the module. - if ( - sourceFile.text - .substring(comment.pos, comment.end) - .includes("@module") || - sourceFile.text - .substring(comment.pos, comment.end) - .includes("@packageDocumentation") - ) { - return; - } - } - - return sourceFile.text.substring(comment.pos, comment.end); - } else { - return; - } -} - -/** - * Parse the given doc comment string. - * - * @param text The doc comment string that should be parsed. - * @param comment The {@link Comment} instance the parsed results should be stored into. - * @returns A populated {@link Comment} instance. - */ -export function parseComment( - text: string, - comment: Comment = new Comment() -): Comment { - let currentTag: CommentTag; - let shortText = 0; - - function consumeTypeData(line: string): string { - line = line.replace(/^\{(?!@)[^}]*\}+/, ""); - line = line.replace(/^\[[^[][^\]]*\]+/, ""); - return line.trim(); - } - - function readBareLine(line: string) { - if (currentTag) { - currentTag.text += "\n" + line; - } else if (line === "" && shortText === 0) { - // Ignore - } else if (line === "" && shortText === 1) { - shortText = 2; - } else { - if (shortText === 2) { - comment.text += (comment.text === "" ? "" : "\n") + line; - } else { - comment.shortText += - (comment.shortText === "" ? "" : "\n") + line; - shortText = 1; - } - } - } - - function readTagLine(line: string, tag: RegExpExecArray) { - let tagName = tag[1].toLowerCase(); - let paramName: string | undefined; - line = tag[2].trim(); - - if (tagName === "return") { - tagName = "returns"; - } - if (tagName === "example") { - line = line.replace(/<\/?caption>/g, ""); - } - if ( - tagName === "param" || - tagName === "typeparam" || - tagName === "template" || - tagName === "inheritdoc" - ) { - line = consumeTypeData(line); - const param = /[^\s]+/.exec(line); - if (param) { - paramName = param[0]; - line = line.substr(paramName.length + 1).trim(); - } - line = consumeTypeData(line); - line = line.replace(/^-\s+/, ""); - } else if (tagName === "returns") { - line = consumeTypeData(line); - } - - currentTag = new CommentTag(tagName, paramName, line); - comment.tags.push(currentTag); - } - - const CODE_FENCE = /^\s*```(?!.*```)/; - let inFencedCode = false; - function readLine(line: string) { - line = line.replace(/^\s*\*? ?/, ""); - const rawLine = line; - line = line.replace(/\s*$/, ""); - - if (CODE_FENCE.test(line)) { - inFencedCode = !inFencedCode; - } - - // Four spaces can be used to make code blocks too. - if (!inFencedCode && !line.startsWith(" ")) { - const tag = /^\s*@(\S+)(.*)$/.exec(line); - if (tag) { - return readTagLine(line, tag); - } - } - if (inFencedCode) { - // This will not include code blocks declared with four spaces - readBareLine(rawLine); - } else { - readBareLine(line); - } - } - - text = text.replace(/^\s*\/\*+/, ""); - text = text.replace(/\*+\/\s*$/, ""); - text.split(/\r\n?|\n/).forEach(readLine); - - return comment; -} diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index ddf62f11e..513144027 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -16,6 +16,7 @@ import type { Context } from "../context"; import { ConverterEvents } from "../converter-events"; import { convertDefaultValue } from "../convert-expression"; import { removeUndefined } from "../utils/reflections"; +import { getJsDocComment, getSignatureComment } from "../comments"; export function createSignature( context: Context, @@ -25,26 +26,14 @@ export function createSignature( | ReflectionKind.GetSignature | ReflectionKind.SetSignature, signature: ts.Signature, - declaration?: ts.SignatureDeclaration, - commentDeclaration?: ts.Node + declaration?: ts.SignatureDeclaration | ts.JSDocSignature ) { assert(context.scope instanceof DeclarationReflection); - // signature.getDeclaration might return undefined. - // https://github.com/microsoft/TypeScript/issues/30014 - declaration ??= signature.getDeclaration() as + + declaration ||= signature.getDeclaration() as | ts.SignatureDeclaration | undefined; - if ( - !commentDeclaration && - declaration && - (ts.isArrowFunction(declaration) || - ts.isFunctionExpression(declaration)) - ) { - commentDeclaration = declaration.parent; - } - commentDeclaration ??= declaration; - const sigRef = new SignatureReflection( kind == ReflectionKind.ConstructorSignature ? `new ${context.scope.parent!.name}` @@ -52,6 +41,14 @@ export function createSignature( kind, context.scope ); + if (declaration) { + sigRef.comment = getSignatureComment( + declaration, + context.converter.config, + context.logger, + context.converter.commentStyle + ); + } sigRef.typeParameters = convertTypeParameters( context, @@ -101,18 +98,17 @@ export function createSignature( break; } - context.trigger( - ConverterEvents.CREATE_SIGNATURE, - sigRef, - commentDeclaration - ); + context.trigger(ConverterEvents.CREATE_SIGNATURE, sigRef); } function convertParameters( context: Context, sigRef: SignatureReflection, - parameters: ReadonlyArray, - parameterNodes: readonly ts.ParameterDeclaration[] | undefined + parameters: readonly (ts.Symbol & { type?: ts.Type })[], + parameterNodes: + | readonly ts.ParameterDeclaration[] + | readonly ts.JSDocParameterTag[] + | undefined ) { return parameters.map((param, i) => { const declaration = param.valueDeclaration as @@ -128,12 +124,15 @@ function convertParameters( ReflectionKind.Parameter, sigRef ); + if (declaration && ts.isJSDocParameterTag(declaration)) { + paramRefl.comment = getJsDocComment( + declaration, + context.converter.config, + context.logger + ); + } context.registerReflection(paramRefl, param); - context.trigger( - ConverterEvents.CREATE_PARAMETER, - paramRefl, - declaration - ); + context.trigger(ConverterEvents.CREATE_PARAMETER, paramRefl); let type: ts.Type | ts.TypeNode | undefined; if (declaration) { @@ -153,7 +152,10 @@ function convertParameters( let isOptional = false; if (declaration) { isOptional = ts.isParameter(declaration) - ? !!declaration.questionToken + ? !!declaration.questionToken || + ts + .getJSDocParameterTags(declaration) + .some((tag) => tag.isBracketed) : declaration.isBracketed; } @@ -192,10 +194,18 @@ export function convertParameterNodes( ReflectionKind.Parameter, sigRef ); + if (ts.isJSDocParameterTag(param)) { + paramRefl.comment = getJsDocComment( + param, + context.converter.config, + context.logger + ); + } context.registerReflection( paramRefl, context.getSymbolAtLocation(param) ); + context.trigger(ConverterEvents.CREATE_PARAMETER, paramRefl); paramRefl.type = context.converter.convertType( context.withScope(paramRefl), @@ -286,6 +296,15 @@ export function createTypeParamReflection( getVariance(param.modifiers) ); context.registerReflection(paramRefl, param.symbol); + + if (ts.isJSDocTemplateTag(param.parent)) { + paramRefl.comment = getJsDocComment( + param.parent, + context.converter.config, + context.logger + ); + } + context.trigger(ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl, param); return paramRefl; } diff --git a/src/lib/converter/index.ts b/src/lib/converter/index.ts index aa7c15d25..7e474e313 100644 --- a/src/lib/converter/index.ts +++ b/src/lib/converter/index.ts @@ -1,6 +1,6 @@ export { Context } from "./context"; export { Converter } from "./converter"; - +export type { CommentParserConfig } from "./comments/index"; export { convertDefaultValue, convertExpression } from "./convert-expression"; import "./plugins/index"; diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index 4f16759af..9f6ace5a6 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -11,7 +11,7 @@ import { ReflectionType, SignatureReflection, } from "../models"; -import { flatMap } from "../utils/array"; +import { getJsDocComment } from "./comments"; import type { Context } from "./context"; import { ConverterEvents } from "./converter-events"; import { @@ -38,6 +38,11 @@ export function convertJsDocAlias( symbol, exportSymbol ); + reflection.comment = getJsDocComment( + declaration, + context.converter.config, + context.logger + ); reflection.type = context.converter.convertType( context.withScope(reflection), @@ -49,7 +54,7 @@ export function convertJsDocAlias( declaration.parent ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } export function convertJsDocCallback( @@ -63,7 +68,12 @@ export function convertJsDocCallback( symbol, exportSymbol ); - context.finalizeDeclarationReflection(alias, symbol, exportSymbol); + alias.comment = getJsDocComment( + declaration, + context.converter.config, + context.logger + ); + context.finalizeDeclarationReflection(alias); const ac = context.withScope(alias); @@ -82,7 +92,12 @@ function convertJsDocInterface( symbol, exportSymbol ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + reflection.comment = getJsDocComment( + declaration, + context.converter.config, + context.logger + ); + context.finalizeDeclarationReflection(reflection); const rc = context.withScope(reflection); @@ -107,7 +122,7 @@ function convertJsDocSignature(context: Context, node: ts.JSDocSignature) { context.scope ); context.registerReflection(reflection, symbol); - context.trigger(ConverterEvents.CREATE_DECLARATION, reflection, node); + context.trigger(ConverterEvents.CREATE_DECLARATION, reflection); const signature = new SignatureReflection( "__type", @@ -147,6 +162,6 @@ function convertTemplateParameterNodes( context: Context, nodes: readonly ts.JSDocTemplateTag[] | undefined ) { - const params = flatMap(nodes ?? [], (tag) => tag.typeParameters); + const params = (nodes ?? []).flatMap((tag) => tag.typeParameters); return convertTypeParameterNodes(context, params); } diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index b2ad795ce..9748ae114 100644 --- a/src/lib/converter/plugins/CategoryPlugin.ts +++ b/src/lib/converter/plugins/CategoryPlugin.ts @@ -2,14 +2,13 @@ import { Reflection, ContainerReflection, DeclarationReflection, - CommentTag, + Comment, } from "../../models"; import { ReflectionCategory } from "../../models"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; -import { BindOption } from "../../utils"; -import type { Comment } from "../../models"; +import { BindOption, removeIf } from "../../utils"; /** * A handler that sorts and categorizes the found reflections in the resolving phase. @@ -27,6 +26,11 @@ export class CategoryPlugin extends ConverterComponent { @BindOption("categorizeByGroup") categorizeByGroup!: boolean; + @BindOption("searchCategoryBoosts") + boosts!: Record; + + usedBoosts = new Set(); + // For use in static methods static defaultCategory = "Other"; static WEIGHTS: string[] = []; @@ -66,12 +70,9 @@ export class CategoryPlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. * @param reflection The reflection that is currently resolved. */ - private onResolve(context: Context, reflection: Reflection) { + private onResolve(_context: Context, reflection: Reflection) { if (reflection instanceof ContainerReflection) { - this.categorize( - reflection, - context.getSearchOptions()?.searchCategoryBoosts ?? {} - ); + this.categorize(reflection); } } @@ -82,37 +83,40 @@ export class CategoryPlugin extends ConverterComponent { */ private onEndResolve(context: Context) { const project = context.project; - this.categorize( - project, - context.getSearchOptions()?.searchCategoryBoosts ?? {} - ); + this.categorize(project); + + const unusedBoosts = new Set(Object.keys(this.boosts)); + for (const boost of this.usedBoosts) { + unusedBoosts.delete(boost); + } + this.usedBoosts.clear(); + + if (unusedBoosts.size) { + context.logger.warn( + `Not all categories specified in searchCategoryBoosts were used in the documentation.` + + ` The unused categories were:\n\t${Array.from( + unusedBoosts + ).join("\n\t")}` + ); + } } - private categorize( - obj: ContainerReflection, - categorySearchBoosts: { [key: string]: number } - ) { + private categorize(obj: ContainerReflection) { if (this.categorizeByGroup) { - this.groupCategorize(obj, categorySearchBoosts); + this.groupCategorize(obj); } else { - CategoryPlugin.lumpCategorize(obj, categorySearchBoosts); + this.lumpCategorize(obj); } } - private groupCategorize( - obj: ContainerReflection, - categorySearchBoosts: { [key: string]: number } - ) { + private groupCategorize(obj: ContainerReflection) { if (!obj.groups || obj.groups.length === 0) { return; } obj.groups.forEach((group) => { if (group.categories) return; - group.categories = CategoryPlugin.getReflectionCategories( - group.children, - categorySearchBoosts - ); + group.categories = this.getReflectionCategories(group.children); if (group.categories && group.categories.length > 1) { group.categories.sort(CategoryPlugin.sortCatCallback); } else if ( @@ -125,17 +129,11 @@ export class CategoryPlugin extends ConverterComponent { }); } - static lumpCategorize( - obj: ContainerReflection, - categorySearchBoosts: { [key: string]: number } - ) { + private lumpCategorize(obj: ContainerReflection) { if (!obj.children || obj.children.length === 0 || obj.categories) { return; } - obj.categories = CategoryPlugin.getReflectionCategories( - obj.children, - categorySearchBoosts - ); + obj.categories = this.getReflectionCategories(obj.children); if (obj.categories && obj.categories.length > 1) { obj.categories.sort(CategoryPlugin.sortCatCallback); } else if ( @@ -155,14 +153,13 @@ export class CategoryPlugin extends ConverterComponent { * relevance boost to be used when searching * @returns An array containing all children of the given reflection categorized */ - static getReflectionCategories( - reflections: DeclarationReflection[], - categorySearchBoosts: { [key: string]: number } + getReflectionCategories( + reflections: DeclarationReflection[] ): ReflectionCategory[] { const categories: ReflectionCategory[] = []; let defaultCat: ReflectionCategory | undefined; reflections.forEach((child) => { - const childCategories = CategoryPlugin.getCategories(child); + const childCategories = this.getCategories(child); if (childCategories.size === 0) { if (!defaultCat) { defaultCat = categories.find( @@ -183,11 +180,6 @@ export class CategoryPlugin extends ConverterComponent { for (const childCat of childCategories) { let category = categories.find((cat) => cat.title === childCat); - const catBoost = categorySearchBoosts[childCat ?? -1]; - if (catBoost != undefined) { - child.relevanceBoost = - (child.relevanceBoost ?? 1) * catBoost; - } if (category) { category.children.push(child); continue; @@ -205,46 +197,46 @@ export class CategoryPlugin extends ConverterComponent { * * @param reflection The reflection. * @returns The category the reflection belongs to + * + * @privateRemarks + * If you change this, also update getGroups in GroupPlugin accordingly. */ - static getCategories(reflection: DeclarationReflection) { - function extractCategoryTag(comment: Comment | undefined) { - const categories = new Set(); - if (!comment) return categories; + getCategories(reflection: DeclarationReflection) { + const categories = new Set(); + function extractCategoryTags(comment: Comment | undefined) { + if (!comment) return; + removeIf(comment.blockTags, (tag) => { + if (tag.tag === "@category") { + categories.add( + Comment.combineDisplayParts(tag.content).trim() + ); - const tags = comment.tags; - const commentTags: CommentTag[] = []; - tags.forEach((tag) => { - if (tag.tagName !== "category") { - commentTags.push(tag); - return; + return true; } - const text = tag.text.trim(); - if (!text) { - return; - } - categories.add(text); + return false; }); - comment.tags = commentTags; - return categories; } - let categories = new Set(); + extractCategoryTags(reflection.comment); + for (const sig of reflection.getNonIndexSignatures()) { + extractCategoryTags(sig.comment); + } - if (reflection.comment) { - categories = extractCategoryTag(reflection.comment); - } else if (reflection.signatures) { - for (const sig of reflection.signatures) { - for (const cat of extractCategoryTag(sig.comment)) { - categories.add(cat); - } + if (reflection.type?.type === "reflection") { + extractCategoryTags(reflection.type.declaration.comment); + for (const sig of reflection.type.declaration.getNonIndexSignatures()) { + extractCategoryTags(sig.comment); } } - if (reflection.type?.type === "reflection") { - reflection.type.declaration.comment?.removeTags("category"); - reflection.type.declaration.signatures?.forEach((s) => - s.comment?.removeTags("category") - ); + categories.delete(""); + + for (const cat of categories) { + if (cat in this.boosts) { + this.usedBoosts.add(cat); + reflection.relevanceBoost = + (reflection.relevanceBoost ?? 1) * this.boosts[cat]; + } } return categories; diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index fb260f34e..e39e46d67 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -1,6 +1,6 @@ -import * as ts from "typescript"; - -import { Comment, CommentTag } from "../../models/comments/index"; +import { Component, ConverterComponent } from "../components"; +import { Converter } from "../converter"; +import type { Context } from "../context"; import { Reflection, ReflectionFlag, @@ -9,16 +9,12 @@ import { DeclarationReflection, SignatureReflection, ParameterReflection, -} from "../../models/reflections/index"; -import { Component, ConverterComponent } from "../components"; -import { - parseComment, - getRawComment, - getJsDocCommentText, -} from "../factories/comment"; -import { Converter } from "../converter"; -import type { Context } from "../context"; -import { ReflectionType, SourceReference, TypeVisitor } from "../../models"; + Comment, + ReflectionType, + SourceReference, + TypeVisitor, + CommentTag, +} from "../../models"; import { BindOption, filterMap, @@ -37,17 +33,17 @@ import { * These tags will have their type information stripped when parsing, but still * provide useful information for documentation. */ -const TAG_BLACKLIST = [ - "augments", - "callback", - "class", - "constructor", - "enum", - "extends", - "this", - "type", - "typedef", -]; +const NEVER_RENDERED = [ + "@augments", + "@callback", + "@class", + "@constructor", + "@enum", + "@extends", + "@this", + "@type", + "@typedef", +] as const; /** * A handler that parses TypeDoc comments and attaches {@link Comment} instances to @@ -56,7 +52,19 @@ const TAG_BLACKLIST = [ @Component({ name: "comment" }) export class CommentPlugin extends ConverterComponent { @BindOption("excludeTags") - excludeTags!: string[]; + excludeTags!: `@${string}`[]; + + @BindOption("excludeInternal") + excludeInternal!: boolean; + + @BindOption("excludePrivate") + excludePrivate!: boolean; + + @BindOption("excludeProtected") + excludeProtected!: boolean; + + @BindOption("excludeNotDocumented") + excludeNotDocumented!: boolean; /** * Create a new CommentPlugin instance. @@ -78,38 +86,47 @@ export class CommentPlugin extends ConverterComponent { * @param comment The comment that should be searched for modifiers. */ private applyModifiers(reflection: Reflection, comment: Comment) { - if (comment.hasTag("private")) { + if (comment.hasModifier("@private")) { reflection.setFlag(ReflectionFlag.Private); if (reflection.kindOf(ReflectionKind.CallSignature)) { reflection.parent?.setFlag(ReflectionFlag.Private); } - comment.removeTags("private"); + comment.removeModifier("@private"); } - if (comment.hasTag("protected")) { + if (comment.hasModifier("@protected")) { reflection.setFlag(ReflectionFlag.Protected); if (reflection.kindOf(ReflectionKind.CallSignature)) { reflection.parent?.setFlag(ReflectionFlag.Protected); } - comment.removeTags("protected"); + comment.removeModifier("@protected"); } - if (comment.hasTag("public")) { + if (comment.hasModifier("@public")) { reflection.setFlag(ReflectionFlag.Public); if (reflection.kindOf(ReflectionKind.CallSignature)) { reflection.parent?.setFlag(ReflectionFlag.Public); } - comment.removeTags("public"); + comment.removeModifier("@public"); } - if (comment.hasTag("event")) { - if (reflection.kindOf(ReflectionKind.CallSignature)) { - if (reflection.parent) { - reflection.parent.kind = ReflectionKind.Event; - } - } - reflection.kind = ReflectionKind.Event; - comment.removeTags("event"); + if (comment.hasModifier("@readonly")) { + const target = reflection.kindOf(ReflectionKind.GetSignature) + ? reflection.parent! + : reflection; + target.setFlag(ReflectionFlag.Readonly); + comment.removeModifier("@readonly"); + } + + if ( + comment.hasModifier("@event") || + comment.hasModifier("@eventProperty") + ) { + comment.blockTags.push( + new CommentTag("@group", [{ kind: "text", text: "Events" }]) + ); + comment.removeModifier("@event"); + comment.removeModifier("@eventProperty"); } if ( @@ -118,8 +135,8 @@ export class CommentPlugin extends ConverterComponent { ) || reflection.kind === ReflectionKind.Project ) { - comment.removeTags("module"); - comment.removeTags("packagedocumentation"); + comment.removeTags("@module"); + comment.removeModifier("@packageDocumentation"); } } @@ -131,32 +148,27 @@ export class CommentPlugin extends ConverterComponent { */ private onCreateTypeParameter( _context: Context, - reflection: TypeParameterReflection, - node?: ts.Node + reflection: TypeParameterReflection ) { - if (node && ts.isJSDocTemplateTag(node.parent)) { - const comment = getJsDocCommentText(node.parent.comment); - if (comment) { - reflection.comment = new Comment(comment); - } - } - - const comment = reflection.parent && reflection.parent.comment; + const comment = reflection.parent?.comment; if (comment) { - let tag = comment.getTag("typeparam", reflection.name); + let tag = comment.getIdentifiedTag(reflection.name, "@typeParam"); if (!tag) { - tag = comment.getTag("template", reflection.name); + tag = comment.getIdentifiedTag(reflection.name, "@template"); } if (!tag) { - tag = comment.getTag("param", `<${reflection.name}>`); + tag = comment.getIdentifiedTag( + `<${reflection.name}>`, + "@param" + ); } if (!tag) { - tag = comment.getTag("param", reflection.name); + tag = comment.getIdentifiedTag(reflection.name, "@param"); } if (tag) { - reflection.comment = new Comment(tag.text); - removeIfPresent(comment.tags, tag); + reflection.comment = new Comment(tag.content); + removeIfPresent(comment.blockTags, tag); } } } @@ -170,77 +182,25 @@ export class CommentPlugin extends ConverterComponent { * @param reflection The reflection that is currently processed. * @param node The node that is currently processed if available. */ - private onDeclaration( - context: Context, - reflection: Reflection, - node?: ts.Node - ) { - if ( - reflection.kindOf( - ReflectionKind.FunctionOrMethod | ReflectionKind.Constructor - ) - ) { - // We only want a comment on functions/methods if this is a set of overloaded functions. - // In that case, TypeDoc lets you put a comment on the implementation, and will copy it over to - // the available signatures so that you can avoid documenting things multiple times. - // Once TypeDoc has proper support for TSDoc, this will go away since the same thing will be - // possible by using a @inheritDoc tag to specify that docs should be copied from a specific signature. - let specialOverloadCase = false; - if ( - node && - (ts.isFunctionDeclaration(node) || - ts.isMethodDeclaration(node) || - ts.isConstructorDeclaration(node)) - ) { - const symbol = - node.name && context.checker.getSymbolAtLocation(node.name); - if (symbol && symbol.declarations) { - const declarations = symbol.declarations.filter( - (d) => - ts.isFunctionDeclaration(d) || - ts.isMethodDeclaration(d) || - ts.isConstructorDeclaration(d) - ); - if ( - declarations.length > 1 && - "body" in declarations[declarations.length - 1] - ) { - node = declarations[declarations.length - 1]; - specialOverloadCase = true; - } - } - } - - if (!specialOverloadCase) return; - } - - // Clean this up in 0.23. We should really accept a ts.Symbol so we don't need exportSymbol on Context - const exportNode = context.exportSymbol?.getDeclarations()?.[0]; - let rawComment = - exportNode && getRawComment(exportNode, this.application.logger); - rawComment ??= node && getRawComment(node, this.application.logger); - if (!rawComment) { - return; - } - - const comment = parseComment(rawComment, reflection.comment); + private onDeclaration(_context: Context, reflection: Reflection) { + const comment = reflection.comment; + if (!comment) return; if (reflection.kindOf(ReflectionKind.Module)) { - const tag = comment.getTag("module"); + const tag = comment.getTag("@module"); if (tag) { // If no name is specified, this is a flag to mark a comment as a module comment // and should not result in a reflection rename. - const newName = tag.text.trim(); - if (newName.length) { + const newName = Comment.combineDisplayParts(tag.content).trim(); + if (newName.length && !newName.includes("\n")) { reflection.name = newName; } - removeIfPresent(comment.tags, tag); + removeIfPresent(comment.blockTags, tag); } } this.applyModifiers(reflection, comment); this.removeExcludedTags(comment); - reflection.comment = comment; } /** @@ -249,25 +209,25 @@ export class CommentPlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. */ private onBeginResolve(context: Context) { - const excludeInternal = - this.application.options.getValue("excludeInternal"); - const excludePrivate = - this.application.options.getValue("excludePrivate"); - const excludeProtected = - this.application.options.getValue("excludeProtected"); - const project = context.project; const reflections = Object.values(project.reflections); // Remove hidden reflections - const hidden = reflections.filter((reflection) => - CommentPlugin.isHidden( - reflection, - excludeInternal, - excludePrivate, - excludeProtected - ) - ); + const hidden = new Set(); + for (const ref of reflections) { + if (ref.kindOf(ReflectionKind.Accessor) && ref.flags.isReadonly) { + const decl = ref as DeclarationReflection; + if (decl.setSignature) { + hidden.add(decl.setSignature); + } + // Clear flag set by @readonly since it shouldn't be rendered. + ref.setFlag(ReflectionFlag.Readonly, false); + } + + if (this.isHidden(ref)) { + hidden.add(ref); + } + } hidden.forEach((reflection) => project.removeReflection(reflection)); // remove functions with empty signatures after their signatures have been removed @@ -286,9 +246,8 @@ export class CommentPlugin extends ConverterComponent { }); someRemoved.forEach((reflection) => { reflection.sources = unique( - reflection.signatures!.reduce( - (c, s) => c.concat(s.sources || []), - [] + reflection.signatures!.flatMap( + (s) => s.sources ?? [] ) ); }); @@ -297,7 +256,7 @@ export class CommentPlugin extends ConverterComponent { /** * Triggered when the converter resolves a reflection. * - * Cleans up comment tags related to signatures like @param or @return + * Cleans up comment tags related to signatures like `@param` or `@returns` * and moves their data to the corresponding parameter reflections. * * This hook also copies over the comment of function implementations to their @@ -306,25 +265,39 @@ export class CommentPlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. * @param reflection The reflection that is currently resolved. */ - private onResolve(_context: Context, reflection: DeclarationReflection) { + private onResolve(context: Context, reflection: Reflection) { + if (reflection.comment) { + reflection.label = extractLabelTag(reflection.comment); + if (reflection.label && !/[A-Z_][A-Z0-9_]/.test(reflection.label)) { + context.logger.warn( + `The label "${ + reflection.label + }" for ${reflection.getFriendlyFullName()} cannot be referenced with a declaration reference. ` + + `Labels may only contain A-Z, 0-9, and _, and may not start with a number.` + ); + } + + mergeSeeTags(reflection.comment); + } + if (!(reflection instanceof DeclarationReflection)) { return; } if (reflection.type instanceof ReflectionType) { - this.addCommentToSignatures( + this.moveCommentToSignatures( reflection, reflection.type.declaration.getNonIndexSignatures() ); } else { - this.addCommentToSignatures( + this.moveCommentToSignatures( reflection, reflection.getNonIndexSignatures() ); } } - private addCommentToSignatures( + private moveCommentToSignatures( reflection: DeclarationReflection, signatures: SignatureReflection[] ) { @@ -333,91 +306,78 @@ export class CommentPlugin extends ConverterComponent { } const comment = reflection.comment; - if (comment && comment.hasTag("returns")) { - comment.returns = comment.getTag("returns")!.text; - comment.removeTags("returns"); - } - signatures.forEach((signature) => { - let childComment = signature.comment; - if (childComment && childComment.hasTag("returns")) { - childComment.returns = childComment.getTag("returns")!.text; - childComment.removeTags("returns"); - } - - if (comment) { - if (!childComment) { - childComment = signature.comment = new Comment(); - } + // Since this reflection has signatures, remove the comment from the parent + // reflection. This is important so that in type aliases we don't end up with + // a comment rendered twice. + delete reflection.comment; - childComment.shortText ||= comment.shortText; - childComment.text ||= comment.text; - childComment.returns ||= comment.returns; - childComment.tags = childComment.tags.length - ? childComment.tags - : [...comment.tags]; - } + for (const signature of signatures) { + const childComment = (signature.comment ||= comment?.clone()); + if (!childComment) continue; signature.parameters?.forEach((parameter, index) => { - let tag: CommentTag | undefined; - if (childComment && parameter.name === "__namedParameters") { - const commentParams = childComment?.tags.filter( + if (parameter.name === "__namedParameters") { + const commentParams = childComment.blockTags.filter( (tag) => - tag.tagName === "param" && - !tag.paramName.includes(".") + tag.tag === "@param" && !tag.name?.includes(".") ); if ( signature.parameters?.length === commentParams.length && - commentParams[index].paramName + commentParams[index].name ) { - parameter.name = commentParams[index].paramName; + parameter.name = commentParams[index].name!; } } - if (childComment) { - moveNestedParamTags(childComment, parameter); - tag = childComment.getTag("param", parameter.name); - } - if (comment && !tag) { - tag = comment.getTag("param", parameter.name); - } + + moveNestedParamTags(childComment, parameter); + const tag = childComment.getIdentifiedTag( + parameter.name, + "@param" + ); + if (tag) { - parameter.comment = new Comment(tag.text); + parameter.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } }); - signature.typeParameters?.forEach((parameter) => { - let tag: CommentTag | undefined; - if (childComment) { - tag = - childComment.getTag("typeparam", parameter.name) || - childComment.getTag("template", parameter.name) || - childComment.getTag("param", `<${parameter.name}>`); - } - if (comment && !tag) { - tag = - comment.getTag("typeparam", parameter.name) || - comment.getTag("template", parameter.name) || - comment.getTag("param", `<${parameter.name}>`); - } + for (const parameter of signature.typeParameters || []) { + const tag = + childComment.getIdentifiedTag( + parameter.name, + "@typeParam" + ) || + childComment.getIdentifiedTag( + parameter.name, + "@template" + ) || + childComment.getIdentifiedTag( + `<${parameter.name}>`, + "@param" + ); if (tag) { - parameter.comment = new Comment(tag.text); + parameter.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } - }); - - childComment?.removeTags("param"); - childComment?.removeTags("typeparam"); - childComment?.removeTags("template"); - }); + } - delete reflection.comment; + childComment?.removeTags("@param"); + childComment?.removeTags("@typeParam"); + childComment?.removeTags("@template"); + } } private removeExcludedTags(comment: Comment) { - for (const tag of TAG_BLACKLIST) { + for (const tag of NEVER_RENDERED) { comment.removeTags(tag); + comment.removeModifier(tag); } for (const tag of this.excludeTags) { comment.removeTags(tag); + comment.removeModifier(tag); } } @@ -426,57 +386,88 @@ export class CommentPlugin extends ConverterComponent { * * @param reflection Reflection to check if hidden */ - private static isHidden( - reflection: Reflection, - excludeInternal: boolean, - excludePrivate: boolean, - excludeProtected: boolean - ) { + private isHidden(reflection: Reflection): boolean { const comment = reflection.comment; if ( reflection.flags.hasFlag(ReflectionFlag.Private) && - excludePrivate + this.excludePrivate ) { return true; } if ( reflection.flags.hasFlag(ReflectionFlag.Protected) && - excludeProtected + this.excludeProtected ) { return true; } if (!comment) { + if (this.excludeNotDocumented) { + // Only allow excludeNotDocumented to exclude root level reflections + if (!(reflection instanceof DeclarationReflection)) { + return false; + } + + // excludeNotDocumented should hide a module only if it has no visible children + if (reflection.kindOf(ReflectionKind.SomeModule)) { + if (!reflection.children) { + return true; + } + return reflection.children.every((child) => + this.isHidden(child) + ); + } + + // enum members should all be included if the parent enum is documented + if (reflection.kind === ReflectionKind.EnumMember) { + return false; + } + + // excludeNotDocumented should never hide parts of "type" reflections + return inTypeLiteral(reflection) === false; + } return false; } return ( - comment.hasTag("hidden") || - comment.hasTag("ignore") || - (comment.hasTag("internal") && excludeInternal) + comment.hasModifier("@hidden") || + comment.hasModifier("@ignore") || + (comment.hasModifier("@internal") && this.excludeInternal) ); } } +function inTypeLiteral(refl: Reflection | undefined) { + while (refl) { + if (refl.kind === ReflectionKind.TypeLiteral) { + return true; + } + refl = refl.parent; + } + return false; +} + // Moves tags like `@param foo.bar docs for bar` into the `bar` property of the `foo` parameter. function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) { const visitor: Partial = { reflection(target) { - const tags = comment.tags.filter( + const tags = comment.blockTags.filter( (t) => - t.tagName === "param" && - t.paramName.startsWith(`${parameter.name}.`) + t.tag === "@param" && + t.name?.startsWith(`${parameter.name}.`) ); for (const tag of tags) { - const path = tag.paramName.split("."); + const path = tag.name!.split("."); path.shift(); const child = target.declaration.getChildByName(path); if (child && !child.comment) { - child.comment = new Comment(tag.text); + child.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } } }, @@ -491,3 +482,29 @@ function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) { parameter.type?.visit(visitor); } + +function extractLabelTag(comment: Comment): string | undefined { + const index = comment.summary.findIndex( + (part) => part.kind === "inline-tag" && part.tag === "@label" + ); + + if (index !== -1) { + return comment.summary.splice(index, 1)[0].text; + } +} +function mergeSeeTags(comment: Comment) { + const see = comment.getTags("@see"); + + if (see.length < 2) return; + + const index = comment.blockTags.indexOf(see[0]); + comment.removeTags("@see"); + + see[0].content = see.flatMap((part) => [ + { kind: "text", text: " - " }, + ...part.content, + { kind: "text", text: "\n" }, + ]); + + comment.blockTags.splice(index, 0, see[0]); +} diff --git a/src/lib/converter/plugins/DecoratorPlugin.ts b/src/lib/converter/plugins/DecoratorPlugin.ts deleted file mode 100644 index fb8cd8519..000000000 --- a/src/lib/converter/plugins/DecoratorPlugin.ts +++ /dev/null @@ -1,130 +0,0 @@ -import * as ts from "typescript"; - -import { ReferenceType } from "../../models/types"; -import type { Reflection, Decorator } from "../../models/reflections/index"; -import { Component, ConverterComponent } from "../components"; -import { Converter } from "../converter"; -import type { Context } from "../context"; - -/** - * A plugin that detects decorators. - */ -@Component({ name: "decorator" }) -export class DecoratorPlugin extends ConverterComponent { - private readonly usages = new Map(); - - /** - * Create a new ImplementsPlugin instance. - */ - override initialize() { - this.listenTo(this.owner, { - [Converter.EVENT_CREATE_DECLARATION]: this.onDeclaration, - [Converter.EVENT_CREATE_PARAMETER]: this.onDeclaration, - [Converter.EVENT_RESOLVE]: this.onBeginResolve, - [Converter.EVENT_END]: () => this.usages.clear(), - }); - } - - /** - * Create an object describing the arguments a decorator is set with. - * - * @param args The arguments resolved from the decorator's call expression. - * @param signature The signature definition of the decorator being used. - * @returns An object describing the decorator parameters, - */ - private extractArguments( - args: ts.NodeArray, - signature: ts.Signature - ): { [name: string]: string | string[] } { - const result: any = {}; - args.forEach((arg: ts.Expression, index: number) => { - if (index < signature.parameters.length) { - const parameter = signature.parameters[index]; - result[parameter.name] = arg.getText(); - } else { - if (!result["..."]) { - result["..."] = []; - } - result["..."].push(arg.getText()); - } - }); - - return result; - } - - /** - * Triggered when the converter has created a declaration or signature reflection. - * - * @param context The context object describing the current state the converter is in. - * @param reflection The reflection that is currently processed. - * @param node The node that is currently processed if available. - */ - private onDeclaration( - context: Context, - reflection: Reflection, - node?: ts.Node - ) { - node?.decorators?.forEach((decorator) => { - let callExpression: ts.CallExpression | undefined; - let identifier: ts.Expression; - - switch (decorator.expression.kind) { - case ts.SyntaxKind.Identifier: - identifier = decorator.expression; - break; - case ts.SyntaxKind.CallExpression: - callExpression = decorator.expression; - identifier = callExpression.expression; - break; - default: - return; - } - - const info: Decorator = { - name: identifier.getText(), - }; - - const type = context.checker.getTypeAtLocation(identifier); - if (type && type.symbol) { - info.type = ReferenceType.createSymbolReference( - context.resolveAliasedSymbol(type.symbol), - context, - info.name - ); - - if (callExpression && callExpression.arguments) { - const signature = - context.checker.getResolvedSignature(callExpression); - if (signature) { - info.arguments = this.extractArguments( - callExpression.arguments, - signature - ); - } - } - - const usages = this.usages.get(type.symbol) ?? []; - usages.push( - ReferenceType.createResolvedReference( - reflection.name, - reflection, - context.project - ) - ); - this.usages.set(type.symbol, usages); - } - - reflection.decorators ??= []; - reflection.decorators.push(info); - }); - } - - private onBeginResolve(context: Context) { - for (const [symbol, ref] of this.usages) { - const reflection = context.project.getReflectionFromSymbol(symbol); - if (reflection) { - reflection.decorates = ref; - } - } - } -} diff --git a/src/lib/converter/plugins/GroupPlugin.ts b/src/lib/converter/plugins/GroupPlugin.ts index 07544954d..33d54c7d3 100644 --- a/src/lib/converter/plugins/GroupPlugin.ts +++ b/src/lib/converter/plugins/GroupPlugin.ts @@ -5,17 +5,17 @@ import { DeclarationReflection, } from "../../models/reflections/index"; import { ReflectionGroup } from "../../models/ReflectionGroup"; -import type { SourceDirectory } from "../../models/sources/directory"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; import { sortReflections, SortStrategy } from "../../utils/sort"; -import { BindOption } from "../../utils"; +import { BindOption, removeIf } from "../../utils"; +import { Comment } from "../../models"; /** * A handler that sorts and groups the found reflections in the resolving phase. * - * The handler sets the ´groups´ property of all reflections. + * The handler sets the `groups` property of all container reflections. */ @Component({ name: "group" }) export class GroupPlugin extends ConverterComponent { @@ -42,6 +42,11 @@ export class GroupPlugin extends ConverterComponent { @BindOption("sort") sortStrategies!: SortStrategy[]; + @BindOption("searchGroupBoosts") + boosts!: Record; + + usedBoosts = new Set(); + /** * Create a new GroupPlugin instance. */ @@ -72,23 +77,25 @@ export class GroupPlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. */ private onEndResolve(context: Context) { - function walkDirectory(directory: SourceDirectory) { - directory.groups = GroupPlugin.getReflectionGroups( - directory.getAllReflections() - ); + this.group(context.project); - for (const dir of Object.values(directory.directories)) { - walkDirectory(dir); - } + const unusedBoosts = new Set(Object.keys(this.boosts)); + for (const boost of this.usedBoosts) { + unusedBoosts.delete(boost); } + this.usedBoosts.clear(); - const project = context.project; - this.group(project); - - walkDirectory(project.directory); - project.files.forEach((file) => { - file.groups = GroupPlugin.getReflectionGroups(file.reflections); - }); + if ( + unusedBoosts.size && + this.application.options.isSet("searchGroupBoosts") + ) { + context.logger.warn( + `Not all groups specified in searchGroupBoosts were used in the documentation.` + + ` The unused groups were:\n\t${Array.from( + unusedBoosts + ).join("\n\t")}` + ); + } } private group(reflection: ContainerReflection) { @@ -98,10 +105,56 @@ export class GroupPlugin extends ConverterComponent { !reflection.groups ) { sortReflections(reflection.children, this.sortStrategies); - reflection.groups = GroupPlugin.getReflectionGroups( - reflection.children - ); + reflection.groups = this.getReflectionGroups(reflection.children); + } + } + + /** + * Extracts the groups for a given reflection. + * + * @privateRemarks + * If you change this, also update getCategories in CategoryPlugin accordingly. + */ + getGroups(reflection: DeclarationReflection) { + const groups = new Set(); + function extractGroupTags(comment: Comment | undefined) { + if (!comment) return; + removeIf(comment.blockTags, (tag) => { + if (tag.tag === "@group") { + groups.add(Comment.combineDisplayParts(tag.content).trim()); + + return true; + } + return false; + }); + } + + extractGroupTags(reflection.comment); + for (const sig of reflection.getNonIndexSignatures()) { + extractGroupTags(sig.comment); + } + + if (reflection.type?.type === "reflection") { + extractGroupTags(reflection.type.declaration.comment); + for (const sig of reflection.type.declaration.getNonIndexSignatures()) { + extractGroupTags(sig.comment); + } + } + + groups.delete(""); + if (groups.size === 0) { + groups.add(GroupPlugin.getKindPlural(reflection.kind)); } + + for (const group of groups) { + if (group in this.boosts) { + this.usedBoosts.add(group); + reflection.relevanceBoost = + (reflection.relevanceBoost ?? 1) * this.boosts[group]; + } + } + + return groups; } /** @@ -112,56 +165,24 @@ export class GroupPlugin extends ConverterComponent { * @param reflections The reflections that should be grouped. * @returns An array containing all children of the given reflection grouped by their kind. */ - static getReflectionGroups( + getReflectionGroups( reflections: DeclarationReflection[] ): ReflectionGroup[] { - const groups: ReflectionGroup[] = []; + const groups = new Map(); + reflections.forEach((child) => { - for (let i = 0; i < groups.length; i++) { - const group = groups[i]; - if (group.kind !== child.kind) { - continue; + for (const name of this.getGroups(child)) { + let group = groups.get(name); + if (!group) { + group = new ReflectionGroup(name); + groups.set(name, group); } group.children.push(child); - return; } - - const group = new ReflectionGroup( - GroupPlugin.getKindPlural(child.kind), - child.kind - ); - group.children.push(child); - groups.push(group); - }); - - groups.forEach((group) => { - let allInherited = true; - let allPrivate = true; - let allProtected = true; - let allExternal = true; - - group.children.forEach((child) => { - allPrivate = child.flags.isPrivate && allPrivate; - allProtected = - (child.flags.isPrivate || child.flags.isProtected) && - allProtected; - allExternal = child.flags.isExternal && allExternal; - - if (child instanceof DeclarationReflection) { - allInherited = !!child.inheritedFrom && allInherited; - } else { - allInherited = false; - } - }); - - group.allChildrenAreInherited = allInherited; - group.allChildrenArePrivate = allPrivate; - group.allChildrenAreProtectedOrPrivate = allProtected; - group.allChildrenAreExternal = allExternal; }); - return groups; + return Array.from(groups.values()); } /** diff --git a/src/lib/converter/plugins/ImplementsPlugin.ts b/src/lib/converter/plugins/ImplementsPlugin.ts index e8ce3984d..e0674a789 100644 --- a/src/lib/converter/plugins/ImplementsPlugin.ts +++ b/src/lib/converter/plugins/ImplementsPlugin.ts @@ -1,5 +1,6 @@ import * as ts from "typescript"; import { + ContainerReflection, DeclarationReflection, Reflection, ReflectionKind, @@ -10,7 +11,6 @@ import { filterMap, zip } from "../../utils/array"; import { Component, ConverterComponent } from "../components"; import type { Context } from "../context"; import { Converter } from "../converter"; -import { copyComment } from "../utils/reflections"; /** * A plugin that detects interface implementations of functions and @@ -25,7 +25,11 @@ export class ImplementsPlugin extends ConverterComponent { * Create a new ImplementsPlugin instance. */ override initialize() { - this.listenTo(this.owner, Converter.EVENT_RESOLVE, this.onResolve, -10); + this.listenTo( + this.owner, + Converter.EVENT_RESOLVE_END, + this.onResolveEnd + ); this.listenTo( this.owner, Converter.EVENT_CREATE_DECLARATION, @@ -47,38 +51,21 @@ export class ImplementsPlugin extends ConverterComponent { * @param classReflection The reflection of the classReflection class. * @param interfaceReflection The reflection of the interfaceReflection interface. */ - private analyzeClass( + private analyzeImplements( context: Context, classReflection: DeclarationReflection, interfaceReflection: DeclarationReflection ) { + handleInheritedComments(classReflection, interfaceReflection); if (!interfaceReflection.children) { return; } interfaceReflection.children.forEach((interfaceMember) => { - let classMember: DeclarationReflection | undefined; - - if (!classReflection.children) { - return; - } - - for ( - let index = 0, count = classReflection.children.length; - index < count; - index++ - ) { - const child = classReflection.children[index]; - if (child.name !== interfaceMember.name) { - continue; - } - if (child.flags.isStatic !== interfaceMember.flags.isStatic) { - continue; - } - - classMember = child; - break; - } + const classMember = findMatchingMember( + interfaceMember, + classReflection + ); if (!classMember) { return; @@ -92,23 +79,6 @@ export class ImplementsPlugin extends ConverterComponent { interfaceMember, context.project ); - copyComment(classMember, interfaceMember); - - if ( - interfaceMember.kindOf(ReflectionKind.Property) && - classMember.kindOf(ReflectionKind.Accessor) - ) { - if (classMember.getSignature) { - copyComment(classMember.getSignature, interfaceMember); - classMember.getSignature.implementationOf = - classMember.implementationOf; - } - if (classMember.setSignature) { - copyComment(classMember.setSignature, interfaceMember); - classMember.setSignature.implementationOf = - classMember.implementationOf; - } - } if ( interfaceMember.kindOf(ReflectionKind.FunctionOrMethod) && @@ -127,9 +97,10 @@ export class ImplementsPlugin extends ConverterComponent { context.project ); } - copyComment(clsSig, intSig); } } + + handleInheritedComments(classMember, interfaceMember); }); } @@ -150,12 +121,10 @@ export class ImplementsPlugin extends ConverterComponent { ); for (const parent of extendedTypes) { + handleInheritedComments(reflection, parent.reflection); + for (const parentMember of parent.reflection.children ?? []) { - const child = reflection.children?.find( - (child) => - child.name == parentMember.name && - child.flags.isStatic === parentMember.flags.isStatic - ); + const child = findMatchingMember(parentMember, reflection); if (child) { const key = child.overwrites @@ -171,7 +140,6 @@ export class ImplementsPlugin extends ConverterComponent { parentSig, context.project ); - copyComment(childSig, parentSig); } child[key] = ReferenceType.createResolvedReference( @@ -179,20 +147,19 @@ export class ImplementsPlugin extends ConverterComponent { parentMember, context.project ); - copyComment(child, parentMember); + + handleInheritedComments(child, parentMember); } } } } - /** - * Triggered when the converter resolves a reflection. - * - * @param context The context object describing the current state the converter is in. - * @param reflection The reflection that is currently resolved. - */ - private onResolve(context: Context, reflection: DeclarationReflection) { - this.tryResolve(context, reflection); + private onResolveEnd(context: Context) { + for (const reflection of Object.values(context.project.reflections)) { + if (reflection instanceof DeclarationReflection) { + this.tryResolve(context, reflection); + } + } } private tryResolve(context: Context, reflection: DeclarationReflection) { @@ -235,22 +202,19 @@ export class ImplementsPlugin extends ConverterComponent { if ( type.reflection && - type.reflection.kindOf(ReflectionKind.Interface) + type.reflection.kindOf(ReflectionKind.ClassOrInterface) ) { - this.analyzeClass( + this.analyzeImplements( context, reflection, - type.reflection + type.reflection as DeclarationReflection ); } }); } if ( - reflection.kindOf([ - ReflectionKind.Class, - ReflectionKind.Interface, - ]) && + reflection.kindOf(ReflectionKind.ClassOrInterface) && reflection.extendedTypes ) { this.analyzeInheritance(context, reflection); @@ -266,10 +230,7 @@ export class ImplementsPlugin extends ConverterComponent { } // Need this because we re-use reflections for type literals. - if ( - !reflection.parent || - !reflection.parent.kindOf(ReflectionKind.ClassOrInterface) - ) { + if (!reflection.parent?.kindOf(ReflectionKind.ClassOrInterface)) { return; } @@ -463,3 +424,109 @@ function createLink( } } } + +/** + * Responsible for copying comments from "parent" reflections defined + * in either a base class or implemented interface to the child class. + */ +function handleInheritedComments( + child: DeclarationReflection, + parent: DeclarationReflection +) { + copyComment(child, parent); + + if ( + parent.kindOf(ReflectionKind.Property) && + child.kindOf(ReflectionKind.Accessor) + ) { + if (child.getSignature) { + copyComment(child.getSignature, parent); + child.getSignature.implementationOf = child.implementationOf; + } + if (child.setSignature) { + copyComment(child.setSignature, parent); + child.setSignature.implementationOf = child.implementationOf; + } + } + if ( + parent.kindOf(ReflectionKind.Accessor) && + child.kindOf(ReflectionKind.Accessor) + ) { + if (parent.getSignature && child.getSignature) { + copyComment(child.getSignature, parent.getSignature); + } + if (parent.setSignature && child.setSignature) { + copyComment(child.setSignature, parent.setSignature); + } + } + + if ( + parent.kindOf(ReflectionKind.FunctionOrMethod) && + parent.signatures && + child.signatures + ) { + for (const [cs, ps] of zip(child.signatures, parent.signatures)) { + copyComment(cs, ps); + } + } +} + +/** + * Copy the comment of the source reflection to the target reflection with a JSDoc style copy + * function. The TSDoc copy function is in the InheritDocPlugin. + */ +function copyComment(target: Reflection, source: Reflection) { + if (target.comment) { + // We might still want to copy, if the child has a JSDoc style inheritDoc tag. + const tag = target.comment.getTag("@inheritDoc"); + if (!tag || tag.name) { + return; + } + } + + if (!source.comment) { + return; + } + + target.comment = source.comment.clone(); + + if ( + target instanceof DeclarationReflection && + source instanceof DeclarationReflection + ) { + for (const [tt, ts] of zip( + target.typeParameters || [], + source.typeParameters || [] + )) { + copyComment(tt, ts); + } + } + if ( + target instanceof SignatureReflection && + source instanceof SignatureReflection + ) { + for (const [tt, ts] of zip( + target.typeParameters || [], + source.typeParameters || [] + )) { + copyComment(tt, ts); + } + for (const [pt, ps] of zip( + target.parameters || [], + source.parameters || [] + )) { + copyComment(pt, ps); + } + } +} + +function findMatchingMember( + toMatch: Reflection, + container: ContainerReflection +) { + return container.children?.find( + (child) => + child.name == toMatch.name && + child.flags.isStatic === toMatch.flags.isStatic + ); +} diff --git a/src/lib/converter/plugins/InheritDocPlugin.ts b/src/lib/converter/plugins/InheritDocPlugin.ts index 7491cb5e7..64af5b1b6 100644 --- a/src/lib/converter/plugins/InheritDocPlugin.ts +++ b/src/lib/converter/plugins/InheritDocPlugin.ts @@ -1,20 +1,21 @@ import { - ContainerReflection, + Comment, DeclarationReflection, - ReflectionKind, SignatureReflection, } from "../../models"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; -import { copyComment } from "../utils/reflections"; -import { - Reflection, - TraverseCallback, -} from "../../models/reflections/abstract"; +import type { Reflection } from "../../models/reflections/abstract"; +import { DefaultMap } from "../../utils"; +import { zip } from "../../utils/array"; +import { parseDeclarationReference } from "../comments/declarationReference"; +import { resolveDeclarationReference } from "../comments/declarationReferenceResolver"; /** - * A plugin that handles `inheritDoc` by copying documentation from another API item. + * A plugin that handles `@inheritDoc` tags by copying documentation from another API item. + * It is NOT responsible for handling bare JSDoc style `@inheritDoc` tags which do not specify + * a target to inherit from. Those are handled by the ImplementsPlugin class. * * What gets copied: * - short text @@ -26,65 +27,177 @@ import { */ @Component({ name: "inheritDoc" }) export class InheritDocPlugin extends ConverterComponent { + // Key is depended on by Values + private dependencies = new DefaultMap(() => []); + /** * Create a new InheritDocPlugin instance. */ override initialize() { - this.listenTo( - this.owner, - { - [Converter.EVENT_RESOLVE]: this.onResolve, - }, - undefined, - -200 + this.owner.on( + Converter.EVENT_RESOLVE_END, + this.processInheritDoc, + this ); } /** - * Triggered when the converter resolves a reflection. - * * Traverse through reflection descendant to check for `inheritDoc` tag. - * If encountered, the parameter of the tag iss used to determine a source reflection + * If encountered, the parameter of the tag is used to determine a source reflection * that will provide actual comment. * * @param context The context object describing the current state the converter is in. * @param reflection The reflection that is currently resolved. */ - private onResolve(_context: Context, reflection: DeclarationReflection) { - if (reflection instanceof ContainerReflection) { - const descendantsCallback: TraverseCallback = (item) => { - item.traverse(descendantsCallback); - const inheritDoc = - item.comment?.getTag("inheritdoc")?.paramName; - const source = - inheritDoc && reflection.findReflectionByName(inheritDoc); - let referencedReflection = source; - if ( - source instanceof DeclarationReflection && - item instanceof SignatureReflection - ) { - const isFunction = source.kindOf( - ReflectionKind.FunctionOrMethod - ); - - if (isFunction) { - // Assumes that if there are overloads, they are declared in the same order as the parent. - // TS doesn't check this, but if a user messes this up then they are almost - // guaranteed to run into bugs where they can't call a method on a child class - // but if they assign (without a type assertion) that child to a variable of the parent class - // then they can call the method. - const itemIndex = - item.parent.signatures?.indexOf(item) ?? 0; - referencedReflection = source.signatures?.[itemIndex]; - } - } + private processInheritDoc(context: Context) { + for (const reflection of Object.values(context.project.reflections)) { + const source = extractInheritDocTagReference(reflection); + if (!source) continue; + + const declRef = parseDeclarationReference(source, 0, source.length); + if (!declRef || /\S/.test(source.substring(declRef[1]))) { + context.logger.warn( + `Declaration reference in @inheritDoc for ${reflection.getFriendlyFullName()} was not fully parsed and may resolve incorrectly.` + ); + } + let sourceRefl = + declRef && resolveDeclarationReference(reflection, declRef[0]); - if (referencedReflection instanceof Reflection) { - copyComment(item, referencedReflection); + if (reflection instanceof SignatureReflection) { + // Assumes that if there are overloads, they are declared in the same order as the parent. + // TS doesn't check this, but if a user messes this up then they are almost + // guaranteed to run into bugs where they can't call a method on a child class + // but if they assign (without a type assertion) that child to a variable of the parent class + // then they can call the method. + if (sourceRefl instanceof DeclarationReflection) { + const index = reflection.parent + .getAllSignatures() + .indexOf(reflection); + sourceRefl = sourceRefl.getAllSignatures()[index]; } - return true; - }; - reflection.traverse(descendantsCallback); + } + + if (!sourceRefl) { + this.application.logger.warn( + `Failed to find "${source}" to inherit the comment from in the comment for ${reflection.getFullName()}` + ); + continue; + } + + this.copyComment(sourceRefl, reflection); + } + + this.createCircularDependencyWarnings(); + this.dependencies.clear(); + } + + private copyComment(source: Reflection, target: Reflection) { + if (!target.comment) return; + + if (!source.comment) { + this.application.logger.warn( + `${target.getFullName()} tried to copy a comment from ${source.getFullName()} with @inheritDoc, but the source has no associated comment.` + ); + return; + } + + // If the source also has a @inheritDoc tag, we can't do anything yet. + // We'll try again later, once we've resolved the source's @inheritDoc reference. + if (extractInheritDocTagReference(source)) { + this.dependencies.get(source).push(target); + return; + } + + target.comment.removeTags("@inheritDoc"); + target.comment.summary = Comment.cloneDisplayParts( + source.comment.summary + ); + const remarks = source.comment.getTag("@remarks"); + if (remarks) { + target.comment.blockTags.unshift(remarks.clone()); + } + const returns = source.comment.getTag("@returns"); + if (returns) { + target.comment.blockTags.push(returns.clone()); + } + + if ( + source instanceof SignatureReflection && + target instanceof SignatureReflection + ) { + copySummaries(source.parameters, target.parameters); + copySummaries(source.typeParameters, target.typeParameters); + } else if ( + source instanceof DeclarationReflection && + target instanceof DeclarationReflection + ) { + copySummaries(source.typeParameters, target.typeParameters); } + + // Now copy the comment for anyone who depends on me. + const dependent = this.dependencies.get(target); + this.dependencies.delete(target); + for (const target2 of dependent) { + this.copyComment(target, target2); + } + } + + private createCircularDependencyWarnings() { + const unwarned = new Set(this.dependencies.keys()); + + const generateWarning = (orig: Reflection) => { + const parts = [orig.name]; + unwarned.delete(orig); + let work = orig; + + do { + work = this.dependencies.get(work)[0]; + unwarned.delete(work); + parts.push(work.name); + } while (!this.dependencies.get(work).includes(orig)); + parts.push(orig.name); + + this.application.logger.warn( + `@inheritDoc specifies a circular inheritance chain: ${parts + .reverse() + .join(" -> ")}` + ); + }; + + for (const orig of this.dependencies.keys()) { + if (unwarned.has(orig)) { + generateWarning(orig); + } + } + } +} + +function copySummaries( + source: Reflection[] | undefined, + target: Reflection[] | undefined +) { + for (const [s, t] of zip(source || [], target || [])) { + t.comment = new Comment(s.comment?.summary); + } +} + +function extractInheritDocTagReference( + reflection: Reflection +): string | undefined { + const comment = reflection.comment; + if (!comment) return; + + const blockTag = comment.blockTags.find((tag) => tag.tag === "@inheritDoc"); + + if (blockTag) { + return blockTag.name; + } + + const inlineTag = comment.summary.find( + (part) => part.kind === "inline-tag" && part.tag === "@inheritDoc" + ); + + if (inlineTag) { + return inlineTag.text; } } diff --git a/src/lib/converter/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts new file mode 100644 index 000000000..78be33191 --- /dev/null +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -0,0 +1,272 @@ +import type { Reflection } from "../../models/reflections/abstract"; +import { Component, ConverterComponent } from "../components"; +import type { Context } from "../../converter"; +import { ConverterEvents } from "../converter-events"; +import { parseDeclarationReference } from "../comments/declarationReference"; +import ts = require("typescript"); +import { BindOption, ValidationOptions } from "../../utils"; +import { resolveDeclarationReference } from "../comments/declarationReferenceResolver"; +import type { + CommentDisplayPart, + InlineTagDisplayPart, +} from "../../models/comments"; + +const urlPrefix = /^(http|ftp)s?:\/\//; +const brackets = /\[\[([^\]]+)\]\]/g; +/** + * A plugin that resolves `{@link Foo}` tags. + */ +@Component({ name: "link-resolver" }) +export class LinkResolverPlugin extends ConverterComponent { + @BindOption("validation") + validation!: ValidationOptions; + + /** + * Create a new LinkResolverPlugin instance. + */ + override initialize() { + super.initialize(); + this.owner.on(ConverterEvents.RESOLVE_END, this.onResolve, this, -300); + } + + /** + * Find all old style double bracket references to symbols within the given text and transform them into a link. + * + * @param text The text that should be parsed. + * @returns The text with symbol references replaced by links. + */ + private replaceBrackets( + reflection: Reflection, + text: string + ): CommentDisplayPart[] { + const parts: CommentDisplayPart[] = []; + + let begin = 0; + brackets.lastIndex = 0; + for (const match of text.matchAll(brackets)) { + if (begin != match.index) { + parts.push({ + kind: "text", + text: text.substring(begin, match.index), + }); + } + begin = match.index! + match[0].length; + const content = match[1]; + + const { target, caption } = + LinkResolverPlugin.splitLinkText(content); + + if (urlPrefix.test(target)) { + parts.push({ + kind: "inline-tag", + tag: "@link", + text: caption, + target, + }); + } else { + const targetRefl = reflection.findReflectionByName(target); + if (targetRefl) { + parts.push({ + kind: "inline-tag", + tag: "@link", + text: caption, + target: targetRefl, + }); + } else { + if (this.validation.invalidLink) { + this.application.logger.warn( + "Failed to find target: " + content + ); + } + parts.push({ + kind: "inline-tag", + tag: "@link", + text: content, + }); + } + } + } + parts.push({ + kind: "text", + text: text.substring(begin), + }); + + return parts; + } + + onResolve(context: Context) { + for (const reflection of Object.values(context.project.reflections)) { + this.processReflection(reflection); + } + + let warned = false; + const warn = () => { + if (!warned) { + warned = true; + this.application.logger.warn( + `README: Comment [[target]] style links are deprecated and will be removed in 0.24` + ); + } + }; + + if (context.project.readme) { + context.project.readme = this.processParts( + context.project, + context.project.readme, + warn + ); + } + } + + processReflection(reflection: Reflection) { + const comment = reflection.comment; + if (!comment) return; + + let warned = false; + const warn = () => { + if (!warned) { + warned = true; + this.application.logger.warn( + `${reflection.getFriendlyFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24` + ); + } + }; + + comment.summary = this.processParts(reflection, comment.summary, warn); + for (const tag of comment.blockTags) { + tag.content = this.processParts(reflection, tag.content, warn); + } + } + + private processParts( + reflection: Reflection, + parts: CommentDisplayPart[], + warn: () => void + ): CommentDisplayPart[] { + return parts.flatMap((part) => + this.processPart(reflection, part, warn) + ); + } + + private processPart( + reflection: Reflection, + part: CommentDisplayPart, + warn: () => void + ): CommentDisplayPart | CommentDisplayPart[] { + if (part.kind === "text" && brackets.test(part.text)) { + warn(); + return this.replaceBrackets(reflection, part.text); + } + + if (part.kind === "inline-tag") { + if ( + part.tag === "@link" || + part.tag === "@linkcode" || + part.tag === "@linkplain" + ) { + return resolveLinkTag(reflection, part, (msg: string) => { + if (this.validation.invalidLink) { + this.application.logger.warn(msg); + } + }); + } + } + + return part; + } + + /** + * Split the given link into text and target at first pipe or space. + * + * @param text The source string that should be checked for a split character. + * @returns An object containing the link text and target. + */ + static splitLinkText(text: string): { caption: string; target: string } { + let splitIndex = text.indexOf("|"); + if (splitIndex === -1) { + splitIndex = text.search(/\s/); + } + + if (splitIndex !== -1) { + return { + caption: text + .substring(splitIndex + 1) + .replace(/\n+/, " ") + .trim(), + target: text.substring(0, splitIndex).trim(), + }; + } else { + return { + caption: text, + target: text, + }; + } + } +} + +function resolveLinkTag( + reflection: Reflection, + part: InlineTagDisplayPart, + warn: (message: string) => void +) { + let pos = 0; + const end = part.text.length; + + // Try to parse one + const declRef = parseDeclarationReference(part.text, pos, end); + + let target: Reflection | undefined; + if (declRef) { + // Got one, great! Try to resolve the link + target = resolveDeclarationReference(reflection, declRef[0]); + pos = declRef[1]; + } + + // If resolution via a declaration reference failed, revert to the legacy "split and check" + // method... this should go away in 0.24, once people have had a chance to migrate any failing links. + if (!target) { + const resolved = legacyResolveLinkTag(reflection, part); + if (resolved) { + warn( + `Failed to resolve {@link ${ + part.text + }} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.` + ); + } + return resolved; + } + + // Remaining text after an optional pipe is the link text, so advance + // until that's consumed. + while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) { + pos++; + } + if (pos < end && part.text[pos] === "|") { + pos++; + } + + part.target = target; + part.text = part.text.substring(pos).trim() || target.name; + + return part; +} + +function legacyResolveLinkTag( + reflection: Reflection, + part: InlineTagDisplayPart +) { + const { caption, target } = LinkResolverPlugin.splitLinkText(part.text); + + if (urlPrefix.test(target)) { + part.text = caption; + part.target = target; + } else { + const targetRefl = reflection.findReflectionByName(target); + if (targetRefl) { + part.text = caption; + part.target = targetRefl; + } + } + + return part; +} diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts index c39dff91e..79e6969c6 100644 --- a/src/lib/converter/plugins/PackagePlugin.ts +++ b/src/lib/converter/plugins/PackagePlugin.ts @@ -7,6 +7,8 @@ import type { Context } from "../context"; import { BindOption, readFile } from "../../utils"; import { getCommonDirectory } from "../../utils/fs"; import { nicePath } from "../../utils/paths"; +import { lexCommentString } from "../comments/rawLexer"; +import { parseComment } from "../comments/parser"; /** * A handler that tries to find the package.json and readme.md files of the @@ -98,24 +100,47 @@ export class PackagePlugin extends ConverterComponent { private onBeginResolve(context: Context) { const project = context.project; if (this.readmeFile) { - project.readme = readFile(this.readmeFile); + const readme = readFile(this.readmeFile); + const comment = parseComment( + lexCommentString(readme), + context.converter.config, + (msg) => { + this.application.logger.warn( + `${msg} in ${this.readmeFile}` + ); + } + ); + + if (comment.blockTags.length || comment.modifierTags.size) { + const ignored = [ + ...comment.blockTags.map((tag) => tag.tag), + ...comment.modifierTags, + ]; + this.application.logger.warn( + `Block and modifier tags will be ignored within the readme:\n\t${ignored.join( + "\n\t" + )}` + ); + } + + project.readme = comment.summary; } if (this.packageFile) { - project.packageInfo = JSON.parse(readFile(this.packageFile)); + const packageInfo = JSON.parse(readFile(this.packageFile)); if (!project.name) { - if (!project.packageInfo.name) { + if (!packageInfo.name) { context.logger.warn( 'The --name option was not specified, and package.json does not have a name field. Defaulting project name to "Documentation".' ); project.name = "Documentation"; } else { - project.name = String(project.packageInfo.name); + project.name = String(packageInfo.name); } } if (this.includeVersion) { - if (project.packageInfo.version) { - project.name = `${project.name} - v${project.packageInfo.version}`; + if (packageInfo.version) { + project.name = `${project.name} - v${packageInfo.version}`; } else { context.logger.warn( "--includeVersion was specified, but package.json does not specify a version." diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index f5630c926..8a9971226 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -1,20 +1,15 @@ -import * as Path from "path"; import * as ts from "typescript"; -import { - Reflection, - ProjectReflection, - DeclarationReflection, -} from "../../models/reflections/index"; -import { SourceDirectory, SourceFile } from "../../models/sources/index"; +import type { Reflection } from "../../models/reflections/index"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; import { BindOption } from "../../utils"; import { isNamedNode } from "../utils/nodes"; import { getCommonDirectory, normalizePath } from "../../utils/fs"; -import { relative } from "path"; -import * as assert from "assert"; +import { dirname, relative } from "path"; +import { SourceReference } from "../../models"; +import { gitIsInstalled, Repository } from "../utils/repository"; /** * A handler that attaches source file information to reflections. @@ -24,16 +19,26 @@ export class SourcePlugin extends ConverterComponent { @BindOption("disableSources") readonly disableSources!: boolean; - /** - * A map of all generated {@link SourceFile} instances. - */ - private fileMappings: { [name: string]: SourceFile } = {}; + @BindOption("gitRevision") + readonly gitRevision!: string; + + @BindOption("gitRemote") + readonly gitRemote!: string; /** * All file names to find the base path from. */ private fileNames = new Set(); - private basePath?: string; + + /** + * List of known repositories. + */ + private repositories: { [path: string]: Repository } = {}; + + /** + * List of paths known to be not under git control. + */ + private ignoredPaths = new Set(); /** * Create a new SourceHandler instance. @@ -44,28 +49,12 @@ export class SourcePlugin extends ConverterComponent { [Converter.EVENT_CREATE_DECLARATION]: this.onDeclaration, [Converter.EVENT_CREATE_SIGNATURE]: this.onDeclaration, [Converter.EVENT_RESOLVE_BEGIN]: this.onBeginResolve, - [Converter.EVENT_RESOLVE]: this.onResolve, - [Converter.EVENT_RESOLVE_END]: this.onEndResolve, }); } - private getSourceFile( - fileName: string, - project: ProjectReflection - ): SourceFile { - if (!this.fileMappings[fileName]) { - const file = new SourceFile(fileName); - this.fileMappings[fileName] = file; - project.files.push(file); - } - - return this.fileMappings[fileName]; - } - private onEnd() { - this.fileMappings = {}; + // Should probably clear repositories/ignoredPaths here, but these aren't likely to change between runs... this.fileNames.clear(); - this.basePath = void 0; } /** @@ -73,50 +62,40 @@ export class SourcePlugin extends ConverterComponent { * * Attach the current source file to the {@link DeclarationReflection.sources} array. * - * @param context The context object describing the current state the converter is in. + * @param _context The context object describing the current state the converter is in. * @param reflection The reflection that is currently processed. - * @param node The node that is currently processed if available. */ - private onDeclaration( - context: Context, - reflection: Reflection, - node?: ts.Node - ) { - if (!node || this.disableSources) { - return; - } - const sourceFile = node.getSourceFile(); - const fileName = sourceFile.fileName; - this.fileNames.add(fileName); - const file: SourceFile = this.getSourceFile(fileName, context.project); - - let position: ts.LineAndCharacter; - if (isNamedNode(node)) { - position = ts.getLineAndCharacterOfPosition( - sourceFile, - node.name.getStart() - ); - } else { - position = ts.getLineAndCharacterOfPosition( - sourceFile, - node.getStart() - ); - } - - if (reflection instanceof DeclarationReflection) { - file.reflections.push(reflection); - } + private onDeclaration(_context: Context, reflection: Reflection) { + if (this.disableSources) return; + + const symbol = reflection.project.getSymbolFromReflection(reflection); + for (const node of symbol?.declarations || []) { + const sourceFile = node.getSourceFile(); + const fileName = sourceFile.fileName; + this.fileNames.add(fileName); + + let position: ts.LineAndCharacter; + if (isNamedNode(node)) { + position = ts.getLineAndCharacterOfPosition( + sourceFile, + node.name.getStart() + ); + } else { + position = ts.getLineAndCharacterOfPosition( + sourceFile, + node.getStart() + ); + } - if (!reflection.sources) { - reflection.sources = []; + reflection.sources ||= []; + reflection.sources.push( + new SourceReference( + fileName, + position.line + 1, + position.character + ) + ); } - - reflection.sources.push({ - file: file, - fileName: fileName, - line: position.line + 1, - character: position.character, - }); } /** @@ -125,66 +104,64 @@ export class SourcePlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. */ private onBeginResolve(context: Context) { - this.basePath = getCommonDirectory([...this.fileNames]); - for (const file of context.project.files) { - const fileName = (file.fileName = normalizePath( - relative(this.basePath, file.fileName) - )); - this.fileMappings[fileName] = file; + if (this.disableSources) return; + + const basePath = getCommonDirectory([...this.fileNames]); + + for (const refl of Object.values(context.project.reflections)) { + for (const source of refl.sources || []) { + if (gitIsInstalled) { + const repo = this.getRepository(source.fullFileName); + source.url = repo?.getURL(source.fullFileName); + if (source.url) { + source.url += `#${repo!.getLineNumberAnchor( + source.line + )}`; + } + } + + source.fileName = normalizePath( + relative(basePath, source.fullFileName) + ); + } } } /** - * Triggered when the converter resolves a reflection. + * Check whether the given file is placed inside a repository. * - * @param context The context object describing the current state the converter is in. - * @param reflection The reflection that is currently resolved. + * @param fileName The name of the file a repository should be looked for. + * @returns The found repository info or undefined. */ - private onResolve(_context: Context, reflection: Reflection) { - assert(this.basePath != null); - for (const source of reflection.sources ?? []) { - source.fileName = normalizePath( - relative(this.basePath, source.fileName) - ); + private getRepository(fileName: string): Repository | undefined { + // Check for known non-repositories + const dirName = dirname(fileName); + const segments = dirName.split("/"); + for (let i = segments.length; i > 0; i--) { + if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) { + return; + } } - } - /** - * Triggered when the converter has finished resolving a project. - * - * @param context The context object describing the current state the converter is in. - */ - private onEndResolve(context: Context) { - const project = context.project; - const home = project.directory; - project.files.forEach((file) => { - const reflections: DeclarationReflection[] = []; - file.reflections.forEach((reflection) => { - reflections.push(reflection); - }); - - let directory = home; - const path = Path.dirname(file.fileName); - if (path !== ".") { - path.split("/").forEach((pathPiece) => { - if ( - !Object.prototype.hasOwnProperty.call( - directory.directories, - pathPiece - ) - ) { - directory.directories[pathPiece] = new SourceDirectory( - pathPiece, - directory - ); - } - directory = directory.directories[pathPiece]; - }); + // Check for known repositories + for (const path of Object.keys(this.repositories)) { + if (fileName.toLowerCase().startsWith(path)) { + return this.repositories[path]; } + } - directory.files.push(file); - file.parent = directory; - file.reflections = reflections; - }); + // Try to create a new repository + const repository = Repository.tryCreateRepository( + dirName, + this.gitRevision, + this.gitRemote + ); + if (repository) { + this.repositories[repository.path.toLowerCase()] = repository; + return repository; + } + + // No repository found, add path to ignored paths + this.ignoredPaths.add(dirName); } } diff --git a/src/lib/converter/plugins/index.ts b/src/lib/converter/plugins/index.ts index 2bc97b75f..29564d1f4 100644 --- a/src/lib/converter/plugins/index.ts +++ b/src/lib/converter/plugins/index.ts @@ -1,10 +1,9 @@ export { CategoryPlugin } from "./CategoryPlugin"; export { CommentPlugin } from "./CommentPlugin"; -export { DecoratorPlugin } from "./DecoratorPlugin"; -export { SourceLinkPlugin } from "./SourceLinkPlugin"; export { GroupPlugin } from "./GroupPlugin"; export { ImplementsPlugin } from "./ImplementsPlugin"; +export { InheritDocPlugin } from "./InheritDocPlugin"; +export { LinkResolverPlugin } from "./LinkResolverPlugin"; export { PackagePlugin } from "./PackagePlugin"; export { SourcePlugin } from "./SourcePlugin"; export { TypePlugin } from "./TypePlugin"; -export { InheritDocPlugin } from "./InheritDocPlugin"; diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 24d4ecb2c..201cf22a8 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -17,7 +17,6 @@ import { } from "../utils/enum"; import type { Context } from "./context"; import { convertDefaultValue } from "./convert-expression"; -import { ConverterEvents } from "./converter-events"; import { convertIndexSignature } from "./factories/index-signature"; import { createSignature, @@ -49,6 +48,7 @@ const symbolConverters: { [ts.SymbolFlags.Alias]: convertAlias, [ts.SymbolFlags.BlockScopedVariable]: convertVariable, [ts.SymbolFlags.FunctionScopedVariable]: convertVariable, + [ts.SymbolFlags.ExportValue]: convertVariable, [ts.SymbolFlags.GetAccessor]: convertAccessor, [ts.SymbolFlags.SetAccessor]: convertAccessor, }; @@ -70,6 +70,7 @@ const conversionOrder = [ // Before type alias ts.SymbolFlags.BlockScopedVariable, ts.SymbolFlags.FunctionScopedVariable, + ts.SymbolFlags.ExportValue, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.Function, @@ -226,7 +227,7 @@ function convertEnum( reflection.setFlag(ReflectionFlag.Const); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); convertSymbols( context.withScope(reflection), @@ -250,7 +251,6 @@ function convertEnumMember( const defaultValue = context.checker.getConstantValue( symbol.getDeclarations()![0] as ts.EnumMember ); - reflection.defaultValue = JSON.stringify(defaultValue); if (defaultValue !== undefined) { reflection.type = new LiteralType(defaultValue); @@ -260,7 +260,7 @@ function convertEnumMember( reflection.type = new IntrinsicType("number"); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } function convertNamespace( @@ -289,7 +289,7 @@ function convertNamespace( symbol, exportSymbol ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); convertSymbols( context.withScope(reflection), @@ -333,11 +333,10 @@ function convertTypeAlias( declaration.type ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); // Do this after finalization so that the CommentPlugin can get @typeParam tags - // from the parent comment. Ugly, but works for now. Should be cleaned up with TSDoc - // support. + // from the parent comment. Ugly, but works for now. Should be cleaned up eventually. reflection.typeParameters = declaration.typeParameters?.map((param) => createTypeParamReflection(param, context.withScope(reflection)) ); @@ -416,7 +415,7 @@ function convertFunctionOrMethod( // All method signatures must have the same modifier flags. setModifiers(symbol, symbol.declarations[0], reflection); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const scope = context.withScope(reflection); reflection.signatures ??= []; @@ -484,7 +483,7 @@ function convertClassOrInterface( reflection.implementedTypes = implementedTypes; } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); if (classDeclaration) { // Classes can have static props @@ -505,17 +504,13 @@ function convertClassOrInterface( } reflectionContext.shouldBeStatic = false; - const constructMember = new DeclarationReflection( - "constructor", - ReflectionKind.Constructor, - reflection - ); - reflectionContext.addChild(constructMember); - const ctors = staticType.getConstructSignatures(); - context.registerReflection( - constructMember, - ctors?.[0]?.declaration?.symbol + + const constructMember = reflectionContext.createDeclarationReflection( + ReflectionKind.Constructor, + ctors?.[0]?.declaration?.symbol, + void 0, + "constructor" ); // Modifiers are the same for all constructors @@ -523,13 +518,7 @@ function convertClassOrInterface( setModifiers(symbol, ctors[0].declaration, constructMember); } - context.trigger( - ConverterEvents.CREATE_DECLARATION, - constructMember, - ts.isClassDeclaration(classDeclaration) - ? classDeclaration.members.find(ts.isConstructorDeclaration) - : void 0 - ); + context.finalizeDeclarationReflection(constructMember); const constructContext = reflectionContext.withScope(constructMember); @@ -666,20 +655,17 @@ function convertProperty( } reflection.defaultValue = declaration && convertDefaultValue(declaration); - // FIXME: Once we drop support for TS 4.5, we can use context.checker.getTypeOfSymbol(symbol) here. reflection.type = context.converter.convertType( context, (context.isConvertingTypeNode() ? parameterType : void 0) ?? - context.checker.getTypeOfSymbolAtLocation(symbol, { - kind: ts.SyntaxKind.SourceFile, - } as any) + context.checker.getTypeOfSymbol(symbol) ); if (reflection.flags.isOptional) { reflection.type = removeUndefined(reflection.type); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } function convertArrowAsMethod( @@ -695,7 +681,7 @@ function convertArrowAsMethod( void 0 ); setModifiers(symbol, arrow.parent as ts.PropertyDeclaration, reflection); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const rc = context.withScope(reflection); @@ -712,7 +698,7 @@ function convertConstructor(context: Context, symbol: ts.Symbol) { void 0, "constructor" ); - context.finalizeDeclarationReflection(reflection, symbol); + context.finalizeDeclarationReflection(reflection); const reflectionContext = context.withScope(reflection); @@ -748,18 +734,8 @@ function convertConstructSignatures(context: Context, symbol: ts.Symbol) { ReflectionKind.Constructor, context.scope ); - context.addChild(constructMember); - context.registerReflection(constructMember, undefined); - - context.trigger( - ConverterEvents.CREATE_DECLARATION, - constructMember, - // FIXME this isn't good enough. - context.converter.getNodesForSymbol( - symbol, - ReflectionKind.Constructor - )[0] - ); + context.postReflectionCreation(constructMember, symbol, void 0); + context.finalizeDeclarationReflection(constructMember); const constructContext = context.withScope(constructMember); @@ -805,15 +781,8 @@ function createAlias( target, context.scope ); - context.addChild(ref); - context.registerReflection(ref, symbol); - - context.trigger( - ConverterEvents.CREATE_DECLARATION, - ref, - // FIXME this isn't good enough. - context.converter.getNodesForSymbol(symbol, ReflectionKind.Reference)[0] - ); + context.postReflectionCreation(ref, symbol, exportSymbol); + context.finalizeDeclarationReflection(ref); } function convertVariable( @@ -858,7 +827,9 @@ function convertVariable( reflection.defaultValue = convertDefaultValue(declaration); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); + + return ts.SymbolFlags.Property; } function isEnumLike(checker: ts.TypeChecker, type: ts.Type, location: ts.Node) { @@ -889,7 +860,7 @@ function convertVariableAsEnum( symbol, exportSymbol ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const rc = context.withScope(reflection); const declaration = symbol.declarations![0] as ts.VariableDeclaration; @@ -909,11 +880,7 @@ function convertVariableAsEnum( reflection.type = context.converter.convertType(context, propType); - if (propType.isStringLiteral() || propType.isNumberLiteral()) { - reflection.defaultValue = JSON.stringify(propType.value); - } - - rc.finalizeDeclarationReflection(reflection, prop, void 0); + rc.finalizeDeclarationReflection(reflection); } // Skip converting the type alias, if there is one @@ -942,7 +909,7 @@ function convertVariableAsFunction( ); setModifiers(symbol, accessDeclaration, reflection); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const reflectionContext = context.withScope(reflection); @@ -951,11 +918,11 @@ function convertVariableAsFunction( createSignature( reflectionContext, ReflectionKind.CallSignature, - signature, - void 0, - declaration + signature ); } + + return ts.SymbolFlags.Property; } function convertAccessor( @@ -975,7 +942,7 @@ function convertAccessor( setModifiers(symbol, declaration, reflection); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const getDeclaration = symbol.getDeclarations()?.find(ts.isGetAccessor); if (getDeclaration) { diff --git a/src/lib/converter/types.ts b/src/lib/converter/types.ts index 4e625fbc7..927f3e152 100644 --- a/src/lib/converter/types.ts +++ b/src/lib/converter/types.ts @@ -16,7 +16,6 @@ import { ReflectionType, LiteralType, TupleType, - Type, TypeOperatorType, UnionType, UnknownType, @@ -219,7 +218,7 @@ const constructorConverter: TypeConverter = { rc.setConvertingTypeNode(); context.registerReflection(reflection, symbol); - context.trigger(ConverterEvents.CREATE_DECLARATION, reflection, node); + context.trigger(ConverterEvents.CREATE_DECLARATION, reflection); const signature = new SignatureReflection( "__type", @@ -319,7 +318,7 @@ const functionTypeConverter: TypeConverter = { const rc = context.withScope(reflection); context.registerReflection(reflection, symbol); - context.trigger(ConverterEvents.CREATE_DECLARATION, reflection, node); + context.trigger(ConverterEvents.CREATE_DECLARATION, reflection); const signature = new SignatureReflection( "__type", @@ -541,7 +540,7 @@ const typeLiteralConverter: TypeConverter = { rc.setConvertingTypeNode(); context.registerReflection(reflection, symbol); - context.trigger(ConverterEvents.CREATE_DECLARATION, reflection, node); + context.trigger(ConverterEvents.CREATE_DECLARATION, reflection); for (const prop of context.checker.getPropertiesOfType(type)) { convertSymbol(rc, prop); @@ -836,7 +835,7 @@ const templateLiteralConverter: TypeConverter< }, convertType(context, type) { assert(type.texts.length === type.types.length + 1); - const parts: [Type, string][] = []; + const parts: [SomeType, string][] = []; for (const [a, b] of zip(type.types, type.texts.slice(1))) { parts.push([convertType(context, a), b]); } @@ -1004,15 +1003,9 @@ const jsDocNonNullableTypeConverter: TypeConverter = { function requestBugReport(context: Context, nodeOrType: ts.Node | ts.Type) { if ("kind" in nodeOrType) { const kindName = ts.SyntaxKind[nodeOrType.kind]; - const { line, character } = ts.getLineAndCharacterOfPosition( - nodeOrType.getSourceFile(), - nodeOrType.pos - ); context.logger.warn( - `Failed to convert type node with kind: ${kindName} and text ${nodeOrType.getText()}. Please report a bug.\n\t` + - `${nodeOrType.getSourceFile().fileName}:${ - line + 1 - }:${character}` + `Failed to convert type node with kind: ${kindName} and text ${nodeOrType.getText()}. Please report a bug.`, + nodeOrType ); return new UnknownType(nodeOrType.getText()); } else { diff --git a/src/lib/converter/utils/base-path.ts b/src/lib/converter/utils/base-path.ts index d4505dbef..d237fde38 100644 --- a/src/lib/converter/utils/base-path.ts +++ b/src/lib/converter/utils/base-path.ts @@ -60,8 +60,8 @@ export class BasePath { fileName = BasePath.normalize(fileName); for (let n = 0, c = this.basePaths.length; n < c; n++) { const basePath = this.basePaths[n]; - if (fileName.substr(0, basePath.length) === basePath) { - return fileName.substr(basePath.length + 1); + if (fileName.substring(0, basePath.length) === basePath) { + return fileName.substring(basePath.length + 1); } } diff --git a/src/lib/converter/utils/nodes.ts b/src/lib/converter/utils/nodes.ts index 58a33ff62..4825ca9d4 100644 --- a/src/lib/converter/utils/nodes.ts +++ b/src/lib/converter/utils/nodes.ts @@ -1,5 +1,4 @@ import * as ts from "typescript"; -import { flatMap } from "../../utils/array"; export function isNamedNode(node: ts.Node): node is ts.Node & { name: ts.Identifier | ts.PrivateIdentifier | ts.ComputedPropertyName; @@ -16,11 +15,12 @@ export function getHeritageTypes( declarations: readonly (ts.ClassDeclaration | ts.InterfaceDeclaration)[], kind: ts.SyntaxKind.ImplementsKeyword | ts.SyntaxKind.ExtendsKeyword ): ts.ExpressionWithTypeArguments[] { - const exprs = flatMap(declarations, (d) => - flatMap( - d.heritageClauses?.filter((hc) => hc.token === kind) ?? [], - (hc) => hc.types as readonly ts.ExpressionWithTypeArguments[] - ) + const exprs = declarations.flatMap((d) => + (d.heritageClauses ?? []) + .filter((hc) => hc.token === kind) + .flatMap( + (hc) => hc.types as readonly ts.ExpressionWithTypeArguments[] + ) ); const seenTexts = new Set(); diff --git a/src/lib/converter/utils/reflections.ts b/src/lib/converter/utils/reflections.ts index ceb8d5db7..91f12165b 100644 --- a/src/lib/converter/utils/reflections.ts +++ b/src/lib/converter/utils/reflections.ts @@ -1,12 +1,4 @@ -import { - Comment, - DeclarationReflection, - IntrinsicType, - Reflection, - SignatureReflection, - SomeType, - UnionType, -} from "../../models"; +import { IntrinsicType, SomeType, UnionType } from "../../models"; export function removeUndefined(type: SomeType): SomeType { if (type instanceof UnionType) { @@ -24,82 +16,3 @@ export function removeUndefined(type: SomeType): SomeType { } return type; } - -/** - * Copy the comment of the source reflection to the target reflection. - * - * @param target - Reflection with comment containing `inheritdoc` tag - * @param source - Referenced reflection - */ -export function copyComment(target: Reflection, source: Reflection) { - if ( - target.comment && - source.comment && - target.comment.hasTag("inheritdoc") - ) { - if ( - target instanceof DeclarationReflection && - source instanceof DeclarationReflection - ) { - target.typeParameters = source.typeParameters; - } - if ( - target instanceof SignatureReflection && - source instanceof SignatureReflection - ) { - target.typeParameters = source.typeParameters; - /** - * TSDoc overrides existing parameters entirely with inherited ones, while - * existing implementation merges them. - * To avoid breaking things, `inheritDoc` tag is additionally checked for the parameter, - * so the previous behavior will continue to work. - * - * TODO: When breaking change becomes acceptable remove legacy implementation - */ - if (target.comment.getTag("inheritdoc")?.paramName) { - target.parameters = source.parameters; - } else { - legacyCopyImplementation(target, source); - } - } - target.comment.removeTags("inheritdoc"); - target.comment.copyFrom(source.comment); - } else if (!target.comment && source.comment) { - if ( - target instanceof DeclarationReflection && - source instanceof DeclarationReflection - ) { - target.typeParameters = source.typeParameters; - } - target.comment = new Comment(); - target.comment.copyFrom(source.comment); - } -} - -/** - * Copy comments from source reflection to target reflection, parameters are merged. - * - * @param target - Reflection with comment containing `inheritdoc` tag - * @param source - Parent reflection - */ -function legacyCopyImplementation( - target: SignatureReflection, - source: SignatureReflection -) { - if (target.parameters && source.parameters) { - for ( - let index = 0, count = target.parameters.length; - index < count; - index++ - ) { - const sourceParameter = source.parameters[index]; - if (sourceParameter && sourceParameter.comment) { - const targetParameter = target.parameters[index]; - if (!targetParameter.comment) { - targetParameter.comment = new Comment(); - targetParameter.comment.copyFrom(sourceParameter.comment); - } - } - } - } -} diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/utils/repository.ts similarity index 55% rename from src/lib/converter/plugins/SourceLinkPlugin.ts rename to src/lib/converter/utils/repository.ts index 2c7d074d5..99ba4cca1 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/utils/repository.ts @@ -1,13 +1,6 @@ -import * as Path from "path"; import { spawnSync } from "child_process"; - -import type { SourceReference } from "../../models/sources/file"; -import { Component, ConverterComponent } from "../components"; -import { BasePath } from "../utils/base-path"; -import { Converter } from "../converter"; -import type { Context } from "../context"; -import { BindOption } from "../../utils"; import { RepositoryType } from "../../models"; +import { BasePath } from "../utils/base-path"; const TEN_MEGABYTES: number = 1024 * 10000; @@ -19,6 +12,8 @@ function git(...args: string[]) { }); } +export const gitIsInstalled = git("--version").status === 0; + /** * Stores data of a repository. */ @@ -63,6 +58,8 @@ export class Repository { */ type: RepositoryType = RepositoryType.GitHub; + private urlCache = new Map(); + /** * Create a new Repository instance. * @@ -97,11 +94,8 @@ export class Repository { this.hostname = match[1]; this.user = match[2]; this.project = match[3]; - if (this.project.substr(-4) === ".git") { - this.project = this.project.substr( - 0, - this.project.length - 4 - ); + if (this.project.endsWith(".git")) { + this.project = this.project.slice(0, -4); } break; } @@ -149,21 +143,39 @@ export class Repository { * @returns A URL pointing to the web preview of the given file or undefined. */ getURL(fileName: string): string | undefined { + if (this.urlCache.has(fileName)) { + return this.urlCache.get(fileName)!; + } + if (!this.user || !this.project || !this.contains(fileName)) { return; } - return [ + const url = [ `https://${this.hostname}`, this.user, this.project, this.type === RepositoryType.GitLab ? "-" : undefined, this.type === RepositoryType.Bitbucket ? "src" : "blob", this.branch, - fileName.substr(this.path.length + 1), + fileName.substring(this.path.length + 1), ] .filter((s) => !!s) .join("/"); + + this.urlCache.set(fileName, url); + return url; + } + + getLineNumberAnchor(lineNumber: number): string { + switch (this.type) { + default: + case RepositoryType.GitHub: + case RepositoryType.GitLab: + return "L" + lineNumber; + case RepositoryType.Bitbucket: + return "lines-" + lineNumber; + } } /** @@ -193,129 +205,4 @@ export class Repository { remotesOutput.stdout.split("\n") ); } - - static getLineNumberAnchor( - lineNumber: number, - repositoryType: RepositoryType | undefined - ): string { - switch (repositoryType) { - default: - case RepositoryType.GitHub: - case RepositoryType.GitLab: - return "L" + lineNumber; - case RepositoryType.Bitbucket: - return "lines-" + lineNumber; - } - } -} - -/** - * A handler that watches for repositories with GitHub origin and links - * their source files to the related GitHub pages. - */ -@Component({ name: "source-link" }) -export class SourceLinkPlugin extends ConverterComponent { - /** - * List of known repositories. - */ - private repositories: { [path: string]: Repository } = {}; - - /** - * List of paths known to be not under git control. - */ - private ignoredPaths: string[] = []; - - @BindOption("gitRevision") - readonly gitRevision!: string; - - @BindOption("gitRemote") - readonly gitRemote!: string; - - /** - * Create a new GitHubHandler instance. - * - * @param converter The converter this plugin should be attached to. - */ - override initialize() { - if (git("--version").status === 0) { - this.listenTo( - this.owner, - Converter.EVENT_RESOLVE_END, - this.onEndResolve - ); - } - } - - /** - * Check whether the given file is placed inside a repository. - * - * @param fileName The name of the file a repository should be looked for. - * @returns The found repository info or undefined. - */ - private getRepository(fileName: string): Repository | undefined { - // Check for known non-repositories - const dirName = Path.dirname(fileName); - for (let i = 0, c = this.ignoredPaths.length; i < c; i++) { - if (this.ignoredPaths[i] === dirName) { - return; - } - } - - // Check for known repositories - for (const path of Object.keys(this.repositories)) { - if (fileName.substr(0, path.length).toLowerCase() === path) { - return this.repositories[path]; - } - } - - // Try to create a new repository - const repository = Repository.tryCreateRepository( - dirName, - this.gitRevision, - this.gitRemote - ); - if (repository) { - this.repositories[repository.path.toLowerCase()] = repository; - return repository; - } - - // No repository found, add path to ignored paths - const segments = dirName.split("/"); - for (let i = segments.length; i > 0; i--) { - this.ignoredPaths.push(segments.slice(0, i).join("/")); - } - } - - /** - * Triggered when the converter has finished resolving a project. - * - * @param context The context object describing the current state the converter is in. - */ - private onEndResolve(context: Context) { - const project = context.project; - project.files.forEach((sourceFile) => { - const repository = this.getRepository(sourceFile.fullFileName); - if (repository) { - sourceFile.url = repository.getURL(sourceFile.fullFileName); - sourceFile.repositoryType = repository.type; - } - }); - - for (const key in project.reflections) { - const reflection = project.reflections[key]; - if (reflection.sources) { - reflection.sources.forEach((source: SourceReference) => { - if (source.file && source.file.url) { - source.url = - source.file.url + - "#" + - Repository.getLineNumberAnchor( - source.line, - source.file.repositoryType - ); - } - }); - } - } - } } diff --git a/src/lib/models/ReflectionCategory.ts b/src/lib/models/ReflectionCategory.ts index 0169268b3..ae2014b29 100644 --- a/src/lib/models/ReflectionCategory.ts +++ b/src/lib/models/ReflectionCategory.ts @@ -1,4 +1,5 @@ import type { DeclarationReflection } from "."; +import type { Serializer, JSONOutput } from "../serialization"; /** * A category of reflections. @@ -33,4 +34,14 @@ export class ReflectionCategory { allChildrenHaveOwnDocument(): boolean { return this.children.every((child) => child.hasOwnDocument); } + + toObject(_serializer: Serializer): JSONOutput.ReflectionCategory { + return { + title: this.title, + children: + this.children.length > 0 + ? this.children.map((child) => child.id) + : undefined, + }; + } } diff --git a/src/lib/models/ReflectionGroup.ts b/src/lib/models/ReflectionGroup.ts index 62e851683..be3ce0f5e 100644 --- a/src/lib/models/ReflectionGroup.ts +++ b/src/lib/models/ReflectionGroup.ts @@ -1,6 +1,6 @@ -import type { ReflectionKind } from "./reflections/kind"; import type { ReflectionCategory } from "./ReflectionCategory"; import type { DeclarationReflection } from "."; +import type { Serializer, JSONOutput } from "../serialization"; /** * A group of reflections. All reflections in a group are of the same kind. @@ -15,42 +15,11 @@ export class ReflectionGroup { */ title: string; - /** - * The original typescript kind of the children of this group. - */ - kind: ReflectionKind; - /** * All reflections of this group. */ children: DeclarationReflection[] = []; - /** - * A list of generated css classes that should be applied to representations of this - * group in the generated markup. - */ - cssClasses?: string; - - /** - * Are all children inherited members? - */ - allChildrenAreInherited?: boolean; - - /** - * Are all children private members? - */ - allChildrenArePrivate?: boolean; - - /** - * Are all children private or protected members? - */ - allChildrenAreProtectedOrPrivate?: boolean; - - /** - * Are all children external members? - */ - allChildrenAreExternal?: boolean; - /** * Categories contained within this group. */ @@ -60,11 +29,9 @@ export class ReflectionGroup { * Create a new ReflectionGroup instance. * * @param title The title of this group. - * @param kind The original typescript kind of the children of this group. */ - constructor(title: string, kind: ReflectionKind) { + constructor(title: string) { this.title = title; - this.kind = kind; } /** @@ -73,4 +40,15 @@ export class ReflectionGroup { allChildrenHaveOwnDocument(): boolean { return this.children.every((child) => child.hasOwnDocument); } + + toObject(serializer: Serializer): JSONOutput.ReflectionGroup { + return { + title: this.title, + children: + this.children.length > 0 + ? this.children.map((child) => child.id) + : undefined, + categories: serializer.toObjectsOptional(this.categories), + }; + } } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 467aeed96..37079324c 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -1,7 +1,92 @@ -import { removeIf } from "../../utils"; -import { CommentTag } from "./tag"; +import { assertNever, removeIf } from "../../utils"; +import type { Reflection } from "../reflections"; -const COPIED_TAGS = ["remarks"]; +import type { Serializer, JSONOutput } from "../../serialization"; + +export type CommentDisplayPart = + | { kind: "text"; text: string } + | { kind: "code"; text: string } + | InlineTagDisplayPart; + +/** + * The `@link`, `@linkcode`, and `@linkplain` tags may have a `target` + * property set indicating which reflection/url they link to. + */ +export interface InlineTagDisplayPart { + kind: "inline-tag"; + tag: `@${string}`; + text: string; + target?: Reflection | string; +} + +function serializeDisplayPart( + part: CommentDisplayPart +): JSONOutput.CommentDisplayPart { + switch (part.kind) { + case "text": + case "code": + return part; + case "inline-tag": { + return { + ...part, + target: + typeof part.target === "object" + ? part.target.id + : part.target, + }; + } + } +} + +/** + * A model that represents a single TypeDoc comment tag. + * + * Tags are stored in the {@link Comment.blockTags} property. + */ +export class CommentTag { + /** + * The name of this tag, e.g. `@returns`, `@example` + */ + tag: `@${string}`; + + /** + * Some tags, (`@typedef`, `@param`, `@property`, etc.) may have a user defined identifier associated with them. + * If this tag is one of those, it will be parsed out and included here. + */ + name?: string; + + /** + * The actual body text of this tag. + */ + content: CommentDisplayPart[]; + + /** + * Create a new CommentTag instance. + */ + constructor(tag: `@${string}`, text: CommentDisplayPart[]) { + this.tag = tag; + this.content = text; + } + + clone(): CommentTag { + const tag = new CommentTag( + this.tag, + Comment.cloneDisplayParts(this.content) + ); + if (this.name) { + tag.name = this.name; + } + return tag; + } + + toObject(): JSONOutput.CommentTag { + return { + tag: this.tag, + name: this.name, + content: this.content.map(serializeDisplayPart), + }; + } +} /** * A model that represents a comment. @@ -11,32 +96,83 @@ const COPIED_TAGS = ["remarks"]; */ export class Comment { /** - * The abstract of the comment. TypeDoc interprets the first paragraph of a comment - * as the abstract. + * Debugging utility for combining parts into a simple string. Not suitable for + * rendering, but can be useful in tests. */ - shortText: string; + static combineDisplayParts( + parts: readonly CommentDisplayPart[] | undefined + ): string { + let result = ""; + + for (const item of parts || []) { + switch (item.kind) { + case "text": + case "code": + result += item.text; + break; + case "inline-tag": + result += `{${item.tag} ${item.text}}`; + break; + default: + assertNever(item); + } + } + + return result; + } /** - * The full body text of the comment. Excludes the {@link shortText}. + * Helper utility to clone {@link Comment.summary} or {@link CommentTag.content} */ - text: string; + static cloneDisplayParts(parts: CommentDisplayPart[]) { + return parts.map((p) => ({ ...p })); + } /** - * The text of the ```@returns``` tag if present. + * The content of the comment which is not associated with a block tag. */ - returns?: string; + summary: CommentDisplayPart[]; /** - * All associated tags. + * All associated block level tags. */ - tags: CommentTag[] = []; + blockTags: CommentTag[] = []; + + /** + * All modifier tags present on the comment, e.g. `@alpha`, `@beta`. + */ + modifierTags: Set = new Set(); /** * Creates a new Comment instance. */ - constructor(shortText?: string, text?: string) { - this.shortText = shortText || ""; - this.text = text || ""; + constructor( + summary: CommentDisplayPart[] = [], + blockTags: CommentTag[] = [], + modifierTags: Set = new Set() + ) { + this.summary = summary; + this.blockTags = blockTags; + this.modifierTags = modifierTags; + } + + /** + * Create a deep clone of this comment. + */ + clone() { + return new Comment( + Comment.cloneDisplayParts(this.summary), + this.blockTags.map((tag) => tag.clone()), + new Set(this.modifierTags) + ); + } + + /** + * Returns true if this comment is completely empty. + * @internal + */ + isEmpty() { + return !this.hasVisibleComponent() && this.modifierTags.size === 0; } /** @@ -45,7 +181,10 @@ export class Comment { * @returns TRUE when this comment has a visible component. */ hasVisibleComponent(): boolean { - return !!this.shortText || !!this.text || this.tags.length > 0; + return ( + this.summary.some((x) => x.kind !== "text" || x.text !== "") || + this.blockTags.length > 0 + ); } /** @@ -54,60 +193,54 @@ export class Comment { * @param tagName The name of the tag to look for. * @returns TRUE when this comment contains a tag with the given name, otherwise FALSE. */ - hasTag(tagName: string): boolean { - return this.tags.some((tag) => tag.tagName === tagName); + hasModifier(tagName: `@${string}`): boolean { + return this.modifierTags.has(tagName); + } + + removeModifier(tagName: `@${string}`) { + this.modifierTags.delete(tagName); } /** * Return the first tag with the given name. * - * You can optionally pass a parameter name that should be searched to. - * * @param tagName The name of the tag to look for. * @param paramName An optional parameter name to look for. * @returns The found tag or undefined. */ - getTag(tagName: string, paramName?: string): CommentTag | undefined { - return this.tags.find((tag) => { - return ( - tag.tagName === tagName && - (paramName === void 0 || tag.paramName === paramName) - ); - }); + getTag(tagName: `@${string}`): CommentTag | undefined { + return this.blockTags.find((tag) => tag.tag === tagName); } /** - * Removes all tags with the given tag name from the comment. - * @param tagName + * Get all tags with the given tag name. */ - removeTags(tagName: string) { - removeIf(this.tags, (tag) => tag.tagName === tagName); + getTags(tagName: `@${string}`): CommentTag[] { + return this.blockTags.filter((tag) => tag.tag === tagName); + } + + getIdentifiedTag(identifier: string, tagName: `@${string}`) { + return this.blockTags.find( + (tag) => tag.tag === tagName && tag.name === identifier + ); } /** - * Copy the data of the given comment into this comment. - * - * `shortText`, `text`, `returns` and tags from `COPIED_TAGS` are copied; - * other instance tags left unchanged. - * - * @param comment - Source comment to copy from - */ - copyFrom(comment: Comment) { - this.shortText = comment.shortText; - this.text = comment.text; - this.returns = comment.returns; - const overrideTags: CommentTag[] = comment.tags - .filter((tag) => COPIED_TAGS.includes(tag.tagName)) - .map((tag) => new CommentTag(tag.tagName, tag.paramName, tag.text)); - this.tags.forEach((tag, index) => { - const matchingTag = overrideTags.find( - (matchingOverride) => matchingOverride?.tagName === tag.tagName - ); - if (matchingTag) { - this.tags[index] = matchingTag; - overrideTags.splice(overrideTags.indexOf(matchingTag), 1); - } - }); - this.tags = [...this.tags, ...overrideTags]; + * Removes all block tags with the given tag name from the comment. + * @param tagName + */ + removeTags(tagName: `@${string}`) { + removeIf(this.blockTags, (tag) => tag.tag === tagName); + } + + toObject(serializer: Serializer): JSONOutput.Comment { + return { + summary: this.summary.map(serializeDisplayPart), + blockTags: serializer.toObjectsOptional(this.blockTags), + modifierTags: + this.modifierTags.size > 0 + ? Array.from(this.modifierTags) + : undefined, + }; } } diff --git a/src/lib/models/comments/index.ts b/src/lib/models/comments/index.ts index eb0c512ee..15dc5eeb4 100644 --- a/src/lib/models/comments/index.ts +++ b/src/lib/models/comments/index.ts @@ -1,2 +1,2 @@ -export { Comment } from "./comment"; -export { CommentTag } from "./tag"; +export { Comment, CommentTag } from "./comment"; +export type { CommentDisplayPart, InlineTagDisplayPart } from "./comment"; diff --git a/src/lib/models/comments/tag.ts b/src/lib/models/comments/tag.ts deleted file mode 100644 index 55611bacd..000000000 --- a/src/lib/models/comments/tag.ts +++ /dev/null @@ -1,30 +0,0 @@ -/** - * A model that represents a single javadoc comment tag. - * - * Tags are stored in the {@link Comment.tags} property. - */ -export class CommentTag { - /** - * The name of this tag. - */ - tagName: string; - - /** - * The name of the related parameter when this is a ```@param``` tag. - */ - paramName: string; - - /** - * The actual body text of this tag. - */ - text: string; - - /** - * Create a new CommentTag instance. - */ - constructor(tagName: string, paramName?: string, text?: string) { - this.tagName = tagName; - this.paramName = paramName || ""; - this.text = text || ""; - } -} diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index 9a1a76ad7..6105eca25 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -1,11 +1,11 @@ import { ok } from "assert"; import type { SourceReference } from "../sources/file"; -import type { Type } from "../types"; import type { Comment } from "../comments/comment"; import { splitUnquotedString } from "./utils"; import type { ProjectReflection } from "./project"; import type { NeverIfInternal } from "../../utils"; import { ReflectionKind } from "./kind"; +import type { Serializer, JSONOutput } from "../../serialization"; /** * Holds all data models used by TypeDoc. @@ -185,6 +185,28 @@ export class ReflectionFlags extends Array { this.flags |= flag; } } + + private static serializedFlags = [ + "isPrivate", + "isProtected", + "isPublic", + "isStatic", + "isExternal", + "isOptional", + "isRest", + "hasExportAssignment", + "isAbstract", + "isConst", + "isReadonly", + ] as const; + + toObject(): JSONOutput.ReflectionFlags { + return Object.fromEntries( + ReflectionFlags.serializedFlags + .filter((flag) => this[flag]) + .map((flag) => [flag, true]) + ); + } } export enum TraverseProperty { @@ -208,27 +230,6 @@ export interface TraverseCallback { | NeverIfInternal; } -/** - * Defines the usage of a decorator. - */ -export interface Decorator { - /** - * The name of the decorator being applied. - */ - name: string; - - /** - * The type declaring the decorator. - * Usually a ReferenceType instance pointing to the decorator function. - */ - type?: Type; - - /** - * A named map of arguments the decorator is applied with. - */ - arguments?: any; -} - /** * Base class for all reflection classes. * @@ -237,8 +238,8 @@ export interface Decorator { * by the {@link DeclarationReflection} class. * * This base class exposes the basic properties one may use to traverse the reflection tree. - * You can use the {@link ContainerReflection.children} and {@link parent} properties to walk the tree. The {@link groups} property - * contains a list of all children grouped and sorted for being rendered. + * You can use the {@link ContainerReflection.children} and {@link parent} properties to walk the tree. The {@link ContainerReflection.groups} property + * contains a list of all children grouped and sorted for rendering. */ export abstract class Reflection { /** @@ -256,6 +257,12 @@ export abstract class Reflection { */ originalName: string; + /** + * Label associated with this reflection, if any (https://tsdoc.org/pages/tags/label/) + * Added by the CommentPlugin during resolution. + */ + label?: string; + /** * The kind of this reflection. */ @@ -293,16 +300,6 @@ export abstract class Reflection { */ sources?: SourceReference[]; - /** - * A list of all decorators attached to this reflection. - */ - decorators?: Decorator[]; - - /** - * A list of all types that are decorated by this reflection. - */ - decorates?: Type[]; - /** * The url of this reflection in the generated documentation. * TODO: Reflections shouldn't know urls exist. Move this to a serializer. @@ -339,9 +336,6 @@ export abstract class Reflection { private _aliases?: Map; - /** - * Create a new BaseReflection instance. - */ constructor(name: string, kind: ReflectionKind, parent?: Reflection) { this.id = REFLECTION_ID++; this.parent = parent; @@ -415,23 +409,17 @@ export abstract class Reflection { */ getAlias(): string { if (!this._alias) { - let alias = this.name.replace(/[^a-z0-9]/gi, "_"); + let alias = this.name.replace(/\W/g, "_"); if (alias === "") { alias = "reflection-" + this.id; } - let target = this; - while ( - target.parent && - !target.parent.isProject() && - !target.hasOwnDocument - ) { + let target = this as Reflection; + while (target.parent && !target.hasOwnDocument) { target = target.parent; } - if (!target._aliases) { - target._aliases = new Map(); - } + target._aliases ||= new Map(); let suffix = ""; if (!target._aliases.has(alias)) { @@ -497,10 +485,24 @@ export abstract class Reflection { return false; } + /** + * Check if this reflection has been marked with the `@deprecated` tag. + */ + isDeprecated(): boolean { + if (this.comment?.getTag("@deprecated")) { + return true; + } + + return this.parent?.isDeprecated() ?? false; + } + /** * Try to find a reflection by its name. * * @return The found reflection or null. + * @deprecated This method not be used, it naively splits the name by a `.` and searches recursively up + * the parent tree, which is not how any other name resolver works. If you are currently using this and + * need another method, please open an issue. For tests {@link getChildByName} should generally be sufficient. */ findReflectionByName(arg: string | string[]): Reflection | undefined { const names: string[] = Array.isArray(arg) @@ -550,4 +552,20 @@ export abstract class Reflection { return lines.join("\n"); } + + toObject(serializer: Serializer): JSONOutput.Reflection { + return { + id: this.id, + name: this.name, + kind: this.kind, + kindString: this.kindString, + flags: this.flags.toObject(), + comment: + this.comment && !this.comment.isEmpty() + ? serializer.toObject(this.comment) + : undefined, + originalName: + this.originalName !== this.name ? this.originalName : undefined, + }; + } } diff --git a/src/lib/models/reflections/container.ts b/src/lib/models/reflections/container.ts index ea7570e54..181f4d799 100644 --- a/src/lib/models/reflections/container.ts +++ b/src/lib/models/reflections/container.ts @@ -3,6 +3,7 @@ import type { ReflectionCategory } from "../ReflectionCategory"; import type { ReflectionGroup } from "../ReflectionGroup"; import type { DeclarationReflection } from "./declaration"; import type { ReflectionKind } from "./kind"; +import type { Serializer, JSONOutput } from "../../serialization"; export class ContainerReflection extends Reflection { /** @@ -21,8 +22,8 @@ export class ContainerReflection extends Reflection { categories?: ReflectionCategory[]; /** - * A precomputed boost derived from the searchCategoryBoosts typedoc.json setting, to be used when - * boosting search relevance scores at runtime. + * A precomputed boost derived from the searchCategoryBoosts and searchGroupBoosts options, used when + * boosting search relevance scores at runtime. May be modified by plugins. */ relevanceBoost?: number; @@ -51,4 +52,14 @@ export class ContainerReflection extends Reflection { } } } + + override toObject(serializer: Serializer): JSONOutput.ContainerReflection { + return { + ...super.toObject(serializer), + children: serializer.toObjectsOptional(this.children), + groups: serializer.toObjectsOptional(this.groups), + categories: serializer.toObjectsOptional(this.categories), + sources: serializer.toObjectsOptional(this.sources), + }; + } } diff --git a/src/lib/models/reflections/declaration.ts b/src/lib/models/reflections/declaration.ts index a589f98c6..540918a5b 100644 --- a/src/lib/models/reflections/declaration.ts +++ b/src/lib/models/reflections/declaration.ts @@ -1,10 +1,10 @@ import type * as ts from "typescript"; -import type { SomeType } from ".."; -import { ReferenceType, ReflectionType, Type } from "../types"; -import { TraverseCallback, TraverseProperty } from "./abstract"; +import { ReferenceType, ReflectionType, Type, type SomeType } from "../types"; +import { type TraverseCallback, TraverseProperty } from "./abstract"; import { ContainerReflection } from "./container"; import type { SignatureReflection } from "./signature"; import type { TypeParameterReflection } from "./type-parameter"; +import type { Serializer, JSONOutput } from "../../serialization"; /** * Stores hierarchical type data. @@ -78,9 +78,7 @@ export class DeclarationReflection extends ContainerReflection { /** * The default value of this reflection. * - * Applies to function parameters. - * - * Note: Using this for enum members is DEPRECATED and will be removed in 0.23. + * Applies to function parameters, variables, and properties. */ defaultValue?: string; @@ -108,7 +106,7 @@ export class DeclarationReflection extends ContainerReflection { /** * A list of all types this reflection extends (e.g. the parent classes). */ - extendedTypes?: Type[]; + extendedTypes?: SomeType[]; /** * A list of all types that extend this reflection (e.g. the subclasses). @@ -118,7 +116,7 @@ export class DeclarationReflection extends ContainerReflection { /** * A list of all types this reflection implements. */ - implementedTypes?: Type[]; + implementedTypes?: SomeType[]; /** * A list of all types that implement this reflection. @@ -234,10 +232,9 @@ export class DeclarationReflection extends ContainerReflection { let result = super.toString(); if (this.typeParameters) { - const parameters: string[] = []; - this.typeParameters.forEach((parameter) => { - parameters.push(parameter.name); - }); + const parameters: string[] = this.typeParameters.map( + (parameter) => parameter.name + ); result += "<" + parameters.join(", ") + ">"; } @@ -247,4 +244,28 @@ export class DeclarationReflection extends ContainerReflection { return result; } + + override toObject( + serializer: Serializer + ): JSONOutput.DeclarationReflection { + return { + ...super.toObject(serializer), + typeParameters: serializer.toObjectsOptional(this.typeParameters), + type: serializer.toObject(this.type), + signatures: serializer.toObjectsOptional(this.signatures), + indexSignature: serializer.toObject(this.indexSignature), + getSignature: serializer.toObject(this.getSignature), + setSignature: serializer.toObject(this.setSignature), + defaultValue: this.defaultValue, + overwrites: serializer.toObject(this.overwrites), + inheritedFrom: serializer.toObject(this.inheritedFrom), + implementationOf: serializer.toObject(this.implementationOf), + extendedTypes: serializer.toObjectsOptional(this.extendedTypes), + extendedBy: serializer.toObjectsOptional(this.extendedBy), + implementedTypes: serializer.toObjectsOptional( + this.implementedTypes + ), + implementedBy: serializer.toObjectsOptional(this.implementedBy), + }; + } } diff --git a/src/lib/models/reflections/index.ts b/src/lib/models/reflections/index.ts index 8315ddfde..6a5ef9dad 100644 --- a/src/lib/models/reflections/index.ts +++ b/src/lib/models/reflections/index.ts @@ -4,7 +4,7 @@ export { ReflectionFlags, TraverseProperty, } from "./abstract"; -export type { Decorator, TraverseCallback } from "./abstract"; +export type { TraverseCallback } from "./abstract"; export { ContainerReflection } from "./container"; export { DeclarationReflection } from "./declaration"; export type { DeclarationHierarchy } from "./declaration"; diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index 660ba0294..f96043428 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -25,8 +25,7 @@ export enum ReflectionKind { SetSignature = 0x100000, ObjectLiteral = 0x200000, TypeAlias = 0x400000, - Event = 0x800000, - Reference = 0x1000000, + Reference = 0x800000, } /** @hidden */ @@ -43,8 +42,7 @@ export namespace ReflectionKind { ReflectionKind.Accessor | ReflectionKind.Constructor | ReflectionKind.Method | - ReflectionKind.Property | - ReflectionKind.Event; + ReflectionKind.Property; export const SomeSignature = ReflectionKind.CallSignature | ReflectionKind.IndexSignature | @@ -62,6 +60,26 @@ export namespace ReflectionKind { ReflectionKind.Function | ReflectionKind.ObjectLiteral; + export const SomeMember = + ReflectionKind.EnumMember | + ReflectionKind.Property | + ReflectionKind.Method | + ReflectionKind.Accessor; + + export const SomeExport = + ReflectionKind.Module | + ReflectionKind.Namespace | + ReflectionKind.Enum | + ReflectionKind.Variable | + ReflectionKind.Function | + ReflectionKind.Class | + ReflectionKind.Interface | + ReflectionKind.TypeAlias | + ReflectionKind.Reference; + + export const ExportContainer = + ReflectionKind.SomeModule | ReflectionKind.Project; + /** @internal */ export const Inheritable = ReflectionKind.Accessor | @@ -69,4 +87,10 @@ export namespace ReflectionKind { ReflectionKind.Property | ReflectionKind.Method | ReflectionKind.Constructor; + + /** @internal */ + export const ContainsCallSignatures = + ReflectionKind.Constructor | + ReflectionKind.Function | + ReflectionKind.Method; } diff --git a/src/lib/models/reflections/parameter.ts b/src/lib/models/reflections/parameter.ts index e6c3ccd9f..9bfa6b69d 100644 --- a/src/lib/models/reflections/parameter.ts +++ b/src/lib/models/reflections/parameter.ts @@ -2,6 +2,7 @@ import type { SomeType } from ".."; import { ReflectionType } from "../types"; import { Reflection, TraverseCallback, TraverseProperty } from "./abstract"; import type { SignatureReflection } from "./signature"; +import type { Serializer, JSONOutput } from "../../serialization"; export class ParameterReflection extends Reflection { override parent?: SignatureReflection; @@ -39,4 +40,12 @@ export class ParameterReflection extends Reflection { override toString() { return super.toString() + (this.type ? ":" + this.type.toString() : ""); } + + override toObject(serializer: Serializer): JSONOutput.ParameterReflection { + return { + ...super.toObject(serializer), + type: serializer.toObject(this.type), + defaultValue: this.defaultValue, + }; + } } diff --git a/src/lib/models/reflections/project.ts b/src/lib/models/reflections/project.ts index 4c92c2d46..3d25107d5 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -1,7 +1,5 @@ -import { SourceFile, SourceDirectory } from "../sources/index"; import { Reflection, TraverseProperty } from "./abstract"; import { ContainerReflection } from "./container"; -import { splitUnquotedString } from "./utils"; import { ReferenceReflection } from "./reference"; import type { DeclarationReflection } from "./declaration"; import type { SignatureReflection } from "./signature"; @@ -11,6 +9,7 @@ import type { TypeParameterReflection } from "./type-parameter"; import { removeIfPresent } from "../../utils"; import type * as ts from "typescript"; import { ReflectionKind } from "./kind"; +import type { CommentDisplayPart } from "../comments"; /** * A reflection that represents the root of the project. @@ -28,45 +27,19 @@ export class ProjectReflection extends ContainerReflection { private referenceGraph?: Map; /** - * A list of all reflections within the project. - * @deprecated use {@link getReflectionById}, this will eventually be removed. - * To iterate over all reflections, prefer {@link getReflectionsByKind}. - */ - reflections: { [id: number]: Reflection } = {}; - - /** - * The root directory of the project. - */ - directory: SourceDirectory = new SourceDirectory(); - - /** - * A list of all source files within the project. - */ - files: SourceFile[] = []; - - /** - * The name of the project. + * A list of all reflections within the project. DO NOT MUTATE THIS OBJECT. + * All mutation should be done via {@link registerReflection} and {@link removeReflection} + * to ensure that links to reflections remain valid. * - * The name can be passed as a command line argument or it is read from the package info. - * this.name is assigned in the Reflection class. + * This may be replaced with a `Map` someday. */ - override name!: string; + reflections: { [id: number]: Reflection } = {}; /** * The contents of the readme.md file of the project when found. */ - readme?: string; + readme?: CommentDisplayPart[]; - /** - * The parsed data of the package.json file of the project when found. - */ - packageInfo: any; - - /** - * Create a new ProjectReflection instance. - * - * @param name The name of the project. - */ constructor(name: string) { super(name, ReflectionKind.Project); } @@ -90,41 +63,6 @@ export class ProjectReflection extends ContainerReflection { ); } - /** - * Try to find a reflection by its name. - * - * @param names The name hierarchy to look for, if a string, the name will be split on "." - * @return The found reflection or undefined. - */ - override findReflectionByName( - arg: string | string[] - ): Reflection | undefined { - const names: string[] = Array.isArray(arg) - ? arg - : splitUnquotedString(arg, "."); - const name = names.pop(); - - search: for (const key in this.reflections) { - const reflection = this.reflections[key]; - if (reflection.name !== name) { - continue; - } - - let depth = names.length - 1; - let target: Reflection | undefined = reflection; - while ((target = target.parent) && depth >= 0) { - if (target.name !== names[depth]) { - continue search; - } - depth -= 1; - } - - return reflection; - } - - return undefined; - } - /** * When excludeNotExported is set, if a symbol is exported only under a different name * there will be a reference which points to the symbol, but the symbol will not be converted diff --git a/src/lib/models/reflections/reference.ts b/src/lib/models/reflections/reference.ts index 3edcde9b7..1a83372d2 100644 --- a/src/lib/models/reflections/reference.ts +++ b/src/lib/models/reflections/reference.ts @@ -3,6 +3,7 @@ import { Reflection } from "./abstract"; import { DeclarationReflection } from "./declaration"; import { ReflectionKind } from "./kind"; import type { ProjectReflection } from "./project"; +import type { Serializer, JSONOutput } from "../../serialization"; /** * Describes a reflection which does not exist at this location, but is referenced. Used for imported reflections. @@ -90,6 +91,10 @@ export class ReferenceReflection extends DeclarationReflection { return result; } + override getChildByName(arg: string | string[]): Reflection | undefined { + return this.getTargetReflection().getChildByName(arg); + } + private _ensureProject() { if (this._project) { return; @@ -107,4 +112,11 @@ export class ReferenceReflection extends DeclarationReflection { ); } } + + override toObject(serializer: Serializer): JSONOutput.ReferenceReflection { + return { + ...super.toObject(serializer), + target: this.tryGetTargetReflection()?.id ?? -1, + }; + } } diff --git a/src/lib/models/reflections/signature.ts b/src/lib/models/reflections/signature.ts index 8ef0ba4b7..73660275d 100644 --- a/src/lib/models/reflections/signature.ts +++ b/src/lib/models/reflections/signature.ts @@ -1,14 +1,12 @@ -import { Type, ReflectionType, ReferenceType } from "../types"; +import { SomeType, ReflectionType, ReferenceType } from "../types"; import { Reflection, TraverseProperty, TraverseCallback } from "./abstract"; import type { ParameterReflection } from "./parameter"; import type { TypeParameterReflection } from "./type-parameter"; import type { DeclarationReflection } from "./declaration"; import type { ReflectionKind } from "./kind"; +import type { Serializer, JSONOutput } from "../../serialization"; export class SignatureReflection extends Reflection { - /** - * Create a new SignatureReflection to contain a specific type of signature. - */ constructor( name: string, kind: SignatureReflection["kind"], @@ -30,7 +28,7 @@ export class SignatureReflection extends Reflection { typeParameters?: TypeParameterReflection[]; - type?: Type; + type?: SomeType; /** * A type that points to the reflection that has been overwritten by this reflection. @@ -95,9 +93,8 @@ export class SignatureReflection extends Reflection { let result = super.toString(); if (this.typeParameters) { - const parameters: string[] = []; - this.typeParameters.forEach((parameter) => - parameters.push(parameter.name) + const parameters: string[] = this.typeParameters.map( + (parameter) => parameter.name ); result += "<" + parameters.join(", ") + ">"; } @@ -108,4 +105,16 @@ export class SignatureReflection extends Reflection { return result; } + + override toObject(serializer: Serializer): JSONOutput.SignatureReflection { + return { + ...super.toObject(serializer), + typeParameter: serializer.toObjectsOptional(this.typeParameters), + parameters: serializer.toObjectsOptional(this.parameters), + type: serializer.toObject(this.type), + overwrites: serializer.toObject(this.overwrites), + inheritedFrom: serializer.toObject(this.inheritedFrom), + implementationOf: serializer.toObject(this.implementationOf), + }; + } } diff --git a/src/lib/models/reflections/type-parameter.ts b/src/lib/models/reflections/type-parameter.ts index 0c17b465c..1b64089cb 100644 --- a/src/lib/models/reflections/type-parameter.ts +++ b/src/lib/models/reflections/type-parameter.ts @@ -1,7 +1,8 @@ -import type { Type } from "../types"; +import type { SomeType } from "../types"; import { Reflection } from "./abstract"; import type { DeclarationReflection } from "./declaration"; import { ReflectionKind } from "./kind"; +import type { Serializer, JSONOutput } from "../../serialization"; /** * Modifier flags for type parameters, added in TS 4.7 @@ -18,16 +19,16 @@ export type VarianceModifier = export class TypeParameterReflection extends Reflection { override parent?: DeclarationReflection; - type?: Type; + type?: SomeType; - default?: Type; + default?: SomeType; varianceModifier?: VarianceModifier; constructor( name: string, - constraint: Type | undefined, - defaultType: Type | undefined, + constraint: SomeType | undefined, + defaultType: SomeType | undefined, parent: Reflection, varianceModifier: VarianceModifier | undefined ) { @@ -36,4 +37,15 @@ export class TypeParameterReflection extends Reflection { this.default = defaultType; this.varianceModifier = varianceModifier; } + + override toObject( + serializer: Serializer + ): JSONOutput.TypeParameterReflection { + return { + ...super.toObject(serializer), + type: serializer.toObject(this.type), + default: serializer.toObject(this.default), + varianceModifier: this.varianceModifier, + }; + } } diff --git a/src/lib/models/reflections/utils.ts b/src/lib/models/reflections/utils.ts index 50b581f5a..177587cdb 100644 --- a/src/lib/models/reflections/utils.ts +++ b/src/lib/models/reflections/utils.ts @@ -19,9 +19,10 @@ export function splitUnquotedString( return [input]; } else { const remainder = input.substring(closingQuoteIndex + 1); - const result = [input.substring(0, closingQuoteIndex + 1)]; - result.push(...splitUnquotedString(remainder, delimiter)); - return result; + return [ + input.substring(0, closingQuoteIndex + 1), + ...splitUnquotedString(remainder, delimiter), + ]; } } else { return input.split(delimiter); diff --git a/src/lib/models/sources/directory.ts b/src/lib/models/sources/directory.ts deleted file mode 100644 index 89bed50e1..000000000 --- a/src/lib/models/sources/directory.ts +++ /dev/null @@ -1,89 +0,0 @@ -import type { ReflectionGroup } from "../ReflectionGroup"; -import type { SourceFile } from "./file"; -import type { DeclarationReflection } from ".."; -import { flatMap } from "../../utils/array"; - -/** - * Exposes information about a directory containing source files. - * - * One my access the root directory of a project through the {@link ProjectReflection.directory} - * property. Traverse through directories by utilizing the {@link SourceDirectory.parent} or - * {@link SourceDirectory.directories} properties. - */ -export class SourceDirectory { - /** - * The parent directory or undefined if this is a root directory. - */ - parent?: SourceDirectory; - - /** - * A list of all subdirectories. - */ - directories: { [name: string]: SourceDirectory } = {}; - - groups?: ReflectionGroup[]; - - /** - * A list of all files in this directory. - */ - files: SourceFile[] = []; - - /** - * The name of this directory. - */ - name?: string; - - /** - * The relative path from the root directory to this directory. - */ - dirName?: string; - - /** - * The url of the page displaying the directory contents. - */ - url?: string; - - /** - * Create a new SourceDirectory instance. - * - * @param name The new of directory. - * @param parent The parent directory instance. - */ - constructor(name?: string, parent?: SourceDirectory) { - if (name && parent) { - this.name = name; - this.dirName = (parent.dirName ? parent.dirName + "/" : "") + name; - this.parent = parent; - } - } - - /** - * Return a string describing this directory and its contents. - * - * @param indent Used internally for indention. - * @returns A string representing this directory and all of its children. - */ - toString(indent = "") { - let res = indent + this.name; - - for (const dir of Object.values(this.directories)) { - res += "\n" + dir.toString(indent + " "); - } - - this.files.forEach((file) => { - res += "\n" + indent + " " + file.fileName; - }); - - return res; - } - - /** - * Return a list of all reflections exposed by the files within this directory. - * - * @returns An aggregated list of all {@link DeclarationReflection} defined in the - * files of this directory. - */ - getAllReflections(): DeclarationReflection[] { - return flatMap(this.files, (file) => file.reflections); - } -} diff --git a/src/lib/models/sources/file.ts b/src/lib/models/sources/file.ts index 6fcda3b4e..5753aecc6 100644 --- a/src/lib/models/sources/file.ts +++ b/src/lib/models/sources/file.ts @@ -1,99 +1,49 @@ -import * as Path from "path"; - -import type { ReflectionGroup } from "../ReflectionGroup"; -import type { SourceDirectory } from "./directory"; -import type { RepositoryType } from "./repository"; -import type { DeclarationReflection } from ".."; +import type { SourceReference as JSONSourceReference } from "../../serialization/schema"; /** * Represents references of reflections to their defining source files. * * @see {@link DeclarationReflection.sources} */ -export interface SourceReference { - /** - * A reference to the corresponding file instance. - */ - file?: SourceFile; - +export class SourceReference { /** * The filename of the source file. */ fileName: string; /** - * The number of the line that emitted the declaration. - */ - line: number; - - character: number; - - /** - * URL for displaying the source file. - */ - url?: string; -} - -/** - * Exposes information about a source file. - * - * One may access a list of all source files through the {@link ProjectReflection.files} property or as - * a tree structure through the {@link ProjectReflection.directory} property. - * - * Furthermore each reflection carries references to the related SourceFile with their - * {@link DeclarationReflection.sources} property. It is an array of of {@link SourceReference} instances - * containing the reference in their {@link SourceReference.file} field. - */ -export class SourceFile { - /** - * The original full system file name. + * The absolute filename of the source file. */ fullFileName: string; /** - * A trimmed version of the file name. Contains only the path relative to the - * determined base path. + * The number of the line that emitted the declaration. */ - fileName: string; + line: number; /** - * The base name of the file. + * The index of the character that emitted the declaration. */ - name: string; + character: number; /** - * A URL pointing to a page displaying the contents of this file. + * URL for displaying the source file. */ url?: string; - /** - * The type of repository where this file is hosted. - */ - repositoryType?: RepositoryType; - - /** - * The representation of the parent directory of this source file. - */ - parent?: SourceDirectory; - - /** - * A list of all reflections that are declared in this file. - */ - reflections: DeclarationReflection[] = []; - - /** - * A grouped list of the reflections declared in this file. - */ - groups?: ReflectionGroup[]; + constructor(fileName: string, line: number, character: number) { + this.fileName = fileName; + this.fullFileName = fileName; + this.line = line; + this.character = character; + } - /** - * Create a new SourceFile instance. - * - * @param fullFileName The full file name. - */ - constructor(fullFileName: string) { - this.fileName = fullFileName; - this.fullFileName = fullFileName; - this.name = Path.basename(fullFileName); + toObject(): JSONSourceReference { + return { + fileName: this.fileName, + line: this.line, + character: this.character, + url: this.url, + }; } } diff --git a/src/lib/models/sources/index.ts b/src/lib/models/sources/index.ts index e09c10a40..28f44711b 100644 --- a/src/lib/models/sources/index.ts +++ b/src/lib/models/sources/index.ts @@ -1,4 +1,2 @@ -export { SourceDirectory } from "./directory"; -export { SourceFile } from "./file"; -export type { SourceReference } from "./file"; +export { SourceReference } from "./file"; export { RepositoryType } from "./repository"; diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index 6610d6317..241f96999 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -3,6 +3,7 @@ import type { Context } from "../converter"; import { Reflection } from "./reflections/abstract"; import type { DeclarationReflection } from "./reflections/declaration"; import type { ProjectReflection } from "./reflections/project"; +import type { Serializer, JSONOutput } from "../serialization"; /** * Base class of all type definitions. @@ -36,6 +37,8 @@ export abstract class Type { return this.getTypeString(); } + abstract toObject(serializer: Serializer): JSONOutput.SomeType; + abstract needsParenthesis(context: TypeContext): boolean; /** @@ -213,13 +216,10 @@ export class ArrayType extends Type { override readonly type = "array"; /** - * The type of the array elements. + * @param elementType The type of the elements in the array. */ - elementType: Type; - - constructor(elementType: Type) { + constructor(public elementType: SomeType) { super(); - this.elementType = elementType; } protected override getTypeString() { @@ -229,6 +229,13 @@ export class ArrayType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.ArrayType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -242,10 +249,10 @@ export class ConditionalType extends Type { override readonly type = "conditional"; constructor( - public checkType: Type, - public extendsType: Type, - public trueType: Type, - public falseType: Type + public checkType: SomeType, + public extendsType: SomeType, + public trueType: SomeType, + public falseType: SomeType ) { super(); } @@ -291,6 +298,16 @@ export class ConditionalType extends Type { return map[context]; } + + override toObject(serializer: Serializer): JSONOutput.ConditionalType { + return { + type: this.type, + checkType: serializer.toObject(this.checkType), + extendsType: serializer.toObject(this.extendsType), + trueType: serializer.toObject(this.trueType), + falseType: serializer.toObject(this.falseType), + }; + } } /** @@ -299,7 +316,7 @@ export class ConditionalType extends Type { export class IndexedAccessType extends Type { override readonly type = "indexedAccess"; - constructor(public objectType: Type, public indexType: Type) { + constructor(public objectType: SomeType, public indexType: SomeType) { super(); } @@ -315,6 +332,14 @@ export class IndexedAccessType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.IndexedAccessType { + return { + type: this.type, + indexType: serializer.toObject(this.indexType), + objectType: serializer.toObject(this.objectType), + }; + } } /** @@ -369,6 +394,14 @@ export class InferredType extends Type { return map[context]; } + + override toObject(serializer: Serializer): JSONOutput.InferredType { + return { + type: this.type, + name: this.name, + constraint: serializer.toObject(this.constraint), + }; + } } /** @@ -381,7 +414,7 @@ export class InferredType extends Type { export class IntersectionType extends Type { override readonly type = "intersection"; - constructor(public types: Type[]) { + constructor(public types: SomeType[]) { super(); } @@ -420,6 +453,13 @@ export class IntersectionType extends Type { return map[context]; } + + override toObject(serializer: Serializer): JSONOutput.IntersectionType { + return { + type: this.type, + types: this.types.map((t) => serializer.toObject(t)), + }; + } } /** @@ -440,6 +480,13 @@ export class IntrinsicType extends Type { return this.name; } + override toObject(): JSONOutput.IntrinsicType { + return { + type: this.type, + name: this.name, + }; + } + override needsParenthesis(): boolean { return false; } @@ -473,6 +520,23 @@ export class LiteralType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(): JSONOutput.LiteralType { + if (typeof this.value === "bigint") { + return { + type: this.type, + value: { + value: this.value.toString().replace("-", ""), + negative: this.value < BigInt("0"), + }, + }; + } + + return { + type: this.type, + value: this.value, + }; + } } /** @@ -487,11 +551,11 @@ export class MappedType extends Type { constructor( public parameter: string, - public parameterType: Type, - public templateType: Type, + public parameterType: SomeType, + public templateType: SomeType, public readonlyModifier?: "+" | "-", public optionalModifier?: "+" | "-", - public nameType?: Type + public nameType?: SomeType ) { super(); } @@ -535,6 +599,18 @@ export class MappedType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.MappedType { + return { + type: this.type, + parameter: this.parameter, + parameterType: serializer.toObject(this.parameterType), + templateType: serializer.toObject(this.templateType), + readonlyModifier: this.readonlyModifier, + optionalModifier: this.optionalModifier, + nameType: serializer.toObject(this.nameType), + }; + } } /** @@ -547,9 +623,9 @@ export class MappedType extends Type { export class OptionalType extends Type { override readonly type = "optional"; - elementType: Type; + elementType: SomeType; - constructor(elementType: Type) { + constructor(elementType: SomeType) { super(); this.elementType = elementType; } @@ -561,6 +637,13 @@ export class OptionalType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.OptionalType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -574,32 +657,22 @@ export class OptionalType extends Type { export class PredicateType extends Type { override readonly type = "predicate"; - /** - * The type that the identifier is tested to be. - * May be undefined if the type is of the form `asserts val`. - * Will be defined if the type is of the form `asserts val is string` or `val is string`. - */ - targetType?: Type; - - /** - * The identifier name which is tested by the predicate. - */ - name: string; - - /** - * True if the type is of the form `asserts val is string`, false if - * the type is of the form `val is string` - */ - asserts: boolean; - /** * Create a new PredicateType instance. + * + * @param name The identifier name which is tested by the predicate. + * @param asserts True if the type is of the form `asserts val is string`, + * false if the type is of the form `val is string` + * @param targetType The type that the identifier is tested to be. + * May be undefined if the type is of the form `asserts val`. + * Will be defined if the type is of the form `asserts val is string` or `val is string`. */ - constructor(name: string, asserts: boolean, targetType?: Type) { + constructor( + public name: string, + public asserts: boolean, + public targetType?: SomeType + ) { super(); - this.name = name; - this.asserts = asserts; - this.targetType = targetType; } /** @@ -620,6 +693,15 @@ export class PredicateType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.PredicateType { + return { + type: this.type, + name: this.name, + asserts: this.asserts, + targetType: serializer.toObject(this.targetType), + }; + } } /** @@ -654,6 +736,13 @@ export class QueryType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.QueryType { + return { + type: this.type, + queryType: serializer.toObject(this.queryType), + }; + } } /** @@ -677,7 +766,7 @@ export class ReferenceType extends Type { /** * The type arguments of this reference. */ - typeArguments?: Type[]; + typeArguments?: SomeType[]; /** * The resolved reflection. @@ -806,6 +895,22 @@ export class ReferenceType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.ReferenceType { + const result: JSONOutput.ReferenceType = { + type: this.type, + id: this.reflection?.id, + typeArguments: serializer.toObjectsOptional(this.typeArguments), + name: this.name, + }; + + if (this.qualifiedName && this.package) { + result.qualifiedName = this.qualifiedName; + result.package = this.package; + } + + return result; + } } /** @@ -842,6 +947,13 @@ export class ReflectionType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.ReflectionType { + return { + type: this.type, + declaration: serializer.toObject(this.declaration), + }; + } } /** @@ -854,7 +966,7 @@ export class ReflectionType extends Type { export class RestType extends Type { override readonly type = "rest"; - constructor(public elementType: Type) { + constructor(public elementType: SomeType) { super(); } @@ -865,6 +977,13 @@ export class RestType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.RestType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -876,7 +995,7 @@ export class RestType extends Type { export class TemplateLiteralType extends Type { override readonly type = "template-literal"; - constructor(public head: string, public tail: [Type, string][]) { + constructor(public head: string, public tail: [SomeType, string][]) { super(); } @@ -899,6 +1018,17 @@ export class TemplateLiteralType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.TemplateLiteralType { + return { + type: this.type, + head: this.head, + tail: this.tail.map(([type, text]) => [ + serializer.toObject(type), + text, + ]), + }; + } } /** @@ -912,13 +1042,10 @@ export class TupleType extends Type { override readonly type = "tuple"; /** - * The ordered type elements of the tuple type. + * @param elements The ordered type elements of the tuple type. */ - elements: Type[]; - - constructor(elements: Type[]) { + constructor(public elements: SomeType[]) { super(); - this.elements = elements; } protected override getTypeString() { @@ -934,6 +1061,13 @@ export class TupleType extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.TupleType { + return { + type: this.type, + elements: serializer.toObjectsOptional(this.elements), + }; + } } /** @@ -949,7 +1083,7 @@ export class NamedTupleMember extends Type { constructor( public name: string, public isOptional: boolean, - public element: Type + public element: SomeType ) { super(); } @@ -966,6 +1100,15 @@ export class NamedTupleMember extends Type { override needsParenthesis(): boolean { return false; } + + override toObject(serializer: Serializer): JSONOutput.NamedTupleMemberType { + return { + type: this.type, + name: this.name, + isOptional: this.isOptional, + element: serializer.toObject(this.element), + }; + } } /** @@ -980,7 +1123,7 @@ export class TypeOperatorType extends Type { override readonly type = "typeOperator"; constructor( - public target: Type, + public target: SomeType, public operator: "keyof" | "unique" | "readonly" ) { super(); @@ -1021,6 +1164,14 @@ export class TypeOperatorType extends Type { return map[context]; } + + override toObject(serializer: Serializer): JSONOutput.TypeOperatorType { + return { + type: this.type, + operator: this.operator, + target: serializer.toObject(this.target), + }; + } } /** @@ -1102,6 +1253,13 @@ export class UnionType extends Type { ); } } + + override toObject(serializer: Serializer): JSONOutput.UnionType { + return { + type: this.type, + types: this.types.map((t) => serializer.toObject(t)), + }; + } } /** @@ -1131,4 +1289,11 @@ export class UnknownType extends Type { override needsParenthesis(context: TypeContext): boolean { return context !== TypeContext.none; } + + override toObject(): JSONOutput.UnknownType { + return { + type: this.type, + name: this.name, + }; + } } diff --git a/src/lib/output/events.ts b/src/lib/output/events.ts index a03ba37da..989d1914b 100644 --- a/src/lib/output/events.ts +++ b/src/lib/output/events.ts @@ -3,7 +3,6 @@ import * as Path from "path"; import { Event } from "../utils/events"; import type { ProjectReflection } from "../models/reflections/project"; import type { RenderTemplate, UrlMapping } from "./models/UrlMapping"; -import type { LegendItem } from "./plugins/LegendPlugin"; /** * An event emitted by the {@link Renderer} class at the very beginning and @@ -105,12 +104,6 @@ export class PageEvent extends Event { */ template!: RenderTemplate; - /** - * The legend items that are applicable for this page - * @internal this is going away. The footer will do the logic itself. - */ - legend?: LegendItem[][]; - /** * The final html content of this page. * @@ -132,10 +125,9 @@ export class PageEvent extends Event { } /** - * An event emitted by the {@link MarkedPlugin} on the {@link Renderer} after a chunk of - * markdown has been processed. Allows other plugins to manipulate the result. + * An event emitted when markdown is being parsed. Allows other plugins to manipulate the result. * - * @see {@link MarkedPlugin.EVENT_PARSE_MARKDOWN} + * @see {@link PARSE} */ export class MarkdownEvent extends Event { /** diff --git a/src/lib/output/plugins/JavascriptIndexPlugin.ts b/src/lib/output/plugins/JavascriptIndexPlugin.ts index ad7d1f137..f995390ae 100644 --- a/src/lib/output/plugins/JavascriptIndexPlugin.ts +++ b/src/lib/output/plugins/JavascriptIndexPlugin.ts @@ -42,11 +42,6 @@ export class JavascriptIndexPlugin extends RendererComponent { const rows: any[] = []; const kinds: { [K in ReflectionKind]?: string } = {}; - const kindBoosts = - (this.application.options.getValue("searchGroupBoosts") as { - [key: string]: number; - }) ?? {}; - for (const reflection of event.project.getReflectionsByKind( ReflectionKind.All )) { @@ -57,14 +52,13 @@ export class JavascriptIndexPlugin extends RendererComponent { if ( !reflection.url || !reflection.name || - reflection.flags.isExternal || - reflection.name === "" + reflection.flags.isExternal ) { continue; } let parent = reflection.parent; - let boost = reflection.relevanceBoost ?? 1; + const boost = reflection.relevanceBoost ?? 1; if (parent instanceof ProjectReflection) { parent = undefined; } @@ -75,11 +69,6 @@ export class JavascriptIndexPlugin extends RendererComponent { ); } - const kindBoost = kindBoosts[kinds[reflection.kind] ?? ""]; - if (kindBoost != undefined) { - boost *= kindBoost; - } - const row: any = { id: rows.length, kind: reflection.kind, diff --git a/src/lib/output/plugins/LegendPlugin.ts b/src/lib/output/plugins/LegendPlugin.ts deleted file mode 100644 index ba156900f..000000000 --- a/src/lib/output/plugins/LegendPlugin.ts +++ /dev/null @@ -1,326 +0,0 @@ -import { - Reflection, - DeclarationReflection, - ProjectReflection, -} from "../../models/reflections/index"; -import { Component, RendererComponent } from "../components"; -import { PageEvent, RendererEvent } from "../events"; - -export interface LegendItem { - /** - * Legend item name - */ - name: string; - - /** - * List of css classes that represent the legend item - */ - classes: string[]; -} - -const ignoredClasses = new Set(["tsd-parent-kind-module", "tsd-is-overwrite"]); - -const completeLegend: LegendItem[][] = [ - [ - { name: "Namespace", classes: ["tsd-kind-namespace"] }, - { name: "Object literal", classes: ["tsd-kind-object-literal"] }, - { name: "Variable", classes: ["tsd-kind-variable"] }, - { name: "Function", classes: ["tsd-kind-function"] }, - { - name: "Function with type parameter", - classes: ["tsd-kind-function", "tsd-has-type-parameter"], - }, - { name: "Index signature", classes: ["tsd-kind-index-signature"] }, - { name: "Type alias", classes: ["tsd-kind-type-alias"] }, - { - name: "Type alias with type parameter", - classes: ["tsd-kind-type-alias", "tsd-has-type-parameter"], - }, - ], - [ - { name: "Enumeration", classes: ["tsd-kind-enum"] }, - { name: "Enumeration Member", classes: ["tsd-kind-enum-member"] }, - { - name: "Property", - classes: ["tsd-kind-property", "tsd-parent-kind-enum"], - }, - { - name: "Method", - classes: ["tsd-kind-method", "tsd-parent-kind-enum"], - }, - ], - [ - { name: "Interface", classes: ["tsd-kind-interface"] }, - { - name: "Interface with type parameter", - classes: ["tsd-kind-interface", "tsd-has-type-parameter"], - }, - { - name: "Constructor", - classes: ["tsd-kind-constructor", "tsd-parent-kind-interface"], - }, - { - name: "Property", - classes: ["tsd-kind-property", "tsd-parent-kind-interface"], - }, - { - name: "Method", - classes: ["tsd-kind-method", "tsd-parent-kind-interface"], - }, - { - name: "Index signature", - classes: ["tsd-kind-index-signature", "tsd-parent-kind-interface"], - }, - ], - [ - { name: "Class", classes: ["tsd-kind-class"] }, - { - name: "Class with type parameter", - classes: ["tsd-kind-class", "tsd-has-type-parameter"], - }, - { - name: "Constructor", - classes: ["tsd-kind-constructor", "tsd-parent-kind-class"], - }, - { - name: "Property", - classes: ["tsd-kind-property", "tsd-parent-kind-class"], - }, - { - name: "Method", - classes: ["tsd-kind-method", "tsd-parent-kind-class"], - }, - { - name: "Accessor", - classes: ["tsd-kind-accessor", "tsd-parent-kind-class"], - }, - { - name: "Index signature", - classes: ["tsd-kind-index-signature", "tsd-parent-kind-class"], - }, - ], - [ - { - name: "Inherited constructor", - classes: [ - "tsd-kind-constructor", - "tsd-parent-kind-class", - "tsd-is-inherited", - ], - }, - { - name: "Inherited property", - classes: [ - "tsd-kind-property", - "tsd-parent-kind-class", - "tsd-is-inherited", - ], - }, - { - name: "Inherited method", - classes: [ - "tsd-kind-method", - "tsd-parent-kind-class", - "tsd-is-inherited", - ], - }, - { - name: "Inherited accessor", - classes: [ - "tsd-kind-accessor", - "tsd-parent-kind-class", - "tsd-is-inherited", - ], - }, - ], - [ - { - name: "Protected property", - classes: [ - "tsd-kind-property", - "tsd-parent-kind-class", - "tsd-is-protected", - ], - }, - { - name: "Protected method", - classes: [ - "tsd-kind-method", - "tsd-parent-kind-class", - "tsd-is-protected", - ], - }, - { - name: "Protected accessor", - classes: [ - "tsd-kind-accessor", - "tsd-parent-kind-class", - "tsd-is-protected", - ], - }, - ], - [ - { - name: "Private property", - classes: [ - "tsd-kind-property", - "tsd-parent-kind-class", - "tsd-is-private", - ], - }, - { - name: "Private method", - classes: [ - "tsd-kind-method", - "tsd-parent-kind-class", - "tsd-is-private", - ], - }, - { - name: "Private accessor", - classes: [ - "tsd-kind-accessor", - "tsd-parent-kind-class", - "tsd-is-private", - ], - }, - ], - [ - { - name: "Static property", - classes: [ - "tsd-kind-property", - "tsd-parent-kind-class", - "tsd-is-static", - ], - }, - { - name: "Static method", - classes: [ - "tsd-kind-method", - "tsd-parent-kind-class", - "tsd-is-static", - ], - }, - ], -]; - -export class LegendBuilder { - private _classesList: Set[]; - - constructor() { - this._classesList = []; - } - - build(): LegendItem[][] { - const filteredLegend = completeLegend - .map((list) => { - return list.filter((item) => { - for (const classes of this._classesList) { - if (this.isArrayEqualToSet(item.classes, classes)) { - return true; - } - } - return false; - }); - }) - .filter((list) => list.length); - - return filteredLegend; - } - - registerCssClasses(classArray: string[]) { - let exists = false; - const items = classArray.filter((cls) => !ignoredClasses.has(cls)); - - for (const classes of this._classesList) { - if (this.isArrayEqualToSet(items, classes)) { - exists = true; - break; - } - } - - if (!exists) { - this._classesList.push(new Set(items)); - } - } - - private isArrayEqualToSet(a: T[], b: Set) { - if (a.length !== b.size) { - return false; - } - - for (const value of a) { - if (!b.has(value)) { - return false; - } - } - return true; - } -} - -/** - * A plugin that generates the legend for the current page. - * - * This plugin sets the {@link PageEvent.legend} property. - */ -@Component({ name: "legend" }) -export class LegendPlugin extends RendererComponent { - private _project?: ProjectReflection; - - /** - * Create a new LegendPlugin instance. - */ - override initialize() { - this.listenTo(this.owner, { - [RendererEvent.BEGIN]: this.onRenderBegin, - [PageEvent.BEGIN]: this.onRendererBeginPage, - [RendererEvent.END]: () => (this._project = void 0), - }); - } - - private onRenderBegin(event: RendererEvent) { - this._project = event.project; - } - - /** - * Triggered before a document will be rendered. - * - * @param page An event object describing the current render operation. - */ - private onRendererBeginPage(page: PageEvent) { - const model = page.model; - const builder = new LegendBuilder(); - - // immediate children - this.buildLegend(model, builder); - - // top level items (as appears in navigation) - this._project?.children?.forEach((reflection) => { - if (reflection !== model) { - this.buildLegend(reflection, builder); - } - }); - - page.legend = builder.build().sort((a, b) => b.length - a.length); - } - - private buildLegend(model: Reflection, builder: LegendBuilder) { - if (model instanceof DeclarationReflection) { - const children = ( - model.children || ([] as Array) - ) - .concat(...(model.groups?.map((group) => group.children) || [])) - .concat(...model.getAllSignatures()) - .concat(model.indexSignature as Reflection) - .filter((item) => item); - - for (const child of children) { - const cssClasses = child?.cssClasses?.split(" "); - if (cssClasses) { - builder.registerCssClasses(cssClasses); - } - } - } - } -} diff --git a/src/lib/output/plugins/MarkedLinksPlugin.ts b/src/lib/output/plugins/MarkedLinksPlugin.ts deleted file mode 100644 index d078068f6..000000000 --- a/src/lib/output/plugins/MarkedLinksPlugin.ts +++ /dev/null @@ -1,217 +0,0 @@ -import * as Util from "util"; - -import type { Reflection } from "../../models/reflections/abstract"; -import { Component, ContextAwareRendererComponent } from "../components"; -import { MarkdownEvent, RendererEvent } from "../events"; -import { BindOption, ValidationOptions } from "../../utils"; - -/** - * A plugin that builds links in markdown texts. - */ -@Component({ name: "marked-links" }) -export class MarkedLinksPlugin extends ContextAwareRendererComponent { - /** - * Regular expression for detecting bracket links. - */ - private brackets = /\[\[([^\]]+)\]\]/g; - - /** - * Regular expression for detecting inline tags like {&link ...}. - */ - private inlineTag = - /(?:\[(.+?)\])?\{@(link|linkcode|linkplain)\s+((?:.|\n)+?)\}/gi; - - @BindOption("listInvalidSymbolLinks") - listInvalidSymbolLinks!: boolean; - - @BindOption("validation") - validation!: ValidationOptions; - - private warnings: string[] = []; - - /** - * Create a new MarkedLinksPlugin instance. - */ - override initialize() { - super.initialize(); - this.listenTo( - this.owner, - { - [MarkdownEvent.PARSE]: this.onParseMarkdown, - [RendererEvent.END]: this.onEndRenderer, - }, - undefined, - 100 - ); - } - - /** - * Find all references to symbols within the given text and transform them into a link. - * - * This function is aware of the current context and will try to find the symbol within the - * current reflection. It will walk up the reflection chain till the symbol is found or the - * root reflection is reached. As a last resort the function will search the entire project - * for the given symbol. - * - * @param text The text that should be parsed. - * @returns The text with symbol references replaced by links. - */ - private replaceBrackets(text: string): string { - return text.replace( - this.brackets, - (match: string, content: string): string => { - const monospace = - content[0] === "`" && content[content.length - 1] === "`"; - const split = MarkedLinksPlugin.splitLinkText( - monospace ? content.slice(1, -1) : content - ); - return this.buildLink( - match, - split.target, - split.caption, - monospace - ); - } - ); - } - - /** - * Find symbol {&link ...} strings in text and turn into html links - * - * @param text The string in which to replace the inline tags. - * @return The updated string. - */ - private replaceInlineTags(text: string): string { - return text.replace( - this.inlineTag, - ( - match: string, - leading: string, - tagName: string, - content: string - ): string => { - const split = MarkedLinksPlugin.splitLinkText(content); - const target = split.target; - const caption = leading || split.caption; - const monospace = tagName === "linkcode"; - - return this.buildLink(match, target, caption, monospace); - } - ); - } - - /** - * Format a link with the given text and target. - * - * @param original The original link string, will be returned if the target cannot be resolved.. - * @param target The link target. - * @param caption The caption of the link. - * @param monospace Whether to use monospace formatting or not. - * @returns A html link tag. - */ - private buildLink( - original: string, - target: string, - caption: string, - monospace?: boolean - ): string { - let attributes = ""; - if (this.urlPrefix.test(target)) { - attributes = ' class="external"'; - } else { - let reflection: Reflection | undefined; - if (this.reflection) { - reflection = this.reflection.findReflectionByName(target); - } else if (this.project) { - reflection = this.project.findReflectionByName(target); - } - - if (reflection && reflection.url) { - if (this.urlPrefix.test(reflection.url)) { - target = reflection.url; - attributes = ' class="external"'; - } else { - target = this.getRelativeUrl(reflection.url); - } - } else { - const fullName = (this.reflection || - this.project)!.getFriendlyFullName(); - this.warnings.push(`In ${fullName}: ${original}`); - return original; - } - } - - if (monospace) { - caption = "" + caption + ""; - } - - return Util.format( - '%s', - target, - attributes, - caption - ); - } - - /** - * Triggered when {@link MarkedPlugin} parses a markdown string. - * - * @param event - */ - onParseMarkdown(event: MarkdownEvent) { - event.parsedText = this.replaceInlineTags( - this.replaceBrackets(event.parsedText) - ); - } - - /** - * Triggered when {@link Renderer} is finished - */ - onEndRenderer(_event: RendererEvent) { - const enabled = - this.listInvalidSymbolLinks || this.validation.invalidLink; - if (this.listInvalidSymbolLinks) { - this.application.logger.warn( - "listInvalidSymbolLinks is deprecated and will be removed in 0.23, set validation.invalidLink instead." - ); - } - - if (enabled && this.warnings.length > 0) { - this.application.logger.warn( - "\n[MarkedLinksPlugin]: Found invalid symbol reference(s) in JSDocs, " + - "they will not render as links in the generated documentation." + - "\n " + - this.warnings.join("\n ") - ); - } - this.warnings = []; - } - - /** - * Split the given link into text and target at first pipe or space. - * - * @param text The source string that should be checked for a split character. - * @returns An object containing the link text and target. - */ - static splitLinkText(text: string): { caption: string; target: string } { - let splitIndex = text.indexOf("|"); - if (splitIndex === -1) { - splitIndex = text.search(/\s/); - } - - if (splitIndex !== -1) { - return { - caption: text - .substr(splitIndex + 1) - .replace(/\n+/, " ") - .trim(), - target: text.substr(0, splitIndex).trim(), - }; - } else { - return { - caption: text, - target: text, - }; - } - } -} diff --git a/src/lib/output/plugins/index.ts b/src/lib/output/plugins/index.ts index 18bce1ddd..5eefc0379 100644 --- a/src/lib/output/plugins/index.ts +++ b/src/lib/output/plugins/index.ts @@ -1,5 +1,3 @@ export { AssetsPlugin } from "./AssetsPlugin"; export { JavascriptIndexPlugin } from "./JavascriptIndexPlugin"; -export { MarkedLinksPlugin } from "./MarkedLinksPlugin"; export { MarkedPlugin } from "../themes/MarkedPlugin"; -export { LegendPlugin } from "./LegendPlugin"; diff --git a/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index 63e297f98..8db59e343 100644 --- a/src/lib/output/renderer.ts +++ b/src/lib/output/renderer.ts @@ -14,7 +14,7 @@ import type { Theme } from "./theme"; import { RendererEvent, PageEvent } from "./events"; import type { ProjectReflection } from "../models/reflections/project"; import type { UrlMapping } from "./models/UrlMapping"; -import { remove, writeFileSync } from "../utils/fs"; +import { writeFileSync } from "../utils/fs"; import { DefaultTheme } from "./themes/default/DefaultTheme"; import { RendererComponent } from "./components"; import { Component, ChildableComponent } from "../utils/component"; @@ -24,6 +24,7 @@ import type { Theme as ShikiTheme } from "shiki"; import { ReferenceType, Reflection } from "../models"; import type { JsxElement } from "../utils/jsx.elements"; import type { DefaultThemeRenderContext } from "./themes/default/DefaultThemeRenderContext"; +import { clearSeenIconCache } from "./themes/default/partials/icon"; /** * Describes the hooks available to inject output in the default theme. @@ -149,22 +150,10 @@ export class Renderer extends ChildableComponent< @BindOption("cname") cname!: string; - /** @internal */ - @BindOption("gaID") - gaID!: string; - - /** @internal */ - @BindOption("gaSite") - gaSite!: string; - /** @internal */ @BindOption("githubPages") githubPages!: boolean; - /** @internal */ - @BindOption("hideGenerator") - hideGenerator!: boolean; - /** @internal */ @BindOption("lightHighlightTheme") lightTheme!: ShikiTheme; @@ -175,10 +164,8 @@ export class Renderer extends ChildableComponent< /** * Define a new theme that can be used to render output. - * This API will likely be changing in TypeDoc 0.23. - * (sorry... changing as soon as it's introduced) - * As it is, it provides reasonable flexibility, but doesn't give users a sufficiently - * easy way to overwrite parts of a theme. + * This API will likely be changing at some point, to allow more easily overriding parts of the theme without + * requiring additional boilerplate. * @param name * @param theme */ @@ -264,6 +251,7 @@ export class Renderer extends ChildableComponent< if (!output.isDefaultPrevented) { output.urls.forEach((mapping: UrlMapping) => { + clearSeenIconCache(); this.renderDocument(output.createPageEvent(mapping)); }); @@ -349,7 +337,10 @@ export class Renderer extends ChildableComponent< private async prepareOutputDirectory(directory: string): Promise { if (this.cleanOutputDir) { try { - await remove(directory); + await fs.promises.rm(directory, { + recursive: true, + force: true, + }); } catch (error) { this.application.logger.warn( "Could not empty the output directory." diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index bddba2bbf..de59eba96 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -6,8 +6,8 @@ import { ProjectReflection, ContainerReflection, DeclarationReflection, -} from "../../../models/reflections/index"; -import type { ReflectionGroup } from "../../../models/ReflectionGroup"; + SignatureReflection, +} from "../../../models"; import { RenderTemplate, UrlMapping } from "../../models/UrlMapping"; import { PageEvent, RendererEvent } from "../../events"; import type { MarkedPlugin } from "../../plugins"; @@ -25,12 +25,6 @@ interface TemplateMapping { */ kind: ReflectionKind[]; - /** - * Can this mapping have children or should all further reflections be rendered - * to the defined output page? - */ - isLeaf: boolean; - /** * The name of the directory the output files should be written to. */ @@ -49,6 +43,7 @@ interface TemplateMapping { export class DefaultTheme extends Theme { /** @internal */ markedPlugin: MarkedPlugin; + private _renderContext?: DefaultThemeRenderContext; getRenderContext(_pageEvent: PageEvent) { if (!this._renderContext) { @@ -73,28 +68,39 @@ export class DefaultTheme extends Theme { private mappings: TemplateMapping[] = [ { kind: [ReflectionKind.Class], - isLeaf: false, directory: "classes", template: this.reflectionTemplate, }, { kind: [ReflectionKind.Interface], - isLeaf: false, directory: "interfaces", template: this.reflectionTemplate, }, { kind: [ReflectionKind.Enum], - isLeaf: false, directory: "enums", template: this.reflectionTemplate, }, { kind: [ReflectionKind.Namespace, ReflectionKind.Module], - isLeaf: false, directory: "modules", template: this.reflectionTemplate, }, + { + kind: [ReflectionKind.TypeAlias], + directory: "types", + template: this.reflectionTemplate, + }, + { + kind: [ReflectionKind.Function], + directory: "functions", + template: this.reflectionTemplate, + }, + { + kind: [ReflectionKind.Variable], + directory: "variables", + template: this.reflectionTemplate, + }, ]; static URL_PREFIX = /^(http|ftp)s?:\/\//; @@ -145,18 +151,10 @@ export class DefaultTheme extends Theme { * @param event An event object describing the current render operation. */ private onRendererBegin(event: RendererEvent) { - if (event.project.groups) { - event.project.groups.forEach(DefaultTheme.applyGroupClasses); - } - - for (const id in event.project.reflections) { - const reflection = event.project.reflections[id]; + const filters = this.application.options.getValue("visibilityFilters") as Record; + for (const reflection of Object.values(event.project.reflections)) { if (reflection instanceof DeclarationReflection) { - DefaultTheme.applyReflectionClasses(reflection); - } - - if (reflection instanceof ContainerReflection && reflection.groups) { - reflection.groups.forEach(DefaultTheme.applyGroupClasses); + DefaultTheme.applyReflectionClasses(reflection, filters); } } } @@ -207,13 +205,14 @@ export class DefaultTheme extends Theme { reflection.hasOwnDocument = true; } - for (const child of reflection.children || []) { - if (mapping.isLeaf) { - DefaultTheme.applyAnchorUrl(child, reflection); - } else { + reflection.traverse((child) => { + if (child instanceof DeclarationReflection) { this.buildUrls(child, urls); + } else { + DefaultTheme.applyAnchorUrl(child, reflection); } - } + return true; + }); } else if (reflection.parent) { DefaultTheme.applyAnchorUrl(reflection, reflection.parent); } @@ -233,6 +232,10 @@ export class DefaultTheme extends Theme { * @param container The nearest reflection having an own document. */ static applyAnchorUrl(reflection: Reflection, container: Reflection) { + if (!(reflection instanceof DeclarationReflection) && !(reflection instanceof SignatureReflection)) { + return; + } + if (!reflection.url || !DefaultTheme.URL_PREFIX.test(reflection.url)) { const anchor = DefaultTheme.getUrl(reflection, container, "."); @@ -242,9 +245,7 @@ export class DefaultTheme extends Theme { } reflection.traverse((child) => { - if (child instanceof DeclarationReflection) { - DefaultTheme.applyAnchorUrl(child, container); - } + DefaultTheme.applyAnchorUrl(child, container); return true; }); } @@ -255,85 +256,50 @@ export class DefaultTheme extends Theme { * * @param reflection The reflection whose cssClasses property should be generated. */ - static applyReflectionClasses(reflection: DeclarationReflection) { + static applyReflectionClasses(reflection: DeclarationReflection, filters: Record) { const classes: string[] = []; - let kind: string; - - if (reflection.kind === ReflectionKind.Accessor) { - if (!reflection.getSignature) { - classes.push("tsd-kind-set-signature"); - } else if (!reflection.setSignature) { - classes.push("tsd-kind-get-signature"); - } else { - classes.push("tsd-kind-accessor"); - } - } else { - kind = ReflectionKind[reflection.kind]; - classes.push(DefaultTheme.toStyleClass("tsd-kind-" + kind)); - } + + classes.push(DefaultTheme.toStyleClass("tsd-kind-" + ReflectionKind[reflection.kind])); if (reflection.parent && reflection.parent instanceof DeclarationReflection) { - kind = ReflectionKind[reflection.parent.kind]; - classes.push(DefaultTheme.toStyleClass(`tsd-parent-kind-${kind}`)); + classes.push(DefaultTheme.toStyleClass(`tsd-parent-kind-${ReflectionKind[reflection.parent.kind]}`)); } - let hasTypeParameters = !!reflection.typeParameters; - reflection.getAllSignatures().forEach((signature) => { - hasTypeParameters = hasTypeParameters || !!signature.typeParameters; - }); - - if (hasTypeParameters) { - classes.push("tsd-has-type-parameter"); - } - if (reflection.overwrites) { - classes.push("tsd-is-overwrite"); - } - if (reflection.inheritedFrom) { - classes.push("tsd-is-inherited"); - } - if (reflection.flags.isPrivate) { - classes.push("tsd-is-private"); - } - if (reflection.flags.isProtected) { - classes.push("tsd-is-protected"); - } - if (reflection.flags.isStatic) { - classes.push("tsd-is-static"); - } - if (reflection.flags.isExternal) { - classes.push("tsd-is-external"); + // Filter classes should match up with the settings function in + // partials/navigation.tsx. + for (const key of Object.keys(filters)) { + if (key === "inherited") { + if (reflection.inheritedFrom) { + classes.push("tsd-is-inherited"); + } + } else if (key === "protected") { + if (reflection.flags.isProtected) { + classes.push("tsd-is-protected"); + } + } else if (key === "external") { + if (reflection.flags.isExternal) { + classes.push("tsd-is-external"); + } + } else if (key.startsWith("@")) { + if (key === "@deprecated") { + if (reflection.isDeprecated()) { + classes.push(DefaultTheme.toStyleClass(`tsd-is-${key.substring(1)}`)); + } + } else if ( + reflection.comment?.hasModifier(key as `@${string}`) || + reflection.comment?.getTag(key as `@${string}`) + ) { + classes.push(DefaultTheme.toStyleClass(`tsd-is-${key.substring(1)}`)); + } + } } reflection.cssClasses = classes.join(" "); } - /** - * Generate the css classes for the given reflection group and apply them to the - * {@link ReflectionGroup.cssClasses} property. - * - * @param group The reflection group whose cssClasses property should be generated. - */ - static applyGroupClasses(group: ReflectionGroup) { - const classes: string[] = []; - if (group.allChildrenAreInherited) { - classes.push("tsd-is-inherited"); - } - if (group.allChildrenArePrivate) { - classes.push("tsd-is-private"); - } - if (group.allChildrenAreProtectedOrPrivate) { - classes.push("tsd-is-private-protected"); - } - if (group.allChildrenAreExternal) { - classes.push("tsd-is-external"); - } - - group.cssClasses = classes.join(" "); - } - /** * Transform a space separated string into a string suitable to be used as a - * css class, e.g. "constructor method" > "Constructor-method". + * css class, e.g. "constructor method" > "constructor-method". */ static toStyleClass(str: string) { return str.replace(/(\w)([A-Z])/g, (_m, m1, m2) => m1 + "-" + m2).toLowerCase(); diff --git a/src/lib/output/themes/default/DefaultThemeRenderContext.ts b/src/lib/output/themes/default/DefaultThemeRenderContext.ts index b7e07c321..aa276e3d8 100644 --- a/src/lib/output/themes/default/DefaultThemeRenderContext.ts +++ b/src/lib/output/themes/default/DefaultThemeRenderContext.ts @@ -22,6 +22,7 @@ import { members } from "./partials/members"; import { membersGroup } from "./partials/members.group"; import { navigation } from "./partials/navigation"; import { parameter } from "./partials/parameter"; +import { toolbar } from "./partials/toolbar"; import { type } from "./partials/type"; import { typeAndParent } from "./partials/typeAndParent"; import { typeParameters } from "./partials/typeParameters"; @@ -80,6 +81,7 @@ export class DefaultThemeRenderContext { membersGroup = bind(membersGroup, this); navigation = bind(navigation, this); parameter = bind(parameter, this); + toolbar = bind(toolbar, this); type = bind(type, this); typeAndParent = bind(typeAndParent, this); typeParameters = bind(typeParameters, this); diff --git a/src/lib/output/themes/default/assets/bootstrap.ts b/src/lib/output/themes/default/assets/bootstrap.ts index 401911905..064559c10 100644 --- a/src/lib/output/themes/default/assets/bootstrap.ts +++ b/src/lib/output/themes/default/assets/bootstrap.ts @@ -4,6 +4,7 @@ import { initSearch } from "./typedoc/components/Search"; import { Signature } from "./typedoc/components/Signature"; import { Toggle } from "./typedoc/components/Toggle"; import { Filter } from "./typedoc/components/Filter"; +import { Accordion } from "./typedoc/components/Accordion"; import { initTheme } from "./typedoc/Theme"; initSearch(); @@ -11,12 +12,8 @@ initSearch(); registerComponent(MenuHighlight, ".menu-highlight"); registerComponent(Signature, ".tsd-signatures"); registerComponent(Toggle, "a[data-toggle]"); - -if (Filter.isSupported()) { - registerComponent(Filter, "#tsd-filter"); -} else { - document.documentElement.classList.add("no-filter"); -} +registerComponent(Accordion, ".tsd-index-accordion"); +registerComponent(Filter, ".tsd-filter-item input[type=checkbox]"); const themeChoice = document.getElementById("theme"); if (themeChoice) { diff --git a/src/lib/output/themes/default/assets/typedoc/Application.ts b/src/lib/output/themes/default/assets/typedoc/Application.ts index 4ba2ce740..26232059d 100644 --- a/src/lib/output/themes/default/assets/typedoc/Application.ts +++ b/src/lib/output/themes/default/assets/typedoc/Application.ts @@ -38,7 +38,7 @@ export class Application { } /** - * Create all components beneath the given jQuery element. + * Create all components beneath the given element. */ public createComponents(context: HTMLElement) { components.forEach((c) => { diff --git a/src/lib/output/themes/default/assets/typedoc/Theme.ts b/src/lib/output/themes/default/assets/typedoc/Theme.ts index ed7712bb7..270a1818a 100644 --- a/src/lib/output/themes/default/assets/typedoc/Theme.ts +++ b/src/lib/output/themes/default/assets/typedoc/Theme.ts @@ -1,13 +1,14 @@ +import { storage } from "./utils/storage"; + type ThemeChoice = "os" | "light" | "dark"; export function initTheme(choices: HTMLOptionElement) { - const savedTheme = - (localStorage.getItem("tsd-theme") as ThemeChoice) || "os"; + const savedTheme = (storage.getItem("tsd-theme") as ThemeChoice) || "os"; choices.value = savedTheme; setTheme(savedTheme); choices.addEventListener("change", () => { - localStorage.setItem("tsd-theme", choices.value); + storage.setItem("tsd-theme", choices.value); setTheme(choices.value as ThemeChoice); }); } @@ -16,17 +17,5 @@ export function initTheme(choices: HTMLOptionElement) { // - src/lib/output/themes/defaults/layouts/default.tsx // - src/lib/utils/highlighter.tsx function setTheme(theme: ThemeChoice) { - switch (theme) { - case "os": - document.body.classList.remove("light", "dark"); - break; - case "light": - document.body.classList.remove("dark"); - document.body.classList.add("light"); - break; - case "dark": - document.body.classList.remove("light"); - document.body.classList.add("dark"); - break; - } + document.documentElement.dataset.theme = theme; } diff --git a/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts b/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts new file mode 100644 index 000000000..e9ba76b96 --- /dev/null +++ b/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts @@ -0,0 +1,210 @@ +import { Component, IComponentOptions } from "../Component"; +import { storage } from "../utils/storage"; + +/** + * Handles accordion dropdown behavior. + */ +export class Accordion extends Component { + override el!: HTMLDetailsElement; + + /** + * The heading container for this accordion. + */ + private summary: HTMLElement; + + /** + * The chevron icon next to this accordion's heading. + */ + private icon: SVGElement; + + /** + * The key by which to store this accordion's state in storage. + */ + private readonly key: string; + + /** + * The ongoing animation, if there is one. + */ + private animation?: Animation; + + /** + * The accordion's height when collapsed. + */ + private collapsedHeight!: string; + + /** + * The accordion's height when expanded. + */ + private expandedHeight!: string; + + constructor(options: IComponentOptions) { + super(options); + + this.calculateHeights(); + this.summary = this.el.querySelector(".tsd-accordion-summary")!; + this.icon = this.summary.querySelector("svg")!; + this.key = `tsd-accordion-${this.summary + .textContent!.replace(/\s+/g, "-") + .toLowerCase()}`; + + this.setLocalStorage(this.fromLocalStorage(), true); + this.summary.addEventListener("click", (e: MouseEvent) => + this.toggleVisibility(e) + ); + this.icon.style.transform = this.getIconRotation(); + } + + /** + * The transform that should be applied to the chevron based on the accordion's state. + */ + private getIconRotation(open = this.el.open) { + return `rotate(${open ? 0 : -90}deg)`; + } + + /** + * Calculates the accordion's expanded and collapsed heights. + * + * @returns The accordion's expanded and collapsed heights. + */ + private calculateHeights() { + const isOpen = this.el.open, + // Off-screen real quick for a flash of visibility. + { position, left } = this.el.style; + this.el.style.position = "fixed"; + this.el.style.left = "-9999px"; + // Height when open. + this.el.open = true; + this.expandedHeight = this.el.offsetHeight + "px"; + // Height when closed. + this.el.open = false; + this.collapsedHeight = this.el.offsetHeight + "px"; + // Back to normal. + this.el.open = isOpen; + this.el.style.height = isOpen + ? this.expandedHeight + : this.collapsedHeight; + this.el.style.position = position; + this.el.style.left = left; + } + + /** + * Triggered on accordion click. + * + * @param event The emitted mouse event. + */ + private toggleVisibility(event: MouseEvent) { + event.preventDefault(); + this.el.style.overflow = "hidden"; + + if (!this.el.open) { + this.expand(); + } else this.collapse(); + } + + /** + * Expand the accordion. + */ + private expand(animate = true) { + this.el.open = true; + this.animate(this.collapsedHeight, this.expandedHeight, { + opening: true, + duration: animate ? 300 : 0, + }); + } + + /** + * Collapse the accordion. + */ + private collapse(animate = true) { + this.animate(this.expandedHeight, this.collapsedHeight, { + opening: false, + duration: animate ? 300 : 0, + }); + } + + /** + * Animate the accordion between open/close state. + * + * @param startHeight Height to begin at. + * @param endHeight Height to end at. + * @param isOpening Whether the accordion is opening or closing. + * @param duration The duration of the animation. + */ + private animate( + startHeight: string, + endHeight: string, + { opening, duration = 300 }: { opening: boolean; duration?: number } + ) { + if (this.animation) return; + const animationOptions = { duration, easing: "ease" }; + this.animation = this.el.animate( + { + height: [startHeight, endHeight], + }, + animationOptions + ); + this.icon + .animate( + { + transform: [ + this.icon.style.transform || + this.getIconRotation(!opening), + this.getIconRotation(opening), + ], + }, + animationOptions + ) + .addEventListener("finish", () => { + this.icon.style.transform = this.getIconRotation(opening); + }); + + this.animation.addEventListener("finish", () => + this.animationEnd(opening) + ); + } + + /** + * Reset values upon animation end. + * + * @param isOpen Whether the accordion is now open. + */ + private animationEnd(isOpen: boolean) { + this.el.open = isOpen; + this.animation = undefined; + this.el.style.height = "auto"; + this.el.style.overflow = "visible"; + + this.setLocalStorage(isOpen); + } + + /** + * Retrieve value from storage. + */ + private fromLocalStorage(): boolean { + const fromLocalStorage = storage.getItem(this.key); + return fromLocalStorage ? fromLocalStorage === "true" : this.el.open; + } + + /** + * Persist accordion state to local storage. + * + * @param value Value to set. + * @param force Whether to trigger value change even if the value is identical to the previous state. + */ + private setLocalStorage(value: boolean, force: boolean = false): void { + if (this.fromLocalStorage() === value && !force) return; + storage.setItem(this.key, value.toString()); + this.el.open = value; + this.handleValueChange(force); + } + + /** + * Synchronize DOM based on stored value. + * + * @param force Whether to force an animation. + */ + private handleValueChange(force: boolean = false): void { + if (this.fromLocalStorage() === this.el.open && !force) return; + this.fromLocalStorage() ? this.expand(false) : this.collapse(false); + } +} diff --git a/src/lib/output/themes/default/assets/typedoc/components/Filter.ts b/src/lib/output/themes/default/assets/typedoc/components/Filter.ts index f644b8a97..7eec789e6 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Filter.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Filter.ts @@ -1,166 +1,74 @@ import { Component, IComponentOptions } from "../Component"; -import { pointerDown, pointerUp } from "../utils/pointer"; +import { storage } from "../utils/storage"; -abstract class FilterItem { - protected key: string; +const style = document.head.appendChild(document.createElement("style")); +style.dataset.for = "filters"; - protected value: T; - - protected defaultValue: T; - - constructor(key: string, value: T) { - this.key = key; - this.value = value; - this.defaultValue = value; - - this.initialize(); - - if (window.localStorage[this.key]) { - this.setValue(this.fromLocalStorage(window.localStorage[this.key])); - } - } - - // eslint-disable-next-line @typescript-eslint/no-empty-function - protected initialize() {} - - protected abstract handleValueChange(oldValue: T, newValue: T): void; - - protected abstract fromLocalStorage(value: string): T; - - protected abstract toLocalStorage(value: T): string; - - protected setValue(value: T) { - if (this.value == value) return; - - const oldValue = this.value; - this.value = value; - window.localStorage[this.key] = this.toLocalStorage(value); - - this.handleValueChange(oldValue, value); - } -} +/** + * Handles sidebar filtering functionality. + */ +export class Filter extends Component { + override el!: HTMLInputElement; -class FilterItemCheckbox extends FilterItem { - private checkbox!: HTMLInputElement; + /** + * The class name & ID by which to store the filter value. + */ + private readonly key: string; - protected override initialize() { - const checkbox = document.querySelector( - "#tsd-filter-" + this.key - ); - if (!checkbox) return; + /** + * Current filter value, to keep in sync with checkbox state. + */ + private value: boolean; - this.checkbox = checkbox; - this.checkbox.addEventListener("change", () => { - this.setValue(this.checkbox.checked); + constructor(options: IComponentOptions) { + super(options); + this.key = `filter-${this.el.name}`; + this.value = this.el.checked; + this.el.addEventListener("change", () => { + this.setLocalStorage(this.el.checked); }); - } + this.setLocalStorage(this.fromLocalStorage()); - protected handleValueChange(_oldValue: boolean, _newValue: boolean) { - if (!this.checkbox) return; - this.checkbox.checked = this.value; - document.documentElement.classList.toggle( - "toggle-" + this.key, - this.value != this.defaultValue - ); + style.innerHTML += `html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; }\n`; } - protected fromLocalStorage(value: string): boolean { - return value == "true"; + /** + * Retrieve value from storage. + */ + private fromLocalStorage(): boolean { + const fromStorage = storage.getItem(this.key); + return fromStorage ? fromStorage === "true" : this.el.checked; } - protected toLocalStorage(value: boolean): string { - return value ? "true" : "false"; + /** + * Set value to local storage. + * + * @param value Value to set. + */ + private setLocalStorage(value: boolean): void { + storage.setItem(this.key, value.toString()); + this.value = value; + this.handleValueChange(); } -} - -class FilterItemSelect extends FilterItem { - private select!: HTMLElement; - - protected override initialize() { - document.documentElement.classList.add( - "toggle-" + this.key + this.value - ); - - const select = document.querySelector( - "#tsd-filter-" + this.key - ); - if (!select) return; - - this.select = select; - const onActivate = () => { - this.select.classList.add("active"); - }; - const onDeactivate = () => { - this.select.classList.remove("active"); - }; - - this.select.addEventListener(pointerDown, onActivate); - this.select.addEventListener("mouseover", onActivate); - this.select.addEventListener("mouseleave", onDeactivate); - this.select.querySelectorAll("li").forEach((el) => { - el.addEventListener(pointerUp, (e) => { - select.classList.remove("active"); - this.setValue((e.target as HTMLElement).dataset["value"] || ""); + /** + * Synchronize DOM based on value change. + */ + private handleValueChange(): void { + this.el.checked = this.value; + document.documentElement.classList.toggle(this.key, this.value); + + // Hide index headings where all index items are hidden. + // offsetParent == null checks for display: none + document + .querySelectorAll(".tsd-index-section") + .forEach((el) => { + el.style.display = "block"; + const allChildrenHidden = Array.from( + el.querySelectorAll(".tsd-index-link") + ).every((child) => child.offsetParent == null); + + el.style.display = allChildrenHidden ? "none" : "block"; }); - }); - - document.addEventListener(pointerDown, (e) => { - if (this.select.contains(e.target as HTMLElement)) return; - - this.select.classList.remove("active"); - }); - } - - protected handleValueChange(oldValue: string, newValue: string) { - this.select.querySelectorAll("li.selected").forEach((el) => { - el.classList.remove("selected"); - }); - - const selected = this.select.querySelector( - 'li[data-value="' + newValue + '"]' - ); - const label = - this.select.querySelector(".tsd-select-label"); - - if (selected && label) { - selected.classList.add("selected"); - label.textContent = selected.textContent; - } - - document.documentElement.classList.remove("toggle-" + oldValue); - document.documentElement.classList.add("toggle-" + newValue); - } - - protected fromLocalStorage(value: string): string { - return value; - } - - protected toLocalStorage(value: string): string { - return value; - } -} - -export class Filter extends Component { - public readonly optionVisibility: FilterItemSelect; - - public readonly optionInherited: FilterItemCheckbox; - - public readonly optionExternals: FilterItemCheckbox; - - constructor(options: IComponentOptions) { - super(options); - - this.optionVisibility = new FilterItemSelect("visibility", "private"); - this.optionInherited = new FilterItemCheckbox("inherited", true); - this.optionExternals = new FilterItemCheckbox("externals", true); - } - - static isSupported(): boolean { - try { - return typeof window.localStorage != "undefined"; - } catch (e) { - return false; - } } } diff --git a/src/lib/output/themes/default/assets/typedoc/components/MenuHighlight.ts b/src/lib/output/themes/default/assets/typedoc/components/MenuHighlight.ts index 1e6842812..558a43848 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/MenuHighlight.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/MenuHighlight.ts @@ -59,15 +59,15 @@ export class MenuHighlight extends Component { private createAnchors() { let base = window.location.href; if (base.indexOf("#") != -1) { - base = base.substr(0, base.indexOf("#")); + base = base.substring(0, base.indexOf("#")); } this.el.querySelectorAll("a").forEach((el) => { const href = el.href; if (href.indexOf("#") == -1) return; - if (href.substr(0, base.length) != base) return; + if (href.substring(0, base.length) != base) return; - const hash = href.substr(href.indexOf("#") + 1); + const hash = href.substring(href.indexOf("#") + 1); const anchor = document.querySelector( "a.tsd-anchor[name=" + hash + "]" ); diff --git a/src/lib/output/themes/default/assets/typedoc/components/Search.ts b/src/lib/output/themes/default/assets/typedoc/components/Search.ts index 07de070cb..920ba379b 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Search.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Search.ts @@ -193,7 +193,6 @@ function updateResults( const anchor = document.createElement("a"); anchor.href = state.base + row.url; - anchor.classList.add("tsd-kind-icon"); anchor.innerHTML = name; item.append(anchor); @@ -261,7 +260,7 @@ function boldMatches(text: string, search: string) { const lowerText = text.toLocaleLowerCase(); const lowerSearch = search.toLocaleLowerCase(); - const parts = []; + const parts: string[] = []; let lastIndex = 0; let index = lowerText.indexOf(lowerSearch); while (index != -1) { diff --git a/src/lib/output/themes/default/assets/typedoc/components/Signature.ts b/src/lib/output/themes/default/assets/typedoc/components/Signature.ts index 1682c82f4..b3d51b535 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Signature.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Signature.ts @@ -31,10 +31,9 @@ class SignatureGroup { * * @param className The class name to add. */ - addClass(className: string): SignatureGroup { + addClass(className: string) { this.signature.classList.add(className); this.description.classList.add(className); - return this; } /** @@ -42,15 +41,14 @@ class SignatureGroup { * * @param className The class name to remove. */ - removeClass(className: string): SignatureGroup { + removeClass(className: string) { this.signature.classList.remove(className); this.description.classList.remove(className); - return this; } } /** - * Controls the tab like behaviour of methods and functions with multiple signatures. + * Controls the tab like behavior of methods and functions with multiple signatures. */ export class Signature extends Component { /** @@ -89,7 +87,7 @@ export class Signature extends Component { ); }); this.container.classList.add("active"); - this.setIndex(0); + this.setIndex(this.inferIndexFromHash()); } } @@ -107,9 +105,17 @@ export class Signature extends Component { if (this.index > -1) { const from = this.groups[this.index]; - from.removeClass("current").addClass("fade-out"); + from.removeClass("current"); + from.addClass("fade-out"); to.addClass("current"); to.addClass("fade-in"); + + if (to.signature.id) { + const target = new URL(location.href); + target.hash = to.signature.id; + history.replaceState({}, "", target); + } + Viewport.instance.triggerResize(); setTimeout(() => { @@ -154,4 +160,10 @@ export class Signature extends Component { } }); } + + private inferIndexFromHash() { + const hash = location.hash.substring(1); + const index = this.groups.findIndex((s) => s.signature.id === hash); + return Math.max(0, index); + } } diff --git a/src/lib/output/themes/default/assets/typedoc/components/Toggle.ts b/src/lib/output/themes/default/assets/typedoc/components/Toggle.ts index 9c0ec4a11..07f222f10 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Toggle.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Toggle.ts @@ -67,9 +67,9 @@ export class Toggle extends Component { if (link) { let href = window.location.href; if (href.indexOf("#") != -1) { - href = href.substr(0, href.indexOf("#")); + href = href.substring(0, href.indexOf("#")); } - if (link.href.substr(0, href.length) == href) { + if (link.href.substring(0, href.length) == href) { setTimeout(() => this.setActive(false), 250); } } diff --git a/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts b/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts index 79b253f28..0360340c3 100644 --- a/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts +++ b/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts @@ -38,10 +38,11 @@ export class Viewport extends EventTarget { showToolbar: boolean = true; /** - * The sticky side nav that contains members of the current page. - * Might not present on the home page if the project uses `entryPointStrategy` set to `Expand`. + * The side nav that contains members of the current page. */ - secondaryNav?: HTMLElement; + navigation: HTMLElement; + + searchInput: HTMLInputElement | null; /** * Create new Viewport instance. @@ -52,9 +53,7 @@ export class Viewport extends EventTarget { this.toolbar = ( document.querySelector(".tsd-page-toolbar") ); - this.secondaryNav = ( - document.querySelector(".tsd-navigation.secondary") - ); + this.navigation = document.querySelector(".col-menu"); window.addEventListener( "scroll", @@ -65,6 +64,15 @@ export class Viewport extends EventTarget { throttle(() => this.onResize(), 10) ); + this.searchInput = + document.querySelector("#tsd-search input"); + + if (this.searchInput) { + this.searchInput.addEventListener("focus", () => { + this.hideShowToolbar(); + }); + } + this.onResize(); this.onScroll(); } @@ -121,10 +129,13 @@ export class Viewport extends EventTarget { */ hideShowToolbar() { const isShown = this.showToolbar; - this.showToolbar = this.lastY >= this.scrollTop || this.scrollTop <= 0; + this.showToolbar = + this.lastY >= this.scrollTop || + this.scrollTop <= 0 || + (!!this.searchInput && this.searchInput === document.activeElement); if (isShown !== this.showToolbar) { this.toolbar.classList.toggle("tsd-page-toolbar--hide"); - this.secondaryNav?.classList.toggle("tsd-navigation--toolbar-hide"); + this.navigation?.classList.toggle("col-menu--hide"); } this.lastY = this.scrollTop; } diff --git a/src/lib/output/themes/default/assets/typedoc/utils/pointer.ts b/src/lib/output/themes/default/assets/typedoc/utils/pointer.ts index c59e06ec4..744d4c8b5 100644 --- a/src/lib/output/themes/default/assets/typedoc/utils/pointer.ts +++ b/src/lib/output/themes/default/assets/typedoc/utils/pointer.ts @@ -27,7 +27,7 @@ export let pointerUp: string = "mouseup"; export const pointerDownPosition: Point = { x: 0, y: 0 }; /** - * Should the next click on the document be supressed? + * Should the next click on the document be suppressed? */ export let preventNextClick: boolean = false; diff --git a/src/lib/output/themes/default/assets/typedoc/utils/storage.ts b/src/lib/output/themes/default/assets/typedoc/utils/storage.ts new file mode 100644 index 000000000..b2a34a1bd --- /dev/null +++ b/src/lib/output/themes/default/assets/typedoc/utils/storage.ts @@ -0,0 +1,23 @@ +// This exists to abstract away the horrible fact that accessing localStorage can throw +// an exception depending on a user's browser settings. Can't even check typeof localStorage +// so we're stuck with a try..catch. + +export interface MinimalStorage { + getItem(key: string): string | null; + setItem(key: string, value: string): void; +} + +let _storage: MinimalStorage; + +try { + _storage = localStorage; +} catch { + _storage = { + getItem() { + return null; + }, + setItem() {}, + }; +} + +export const storage = _storage; diff --git a/src/lib/output/themes/default/layouts/default.tsx b/src/lib/output/themes/default/layouts/default.tsx index d6766534a..280012b9e 100644 --- a/src/lib/output/themes/default/layouts/default.tsx +++ b/src/lib/output/themes/default/layouts/default.tsx @@ -28,26 +28,25 @@ export const defaultLayout = (context: DefaultThemeRenderContext, props: PageEve {context.hook("body.begin")} - {context.header(props)} + {context.toolbar(props)}
-
-
- {context.hook("content.begin")} - {props.template(props)} - {context.hook("content.end")} -
- +
+ {context.hook("content.begin")} + {context.header(props)} + {props.template(props)} + {context.hook("content.end")} +
+
- {context.footer(props)} + {context.footer()}
diff --git a/src/lib/output/themes/default/partials/analytics.tsx b/src/lib/output/themes/default/partials/analytics.tsx index bdb8b928a..afcf8fbbd 100644 --- a/src/lib/output/themes/default/partials/analytics.tsx +++ b/src/lib/output/themes/default/partials/analytics.tsx @@ -3,21 +3,21 @@ import { JSX } from "../../../../utils"; export function analytics(context: DefaultThemeRenderContext) { const gaID = context.options.getValue("gaID"); - const gaSite = context.options.getValue("gaSite"); if (!gaID) return; const script = ` -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ - (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), - m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); -ga('create', '${gaID}', '${gaSite}'); -ga('send', 'pageview'); +window.dataLayer = window.dataLayer || []; +function gtag(){dataLayer.push(arguments);} +gtag('js', new Date()); +gtag('config', '${gaID}'); `.trim(); return ( - + <> + + + ); } diff --git a/src/lib/output/themes/default/partials/anchor-icon.tsx b/src/lib/output/themes/default/partials/anchor-icon.tsx index e585b39a3..7a5bb5f32 100644 --- a/src/lib/output/themes/default/partials/anchor-icon.tsx +++ b/src/lib/output/themes/default/partials/anchor-icon.tsx @@ -1,20 +1,8 @@ import { JSX } from "../../../../utils"; +import { icons } from "./icon"; export const anchorIcon = (anchor: string | undefined) => ( - - - - - + {icons.anchor()} ); diff --git a/src/lib/output/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 7cbdf80f6..e5ba21dc3 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -1,37 +1,22 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { JSX, Raw } from "../../../../utils"; import type { Reflection } from "../../../../models"; +import { camelToTitleCase, displayPartsToMarkdown } from "../../lib"; -export function comment({ markdown }: DefaultThemeRenderContext, props: Reflection) { +export function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: Reflection) { if (!props.comment?.hasVisibleComponent()) return; + // Note: Comment modifiers are handled in `renderFlags` + return (
- {!!props.comment.shortText && ( -
- -
- )} - {!!props.comment.text && ( -
- -
- )} - {props.comment.tags?.length > 0 && ( -
- {props.comment.tags.map((item) => ( - <> -
- {item.tagName} - {item.paramName ? ` ${item.paramName}` : ""} -
-
- -
- - ))} -
- )} + + {props.comment.blockTags.map((item) => ( + <> +

{camelToTitleCase(item.tag.substring(1))}

+ + + ))}
); } diff --git a/src/lib/output/themes/default/partials/footer.tsx b/src/lib/output/themes/default/partials/footer.tsx index e8ab7da4c..aa16ae5dc 100644 --- a/src/lib/output/themes/default/partials/footer.tsx +++ b/src/lib/output/themes/default/partials/footer.tsx @@ -1,59 +1,17 @@ -import type { Reflection } from "../../../../models"; import { JSX } from "../../../../utils"; -import type { PageEvent } from "../../../events"; -import { classNames } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -export function footer(context: DefaultThemeRenderContext, props: PageEvent) { - const hideLegend = context.options.getValue("hideLegend"); +export function footer(context: DefaultThemeRenderContext) { const hideGenerator = context.options.getValue("hideGenerator"); - return ( - <> -
-
- {!hideLegend && props.legend?.length && ( - <> -

Legend

-
- {props.legend.map((item) => ( -
    - {item.map((item) => ( -
  • - {item.name} -
  • - ))} -
- ))} -
- - )} - -

Settings

-

- Theme{" "} - -

-
-
- - {!hideGenerator && ( -
-

- {"Generated using "} - - TypeDoc - -

-
- )} - - ); + if (!hideGenerator) + return ( +
+

+ {"Generated using "} + + TypeDoc + +

+
+ ); } diff --git a/src/lib/output/themes/default/partials/header.tsx b/src/lib/output/themes/default/partials/header.tsx index 346bbefd5..29e9d13f9 100644 --- a/src/lib/output/themes/default/partials/header.tsx +++ b/src/lib/output/themes/default/partials/header.tsx @@ -1,86 +1,26 @@ -import type { Reflection } from "../../../../models"; -import { JSX } from "../../../../utils"; -import type { PageEvent } from "../../../events"; import { hasTypeParameters, join, renderFlags } from "../../lib"; +import { JSX } from "../../../../utils"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; +import type { PageEvent } from "../../../events"; +import type { Reflection } from "../../../../models"; -export const header = (context: DefaultThemeRenderContext, props: PageEvent) => ( -
-
-
-
- - -
-
- - Options - -
-
- All -
    -
  • Public
  • -
  • Public/Protected
  • -
  • - All -
  • -
-
{" "} - - - {!context.options.getValue("excludeExternals") && ( - <> - - - - )} -
-
- - - Menu - -
-
-
-
+export const header = (context: DefaultThemeRenderContext, props: PageEvent) => { + const HeadingLevel = props.model.isProject() ? "h2" : "h1"; + return (
-
- {!!props.model.parent &&
    {context.breadcrumb(props.model)}
} -

- {props.model.kindString !== "Project" && `${props.model.kindString ?? ""} `} - {props.model.name} - {hasTypeParameters(props.model) && ( - <> - {"<"} - {join(", ", props.model.typeParameters, (item) => item.name)} - {">"} - - )}{" "} - {renderFlags(props.model.flags)} -

-
+ {!!props.model.parent &&
    {context.breadcrumb(props.model)}
} + + {props.model.kindString !== "Project" && `${props.model.kindString ?? ""} `} + {props.model.name} + {hasTypeParameters(props.model) && ( + <> + {"<"} + {join(", ", props.model.typeParameters, (item) => item.name)} + {">"} + + )} + {renderFlags(props.model.flags, props.model.comment)} +
-
-); + ); +}; diff --git a/src/lib/output/themes/default/partials/icon.tsx b/src/lib/output/themes/default/partials/icon.tsx new file mode 100644 index 000000000..914a6105c --- /dev/null +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -0,0 +1,253 @@ +import { ReflectionKind } from "../../../../models"; +import { JSX } from "../../../../utils"; + +type UtilityIcons = Record< + "chevronDown" | "checkbox" | "menu" | "search" | "chevronSmall" | "anchor", + () => JSX.Element +>; + +const seenIcons = new Set(); + +export function clearSeenIconCache() { + seenIcons.clear(); +} + +function cachedPart(key: string, svgPart: JSX.Element) { + if (seenIcons.has(key)) { + return ; + } + + seenIcons.add(key); + return { + ...svgPart, + props: { + ...svgPart.props, + id: `icon-${key}`, + }, + }; +} + +const kindIcon = (kind: ReflectionKind, letterPath: JSX.Element, color: string, circular = false) => ( + + {cachedPart( + `${kind}-path`, + + )} + {cachedPart(`${kind}-text`, letterPath)} + +); + +export const icons: Record JSX.Element> & UtilityIcons = { + [ReflectionKind.Accessor]: () => + kindIcon( + ReflectionKind.Accessor, + , + "#FF4D4D", + true + ), + [ReflectionKind.CallSignature]() { + return this[ReflectionKind.Function](); + }, + [ReflectionKind.Class]: () => + kindIcon( + ReflectionKind.Class, + , + "var(--color-ts-class)" + ), + [ReflectionKind.Constructor]: () => + kindIcon( + ReflectionKind.Constructor, + , + "#4D7FFF", + true + ), + [ReflectionKind.ConstructorSignature]() { + return this[ReflectionKind.Constructor](); + }, + [ReflectionKind.Enum]: () => + kindIcon( + ReflectionKind.Enum, + , + "var(--color-ts-enum)" + ), + [ReflectionKind.EnumMember]() { + return this[ReflectionKind.Property](); + }, + [ReflectionKind.Function]: () => + kindIcon( + ReflectionKind.Function, + , + "var(--color-ts-function)" + ), + [ReflectionKind.GetSignature]() { + return this[ReflectionKind.Accessor](); + }, + [ReflectionKind.IndexSignature]() { + return this[ReflectionKind.Property](); + }, + [ReflectionKind.Interface]: () => + kindIcon( + ReflectionKind.Interface, + , + "var(--color-ts-interface)" + ), + [ReflectionKind.Method]: () => + kindIcon( + ReflectionKind.Method, + , + "#FF4DB8", + true + ), + [ReflectionKind.Module]() { + return this[ReflectionKind.Namespace](); + }, + + [ReflectionKind.Namespace]: () => + kindIcon( + ReflectionKind.Namespace, + , + "var(--color-ts-namespace)" + ), + [ReflectionKind.ObjectLiteral]() { + return this[ReflectionKind.Interface](); + }, + [ReflectionKind.Parameter]() { + return this[ReflectionKind.Property](); + }, + [ReflectionKind.Project]() { + return this[ReflectionKind.Namespace](); + }, + [ReflectionKind.Property]: () => + kindIcon( + ReflectionKind.Property, + , + "#FF984D", + true + ), + [ReflectionKind.Reference]: () => + kindIcon( + ReflectionKind.Reference, + , + "#FF4D82", // extract into a CSS variable potentially? + true + ), + [ReflectionKind.SetSignature]() { + return this[ReflectionKind.Accessor](); + }, + [ReflectionKind.TypeAlias]: () => + kindIcon( + ReflectionKind.TypeAlias, + , + "var(--color-ts)" + ), + [ReflectionKind.TypeLiteral]() { + return this[ReflectionKind.TypeAlias](); + }, + [ReflectionKind.TypeParameter]() { + return this[ReflectionKind.TypeAlias](); + }, + [ReflectionKind.Variable]: () => + kindIcon( + ReflectionKind.Variable, + , + "var(--color-ts-variable)" + ), + chevronDown: () => ( + + + + ), + chevronSmall: () => ( + + + + ), + checkbox: () => ( + + ), + menu: () => ( + + {["3", "7", "11"].map((y) => ( + + ))} + + ), + search: () => ( + + + + ), + anchor: () => ( + + {cachedPart("anchor-a", )} + {cachedPart("anchor-b", )} + {cachedPart("anchor-c", )} + + ), +}; diff --git a/src/lib/output/themes/default/partials/index.tsx b/src/lib/output/themes/default/partials/index.tsx index 19ca5cf70..a6d7ad03b 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -1,66 +1,75 @@ -import { wbr } from "../../lib"; +import { classNames, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { JSX } from "../../../../utils"; import type { ContainerReflection, ReflectionCategory } from "../../../../models"; +import { icons } from "./icon"; function renderCategory({ urlTo }: DefaultThemeRenderContext, item: ReflectionCategory, prependName = "") { return (
-

{prependName ? `${prependName} ${item.title}` : item.title}

- +
); } export function index(context: DefaultThemeRenderContext, props: ContainerReflection) { - if (props.categories && props.categories.length) { - return ( -
-

Index

-
-
{props.categories.map((item) => renderCategory(context, item))}
-
-
+ let content: JSX.Element | JSX.Element[] = []; + + if (props.categories?.length) { + content = props.categories.map((item) => renderCategory(context, item)); + } else if (props.groups?.length) { + content = props.groups.flatMap((item) => + item.categories + ? item.categories.map((item2) => renderCategory(context, item2, item.title)) + : renderCategory(context, item) ); } - if (props.groups && props.groups.length) { - return ( -
-

Index

-
-
- {props.groups.map((item) => ( -
- {item.categories ? ( - item.categories.map((item2) => renderCategory(context, item2, item.title)) - ) : ( - <> -

{item.title}

- - - )} -
- ))} -
-
-
+ // Accordion is only needed if any children don't have their own document. + if ( + [...(props.groups ?? []), ...(props.categories ?? [])].some( + (category) => !category.allChildrenHaveOwnDocument() + ) + ) { + content = ( +
+ + + +
{content}
+
+ ); + } else { + content = ( + <> +

Index

+ {content} + ); } + + return ( +
+
{content}
+
+ ); } diff --git a/src/lib/output/themes/default/partials/member.declaration.tsx b/src/lib/output/themes/default/partials/member.declaration.tsx index 564c9601d..da9dd70c2 100644 --- a/src/lib/output/themes/default/partials/member.declaration.tsx +++ b/src/lib/output/themes/default/partials/member.declaration.tsx @@ -1,11 +1,11 @@ -import { DeclarationReflection, ReflectionKind, ReflectionType } from "../../../../models"; +import { DeclarationReflection, ReflectionType } from "../../../../models"; import { JSX } from "../../../../utils"; -import { renderTypeParametersSignature, wbr } from "../../lib"; +import { hasTypeParameters, renderTypeParametersSignature, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; export const memberDeclaration = (context: DefaultThemeRenderContext, props: DeclarationReflection) => ( <> -
+
{wbr(props.name)} {renderTypeParametersSignature(props.typeParameters)} {props.type && ( @@ -14,7 +14,7 @@ export const memberDeclaration = (context: DefaultThemeRenderContext, props: Dec {context.type(props.type)} )} - {!!props.defaultValue && props.kind !== ReflectionKind.EnumMember && ( + {!!props.defaultValue && ( <> {" = "} @@ -24,11 +24,9 @@ export const memberDeclaration = (context: DefaultThemeRenderContext, props: Dec )}
- {context.memberSources(props)} - {context.comment(props)} - {!!props.typeParameters && ( + {hasTypeParameters(props) && ( <>

Type Parameters

{context.typeParameters(props.typeParameters)} @@ -40,5 +38,7 @@ export const memberDeclaration = (context: DefaultThemeRenderContext, props: Dec {context.parameter(props.type.declaration)}
)} + + {context.memberSources(props)} ); diff --git a/src/lib/output/themes/default/partials/member.getterSetter.tsx b/src/lib/output/themes/default/partials/member.getterSetter.tsx index de197c8c4..41f829820 100644 --- a/src/lib/output/themes/default/partials/member.getterSetter.tsx +++ b/src/lib/output/themes/default/partials/member.getterSetter.tsx @@ -6,15 +6,19 @@ export const memberGetterSetter = (context: DefaultThemeRenderContext, props: De <>
    {!!props.getSignature && ( -
  • +
  • get {props.name} - {context.memberSignatureTitle(props.getSignature, { hideName: true })} + {context.memberSignatureTitle(props.getSignature, { + hideName: true, + })}
  • )} {!!props.setSignature && ( -
  • +
  • set {props.name} - {context.memberSignatureTitle(props.setSignature, { hideName: true })} + {context.memberSignatureTitle(props.setSignature, { + hideName: true, + })}
  • )}
diff --git a/src/lib/output/themes/default/partials/member.signature.body.tsx b/src/lib/output/themes/default/partials/member.signature.body.tsx index 16ccdff86..419f28f3a 100644 --- a/src/lib/output/themes/default/partials/member.signature.body.tsx +++ b/src/lib/output/themes/default/partials/member.signature.body.tsx @@ -1,30 +1,31 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -import { JSX, Raw } from "../../../../utils"; +import { JSX } from "../../../../utils"; import { ReflectionType, SignatureReflection } from "../../../../models"; -import { renderFlags } from "../../lib"; +import { hasTypeParameters, renderFlags } from "../../lib"; + export const memberSignatureBody = ( context: DefaultThemeRenderContext, props: SignatureReflection, { hideSources = false }: { hideSources?: boolean } = {} ) => ( <> - {!hideSources && context.memberSources(props)} + {renderFlags(props.flags, props.comment)} {context.comment(props)} - {!!props.typeParameters && ( - <> + {hasTypeParameters(props) && ( +

Type Parameters

{context.typeParameters(props.typeParameters)} - +
)} {props.parameters && props.parameters.length > 0 && ( - <> +

Parameters

-
    +
      {props.parameters.map((item) => (
    • - {renderFlags(item.flags)} + {renderFlags(item.flags, item.comment)} {!!item.flags.isRest && ...} {item.name} {": "} @@ -41,7 +42,7 @@ export const memberSignatureBody = (
    • ))}
    - +
)} {props.type && ( <> @@ -49,13 +50,9 @@ export const memberSignatureBody = ( {"Returns "} {context.type(props.type)} - {!!props.comment?.returns && ( -
- -
- )} {props.type instanceof ReflectionType && context.parameter(props.type.declaration)} )} + {!hideSources && context.memberSources(props)} ); diff --git a/src/lib/output/themes/default/partials/member.signatures.tsx b/src/lib/output/themes/default/partials/member.signatures.tsx index aa1e4df76..1159b53c1 100644 --- a/src/lib/output/themes/default/partials/member.signatures.tsx +++ b/src/lib/output/themes/default/partials/member.signatures.tsx @@ -6,7 +6,9 @@ export const memberSignatures = (context: DefaultThemeRenderContext, props: Decl <>
    {props.signatures?.map((item) => ( -
  • {context.memberSignatureTitle(item)}
  • +
  • + {context.memberSignatureTitle(item)} +
  • ))}
diff --git a/src/lib/output/themes/default/partials/member.tsx b/src/lib/output/themes/default/partials/member.tsx index 5caeb91d5..e57d62cd3 100644 --- a/src/lib/output/themes/default/partials/member.tsx +++ b/src/lib/output/themes/default/partials/member.tsx @@ -1,4 +1,4 @@ -import { renderFlags, wbr } from "../../lib"; +import { classNames, renderFlags, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { JSX } from "../../../../utils"; import { DeclarationReflection, ReferenceReflection } from "../../../../models"; @@ -9,8 +9,8 @@ export const member = (context: DefaultThemeRenderContext, props: DeclarationRef {!!props.name && ( )} diff --git a/src/lib/output/themes/default/partials/members.group.tsx b/src/lib/output/themes/default/partials/members.group.tsx index ee92f2cf6..5b202be87 100644 --- a/src/lib/output/themes/default/partials/members.group.tsx +++ b/src/lib/output/themes/default/partials/members.group.tsx @@ -7,7 +7,7 @@ export function membersGroup(context: DefaultThemeRenderContext, group: Reflecti return ( <> {group.categories.map((item) => ( -
+

{!!item.title && <>{item.title} } {group.title} @@ -20,7 +20,7 @@ export function membersGroup(context: DefaultThemeRenderContext, group: Reflecti } return ( -
+

{group.title}

{group.children.map((item) => !item.hasOwnDocument && context.member(item))}
diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 9a32ac6b2..3023a2b78 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -1,70 +1,127 @@ import { ContainerReflection, DeclarationReflection, Reflection, ReflectionKind } from "../../../../models"; import { JSX, partition } from "../../../../utils"; import type { PageEvent } from "../../../events"; -import { classNames, wbr } from "../../lib"; +import { classNames, camelToTitleCase, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; +import { icons } from "./icon"; export function navigation(context: DefaultThemeRenderContext, props: PageEvent) { return ( <> + {settings(context)} {primaryNavigation(context, props)} {secondaryNavigation(context, props)} ); } +function buildFilterItem(name: string, displayName: string, defaultValue: boolean) { + return ( +
  • + +
  • + ); +} + +function settings(context: DefaultThemeRenderContext) { + const defaultFilters = context.options.getValue("visibilityFilters") as Record; + + const visibilityOptions: JSX.Element[] = []; + + for (const key of Object.keys(defaultFilters)) { + if (key.startsWith("@")) { + const filterName = key + .substring(1) + .replace(/([a-z])([A-Z])/g, "$1-$2") + .toLowerCase(); + + visibilityOptions.push( + buildFilterItem(filterName, camelToTitleCase(key.substring(1)), defaultFilters[key]) + ); + } else if ( + (key === "protected" && !context.options.getValue("excludeProtected")) || + (key === "private" && !context.options.getValue("excludePrivate")) || + (key === "external" && !context.options.getValue("excludeExternals")) || + key === "inherited" + ) { + visibilityOptions.push(buildFilterItem(key, camelToTitleCase(key), defaultFilters[key])); + } + } + + // Settings panel above navigation + + return ( +
    +
    + +

    {icons.chevronDown()} Settings

    +
    +
    + {visibilityOptions.length && ( +
    +

    Member Visibility

    +
    +
      {...visibilityOptions}
    +
    +
    + )} +
    +

    Theme

    + +
    +
    +
    +
    + ); +} + function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent) { - // Create the navigation for the current page: - // If there are modules marked as "external" then put them in their own group. + // Create the navigation for the current page const modules = props.model.project.getChildrenByKind(ReflectionKind.SomeModule); - const projectLinkName = modules.some((m) => m.kindOf(ReflectionKind.Module)) ? "Modules" : "Exports"; - const [ext, int] = partition(modules, (m) => m.flags.isExternal); - if (ext.length === 0) { - return ( - - ); - } + const selected = props.model.isProject(); + const current = selected || int.some((mod) => inPath(mod, props.model)); return ( ); function link(mod: DeclarationReflection) { const current = inPath(mod, props.model); + const selected = mod.name === props.model.name; let childNav: JSX.Element | undefined; - if (current) { - const childModules = mod.children?.filter((m) => m.kindOf(ReflectionKind.SomeModule)); - if (childModules?.length) { - childNav =
      {childModules.map(link)}
    ; - } + const childModules = mod.children?.filter((m) => m.kindOf(ReflectionKind.SomeModule)); + if (childModules?.length) { + childNav =
      {childModules.map(link)}
    ; } return ( -
  • +
  • {wbr(mod.name)} {childNav}
  • @@ -73,48 +130,61 @@ function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent< } function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEvent) { - const children = props.model instanceof ContainerReflection ? props.model.children || [] : []; - // Multiple entry points, and on main project page. if (props.model.isProject() && props.model.getChildrenByKind(ReflectionKind.Module).length) { return; } - // TODO: TypeDoc 0.21 did special things here. If there were more than 40 - // children of this page's parent, it only displayed this page's children. - // Otherwise, it displayed *everything*. For now, only display page children. - // It seems weird to do this according to a random hardcoded number. At the very - // least this should be added as a configurable flag, but maybe even the whole - // behavior should be configurable globally... - - const pageNavigation = ( -
      - {children - .filter((child) => !child.kindOf(ReflectionKind.SomeModule)) - .map((child) => { - return ( -
    • - - {wbr(child.name)} - -
    • - ); - })} -
    - ); + const effectivePageParent = + (props.model instanceof ContainerReflection && props.model.children?.length) || props.model.isProject() + ? props.model + : props.model.parent!; + + const children = (effectivePageParent as ContainerReflection).children || []; + + const pageNavigation = children + .filter((child) => !child.kindOf(ReflectionKind.SomeModule)) + .map((child) => { + return ( +
  • + + {icons[child.kind]()} + {wbr(child.name)} + +
  • + ); + }); - if (props.model.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project)) { - return ; + if (effectivePageParent.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project)) { + return ( + + ); } return ( @@ -129,6 +199,5 @@ function inPath(thisPage: Reflection, toCheck: Reflection | undefined): boolean toCheck = toCheck.parent; } - return false; } diff --git a/src/lib/output/themes/default/partials/parameter.tsx b/src/lib/output/themes/default/partials/parameter.tsx index 35ae30fbb..ebc17749a 100644 --- a/src/lib/output/themes/default/partials/parameter.tsx +++ b/src/lib/output/themes/default/partials/parameter.tsx @@ -10,15 +10,21 @@ export const parameter = (context: DefaultThemeRenderContext, props: Declaration
    • {props.signatures.map((item) => ( -
    • - {context.memberSignatureTitle(item, { hideName: true })} +
    • + {context.memberSignatureTitle(item, { + hideName: true, + })}
    • ))}
      {props.signatures.map((item) => ( -
    • {context.memberSignatureBody(item, { hideSources: true })}
    • +
    • + {context.memberSignatureBody(item, { + hideSources: true, + })} +
    • ))}
  • @@ -63,7 +69,7 @@ export const parameter = (context: DefaultThemeRenderContext, props: Declaration {/* standard type */}
  • - {renderFlags(item.flags)} + {renderFlags(item.flags, item.comment)} {!!item.flags.isRest && ...} {wbr(item.name)} @@ -85,7 +91,7 @@ export const parameter = (context: DefaultThemeRenderContext, props: Declaration {/* getter */}
  • - {renderFlags(item.getSignature.flags)} + {renderFlags(item.getSignature.flags, item.getSignature.comment)} get {wbr(item.name)} (): @@ -101,7 +107,7 @@ export const parameter = (context: DefaultThemeRenderContext, props: Declaration {/* setter */}
  • - {renderFlags(item.setSignature.flags)} + {renderFlags(item.setSignature.flags, item.setSignature.comment)} set {wbr(item.name)} ( diff --git a/src/lib/output/themes/default/partials/toolbar.tsx b/src/lib/output/themes/default/partials/toolbar.tsx new file mode 100644 index 000000000..2cb57d2da --- /dev/null +++ b/src/lib/output/themes/default/partials/toolbar.tsx @@ -0,0 +1,35 @@ +import type { Reflection } from "../../../../models"; +import { JSX } from "../../../../utils"; +import type { PageEvent } from "../../../events"; +import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; +import { icons } from "./icon"; + +export const toolbar = (context: DefaultThemeRenderContext, props: PageEvent) => ( +
    +
    + + + +
    +
    +); diff --git a/src/lib/output/themes/default/partials/type.tsx b/src/lib/output/themes/default/partials/type.tsx index 46c8e445f..1a5745e38 100644 --- a/src/lib/output/themes/default/partials/type.tsx +++ b/src/lib/output/themes/default/partials/type.tsx @@ -53,7 +53,7 @@ function getUniquePath(reflection: Reflection): Reflection[] { function getNamespacedPath(reflection: Reflection): Reflection[] { const path = [reflection]; let parent = reflection.parent; - while (parent && parent.kindOf(ReflectionKind.Namespace)) { + while (parent?.kindOf(ReflectionKind.Namespace)) { path.unshift(parent); parent = parent.parent; } @@ -279,65 +279,72 @@ const typeRenderers: { return name; }, reflection(context, type) { - if (type.declaration.children) { - // Object literal - return ( - <> - {"{ "} - {join(; , type.declaration.children, (item) => { - if (item.getSignature && item.setSignature) { - return ( - <> - {item.name} - : - {renderType(context, item.getSignature.type, TypeContext.none)} - - ); - } - - if (item.getSignature) { - return ( - <> - get - {item.name} - (): - {renderType(context, item.getSignature.type, TypeContext.none)} - - ); - } - - if (item.setSignature) { - return ( - <> - set - {item.name} - ( - {item.setSignature.parameters?.map((item) => ( - <> - {item.name} - : - {renderType(context, item.type, TypeContext.none)} - - ))} - ) - - ); - } - - return ( + const members: JSX.Element[] = []; + + for (const item of type.declaration.children || []) { + if (item.getSignature && item.setSignature) { + members.push( + <> + {item.name} + : + {renderType(context, item.getSignature.type, TypeContext.none)} + + ); + continue; + } + + if (item.getSignature) { + members.push( + <> + get + {item.name} + (): + {renderType(context, item.getSignature.type, TypeContext.none)} + + ); + continue; + } + + if (item.setSignature) { + members.push( + <> + set + {item.name} + ( + {item.setSignature.parameters?.map((item) => ( <> {item.name} - {item.flags.isOptional ? "?: " : ": "} + : {renderType(context, item.type, TypeContext.none)} - ); - })} - {" }"} + ))} + ) + + ); + continue; + } + + members.push( + <> + {item.name} + {item.flags.isOptional ? "?: " : ": "} + {renderType(context, item.type, TypeContext.none)} ); } - if (type.declaration.signatures?.length === 1) { + if (type.declaration.indexSignature) { + const index = type.declaration.indexSignature; + members.push( + <> + [{index.parameters![0].name}: {renderType(context, index.parameters![0].type, TypeContext.none)}] + : + {renderType(context, index.type, TypeContext.none)} + + ); + } + + if (!members.length && type.declaration.signatures?.length === 1) { return ( <> ( @@ -350,14 +357,19 @@ const typeRenderers: { ); } - if (type.declaration.signatures) { + for (const item of type.declaration.signatures || []) { + members.push(context.memberSignatureTitle(item, { hideName: true })); + } + + if (members.length) { + const membersWithSeparators = members.flatMap((m) => [m, ; ]); + membersWithSeparators.pop(); + return ( <> {"{"} - {join(; , type.declaration.signatures, (item) => - context.memberSignatureTitle(item, { hideName: true }) - )} - {" }"} + {membersWithSeparators} + {"}"} ); } diff --git a/src/lib/output/themes/default/templates/index.tsx b/src/lib/output/themes/default/templates/index.tsx index 096aa4d6a..d57b5aaae 100644 --- a/src/lib/output/themes/default/templates/index.tsx +++ b/src/lib/output/themes/default/templates/index.tsx @@ -2,9 +2,10 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import type { ProjectReflection } from "../../../../models"; import type { PageEvent } from "../../../events"; import { JSX, Raw } from "../../../../utils"; +import { displayPartsToMarkdown } from "../../lib"; -export const indexTemplate = ({ markdown }: DefaultThemeRenderContext, props: PageEvent) => ( +export const indexTemplate = ({ markdown, urlTo }: DefaultThemeRenderContext, props: PageEvent) => (
    - +
    ); diff --git a/src/lib/output/themes/default/templates/reflection.tsx b/src/lib/output/themes/default/templates/reflection.tsx index d71d72ad1..d1342b73a 100644 --- a/src/lib/output/themes/default/templates/reflection.tsx +++ b/src/lib/output/themes/default/templates/reflection.tsx @@ -1,74 +1,80 @@ import { hasTypeParameters } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import type { PageEvent } from "../../../events"; -import { ContainerReflection, DeclarationReflection, ReflectionType } from "../../../../models"; +import { ContainerReflection, DeclarationReflection, ReflectionKind, ReflectionType } from "../../../../models"; import { JSX } from "../../../../utils"; -export const reflectionTemplate = (context: DefaultThemeRenderContext, props: PageEvent) => ( - <> - {props.model.hasComment() &&
    {context.comment(props.model)}
    } +export function reflectionTemplate(context: DefaultThemeRenderContext, props: PageEvent) { + if ( + [ReflectionKind.TypeAlias, ReflectionKind.Variable].includes(props.model.kind) && + props.model instanceof DeclarationReflection + ) + return context.memberDeclaration(props.model); + return ( + <> + {props.model.hasComment() && ( +
    {context.comment(props.model)}
    + )} - {hasTypeParameters(props.model) && ( -
    -

    Type Parameters

    - {context.typeParameters(props.model.typeParameters)} -
    - )} - {props.model instanceof DeclarationReflection && ( - <> - {!!props.model.typeHierarchy && ( -
    -

    Hierarchy

    - {context.hierarchy(props.model.typeHierarchy)} -
    - )} - {!!props.model.implementedTypes && ( -
    -

    Implements

    -
      - {props.model.implementedTypes.map((item) => ( -
    • {context.type(item)}
    • - ))} -
    -
    - )} - {!!props.model.implementedBy && ( -
    -

    Implemented by

    -
      - {props.model.implementedBy.map((item) => ( -
    • {context.type(item)}
    • - ))} -
    -
    - )} - {!!props.model.signatures && ( -
    -

    Callable

    - {context.memberSignatures(props.model)} -
    - )} - {!!props.model.indexSignature && ( -
    -

    Indexable

    -
    - [ - {props.model.indexSignature.parameters!.map((item) => ( - <> - {item.name}: {context.type(item.type)} - - ))} - {"]: "} - {context.type(props.model.indexSignature.type)} -
    - {context.comment(props.model.indexSignature)} - {props.model.indexSignature?.type instanceof ReflectionType && - context.parameter(props.model.indexSignature.type.declaration)} -
    - )} - - )} - {context.index(props.model)} - {context.members(props.model)} - -); + {hasTypeParameters(props.model) && ( +
    +

    Type Parameters

    + {context.typeParameters(props.model.typeParameters)} +
    + )} + {props.model instanceof DeclarationReflection && ( + <> + {!!props.model.typeHierarchy && ( +
    +

    Hierarchy

    + {context.hierarchy(props.model.typeHierarchy)} +
    + )} + {!!props.model.implementedTypes && ( +
    +

    Implements

    +
      + {props.model.implementedTypes.map((item) => ( +
    • {context.type(item)}
    • + ))} +
    +
    + )} + {!!props.model.implementedBy && ( +
    +

    Implemented by

    +
      + {props.model.implementedBy.map((item) => ( +
    • {context.type(item)}
    • + ))} +
    +
    + )} + {!!props.model.signatures && ( +
    {context.memberSignatures(props.model)}
    + )} + {!!props.model.indexSignature && ( +
    +

    Indexable

    +
    + [ + {props.model.indexSignature.parameters!.map((item) => ( + <> + {item.name}: {context.type(item.type)} + + ))} + ]: + {context.type(props.model.indexSignature.type)} +
    + {context.comment(props.model.indexSignature)} + {props.model.indexSignature?.type instanceof ReflectionType && + context.parameter(props.model.indexSignature.type.declaration)} +
    + )} + + )} + {!!props.model.children?.length && context.index(props.model)} + {context.members(props.model)} + + ); +} diff --git a/src/lib/output/themes/lib.tsx b/src/lib/output/themes/lib.tsx index 978b843e8..d2e0f7972 100644 --- a/src/lib/output/themes/lib.tsx +++ b/src/lib/output/themes/lib.tsx @@ -1,11 +1,14 @@ import { + Comment, + CommentDisplayPart, DeclarationReflection, Reflection, ReflectionFlags, SignatureReflection, TypeParameterReflection, } from "../../models"; -import { JSX } from "../../utils"; +import { assertNever, JSX } from "../../utils"; +import type { DefaultThemeRenderContext } from "./default/DefaultThemeRenderContext"; export function stringify(data: unknown) { if (typeof data === "bigint") { @@ -25,12 +28,11 @@ export function stringify(data: unknown) { export function wbr(str: string): (string | JSX.Element)[] { // TODO surely there is a better way to do this, but I'm tired. const ret: (string | JSX.Element)[] = []; - const re = /[\s\S]*?(?:([^_-][_-])(?=[^_-])|([^A-Z])(?=[A-Z][^A-Z]))/g; + const re = /[\s\S]*?(?:[^_-][_-](?=[^_-])|[^A-Z](?=[A-Z][^A-Z]))/g; let match: RegExpExecArray | null; let i = 0; while ((match = re.exec(str))) { - ret.push(match[0]); - ret.push(); + ret.push(match[0], ); i += match[0].length; } ret.push(str.slice(i)); @@ -51,32 +53,41 @@ export function join(joiner: JSX.Children, list: readonly T[], cb: (x: T) => return <>{result}; } -export function renderFlags(flags: ReflectionFlags) { +export function renderFlags(flags: ReflectionFlags, comment: Comment | undefined) { + const allFlags = [...flags]; + if (comment) { + allFlags.push(...Array.from(comment.modifierTags, (tag) => tag.replace(/@([a-z])/, (x) => x[1].toUpperCase()))); + } + return ( <> - {flags.map((item) => ( + {allFlags.map((item) => ( <> - {item}{" "} + {item}{" "} ))} ); } -export function classNames(names: Record) { - return Object.entries(names) - .filter(([, include]) => include) - .map(([key]) => key) - .join(" "); +export function classNames(names: Record, extraCss?: string) { + const css = Object.keys(names) + .filter((key) => names[key]) + .concat(extraCss || "") + .join(" ") + .trim() + .replace(/\s+/g, " "); + return css.length ? css : undefined; } export function hasTypeParameters( reflection: Reflection ): reflection is Reflection & { typeParameters: TypeParameterReflection[] } { - if (reflection instanceof DeclarationReflection || reflection instanceof SignatureReflection) { - return reflection.typeParameters != null; - } - return false; + return ( + (reflection instanceof DeclarationReflection || reflection instanceof SignatureReflection) && + reflection.typeParameters != null && + reflection.typeParameters.length > 0 + ); } export function renderTypeParametersSignature( @@ -101,3 +112,48 @@ export function renderTypeParametersSignature( ); } + +export function camelToTitleCase(text: string) { + return text.substring(0, 1).toUpperCase() + text.substring(1).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); +} + +export function displayPartsToMarkdown(parts: CommentDisplayPart[], urlTo: DefaultThemeRenderContext["urlTo"]) { + const result: string[] = []; + + for (const part of parts) { + switch (part.kind) { + case "text": + case "code": + result.push(part.text); + break; + case "inline-tag": + switch (part.tag) { + case "@label": + case "@inheritdoc": // Shouldn't happen + break; // Not rendered. + case "@link": + case "@linkcode": + case "@linkplain": { + if (part.target) { + const url = typeof part.target === "string" ? part.target : urlTo(part.target); + const wrap = part.tag === "@linkcode" ? "`" : ""; + result.push(url ? `[${wrap}${part.text}${wrap}](${url})` : part.text); + } else { + result.push(part.text); + } + break; + } + default: + // Hmm... probably want to be able to render these somehow, so custom inline tags can be given + // special rendering rules. Future capability. For now, just render their text. + result.push(`{${part.tag} ${part.text}}`); + break; + } + break; + default: + assertNever(part); + } + } + + return result.join(""); +} diff --git a/src/lib/serialization/components.ts b/src/lib/serialization/components.ts index 5830179a6..727904b52 100644 --- a/src/lib/serialization/components.ts +++ b/src/lib/serialization/components.ts @@ -1,5 +1,3 @@ -import { Reflection, Type } from "../models"; - import type { Serializer } from "./serializer"; import type { ModelToObject } from "./schema"; @@ -7,85 +5,23 @@ import type { ModelToObject } from "./schema"; * Represents Serializer plugin component. * * Like {@link Converter} plugins each {@link Serializer} plugin defines a predicate that instructs if an - * object can be serialized by it, this is done dynamically at runtime via a `supports` method. + * object can be serialized by it. This is done dynamically at runtime via a `supports` method. * * Additionally, each {@link Serializer} plugin must define a predicate that instructs the group * it belongs to. - * - * Serializers are grouped to improve performance when finding serializers that apply to a node, - * this makes it possible to skip the `supports` calls for `Type`s when searching for a - * `Reflection` and vise versa. */ -export abstract class SerializerComponent { - /** - * The priority this serializer should be executed with. - * A higher priority means the {@link Serializer} will be applied earlier. - */ - static PRIORITY = 0; - - constructor(owner: Serializer) { - this.owner = owner; - } - - /** - * Set when the SerializerComponent is added to the serializer. - */ - protected owner: Serializer; - - /** - * A high-level predicate filtering which group this serializer belongs to. - * This is a high-level filter before the {@link SerializerComponent.supports} predicate filter. - * - * For example, use the {@link Reflection} class class to group all reflection based serializers: - * ```typescript - * class ReflectionSerializer { - * serializeGroup(instance) { return instance instanceof Reflection } - * } - * ``` - * - * Use the {@link Type} class to group all type based serializers: - * ```typescript - * class TypeSerializer { - * serializeGroup(instance) { return instance instanceof Type } - * } - * ``` - */ - abstract serializeGroup(instance: unknown): boolean; - +export interface SerializerComponent { /** * The priority this serializer should be executed with. * A higher priority means the {@link Serializer} will be applied earlier. */ - get priority(): number { - return ( - (this.constructor as typeof SerializerComponent)["PRIORITY"] || - SerializerComponent.PRIORITY - ); - } + readonly priority: number; - abstract supports(item: unknown): boolean; + supports(item: unknown): item is T; - abstract toObject(item: T, obj?: object): Partial>; -} - -export abstract class ReflectionSerializerComponent< - T extends Reflection -> extends SerializerComponent { - /** - * Filter for instances of {@link Reflection} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof Reflection; - } -} - -export abstract class TypeSerializerComponent< - T extends Type -> extends SerializerComponent { - /** - * Filter for instances of {@link Type} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof Type; - } + toObject( + item: T, + obj: Partial>, + serializer: Serializer + ): Partial>; } diff --git a/src/lib/serialization/events.ts b/src/lib/serialization/events.ts index 17f2b1a2d..b6ec199dc 100644 --- a/src/lib/serialization/events.ts +++ b/src/lib/serialization/events.ts @@ -33,12 +33,12 @@ export class SerializeEvent extends Event { */ outputFile?: string; - output: Partial; + output: JSONProjectReflection | undefined; constructor( name: string, project: ProjectReflection, - output: Partial + output?: JSONProjectReflection ) { super(name); this.project = project; diff --git a/src/lib/serialization/index.ts b/src/lib/serialization/index.ts index 24b960683..27f0badfb 100644 --- a/src/lib/serialization/index.ts +++ b/src/lib/serialization/index.ts @@ -1,37 +1,7 @@ -export { - ReflectionSerializerComponent, - SerializerComponent, - TypeSerializerComponent, -} from "./components"; +export type { SerializerComponent } from "./components"; export { SerializeEvent } from "./events"; export type { SerializeEventData } from "./events"; export { Serializer } from "./serializer"; -export { - ArrayTypeSerializer, - CommentSerializer, - CommentTagSerializer, - ContainerReflectionSerializer, - DeclarationReflectionSerializer, - DecoratorContainerSerializer, - DecoratorWrapper, - IntersectionTypeSerializer, - IntrinsicTypeSerializer, - LiteralTypeSerializer, - ParameterReflectionSerializer, - ReferenceTypeSerializer, - ReflectionCategorySerializer, - ReflectionGroupSerializer, - ReflectionSerializer, - ReflectionTypeSerializer, - SignatureReflectionSerializer, - SourceReferenceContainerSerializer, - SourceReferenceWrapper, - TupleTypeSerializer, - TypeOperatorTypeSerializer, - TypeParameterReflectionSerializer, - TypeSerializer, - UnknownTypeSerializer, -} from "./serializers"; export { JSONOutput }; import * as JSONOutput from "./schema"; diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index b65a07bcd..db21d9729 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -29,7 +29,6 @@ */ import type * as M from "../models"; -import type { SourceReferenceWrapper, DecoratorWrapper } from "./serializers"; /** * Describes the mapping from Model types to the corresponding JSON output type. @@ -73,9 +72,9 @@ type _ModelToObject = ? Comment : T extends M.CommentTag ? CommentTag - : T extends DecoratorWrapper - ? Decorator - : T extends SourceReferenceWrapper + : T extends M.CommentDisplayPart + ? CommentDisplayPart + : T extends M.SourceReference ? SourceReference : never; @@ -101,7 +100,7 @@ type S = { // Reflections export interface ReflectionGroup - extends S { + extends S { children?: M.ReflectionGroup["children"][number]["id"][]; } @@ -152,16 +151,10 @@ export interface DeclarationReflection | "extendedBy" | "implementedTypes" | "implementedBy" - > { - // Weird not to call this typeParameters... preserving backwards compatibility for now. - typeParameter?: ModelToObject; - - // Yep... backwards compatibility. This is an optional one-tuple. - getSignature?: [ModelToObject]; - - // Yep... backwards compatibility. This is an optional one-tuple. - setSignature?: [ModelToObject]; -} + | "getSignature" + | "setSignature" + | "typeParameters" + > {} export interface TypeParameterReflection extends Reflection, @@ -172,41 +165,21 @@ export interface ProjectReflection extends ContainerReflection {} export interface ContainerReflection extends Reflection, - S { - sources?: ModelToObject; -} + S< + M.ContainerReflection, + "children" | "groups" | "categories" | "sources" + > {} export interface Reflection - extends S< - M.Reflection, - "id" | "name" | "kind" | "kindString" | "comment" | "decorates" - > { + extends S { /** Will not be present if name === originalName */ originalName?: M.Reflection["originalName"]; flags: ReflectionFlags; - decorators?: ModelToObject; } // Types -export type SomeType = - | ArrayType - | ConditionalType - | IndexedAccessType - | InferredType - | IntersectionType - | IntrinsicType - | LiteralType - | OptionalType - | PredicateType - | QueryType - | ReferenceType - | ReflectionType - | RestType - | TupleType - | TypeOperatorType - | UnionType - | UnknownType; +export type SomeType = ModelToObject; export type TypeKindMap = { array: ArrayType; @@ -291,11 +264,7 @@ export interface TupleType extends Type, S { export interface NamedTupleMemberType extends Type, - S { - name: string; - isOptional: boolean; - element: ModelToObject; -} + S {} export interface TemplateLiteralType extends Type, @@ -324,10 +293,6 @@ export interface UnionType extends Type, S {} export interface UnknownType extends Type, S {} -/** - * Technically not correct, the `type` property will be set by the abstract serializer. - * But to allow tagged literals, the `type` property is instead defined by each child type. - */ export interface Type {} // Miscellaneous @@ -339,16 +304,28 @@ type BoolKeys = { export interface ReflectionFlags extends Partial>> {} -export interface Comment - extends Partial> {} +export interface Comment extends Partial> { + summary: CommentDisplayPart[]; + modifierTags?: string[]; +} -export interface CommentTag extends S { - tag: M.CommentTag["tagName"]; - param?: M.CommentTag["paramName"]; +export interface CommentTag extends S { + content: CommentDisplayPart[]; } -export interface SourceReference - extends S {} +/** + * If `target` is a number, it is a reflection ID. If a string, it is a URL. + * `target` will only be set for `@link`, `@linkcode`, and `@linkplain` tags. + */ +export type CommentDisplayPart = + | { kind: "text"; text: string } + | { kind: "code"; text: string } + | { + kind: "inline-tag"; + tag: `@${string}`; + text: string; + target?: string | number; + }; -export interface Decorator - extends S {} +export interface SourceReference + extends S {} diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index 71064b985..7d020d3ba 100644 --- a/src/lib/serialization/serializer.ts +++ b/src/lib/serialization/serializer.ts @@ -1,10 +1,9 @@ import { EventDispatcher } from "../utils"; import type { ProjectReflection } from "../models"; -import type { SerializerComponent } from "./components"; import { SerializeEvent, SerializeEventData } from "./events"; import type { ModelToObject } from "./schema"; -import * as S from "./serializers"; +import type { SerializerComponent } from "./components"; export class Serializer extends EventDispatcher { /** @@ -19,50 +18,49 @@ export class Serializer extends EventDispatcher { */ static EVENT_END = "end"; - /** - * Serializers, sorted by their `serializeGroup` function to enable higher performance. - */ - private serializers = new Map< - (instance: unknown) => boolean, - SerializerComponent[] - >(); - - constructor() { - super(); - addSerializers(this); - } + private serializers: SerializerComponent[] = []; addSerializer(serializer: SerializerComponent): void { - let group = this.serializers.get(serializer.serializeGroup); - - if (!group) { - this.serializers.set(serializer.serializeGroup, (group = [])); + if ("serializeGroup" in serializer) { + // Remove this check in 0.24 + throw new Error( + "Support for `serializeGroup` was removed. Use supports instead." + ); } - group.push(serializer); - group.sort((a, b) => b.priority - a.priority); + this.serializers.push(serializer); + this.serializers.sort((a, b) => b.priority - a.priority); } - toObject(value: T, init?: object): ModelToObject; - toObject(value: unknown, init: object = {}): unknown { - if (value == null || typeof value !== "object") { - return value; // Serializing some primitive + toObject }>( + value: T + ): ModelToObject; + toObject }>( + value: T | undefined + ): ModelToObject | undefined; + toObject( + value: { toObject(serializer: Serializer): any } | undefined + ): unknown { + if (value === undefined) { + return undefined; } - if (Array.isArray(value)) { - if (value.length === 0) { - return undefined; - } - return value.map((val) => this.toObject(val)); + return this.serializers + .filter((s) => s.supports(value)) + .reduce( + (val, s) => s.toObject(value, val, this), + value.toObject(this) + ); + } + + toObjectsOptional< + T extends { toObject(serializer: Serializer): ModelToObject } + >(value: T[] | undefined): ModelToObject[] | undefined { + if (!value || value.length === 0) { + return undefined; } - // Note: This type *could* potentially lie, if a serializer declares a partial type but fails to provide - // the defined property, but the benefit of being mostly typed is probably worth it. - // TypeScript errors out if init is correctly typed as `Partial>` - return this.findSerializers(value).reduce( - (result, curr) => curr.toObject(value, result), - init - ); + return value.map((val) => this.toObject(val)); } /** @@ -74,18 +72,14 @@ export class Serializer extends EventDispatcher { value: ProjectReflection, eventData: { begin?: SerializeEventData; end?: SerializeEventData } = {} ): ModelToObject { - const eventBegin = new SerializeEvent( - Serializer.EVENT_BEGIN, - value, - {} - ); + const eventBegin = new SerializeEvent(Serializer.EVENT_BEGIN, value); if (eventData.begin) { eventBegin.outputDirectory = eventData.begin.outputDirectory; eventBegin.outputFile = eventData.begin.outputFile; } this.trigger(eventBegin); - const project = this.toObject(value, eventBegin.output); + const project = this.toObject(value); const eventEnd = new SerializeEvent( Serializer.EVENT_END, @@ -100,70 +94,4 @@ export class Serializer extends EventDispatcher { return project; } - - private findSerializers(value: T): SerializerComponent[] { - const routes: SerializerComponent[] = []; - - for (const [groupSupports, components] of this.serializers.entries()) { - if (groupSupports(value)) { - for (const component of components) { - if (component.supports(value)) { - routes.push(component); - } - } - } - } - - return routes as any; - } -} - -const serializerComponents: (new ( - owner: Serializer -) => SerializerComponent)[] = [ - S.CommentTagSerializer, - S.CommentSerializer, - - S.ReflectionSerializer, - S.ReferenceReflectionSerializer, - S.ContainerReflectionSerializer, - S.DeclarationReflectionSerializer, - S.ParameterReflectionSerializer, - S.SignatureReflectionSerializer, - S.TypeParameterReflectionSerializer, - - S.SourceReferenceContainerSerializer, - - S.TypeSerializer, - S.ArrayTypeSerializer, - S.ConditionalTypeSerializer, - S.IndexedAccessTypeSerializer, - S.InferredTypeSerializer, - S.IntersectionTypeSerializer, - S.IntrinsicTypeSerializer, - S.OptionalTypeSerializer, - S.PredicateTypeSerializer, - S.QueryTypeSerializer, - S.ReferenceTypeSerializer, - S.ReferenceTypeSerializer, - S.ReflectionTypeSerializer, - S.RestTypeSerializer, - S.LiteralTypeSerializer, - S.TupleTypeSerializer, - S.TemplateLiteralTypeSerializer, - S.NamedTupleMemberTypeSerializer, - S.MappedTypeSerializer, - S.TypeOperatorTypeSerializer, - S.UnionTypeSerializer, - S.UnknownTypeSerializer, - - S.DecoratorContainerSerializer, - S.ReflectionCategorySerializer, - S.ReflectionGroupSerializer, -]; - -function addSerializers(owner: Serializer) { - for (const component of serializerComponents) { - owner.addSerializer(new component(owner)); - } } diff --git a/src/lib/serialization/serializers/comments/comment-tag.ts b/src/lib/serialization/serializers/comments/comment-tag.ts deleted file mode 100644 index 06af55957..000000000 --- a/src/lib/serialization/serializers/comments/comment-tag.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { CommentTag } from "../../../models"; - -import { SerializerComponent } from "../../components"; -import type { CommentTag as JSONCommentTag } from "../../schema"; - -export class CommentTagSerializer extends SerializerComponent { - static override PRIORITY = 1000; - - /** - * Filter for instances of {@link CommentTag} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof CommentTag; - } - - supports(_t: unknown) { - return true; - } - - toObject( - tag: CommentTag, - obj: Partial = {} - ): JSONCommentTag { - const result: JSONCommentTag = { - tag: tag.tagName, - text: tag.text, - }; - - if (tag.paramName) { - result.param = tag.paramName; - } - - return { ...obj, ...result }; - } -} diff --git a/src/lib/serialization/serializers/comments/comment.ts b/src/lib/serialization/serializers/comments/comment.ts deleted file mode 100644 index 315a3cc22..000000000 --- a/src/lib/serialization/serializers/comments/comment.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { Comment } from "../../../models"; - -import { SerializerComponent } from "../../components"; -import type { Comment as JSONComment } from "../../schema"; - -export class CommentSerializer extends SerializerComponent { - static override PRIORITY = 1000; - - /** - * Filter for instances of {@link Comment} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof Comment; - } - - supports() { - return true; - } - - toObject(comment: Comment, obj: Partial = {}): JSONComment { - if (comment.shortText) { - obj.shortText = comment.shortText; - } - if (comment.text) { - obj.text = comment.text; - } - if (comment.returns) { - obj.returns = comment.returns; - } - if (comment.tags.length) { - obj.tags = comment.tags.map((tag) => this.owner.toObject(tag)); - } - - return obj; - } -} diff --git a/src/lib/serialization/serializers/comments/index.ts b/src/lib/serialization/serializers/comments/index.ts deleted file mode 100644 index 0c621ad0d..000000000 --- a/src/lib/serialization/serializers/comments/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { CommentSerializer } from "./comment"; -export { CommentTagSerializer } from "./comment-tag"; diff --git a/src/lib/serialization/serializers/decorator.ts b/src/lib/serialization/serializers/decorator.ts deleted file mode 100644 index baf2cdd43..000000000 --- a/src/lib/serialization/serializers/decorator.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { SerializerComponent } from "../components"; -import { DecoratorWrapper } from "./models/decorator-wrapper"; -import type { Decorator } from "../schema"; - -export class DecoratorContainerSerializer extends SerializerComponent { - static override PRIORITY = 1000; - - /** - * Filter for instances of {@link DecoratorWrapper} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof DecoratorWrapper; - } - - supports() { - return true; - } - - toObject( - { decorator }: DecoratorWrapper, - obj?: Partial - ): Decorator { - const result: Decorator = { - ...obj, - name: decorator.name, - }; - - if (decorator.type) { - result.type = this.owner.toObject(decorator.type); - } - - if (decorator.arguments) { - result.arguments = decorator.arguments; - } - - return result; - } -} diff --git a/src/lib/serialization/serializers/index.ts b/src/lib/serialization/serializers/index.ts deleted file mode 100644 index d76a65e0e..000000000 --- a/src/lib/serialization/serializers/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from "./reflections"; -export * from "./types"; -export * from "./comments"; -export * from "./sources"; -export * from "./decorator"; -export * from "./reflection-group"; -export * from "./reflection-category"; -export * from "./models"; diff --git a/src/lib/serialization/serializers/models/decorator-wrapper.ts b/src/lib/serialization/serializers/models/decorator-wrapper.ts deleted file mode 100644 index 3f56f5f9d..000000000 --- a/src/lib/serialization/serializers/models/decorator-wrapper.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { Decorator } from "../../../models"; - -/** - * An internal concrete implementation for the {@link Decorator} interface - * so it can be identified - */ -export class DecoratorWrapper { - constructor(public decorator: Decorator) {} -} diff --git a/src/lib/serialization/serializers/models/index.ts b/src/lib/serialization/serializers/models/index.ts deleted file mode 100644 index bef843a86..000000000 --- a/src/lib/serialization/serializers/models/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { SourceReferenceWrapper } from "./source-reference-wrapper"; -export { DecoratorWrapper } from "./decorator-wrapper"; diff --git a/src/lib/serialization/serializers/models/source-reference-wrapper.ts b/src/lib/serialization/serializers/models/source-reference-wrapper.ts deleted file mode 100644 index f43b6f525..000000000 --- a/src/lib/serialization/serializers/models/source-reference-wrapper.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { SourceReference } from "../../../models"; - -/** - * An internal concrete implementation for the [[ SourceReference ]] interface - * so it can be identified - */ -export class SourceReferenceWrapper { - constructor(public sourceReference: SourceReference) {} -} diff --git a/src/lib/serialization/serializers/reflection-category.ts b/src/lib/serialization/serializers/reflection-category.ts deleted file mode 100644 index e46c4a683..000000000 --- a/src/lib/serialization/serializers/reflection-category.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ReflectionCategory } from "../../models/ReflectionCategory"; - -import { SerializerComponent } from "../components"; -import type { ReflectionCategory as JSONReflectionCategory } from "../schema"; - -export class ReflectionCategorySerializer extends SerializerComponent { - static override PRIORITY = 1000; - - /** - * Filter for instances of {@link ReflectionCategory} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof ReflectionCategory; - } - - supports(r: unknown) { - return r instanceof ReflectionCategory; - } - - toObject( - category: ReflectionCategory, - obj?: Partial - ): JSONReflectionCategory { - const result: JSONReflectionCategory = { - ...obj, - title: category.title, - }; - - if (category.children && category.children.length > 0) { - result.children = category.children.map((child) => child.id); - } - - return result; - } -} diff --git a/src/lib/serialization/serializers/reflection-group.ts b/src/lib/serialization/serializers/reflection-group.ts deleted file mode 100644 index 78966514b..000000000 --- a/src/lib/serialization/serializers/reflection-group.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { ReflectionGroup } from "../../models/ReflectionGroup"; - -import { SerializerComponent } from "../components"; -import type { ReflectionGroup as JSONReflectionGroup } from "../schema"; - -export class ReflectionGroupSerializer extends SerializerComponent { - static override PRIORITY = 1000; - - /** - * Filter for instances of {@link ReflectionGroup} - */ - serializeGroup(instance: unknown): boolean { - return instance instanceof ReflectionGroup; - } - - supports() { - return true; - } - - toObject( - group: ReflectionGroup, - obj?: Partial - ): JSONReflectionGroup { - const result: JSONReflectionGroup = { - ...obj, - title: group.title, - kind: group.kind, - }; - - if (group.children && group.children.length > 0) { - result.children = group.children.map((child) => child.id); - } - - if (group.categories && group.categories.length > 0) { - result.categories = group.categories.map((category) => - this.owner.toObject(category) - ); - } - - return result; - } -} diff --git a/src/lib/serialization/serializers/reflections/abstract.ts b/src/lib/serialization/serializers/reflections/abstract.ts deleted file mode 100644 index ebc2b6f95..000000000 --- a/src/lib/serialization/serializers/reflections/abstract.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Reflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import { DecoratorWrapper } from "../models"; -import type { Reflection as JSONReflection } from "../../schema"; - -export class ReflectionSerializer extends ReflectionSerializerComponent { - static override PRIORITY = 1000; - - supports(t: unknown) { - return t instanceof Reflection; - } - - toObject( - reflection: Reflection, - obj?: Partial - ): JSONReflection { - const result: JSONReflection = { - ...obj, - id: reflection.id, - name: reflection.name, - kind: reflection.kind, - kindString: reflection.kindString, - flags: {}, - comment: this.owner.toObject(reflection.comment), - decorates: this.owner.toObject(reflection.decorates), - decorators: this.owner.toObject( - reflection.decorators?.map((d) => new DecoratorWrapper(d)) - ), - }; - - if (reflection.originalName !== reflection.name) { - result.originalName = reflection.originalName; - } - - const flags = [ - "isPrivate", - "isProtected", - "isPublic", - "isStatic", - "isExternal", - "isOptional", - "isRest", - "hasExportAssignment", - "isAbstract", - "isConst", - "isReadonly", - ] as const; - - for (const key of flags) { - if (reflection.flags[key] === true) { - result.flags[key] = true; - } - } - - return result; - } -} diff --git a/src/lib/serialization/serializers/reflections/container.ts b/src/lib/serialization/serializers/reflections/container.ts deleted file mode 100644 index dcafd7908..000000000 --- a/src/lib/serialization/serializers/reflections/container.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ContainerReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import { SourceReferenceWrapper } from "../models"; -import type { - ContainerReflection as JSONContainerReflection, - Reflection as JSONReflection, -} from "../../schema"; - -export class ContainerReflectionSerializer extends ReflectionSerializerComponent { - supports(t: unknown) { - return t instanceof ContainerReflection; - } - - /** - * Will be run after {@link ReflectionSerializer} so will be passed the result of that serialization. - * @param container - * @param obj - */ - toObject( - container: ContainerReflection, - obj: JSONReflection - ): JSONContainerReflection { - return { - ...obj, - children: this.owner.toObject(container.children), - groups: this.owner.toObject(container.groups), - categories: this.owner.toObject(container.categories), - sources: this.owner.toObject( - container.sources?.map((s) => new SourceReferenceWrapper(s)) - ), - }; - } -} diff --git a/src/lib/serialization/serializers/reflections/declaration.ts b/src/lib/serialization/serializers/reflections/declaration.ts deleted file mode 100644 index 52a609112..000000000 --- a/src/lib/serialization/serializers/reflections/declaration.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { DeclarationReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import { ContainerReflectionSerializer } from "./container"; -import type { - DeclarationReflection as JSONDeclarationReflection, - ContainerReflection as JSONContainerReflection, -} from "../../schema"; - -export class DeclarationReflectionSerializer extends ReflectionSerializerComponent { - static override PRIORITY = ContainerReflectionSerializer.PRIORITY - 1; // mimic inheritance, run after parent - - supports(t: unknown) { - return t instanceof DeclarationReflection; - } - - toObject( - d: DeclarationReflection, - obj: JSONContainerReflection - ): JSONDeclarationReflection { - const result: JSONDeclarationReflection = { - ...obj, - typeParameter: this.owner.toObject(d.typeParameters), - type: this.owner.toObject(d.type), - signatures: this.owner.toObject(d.signatures), - indexSignature: this.owner.toObject(d.indexSignature), - }; - - if (d.getSignature) { - result.getSignature = [this.owner.toObject(d.getSignature)]; - } - if (d.setSignature) { - result.setSignature = [this.owner.toObject(d.setSignature)]; - } - - return Object.assign(result, { - defaultValue: this.owner.toObject(d.defaultValue), - overwrites: this.owner.toObject(d.overwrites), - inheritedFrom: this.owner.toObject(d.inheritedFrom), - implementationOf: this.owner.toObject(d.implementationOf), - extendedTypes: this.owner.toObject(d.extendedTypes), - extendedBy: this.owner.toObject(d.extendedBy), - implementedTypes: this.owner.toObject(d.implementedTypes), - implementedBy: this.owner.toObject(d.implementedBy), - }); - } -} diff --git a/src/lib/serialization/serializers/reflections/index.ts b/src/lib/serialization/serializers/reflections/index.ts deleted file mode 100644 index 0ebc4d94b..000000000 --- a/src/lib/serialization/serializers/reflections/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from "./abstract"; -export * from "./container"; -export * from "./declaration"; -export * from "./parameter"; -export * from "./reference"; -export * from "./signature"; -export * from "./type-parameter"; diff --git a/src/lib/serialization/serializers/reflections/parameter.ts b/src/lib/serialization/serializers/reflections/parameter.ts deleted file mode 100644 index d22a42a01..000000000 --- a/src/lib/serialization/serializers/reflections/parameter.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ParameterReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import type { - ParameterReflection as JSONParameterReflection, - Reflection as JSONReflection, -} from "../../schema"; - -export class ParameterReflectionSerializer extends ReflectionSerializerComponent { - supports(t: unknown) { - return t instanceof ParameterReflection; - } - - toObject( - parameter: ParameterReflection, - obj: JSONReflection - ): JSONParameterReflection { - const result: JSONParameterReflection = { - ...obj, - type: this.owner.toObject(parameter.type), - defaultValue: this.owner.toObject(parameter.defaultValue), - }; - - return result; - } -} diff --git a/src/lib/serialization/serializers/reflections/reference.ts b/src/lib/serialization/serializers/reflections/reference.ts deleted file mode 100644 index bbadd5bef..000000000 --- a/src/lib/serialization/serializers/reflections/reference.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ReferenceReflection } from "../../../models"; -import { ReflectionSerializerComponent } from "../../components"; -import type { - DeclarationReflection as JSONDeclarationReflection, - ReferenceReflection as JSONReferenceReflection, -} from "../../schema"; -import { DeclarationReflectionSerializer } from "./declaration"; - -export class ReferenceReflectionSerializer extends ReflectionSerializerComponent { - static override PRIORITY = DeclarationReflectionSerializer.PRIORITY - 1; - - supports(t: unknown) { - return t instanceof ReferenceReflection; - } - - toObject( - ref: ReferenceReflection, - obj: JSONDeclarationReflection - ): JSONReferenceReflection { - return { - ...obj, - target: ref.tryGetTargetReflection()?.id ?? -1, - }; - } -} diff --git a/src/lib/serialization/serializers/reflections/signature.ts b/src/lib/serialization/serializers/reflections/signature.ts deleted file mode 100644 index 9828a7e62..000000000 --- a/src/lib/serialization/serializers/reflections/signature.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { SignatureReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import type { - SignatureReflection as JSONSignatureReflection, - Reflection as JSONReflection, -} from "../../schema"; - -export class SignatureReflectionSerializer extends ReflectionSerializerComponent { - supports(t: unknown) { - return t instanceof SignatureReflection; - } - - toObject( - signature: SignatureReflection, - obj: JSONReflection - ): JSONSignatureReflection { - return { - ...obj, - typeParameter: this.owner.toObject(signature.typeParameters), - parameters: this.owner.toObject(signature.parameters), - type: this.owner.toObject(signature.type), - overwrites: this.owner.toObject(signature.overwrites), - inheritedFrom: this.owner.toObject(signature.inheritedFrom), - implementationOf: this.owner.toObject(signature.implementationOf), - }; - } -} diff --git a/src/lib/serialization/serializers/reflections/type-parameter.ts b/src/lib/serialization/serializers/reflections/type-parameter.ts deleted file mode 100644 index f32db3721..000000000 --- a/src/lib/serialization/serializers/reflections/type-parameter.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { TypeParameterReflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -import type { - TypeParameterReflection as JSONTypeParameterReflection, - Reflection as JSONReflection, -} from "../../schema"; - -export class TypeParameterReflectionSerializer extends ReflectionSerializerComponent { - supports(t: unknown) { - return t instanceof TypeParameterReflection; - } - - toObject( - typeParameter: TypeParameterReflection, - obj: JSONReflection - ): JSONTypeParameterReflection { - return { - ...obj, - type: this.owner.toObject(typeParameter.type), - default: this.owner.toObject(typeParameter.default), - varianceModifier: typeParameter.varianceModifier, - }; - } -} diff --git a/src/lib/serialization/serializers/sources/index.ts b/src/lib/serialization/serializers/sources/index.ts deleted file mode 100644 index e8b525939..000000000 --- a/src/lib/serialization/serializers/sources/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SourceReferenceContainerSerializer } from "./source-reference"; diff --git a/src/lib/serialization/serializers/sources/source-reference.ts b/src/lib/serialization/serializers/sources/source-reference.ts deleted file mode 100644 index 4df7cde53..000000000 --- a/src/lib/serialization/serializers/sources/source-reference.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { SerializerComponent } from "../../components"; -import { SourceReferenceWrapper } from "../models"; -import type { SourceReference as JSONSourceReference } from "../../schema"; - -export class SourceReferenceContainerSerializer extends SerializerComponent { - static override PRIORITY = 1000; - - serializeGroup(instance: unknown) { - return instance instanceof SourceReferenceWrapper; - } - - supports() { - return true; - } - - toObject( - { sourceReference: ref }: SourceReferenceWrapper, - obj?: Partial - ): JSONSourceReference { - return { - ...obj, - fileName: ref.fileName, - line: ref.line, - character: ref.character, - }; - } -} diff --git a/src/lib/serialization/serializers/types/abstract.ts b/src/lib/serialization/serializers/types/abstract.ts deleted file mode 100644 index f00b5ba02..000000000 --- a/src/lib/serialization/serializers/types/abstract.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Type } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { Type as JSONType } from "../../schema"; - -export class TypeSerializer extends TypeSerializerComponent { - static override PRIORITY = 1000; - - supports(t: unknown) { - return t instanceof Type; - } - - toObject(type: Type, obj?: Partial): JSONType { - return { - ...obj, - type: type.type, - }; - } -} diff --git a/src/lib/serialization/serializers/types/array.ts b/src/lib/serialization/serializers/types/array.ts deleted file mode 100644 index e1b77dc88..000000000 --- a/src/lib/serialization/serializers/types/array.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ArrayType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { ArrayType as JSONArrayType } from "../../schema"; - -export class ArrayTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof ArrayType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject(type: ArrayType, obj: Pick): JSONArrayType { - return { - ...obj, - elementType: this.owner.toObject(type.elementType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/conditional.ts b/src/lib/serialization/serializers/types/conditional.ts deleted file mode 100644 index ac1dbf5d3..000000000 --- a/src/lib/serialization/serializers/types/conditional.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ConditionalType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; -import type { - Type as JSONType, - ConditionalType as JSONConditionalType, -} from "../../schema"; - -export class ConditionalTypeSerializer extends TypeSerializerComponent { - supports(item: unknown): boolean { - return item instanceof ConditionalType; - } - - toObject( - conditional: ConditionalType, - obj: Pick & JSONType - ): JSONConditionalType { - return { - ...obj, - checkType: this.owner.toObject(conditional.checkType), - extendsType: this.owner.toObject(conditional.extendsType), - trueType: this.owner.toObject(conditional.trueType), - falseType: this.owner.toObject(conditional.falseType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/index.ts b/src/lib/serialization/serializers/types/index.ts deleted file mode 100644 index c7d8ce5a0..000000000 --- a/src/lib/serialization/serializers/types/index.ts +++ /dev/null @@ -1,20 +0,0 @@ -export * from "./abstract"; -export * from "./array"; -export * from "./conditional"; -export * from "./indexed-access"; -export * from "./inferred"; -export * from "./intersection"; -export * from "./intrinsic"; -export * from "./literal"; -export * from "./mapped"; -export * from "./optional"; -export * from "./predicate"; -export * from "./query"; -export * from "./reference"; -export * from "./reflection"; -export * from "./rest"; -export * from "./template-literal"; -export * from "./tuple"; -export * from "./type-operator"; -export * from "./union"; -export * from "./unknown"; diff --git a/src/lib/serialization/serializers/types/indexed-access.ts b/src/lib/serialization/serializers/types/indexed-access.ts deleted file mode 100644 index a5f3d5676..000000000 --- a/src/lib/serialization/serializers/types/indexed-access.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { IndexedAccessType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; -import type { - Type as JSONType, - IndexedAccessType as JSONIndexedAccessType, -} from "../../schema"; - -export class IndexedAccessTypeSerializer extends TypeSerializerComponent { - supports(item: unknown): boolean { - return item instanceof IndexedAccessType; - } - - toObject( - type: IndexedAccessType, - obj: Pick & JSONType - ): JSONIndexedAccessType { - return { - ...obj, - indexType: this.owner.toObject(type.indexType), - objectType: this.owner.toObject(type.objectType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/inferred.ts b/src/lib/serialization/serializers/types/inferred.ts deleted file mode 100644 index fdc5e94d9..000000000 --- a/src/lib/serialization/serializers/types/inferred.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { InferredType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; - -import type { - Type as JSONType, - InferredType as JSONInferredType, -} from "../../schema"; - -export class InferredTypeSerializer extends TypeSerializerComponent { - supports(item: unknown): boolean { - return item instanceof InferredType; - } - - toObject( - inferred: InferredType, - obj: JSONType & Pick - ): JSONInferredType { - return { - ...obj, - name: inferred.name, - constraint: inferred.constraint - ? this.owner.toObject(inferred.constraint) - : undefined, - }; - } -} diff --git a/src/lib/serialization/serializers/types/intersection.ts b/src/lib/serialization/serializers/types/intersection.ts deleted file mode 100644 index 3de889849..000000000 --- a/src/lib/serialization/serializers/types/intersection.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IntersectionType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { IntersectionType as JSONIntersectionType } from "../../schema"; - -export class IntersectionTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof IntersectionType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject( - type: IntersectionType, - obj: Pick - ): JSONIntersectionType { - return { - ...obj, - types: type.types.map((t) => this.owner.toObject(t)), - }; - } -} diff --git a/src/lib/serialization/serializers/types/intrinsic.ts b/src/lib/serialization/serializers/types/intrinsic.ts deleted file mode 100644 index b6d13f9d6..000000000 --- a/src/lib/serialization/serializers/types/intrinsic.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { IntrinsicType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { IntrinsicType as JSONIntrinsicType } from "../../schema"; - -export class IntrinsicTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof IntrinsicType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject( - type: IntrinsicType, - obj: Pick - ): JSONIntrinsicType { - return { - ...obj, - name: type.name, - }; - } -} diff --git a/src/lib/serialization/serializers/types/literal.ts b/src/lib/serialization/serializers/types/literal.ts deleted file mode 100644 index 456563cd3..000000000 --- a/src/lib/serialization/serializers/types/literal.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { LiteralType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { LiteralType as JSONLiteralType } from "../../schema"; - -export class LiteralTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof LiteralType; - } - - toObject( - type: LiteralType, - obj: Pick - ): JSONLiteralType { - if (typeof type.value === "bigint") { - return { - ...obj, - value: { - value: type.value.toString().replace("-", ""), - negative: type.value < BigInt("0"), - }, - }; - } - - return { - ...obj, - value: type.value, - }; - } -} diff --git a/src/lib/serialization/serializers/types/mapped.ts b/src/lib/serialization/serializers/types/mapped.ts deleted file mode 100644 index 4d3d84106..000000000 --- a/src/lib/serialization/serializers/types/mapped.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TypeSerializerComponent } from "../../components"; -import { MappedType } from "../../../models"; -import type { MappedType as JSONMappedType } from "../../schema"; - -export class MappedTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof MappedType; - } - - toObject( - map: MappedType, - obj: Pick - ): JSONMappedType { - return { - ...obj, - parameter: map.parameter, - parameterType: this.owner.toObject(map.parameterType), - templateType: this.owner.toObject(map.templateType), - readonlyModifier: map.readonlyModifier, - optionalModifier: map.optionalModifier, - nameType: this.owner.toObject(map.nameType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/optional.ts b/src/lib/serialization/serializers/types/optional.ts deleted file mode 100644 index 05d6a1291..000000000 --- a/src/lib/serialization/serializers/types/optional.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { OptionalType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { OptionalType as JSONOptionalType } from "../../schema"; - -export class OptionalTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof OptionalType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject( - type: OptionalType, - obj: Pick - ): JSONOptionalType { - return { - ...obj, - elementType: this.owner.toObject(type.elementType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/predicate.ts b/src/lib/serialization/serializers/types/predicate.ts deleted file mode 100644 index 6bfea1384..000000000 --- a/src/lib/serialization/serializers/types/predicate.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { PredicateType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; -import type { PredicateType as JSONPredicateType } from "../../schema"; - -export class PredicateTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof PredicateType; - } - - toObject( - type: PredicateType, - obj: Pick - ): JSONPredicateType { - return { - ...obj, - name: type.name, - asserts: type.asserts, - targetType: type.targetType - ? this.owner.toObject(type.targetType) - : undefined, - }; - } -} diff --git a/src/lib/serialization/serializers/types/query.ts b/src/lib/serialization/serializers/types/query.ts deleted file mode 100644 index 7def612f4..000000000 --- a/src/lib/serialization/serializers/types/query.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { QueryType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; -import type { QueryType as JSONQueryType } from "../../schema"; - -export class QueryTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof QueryType; - } - - toObject(type: QueryType, obj: Pick): JSONQueryType { - return { - ...obj, - queryType: this.owner.toObject(type.queryType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/reference.ts b/src/lib/serialization/serializers/types/reference.ts deleted file mode 100644 index 82b3c1340..000000000 --- a/src/lib/serialization/serializers/types/reference.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { ReferenceType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { ReferenceType as JSONReferenceType } from "../../schema"; - -export class ReferenceTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof ReferenceType; - } - - toObject( - type: ReferenceType, - obj: Pick & Partial - ): JSONReferenceType { - if (type.reflection) { - obj.id = type.reflection.id; - } - - if (type.typeArguments && type.typeArguments.length > 0) { - obj.typeArguments = type.typeArguments.map((t) => - this.owner.toObject(t) - ); - } - - if (type.qualifiedName && type.package) { - obj.qualifiedName = type.qualifiedName; - obj.package = type.package; - } - - return { - ...obj, - name: type.name, - }; - } -} diff --git a/src/lib/serialization/serializers/types/reflection.ts b/src/lib/serialization/serializers/types/reflection.ts deleted file mode 100644 index 2727fca81..000000000 --- a/src/lib/serialization/serializers/types/reflection.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ReflectionType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { ReflectionType as JSONReflectionType } from "../../schema"; - -export class ReflectionTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof ReflectionType; - } - - toObject( - reference: ReflectionType, - obj: Pick - ): JSONReflectionType { - const result: JSONReflectionType = { - ...obj, - declaration: this.owner.toObject(reference.declaration), - }; - - return result; - } -} diff --git a/src/lib/serialization/serializers/types/rest.ts b/src/lib/serialization/serializers/types/rest.ts deleted file mode 100644 index ecdd9202e..000000000 --- a/src/lib/serialization/serializers/types/rest.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { RestType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { RestType as JSONRestType } from "../../schema"; - -export class RestTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof RestType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject(type: RestType, obj: Pick): JSONRestType { - return { - ...obj, - elementType: this.owner.toObject(type.elementType), - }; - } -} diff --git a/src/lib/serialization/serializers/types/template-literal.ts b/src/lib/serialization/serializers/types/template-literal.ts deleted file mode 100644 index 0f0c64c7f..000000000 --- a/src/lib/serialization/serializers/types/template-literal.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TemplateLiteralType } from "../../../models"; -import { TypeSerializerComponent } from "../../components"; -import type { TemplateLiteralType as JSONTemplateLiteralType } from "../../schema"; - -export class TemplateLiteralTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof TemplateLiteralType; - } - - toObject( - type: TemplateLiteralType, - obj: Pick - ): JSONTemplateLiteralType { - return { - ...obj, - head: type.head, - tail: type.tail.map(([type, text]) => [ - this.owner.toObject(type), - text, - ]), - }; - } -} diff --git a/src/lib/serialization/serializers/types/tuple.ts b/src/lib/serialization/serializers/types/tuple.ts deleted file mode 100644 index 294dd0d23..000000000 --- a/src/lib/serialization/serializers/types/tuple.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { NamedTupleMember, TupleType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { - TupleType as JSONTupleType, - NamedTupleMemberType as JSONNamedTupleMemberType, -} from "../../schema"; - -export class TupleTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof TupleType; - } - - toObject( - tuple: TupleType, - obj: Pick - ): JSONTupleType { - const result: JSONTupleType = { ...obj }; - - if (tuple.elements && tuple.elements.length > 0) { - result.elements = tuple.elements.map((t) => this.owner.toObject(t)); - } - - return result; - } -} - -export class NamedTupleMemberTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof NamedTupleMember; - } - - toObject( - tuple: NamedTupleMember, - obj: Pick - ): JSONNamedTupleMemberType { - return { - ...obj, - name: tuple.name, - isOptional: tuple.isOptional, - element: this.owner.toObject(tuple.element), - }; - } -} diff --git a/src/lib/serialization/serializers/types/type-operator.ts b/src/lib/serialization/serializers/types/type-operator.ts deleted file mode 100644 index 7bd1c6a20..000000000 --- a/src/lib/serialization/serializers/types/type-operator.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { TypeOperatorType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { TypeOperatorType as JSONTypeOperatorType } from "../../schema"; - -export class TypeOperatorTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof TypeOperatorType; - } - - toObject( - type: TypeOperatorType, - obj: Pick - ): JSONTypeOperatorType { - return { - ...obj, - operator: type.operator, - target: this.owner.toObject(type.target), - }; - } -} diff --git a/src/lib/serialization/serializers/types/union.ts b/src/lib/serialization/serializers/types/union.ts deleted file mode 100644 index 42505017f..000000000 --- a/src/lib/serialization/serializers/types/union.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { UnionType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { UnionType as JSONUnionType } from "../../schema"; - -export class UnionTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof UnionType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject(type: UnionType, obj: Pick): JSONUnionType { - return { - ...obj, - types: type.types.map((t) => this.owner.toObject(t)), - }; - } -} diff --git a/src/lib/serialization/serializers/types/unknown.ts b/src/lib/serialization/serializers/types/unknown.ts deleted file mode 100644 index eae7098bd..000000000 --- a/src/lib/serialization/serializers/types/unknown.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { UnknownType } from "../../../models"; - -import { TypeSerializerComponent } from "../../components"; -import type { UnknownType as JSONUnknownType } from "../../schema"; - -export class UnknownTypeSerializer extends TypeSerializerComponent { - supports(t: unknown) { - return t instanceof UnknownType; - } - - /** - * Will be run after {@link TypeSerializer} so `type` will already be set. - * @param type - * @param obj - */ - toObject( - type: UnknownType, - obj: Pick - ): JSONUnknownType { - return { - ...obj, - name: type.name, - }; - } -} diff --git a/src/lib/types/ts-internal/index.d.ts b/src/lib/types/ts-internal/index.d.ts index 77c5aaa88..ba49a74b0 100644 --- a/src/lib/types/ts-internal/index.d.ts +++ b/src/lib/types/ts-internal/index.d.ts @@ -21,9 +21,8 @@ declare module "typescript" { signature: ts.Signature ): ts.TypePredicate | undefined; - // Since TS 4.6, not available earlier. // https://github.com/microsoft/TypeScript/blob/v4.7.2/src/compiler/types.ts#L4188 - // getTypeOfSymbol(symbol: Symbol): Type; + getTypeOfSymbol(symbol: Symbol): Type; } export interface Signature { diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts index d95ceefdc..a2401c8fb 100644 --- a/src/lib/utils/array.ts +++ b/src/lib/utils/array.ts @@ -82,11 +82,11 @@ export function removeIfPresent(arr: T[] | undefined, item: T) { * @param predicate */ export function removeIf(arr: T[], predicate: (item: T) => boolean) { - const indices = filterMap(arr, (item, index) => - predicate(item) ? index : void 0 - ); - for (const index of indices.reverse()) { - arr.splice(index, 1); + for (let i = 0; i < arr.length; i++) { + if (predicate(arr[i])) { + arr.splice(i, 1); + i--; + } } } @@ -116,17 +116,6 @@ export function partition( return [left, right]; } -/** - * Ensures the given item is an array. - * @param item - */ -export function toArray(item: T | readonly T[] | undefined): T[] { - if (item === void 0) { - return []; - } - return Array.isArray(item) ? [...item] : [item]; -} - export function* zip[]>( ...args: T ): Iterable<{ [K in keyof T]: T[K] extends Iterable ? U : T[K] }> { @@ -142,32 +131,14 @@ export function* zip[]>( } export function filterMap( - arr: readonly T[], - fn: (item: T, index: number) => U | undefined -): U[] { - const result: U[] = []; - - arr.forEach((item, index) => { - const newItem = fn(item, index); - if (newItem !== void 0) { - result.push(newItem); - } - }); - - return result; -} - -export function flatMap( - arr: readonly T[], - fn: (item: T) => U | readonly U[] | undefined + iter: Iterable, + fn: (item: T) => U | undefined ): U[] { const result: U[] = []; - for (const item of arr) { + for (const item of iter) { const newItem = fn(item); - if (newItem instanceof Array) { - result.push(...newItem); - } else if (newItem != null) { + if (newItem !== void 0) { result.push(newItem); } } diff --git a/src/lib/utils/component.ts b/src/lib/utils/component.ts index 38ae6e407..dbb8e826d 100644 --- a/src/lib/utils/component.ts +++ b/src/lib/utils/component.ts @@ -156,13 +156,6 @@ export abstract class AbstractComponent if (this._componentOwner === null) { return this as any as Application; } - // Temporary hack, Application.application is going away. - if ( - this._componentOwner instanceof AbstractComponent && - this._componentOwner._componentOwner === null - ) { - return this._componentOwner as any as Application; - } return this._componentOwner.application; } diff --git a/src/lib/utils/entry-point.ts b/src/lib/utils/entry-point.ts index 85cf808d3..fdb2e5de3 100644 --- a/src/lib/utils/entry-point.ts +++ b/src/lib/utils/entry-point.ts @@ -10,7 +10,7 @@ import { import { createMinimatch, matchesAny } from "./paths"; import type { Logger } from "./loggers"; import type { Options } from "./options"; -import { getCommonDirectory, normalizePath } from "./fs"; +import { getCommonDirectory, glob, normalizePath } from "./fs"; /** * Defines how entry points are interpreted. @@ -52,13 +52,17 @@ export function getEntryPoints( let result: DocumentationEntryPoint[] | undefined; switch (options.getValue("entryPointStrategy")) { case EntryPointStrategy.Resolve: - result = getEntryPointsForPaths(logger, entryPoints, options); + result = getEntryPointsForPaths( + logger, + expandGlobs(entryPoints), + options + ); break; case EntryPointStrategy.Expand: result = getExpandedEntryPointsForPaths( logger, - entryPoints, + expandGlobs(entryPoints), options ); break; @@ -185,6 +189,14 @@ export function getExpandedEntryPointsForPaths( ); } +function expandGlobs(inputFiles: string[]) { + const base = getCommonDirectory(inputFiles); + const result = inputFiles.flatMap((entry) => + glob(entry, base, { includeDirectories: true }) + ); + return result; +} + function getEntryPrograms(logger: Logger, options: Options) { const rootProgram = ts.createProgram({ rootNames: options.getFileNames(), diff --git a/src/lib/utils/enum.ts b/src/lib/utils/enum.ts index 836c7b864..f11462380 100644 --- a/src/lib/utils/enum.ts +++ b/src/lib/utils/enum.ts @@ -1,6 +1,6 @@ export function getEnumFlags(flags: T): T[] { const result: T[] = []; - for (let i = 1; i <= flags; i *= 2) { + for (let i = 1; i <= flags; i <<= 1) { if (flags & i) { result.push(i as T); } @@ -11,7 +11,7 @@ export function getEnumFlags(flags: T): T[] { // T & {} reduces inference priority export function removeFlag(flag: T, remove: T & {}): T { - return ((flag ^ remove) & flag) as T; + return (flag & ~remove) as T; } export function hasAllFlags(flags: number, check: number): boolean { diff --git a/src/lib/utils/events.ts b/src/lib/utils/events.ts index 55a84c603..da4f39f46 100644 --- a/src/lib/utils/events.ts +++ b/src/lib/utils/events.ts @@ -142,7 +142,7 @@ function onApi( options: OnApiOptions ): EventHandlers { if (callback) { - const handlers = events[name] || (events[name] = []); + const handlers = (events[name] ||= []); const context = options.context, ctx = options.ctx, listening = options.listening, diff --git a/src/lib/utils/fs.ts b/src/lib/utils/fs.ts index cffa4b495..e761b9f30 100644 --- a/src/lib/utils/fs.ts +++ b/src/lib/utils/fs.ts @@ -1,5 +1,6 @@ import * as fs from "fs"; import { promises as fsp } from "fs"; +import { Minimatch } from "minimatch"; import { dirname, join } from "path"; /** @@ -133,15 +134,45 @@ export function copySync(src: string, dest: string): void { } /** - * Equivalent to rm -rf - * @param target + * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules. */ -export async function remove(target: string) { - // Since v14.14 - if (fsp.rm) { - await fsp.rm(target, { recursive: true, force: true }); - } else if (fs.existsSync(target)) { - // Ew. We shouldn't need the exists check... Can't wait for Node 14. - await fsp.rmdir(target, { recursive: true }); - } +export function glob( + pattern: string, + root: string, + options?: { includeDirectories?: boolean } +): string[] { + const result: string[] = []; + const mini = new Minimatch(normalizePath(pattern)); + const dirs: string[][] = [normalizePath(root).split("/")]; + + do { + const dir = dirs.shift()!; + + for (const child of fs.readdirSync(dir.join("/"), { + withFileTypes: true, + })) { + if ( + child.isFile() || + (options?.includeDirectories && child.isDirectory()) + ) { + const childPath = [...dir, child.name].join("/"); + if (mini.match(childPath)) { + result.push(childPath); + } + } + + if (child.isDirectory() && child.name !== "node_modules") { + const childPath = dir.concat(child.name); + if ( + mini.set.some((row) => + mini.matchOne(childPath, row, /* partial */ true) + ) + ) { + dirs.push(childPath); + } + } + } + } while (dirs.length); + + return result; } diff --git a/src/lib/utils/general.ts b/src/lib/utils/general.ts index fb9bf4d52..ed7fef3ec 100644 --- a/src/lib/utils/general.ts +++ b/src/lib/utils/general.ts @@ -1,3 +1,5 @@ +import * as Util from "util"; + /** * This type provides a flag that can be used to turn off more lax overloads intended for * plugin use only to catch type errors in the TypeDoc codebase. The prepublishOnly npm @@ -33,6 +35,24 @@ export type IfInternal = InternalOnly extends true ? T : F; */ export type NeverIfInternal = IfInternal; +/** + * Resolves a string type into a union of characters, `"ab"` turns into `"a" | "b"`. + */ +export type Chars = T extends `${infer C}${infer R}` + ? C | Chars + : never; + +/** + * Utility to help type checking ensure that there is no uncovered case. + */ +export function assertNever(x: never): never { + throw new Error( + `Expected handling to cover all possible cases, but it didn't cover: ${Util.inspect( + x + )}` + ); +} + /** * This is a hack to make it possible to detect and warn about installation setups * which result in TypeDoc being installed multiple times. If TypeDoc has been loaded diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index 4d2998211..02315b1ab 100644 --- a/src/lib/utils/highlighter.tsx +++ b/src/lib/utils/highlighter.tsx @@ -1,6 +1,6 @@ import { ok as assert } from "assert"; import { BUNDLED_LANGUAGES, getHighlighter, Highlighter, Theme } from "shiki"; -import { unique } from "./array"; +import { unique, zip } from "./array"; import * as JSX from "./jsx"; const aliases = new Map(); @@ -24,22 +24,17 @@ class DoubleHighlighter { // If this fails... something went *very* wrong. assert(lightTokens.length === darkTokens.length); - const docEls: JSX.Element[][] = []; + const docEls: JSX.Element[] = []; - for (let line = 0; line < lightTokens.length; line++) { - const lightLine = lightTokens[line]; - const darkLine = darkTokens[line]; - - // Different themes can have different grammars... so unfortunately we have to deal with different + for (const [lightLine, darkLine] of zip(lightTokens, darkTokens)) { + // Different themes can have different rules for when colors change... so unfortunately we have to deal with different // sets of tokens.Example: light_plus and dark_plus tokenize " = " differently in the `schemes` // declaration for this file. - const lineEls: JSX.Element[] = []; - while (lightLine.length && darkLine.length) { // Simple case, same token. if (lightLine[0].content === darkLine[0].content) { - lineEls.push( + docEls.push( {lightLine[0].content} ); lightLine.shift(); @@ -48,27 +43,26 @@ class DoubleHighlighter { } if (lightLine[0].content.length < darkLine[0].content.length) { - lineEls.push( + docEls.push( {lightLine[0].content} ); - darkLine[0].content = darkLine[0].content.substr(lightLine[0].content.length); + darkLine[0].content = darkLine[0].content.substring(lightLine[0].content.length); lightLine.shift(); continue; } - lineEls.push( + docEls.push( {darkLine[0].content} ); - lightLine[0].content = lightLine[0].content.substr(darkLine[0].content.length); + lightLine[0].content = lightLine[0].content.substring(darkLine[0].content.length); darkLine.shift(); } - if (line + 1 !== lightTokens.length) { - lineEls.push(
    ); - } - docEls.push(lineEls); + docEls.push(
    ); } + docEls.pop(); // Remove last
    + return JSX.renderElement(<>{docEls}); } @@ -88,15 +82,7 @@ class DoubleHighlighter { i++; } - // GH#1836, our page background is white, but it would be nice to be able to see - // a difference between the code blocks and the background of the page. There's - // probably a better solution to this... revisit once #1794 is merged. - let lightBackground = this.highlighter.getTheme(this.light).bg; - if (isWhite(lightBackground)) { - lightBackground = "#F5F5F5"; - } - - style.push(` --light-code-background: ${lightBackground};`); + style.push(` --light-code-background: ${this.highlighter.getTheme(this.light).bg};`); style.push(` --dark-code-background: ${this.highlighter.getTheme(this.dark).bg};`); lightRules.push(` --code-background: var(--light-code-background);`); darkRules.push(` --code-background: var(--dark-code-background);`); @@ -111,11 +97,11 @@ class DoubleHighlighter { style.push(...darkRules); style.push("} }", ""); - style.push("body.light {"); + style.push(":root[data-theme='light'] {"); style.push(...lightRules); style.push("}", ""); - style.push("body.dark {"); + style.push(":root[data-theme='dark'] {"); style.push(...darkRules); style.push("}", ""); @@ -171,8 +157,3 @@ export function getStyles(): string { assert(highlighter, "Tried to highlight with an uninitialized highlighter"); return highlighter.getStyles(); } - -function isWhite(color: string) { - const colors = new Set(color.toLowerCase().replace(/[^a-f0-9]/g, "")); - return colors.size === 1 && colors.has("f"); -} diff --git a/src/lib/utils/hooks.ts b/src/lib/utils/hooks.ts index 042172ed0..20f02cf83 100644 --- a/src/lib/utils/hooks.ts +++ b/src/lib/utils/hooks.ts @@ -15,12 +15,7 @@ type EventHooksMomento, _R> = { * This is beneficial for the themes since it allows plugins to modify the HTML output * without doing unsafe text replacement. * - * This class is functionally nearly identical to the {@link EventEmitter} class with - * two exceptions. - * 1. The {@link EventEmitter} class only `await`s return values from its listeners, it - * does not return them to the emitter. - * 2. This class requires listeners to by synchronous, unless `R` is specified as to be - * a promise or other deferred type. + * Very simple event emitter class which collects the return values of its listeners. * * @example * ```ts diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index be59a7d18..d3a833063 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -14,15 +14,17 @@ export { getCommonDirectory, normalizePath, readFile, - remove, writeFile, writeFileSync, } from "./fs"; -export type { IfInternal, NeverIfInternal } from "./general"; +export type { IfInternal, NeverIfInternal, Chars } from "./general"; +export { assertNever } from "./general"; export { CallbackLogger, ConsoleLogger, Logger, LogLevel } from "./loggers"; +export { DefaultMap } from "./map"; export { ArgumentsReader, BindOption, + CommentStyle, Options, ParameterHint, ParameterType, @@ -47,6 +49,7 @@ export type { ValidationOptions, TypeDocOptionValues, ParameterTypeToOptionTypeMap, + ManuallyValidatedOption, } from "./options"; export { discoverPlugins, loadPlugins } from "./plugins"; export { sortReflections } from "./sort"; @@ -59,3 +62,5 @@ export * from "./entry-point"; import * as JSX from "./jsx"; export { JSX }; export { Fragment, Raw, renderElement } from "./jsx"; + +export * as Validation from "./validation"; diff --git a/src/lib/utils/jsx.elements.ts b/src/lib/utils/jsx.elements.ts index 3c49a01fd..bf91cb55d 100644 --- a/src/lib/utils/jsx.elements.ts +++ b/src/lib/utils/jsx.elements.ts @@ -116,6 +116,8 @@ export interface IntrinsicElements { // SVG Elements svg: JsxSvgElementProps; path: JsxPathElementProps; + rect: JsxRectElementProps; + use: JsxUseElementProps; } export const JsxFragment = Symbol(); @@ -166,6 +168,8 @@ export interface JsxHtmlGlobalProps { lang?: string; nonce?: string; part?: string; + + role?: string; slot?: string; spellcheck?: boolean; style?: string; @@ -1036,3 +1040,39 @@ export interface JsxPathElementProps d: string; pathLength?: number; } + +/** + * Properties permitted on the `` element. + * + * Reference: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/rect + */ +export interface JsxRectElementProps + extends JsxSvgCoreProps, + JsxSvgStyleProps, + JsxSvgConditionalProcessingProps, + JsxSvgPresentationProps { + height?: string | number; + pathLength?: number; + rx?: string | number; + ry?: string | number; + width?: string | number; + x?: string | number; + y?: string | number; +} + +/** + * Properties permitted on the `` element. + * + * Reference: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/use + */ +export interface JsxUseElementProps + extends JsxSvgCoreProps, + JsxSvgStyleProps, + JsxSvgConditionalProcessingProps, + JsxSvgPresentationProps { + href: string; + x?: string | number; + y?: string | number; + width?: string | number; + height?: string | number; +} diff --git a/src/lib/utils/jsx.ts b/src/lib/utils/jsx.ts index b79f895d1..3aff70359 100644 --- a/src/lib/utils/jsx.ts +++ b/src/lib/utils/jsx.ts @@ -25,6 +25,7 @@ import { JsxFragment as Fragment } from "./jsx.elements"; export type { JsxElement as Element, JsxChildren as Children, + JsxComponent, } from "./jsx.elements"; export { JsxFragment as Fragment } from "./jsx.elements"; @@ -82,6 +83,23 @@ const voidElements = new Set([ "wbr", ]); +const blockElements = new Set([ + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "div", + "section", + "nav", + "details", + "p", + "ul", + "ol", + "li", +]); + /** * JSX factory function to create an "element" that can later be rendered with {@link renderElement} * @param tag @@ -113,6 +131,9 @@ export function renderElement(element: JsxElement | null | undefined): string { const html: string[] = []; if (tag !== Fragment) { + if (blockElements.has(tag)) { + html.push("\n"); + } html.push("<", tag); for (const [key, val] of Object.entries(props ?? {})) { diff --git a/src/lib/utils/loggers.ts b/src/lib/utils/loggers.ts index 743a0d70c..a1d5632b7 100644 --- a/src/lib/utils/loggers.ts +++ b/src/lib/utils/loggers.ts @@ -1,6 +1,7 @@ import * as ts from "typescript"; import { url } from "inspector"; import { resolve } from "path"; +import { nicePath } from "./paths"; const isDebugging = () => !!url(); @@ -19,30 +20,50 @@ const Colors = { yellow: "\u001b[93m", cyan: "\u001b[96m", gray: "\u001b[90m", + black: "\u001b[47m\u001b[30m", reset: "\u001b[0m", }; +function color(text: string, color: keyof typeof Colors) { + if ("NO_COLOR" in process.env) return `${text}`; + + return `${Colors[color]}${text}${Colors.reset}`; +} + const messagePrefixes = { - [LogLevel.Error]: "Error: ", - [LogLevel.Warn]: "Warning: ", - [LogLevel.Info]: "Info: ", - [LogLevel.Verbose]: "Debug: ", + [LogLevel.Error]: color("error", "red"), + [LogLevel.Warn]: color("warning", "yellow"), + [LogLevel.Info]: color("info", "cyan"), + [LogLevel.Verbose]: color("debug", "gray"), }; -const coloredMessagePrefixes = { - [LogLevel.Error]: `${Colors.red}${messagePrefixes[LogLevel.Error]}${ - Colors.reset - }`, - [LogLevel.Warn]: `${Colors.yellow}${messagePrefixes[LogLevel.Warn]}${ - Colors.reset - }`, - [LogLevel.Info]: `${Colors.cyan}${messagePrefixes[LogLevel.Info]}${ - Colors.reset - }`, - [LogLevel.Verbose]: `${Colors.gray}${messagePrefixes[LogLevel.Verbose]}${ - Colors.reset - }`, -}; +function withContext(message: string, level: LogLevel, node?: ts.Node) { + if (!node) { + return `${messagePrefixes[level]} ${message}`; + } + + const file = node.getSourceFile(); + const path = nicePath(file.fileName); + const pos = node.getStart(file, false); + const { line, character } = ts.getLineAndCharacterOfPosition(file, pos); + + const location = `${color(path, "cyan")}:${color( + `${line + 1}`, + "yellow" + )}:${color(`${character}`, "yellow")}`; + + const start = file.text.lastIndexOf("\n", pos) + 1; + let end = file.text.indexOf("\n", start); + if (end === -1) end = file.text.length; + + const prefix = `${location} - ${messagePrefixes[level]}`; + const context = `${color(`${line + 1}`, "black")} ${file.text.substring( + start, + end + )}`; + + return `${prefix} ${message}\n\n${context}\n`; +} /** * A logger that will not produce any output. @@ -120,10 +141,10 @@ export class Logger { * @param text The warning that should be logged. * @param args The arguments that should be printed into the given warning. */ - warn(text: string) { + warn(text: string, node?: ts.Node) { if (this.seenWarnings.has(text)) return; this.seenWarnings.add(text); - this.log(text, LogLevel.Warn); + this.log(text, LogLevel.Warn, node); } /** @@ -132,10 +153,10 @@ export class Logger { * @param text The error that should be logged. * @param args The arguments that should be printed into the given error. */ - error(text: string) { + error(text: string, node?: ts.Node) { if (this.seenErrors.has(text)) return; this.seenErrors.add(text); - this.log(text, LogLevel.Error); + this.log(text, LogLevel.Error, node); } /** @internal */ @@ -152,10 +173,11 @@ export class Logger { /** * Print a log message. * - * @param _message The message itself. - * @param level The urgency of the log message. + * @param _message The message itself. + * @param level The urgency of the log message. + * @param _node Optional node to be used to provide additional context about the message. */ - log(_message: string, level: LogLevel) { + log(_message: string, level: LogLevel, _node?: ts.Node) { if (level === LogLevel.Error) { this.errorCount += 1; } @@ -204,17 +226,11 @@ export class Logger { * A logger that outputs all messages to the console. */ export class ConsoleLogger extends Logger { - /** - * Specifies if the logger is using color codes in its output. - */ - private hasColoredOutput: boolean; - /** * Create a new ConsoleLogger instance. */ constructor() { super(); - this.hasColoredOutput = !("NO_COLOR" in process.env); } /** @@ -223,7 +239,7 @@ export class ConsoleLogger extends Logger { * @param message The message itself. * @param level The urgency of the log message. */ - override log(message: string, level: LogLevel) { + override log(message: string, level: LogLevel, node?: ts.Node) { super.log(message, level); if (level < this.level && !isDebugging()) { return; @@ -238,11 +254,8 @@ export class ConsoleLogger extends Logger { } as const )[level]; - const prefix = this.hasColoredOutput - ? coloredMessagePrefixes[level] - : messagePrefixes[level]; - - console[method](prefix + message); + // eslint-disable-next-line no-console + console[method](withContext(message, level, node)); } } diff --git a/src/lib/utils/map.ts b/src/lib/utils/map.ts new file mode 100644 index 000000000..781a51a13 --- /dev/null +++ b/src/lib/utils/map.ts @@ -0,0 +1,16 @@ +export class DefaultMap extends Map { + constructor(private creator: () => V) { + super(); + } + + override get(key: K): V { + const saved = super.get(key); + if (saved != null) { + return saved; + } + + const created = this.creator(); + this.set(key, created); + return created; + } +} diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 99a0be810..7d810d6f1 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -3,11 +3,10 @@ import type { LogLevel } from "../loggers"; import type { SortStrategy } from "../sort"; import { isAbsolute, join, resolve } from "path"; import type { EntryPointStrategy } from "../entry-point"; -import { ReflectionKind } from "../../models/reflections/kind"; +import type { ReflectionKind } from "../../models/reflections/kind"; +/** @enum */ export const EmitStrategy = { - true: true, // Alias for both, for backwards compatibility until 0.23 - false: false, // Alias for docs, for backwards compatibility until 0.23 both: "both", // Emit both documentation and JS docs: "docs", // Emit documentation, but not JS (default) none: "none", // Emit nothing, just convert and run validation @@ -15,6 +14,18 @@ export const EmitStrategy = { /** @hidden */ export type EmitStrategy = typeof EmitStrategy[keyof typeof EmitStrategy]; +/** + * Determines how TypeDoc searches for comments. + * @enum + */ +export const CommentStyle = { + JSDoc: "jsdoc", + Block: "block", + Line: "line", + All: "all", +} as const; +export type CommentStyle = typeof CommentStyle[keyof typeof CommentStyle]; + /** * An interface describing all TypeDoc specific options. Generated from a * map which contains more information about each option for better types when @@ -23,6 +34,10 @@ export type EmitStrategy = typeof EmitStrategy[keyof typeof EmitStrategy]; export type TypeDocOptions = { [K in keyof TypeDocOptionMap]: unknown extends TypeDocOptionMap[K] ? unknown + : TypeDocOptionMap[K] extends ManuallyValidatedOption< + infer ManuallyValidated + > + ? ManuallyValidated : TypeDocOptionMap[K] extends string | string[] | number | boolean ? TypeDocOptionMap[K] : TypeDocOptionMap[K] extends Record @@ -35,11 +50,15 @@ export type TypeDocOptions = { /** * Describes all TypeDoc specific options as returned by {@link Options.getValue}, this is * slightly more restrictive than the {@link TypeDocOptions} since it does not allow both - * keys and values for mapped option types, and does nto allow partials of flag values. + * keys and values for mapped option types, and does not allow partials of flag values. */ export type TypeDocOptionValues = { [K in keyof TypeDocOptionMap]: unknown extends TypeDocOptionMap[K] ? unknown + : TypeDocOptionMap[K] extends ManuallyValidatedOption< + infer ManuallyValidated + > + ? ManuallyValidated : TypeDocOptionMap[K] extends | string | string[] @@ -50,12 +69,6 @@ export type TypeDocOptionValues = { : TypeDocOptionMap[K][keyof TypeDocOptionMap[K]]; }; -const Kinds = Object.values(ReflectionKind); -export interface SearchConfig { - searchGroupBoosts?: { [key: typeof Kinds[number]]: number }; - searchCategoryBoosts?: { [key: string]: number }; -} - /** * Describes all TypeDoc options. Used internally to provide better types when fetching options. * External consumers should likely use {@link TypeDocOptions} instead. @@ -90,10 +103,16 @@ export interface TypeDocOptionMap { lightHighlightTheme: ShikiTheme; darkHighlightTheme: ShikiTheme; customCss: string; + visibilityFilters: ManuallyValidatedOption<{ + protected?: boolean; + private?: boolean; + inherited?: boolean; + external?: boolean; + [tag: `@${string}`]: boolean; + }>; name: string; includeVersion: boolean; - excludeTags: string[]; readme: string; defaultCategory: string; categoryOrder: string[]; @@ -103,18 +122,22 @@ export interface TypeDocOptionMap { gitRevision: string; gitRemote: string; gaID: string; - gaSite: string; githubPages: boolean; hideGenerator: boolean; - hideLegend: boolean; cleanOutputDir: boolean; + commentStyle: typeof CommentStyle; + excludeTags: `@${string}`[]; + blockTags: `@${string}`[]; + inlineTags: `@${string}`[]; + modifierTags: `@${string}`[]; + help: boolean; version: boolean; showConfig: boolean; plugin: string[]; - searchCategoryBoosts: unknown; - searchGroupBoosts: unknown; + searchCategoryBoosts: ManuallyValidatedOption>; + searchGroupBoosts: ManuallyValidatedOption>; logger: unknown; // string | Function logLevel: typeof LogLevel; markedOptions: unknown; @@ -123,12 +146,16 @@ export interface TypeDocOptionMap { // Validation treatWarningsAsErrors: boolean; intentionallyNotExported: string[]; - /** @deprecated use validation.invalidLink */ - listInvalidSymbolLinks: boolean; validation: ValidationOptions; requiredToBeDocumented: (keyof typeof ReflectionKind)[]; } +/** + * Wrapper type for values in TypeDocOptionMap which are represented with an unknown option type, but + * have a validation function that checks that they are the given type. + */ +export type ManuallyValidatedOption = { __validated: T }; + export type ValidationOptions = { /** * If set, TypeDoc will produce warnings when a symbol is referenced by the documentation, @@ -159,6 +186,8 @@ export type KeyToDeclaration = ? ArrayDeclarationOption : unknown extends TypeDocOptionMap[K] ? MixedDeclarationOption + : TypeDocOptionMap[K] extends ManuallyValidatedOption + ? MixedDeclarationOption & { validate(value: unknown): void } : TypeDocOptionMap[K] extends Record ? FlagsDeclarationOption : TypeDocOptionMap[K] extends Record @@ -285,7 +314,7 @@ export interface ArrayDeclarationOption extends DeclarationOptionBase { /** * If not specified defaults to an empty array. */ - defaultValue?: string[]; + defaultValue?: readonly string[]; /** * An optional validation function that validates a potential value of this option. @@ -565,7 +594,7 @@ const defaultGetters: { return option.defaultValue; }, [ParameterType.Array](option) { - return option.defaultValue ?? []; + return option.defaultValue?.slice() ?? []; }, [ParameterType.PathArray](option) { return ( @@ -600,7 +629,7 @@ export function getDefaultValue(option: DeclarationOption) { function resolveGlobPaths(globs: readonly string[], configPath: string) { return globs.map((path) => { const start = path.match(/^[!#]+/)?.[0] ?? ""; - const remaining = path.substr(start.length); + const remaining = path.substring(start.length); if (!remaining.startsWith("**")) { return start + resolve(configPath, remaining); } diff --git a/src/lib/utils/options/index.ts b/src/lib/utils/options/index.ts index 4583415df..60bdd4998 100644 --- a/src/lib/utils/options/index.ts +++ b/src/lib/utils/options/index.ts @@ -1,7 +1,12 @@ export { Options, BindOption } from "./options"; export type { OptionsReader } from "./options"; export { ArgumentsReader, TypeDocReader, TSConfigReader } from "./readers"; -export { EmitStrategy, ParameterType, ParameterHint } from "./declaration"; +export { + CommentStyle, + EmitStrategy, + ParameterType, + ParameterHint, +} from "./declaration"; export type { TypeDocOptions, @@ -20,4 +25,5 @@ export type { DeclarationOptionToOptionType, TypeDocOptionValues, ParameterTypeToOptionTypeMap, + ManuallyValidatedOption, } from "./declaration"; diff --git a/src/lib/utils/options/options.ts b/src/lib/utils/options/options.ts index 4a30a9858..810bb650f 100644 --- a/src/lib/utils/options/options.ts +++ b/src/lib/utils/options/options.ts @@ -54,6 +54,14 @@ export interface OptionsReader { read(container: Options, logger: Logger): void; } +const optionSnapshots = new WeakMap< + { __optionSnapshot: never }, + { + values: Record; + set: Set; + } +>(); + /** * Maintains a collection of option declarations split into TypeDoc options * and TypeScript options. Ensures options are of the correct type for calling @@ -102,6 +110,31 @@ export class Options { return Object.isFrozen(this._values); } + /** + * Take a snapshot of option values now, used in tests only. + * @internal + */ + snapshot() { + const key = {} as { __optionSnapshot: never }; + + optionSnapshots.set(key, { + values: { ...this._values }, + set: new Set(this._setOptions), + }); + + return key; + } + + /** + * Take a snapshot of option values now, used in tests only. + * @internal + */ + restore(snapshot: { __optionSnapshot: never }) { + const data = optionSnapshots.get(snapshot)!; + this._values = { ...data.values }; + this._setOptions = new Set(data.set); + } + /** * Sets the logger used when an option declaration fails to be added. * @param logger @@ -153,15 +186,6 @@ export class Options { insertPrioritySorted(this._readers, reader); } - /** - * Removes all readers of a given name. - * @param name - * @deprecated should not be used, will be removed in 0.23 - */ - removeReaderByName(name: string): void { - this._readers = this._readers.filter((reader) => reader.name !== name); - } - read(logger: Logger) { for (const reader of this._readers) { reader.read(this, logger); @@ -197,32 +221,6 @@ export class Options { this._values[declaration.name] = getDefaultValue(declaration); } - /** - * Adds the given declarations to the container - * @param declarations - * @deprecated will be removed in 0.23. - */ - addDeclarations(declarations: readonly DeclarationOption[]): void { - for (const decl of declarations) { - this.addDeclaration(decl as any); - } - } - - /** - * Removes a declared option. - * WARNING: This is probably a bad idea. If you do this you will probably cause a crash - * when code assumes that an option that it declared still exists. - * @param name - * @deprecated will be removed in 0.23. - */ - removeDeclarationByName(name: string): void { - const declaration = this.getDeclaration(name); - if (declaration) { - this._declarations.delete(declaration.name); - delete this._values[declaration.name]; - } - } - /** * Gets a declaration by one of its names. * @param name @@ -335,10 +333,7 @@ export class Options { Object.assign(result, overrides); } - if ( - this.getValue("emit") !== "both" && - this.getValue("emit") !== true - ) { + if (this.getValue("emit") !== "both") { result.noEmit = true; delete result.emitDeclarationOnly; } diff --git a/src/lib/utils/options/readers/tsconfig.ts b/src/lib/utils/options/readers/tsconfig.ts index 8f03ac967..042226119 100644 --- a/src/lib/utils/options/readers/tsconfig.ts +++ b/src/lib/utils/options/readers/tsconfig.ts @@ -1,12 +1,27 @@ -import { resolve, join } from "path"; +import { resolve, join, dirname } from "path"; import { existsSync, statSync } from "fs"; import * as ts from "typescript"; -import type { OptionsReader, Options } from "../options"; +import type { Options, OptionsReader } from "../options"; import type { Logger } from "../../loggers"; import { normalizePath } from "../../fs"; import { ok } from "assert"; +import { + additionalProperties, + Infer, + isTagString, + optional, + validate, +} from "../../validation"; +import { nicePath } from "../../paths"; +import { createRequire } from "module"; +import { + tsdocBlockTags, + tsdocInlineTags, + tsdocModifierTags, +} from "../tsdoc-defaults"; +import { unique } from "../../array"; function isFile(file: string) { return existsSync(file) && statSync(file).isFile(); @@ -16,6 +31,41 @@ function isDir(path: string) { return existsSync(path) && statSync(path).isDirectory(); } +function isSupportForTags(obj: unknown): obj is Record<`@${string}`, boolean> { + return ( + validate({}, obj) && + Object.entries(obj).every(([key, val]) => { + return ( + /^@[a-zA-Z][a-zA-Z0-9]*$/.test(key) && typeof val === "boolean" + ); + }) + ); +} + +const tsDocSchema = { + $schema: optional(String), + extends: optional([Array, String]), + noStandardTags: optional(Boolean), + tagDefinitions: optional([ + Array, + { + tagName: isTagString, + syntaxKind: ["inline", "block", "modifier"] as const, + allowMultiple: optional(Boolean), + [additionalProperties]: false, + }, + ]), + supportForTags: optional(isSupportForTags), + + // The official parser has code to support for these two, but + // the schema doesn't allow them... just silently ignore them for now. + supportedHtmlElements: optional({}), + reportUnsupportedHtmlElements: optional(Boolean), + + [additionalProperties]: false, +} as const; +type TsDocSchema = Infer; + export class TSConfigReader implements OptionsReader { /** * Note: Runs after the {@link TypeDocReader}. @@ -24,6 +74,8 @@ export class TSConfigReader implements OptionsReader { name = "tsconfig-json"; + private seenTsdocPaths = new Set(); + /** * Not considered part of the public API. You can use it, but it might break. * @internal @@ -49,27 +101,27 @@ export class TSConfigReader implements OptionsReader { if (!fileToRead) { // If the user didn't give us this option, we shouldn't complain about not being able to find it. if (container.isSet("tsconfig")) { - logger.error(`The tsconfig file ${file} does not exist`); + logger.error( + `The tsconfig file ${nicePath(file)} does not exist` + ); } return; } fileToRead = normalizePath(resolve(fileToRead)); + this.addTagsFromTsdocJson(container, logger, resolve(fileToRead)); - let fatalError = false as boolean; const parsed = ts.getParsedCommandLineOfConfigFile( fileToRead, {}, { ...ts.sys, - onUnRecoverableConfigFileDiagnostic(error) { - logger.diagnostic(error); - fatalError = true; - }, + onUnRecoverableConfigFileDiagnostic: + logger.diagnostic.bind(logger), } ); - if (!parsed || fatalError) { + if (!parsed) { return; } @@ -111,4 +163,130 @@ export class TSConfigReader implements OptionsReader { } } } + + private addTagsFromTsdocJson( + container: Options, + logger: Logger, + tsconfig: string + ) { + this.seenTsdocPaths.clear(); + const tsdoc = join(dirname(tsconfig), "tsdoc.json"); + if (!isFile(tsdoc)) { + return; + } + + const overwritten = ( + ["blockTags", "inlineTags", "modifierTags"] as const + ).filter((opt) => container.isSet(opt)); + if (overwritten.length) { + logger.warn( + `The ${overwritten.join(", ")} defined in typedoc.json will ` + + "be overwritten by configuration in tsdoc.json." + ); + } + + const config = this.readTsDoc(logger, tsdoc); + if (!config) return; + + const supported = (tag: { tagName: `@${string}` }) => { + return config.supportForTags + ? !!config.supportForTags[tag.tagName] + : true; + }; + + const blockTags: `@${string}`[] = []; + const inlineTags: `@${string}`[] = []; + const modifierTags: `@${string}`[] = []; + + if (!config.noStandardTags) { + blockTags.push(...tsdocBlockTags); + inlineTags.push(...tsdocInlineTags); + modifierTags.push(...tsdocModifierTags); + } + + for (const { tagName, syntaxKind } of config.tagDefinitions?.filter( + supported + ) || []) { + const arr = { + block: blockTags, + inline: inlineTags, + modifier: modifierTags, + }[syntaxKind]; + arr.push(tagName); + } + + container.setValue("blockTags", unique(blockTags)); + container.setValue("inlineTags", unique(inlineTags)); + container.setValue("modifierTags", unique(modifierTags)); + } + + private readTsDoc(logger: Logger, path: string): TsDocSchema | undefined { + if (this.seenTsdocPaths.has(path)) { + logger.error( + `Circular reference encountered for "extends" field of ${nicePath( + path + )}` + ); + return; + } + this.seenTsdocPaths.add(path); + + const { config, error } = ts.readConfigFile( + normalizePath(path), + ts.sys.readFile + ); + + if (error) { + logger.error( + `Failed to read tsdoc.json file at ${nicePath(path)}.` + ); + return; + } + + if (!validate(tsDocSchema, config)) { + logger.error( + `The file ${nicePath(path)} is not a valid tsdoc.json file.` + ); + return; + } + + const workingConfig: TsDocSchema = {}; + + if (config.extends) { + const resolver = createRequire(path); + for (const extendedPath of config.extends) { + let resolvedPath: string; + try { + resolvedPath = resolver.resolve(extendedPath); + } catch { + logger.error( + `Failed to resolve ${extendedPath} to a file in ${nicePath( + path + )}` + ); + return; + } + const parentConfig = this.readTsDoc(logger, resolvedPath); + + if (!parentConfig) return; + mergeConfigs(parentConfig, workingConfig); + } + } + + mergeConfigs(config, workingConfig); + return workingConfig; + } +} + +function mergeConfigs(from: TsDocSchema, into: TsDocSchema) { + if (from.supportForTags) { + into.supportForTags ||= {}; + Object.assign(into.supportForTags, from.supportForTags); + } + if (from.tagDefinitions) { + into.tagDefinitions ||= []; + into.tagDefinitions.push(...from.tagDefinitions); + } + + into.noStandardTags = from.noStandardTags ?? into.noStandardTags; } diff --git a/src/lib/utils/options/readers/typedoc.ts b/src/lib/utils/options/readers/typedoc.ts index 1d328f29d..5a3ea92af 100644 --- a/src/lib/utils/options/readers/typedoc.ts +++ b/src/lib/utils/options/readers/typedoc.ts @@ -1,10 +1,14 @@ import { join, dirname, resolve } from "path"; import * as FS from "fs"; +import * as ts from "typescript"; import type { OptionsReader } from ".."; import type { Logger } from "../../loggers"; import type { Options } from "../options"; import { ok } from "assert"; +import { nicePath } from "../../paths"; +import { normalizePath } from "../../fs"; +import { createRequire } from "module"; /** * Obtains option values from typedoc.json @@ -30,7 +34,7 @@ export class TypeDocReader implements OptionsReader { if (!file) { if (container.isSet("options")) { logger.error( - `The options file could not be found with the given path ${path}` + `The options file ${nicePath(path)} does not exist.` ); } return; @@ -54,34 +58,62 @@ export class TypeDocReader implements OptionsReader { ) { if (seen.has(file)) { logger.error( - `Tried to load the options file ${file} multiple times.` + `Tried to load the options file ${nicePath( + file + )} multiple times.` ); return; } seen.add(file); - // eslint-disable-next-line @typescript-eslint/no-var-requires - const fileContent: unknown = require(file); + let fileContent: any; + if (file.endsWith(".json")) { + const readResult = ts.readConfigFile(normalizePath(file), (path) => + FS.readFileSync(path, "utf-8") + ); + + if (readResult.error) { + logger.error( + `Failed to parse ${nicePath( + file + )}, ensure it exists and contains an object.` + ); + return; + } else { + fileContent = readResult.config; + } + } else { + // eslint-disable-next-line @typescript-eslint/no-var-requires + fileContent = require(file); + } if (typeof fileContent !== "object" || !fileContent) { - logger.error(`The file ${file} is not an object.`); + logger.error( + `The root value of ${nicePath(file)} is not an object.` + ); return; } // clone option object to avoid of property changes in re-calling this file - const data: any = { ...fileContent }; + const data = { ...fileContent }; delete data["$schema"]; // Useful for better autocompletion, should not be read as a key. if ("extends" in data) { + const resolver = createRequire(file); const extended: string[] = getStringArray(data["extends"]); for (const extendedFile of extended) { - // Extends is relative to the file it appears in. - this.readFile( - resolve(dirname(file), extendedFile), - container, - logger, - seen - ); + let resolvedParent: string; + try { + resolvedParent = resolver.resolve(extendedFile); + } catch { + logger.error( + `Failed to resolve ${extendedFile} to a file in ${nicePath( + file + )}` + ); + continue; + } + this.readFile(resolvedParent, container, logger, seen); } delete data["extends"]; } @@ -115,6 +147,8 @@ export class TypeDocReader implements OptionsReader { path, join(path, "typedoc.json"), join(path, "typedoc.js"), + join(path, ".config/typedoc.js"), + join(path, ".config/typedoc.json"), ].find((path) => FS.existsSync(path) && FS.statSync(path).isFile()); } } diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index e62192f5c..012de760d 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -1,12 +1,24 @@ import type { Options } from ".."; import { LogLevel } from "../../loggers"; -import { ParameterType, ParameterHint, EmitStrategy } from "../declaration"; +import { + ParameterType, + ParameterHint, + EmitStrategy, + CommentStyle, +} from "../declaration"; import { BUNDLED_THEMES, Theme } from "shiki"; import { SORT_STRATEGIES } from "../../sort"; import { EntryPointStrategy } from "../../entry-point"; import { ReflectionKind } from "../../../models/reflections/kind"; +import * as Validation from "../../validation"; +import { blockTags, inlineTags, modifierTags } from "../tsdoc-defaults"; +// For convenience, added in the same order as they are documented on the website. export function addTypeDocOptions(options: Pick) { + /////////////////////////// + // Configuration Options // + /////////////////////////// + options.addDeclaration({ type: ParameterType.Path, name: "options", @@ -21,10 +33,27 @@ export function addTypeDocOptions(options: Pick) { hint: ParameterHint.File, defaultValue: process.cwd(), }); + options.addDeclaration({ + name: "compilerOptions", + help: "Selectively override the TypeScript compiler options used by TypeDoc.", + type: ParameterType.Mixed, + validate(value) { + if (!Validation.validate({}, value)) { + throw new Error( + "The 'compilerOptions' option must be a non-array object." + ); + } + }, + }); + + /////////////////////////// + ////// Input Options ////// + /////////////////////////// + options.addDeclaration({ name: "entryPoints", help: "The entry points of your documentation.", - type: ParameterType.PathArray, + type: ParameterType.GlobArray, }); options.addDeclaration({ name: "entryPointStrategy", @@ -71,90 +100,21 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Boolean, }); options.addDeclaration({ - name: "searchCategoryBoosts", - help: "Configure search to give a relevance boost to selected categories", - type: ParameterType.Mixed, - validate(value) { - if (!isObject(value)) { - throw new Error( - "The 'searchCategoryBoosts' option must be a non-array object." - ); - } - - if (Object.values(value).some((x) => typeof x !== "number")) { - throw new Error( - "All values of 'searchCategoryBoosts' must be numbers." - ); - } - }, - }); - options.addDeclaration({ - name: "searchGroupBoosts", - help: 'Configure search to give a relevance boost to selected kinds (eg "class")', - type: ParameterType.Mixed, - validate(value: unknown) { - if (!isObject(value)) { - throw new Error( - "The 'searchGroupBoosts' option must be a non-array object." - ); - } - - const validValues = Object.values(ReflectionKind) - .filter((v) => typeof v === "string") - .map((v) => v.toString()); - - for (const kindName in value) { - if (validValues.indexOf(kindName) < 0) { - throw new Error( - `'${kindName}' is an invalid value for 'searchGroupBoosts'. Must be one of: ${validValues.join( - ", " - )}` - ); - } - } - - if (Object.values(value).some((x) => typeof x !== "number")) { - throw new Error( - "All values of 'searchGroupBoosts' must be numbers." - ); - } - }, - }); - options.addDeclaration({ - name: "disableSources", - help: "Disable setting the source of a reflection when documenting it.", - type: ParameterType.Boolean, - }); - options.addDeclaration({ - name: "includes", - help: "Specify the location to look for included documents (use [[include:FILENAME]] in comments).", + name: "media", + help: "Specify the location with media files that should be copied to the output directory.", type: ParameterType.Path, hint: ParameterHint.Directory, }); options.addDeclaration({ - name: "media", - help: "Specify the location with media files that should be copied to the output directory.", + name: "includes", + help: "Specify the location to look for included documents (use [[include:FILENAME]] in comments).", type: ParameterType.Path, hint: ParameterHint.Directory, }); - options.addDeclaration({ - name: "watch", - help: "Watch files for changes and rebuild docs on change.", - type: ParameterType.Boolean, - }); - options.addDeclaration({ - name: "preserveWatchOutput", - help: "If set, TypeDoc will not clear the screen between compilation runs.", - type: ParameterType.Boolean, - }); - options.addDeclaration({ - name: "emit", - help: "Specify what TypeDoc should emit, 'docs', 'both', or 'none'.", - type: ParameterType.Map, - map: EmitStrategy, - defaultValue: "docs", - }); + /////////////////////////// + ///// Output Options ////// + /////////////////////////// options.addDeclaration({ name: "out", @@ -174,12 +134,16 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Boolean, defaultValue: true, }); - + options.addDeclaration({ + name: "emit", + help: "Specify what TypeDoc should emit, 'docs', 'both', or 'none'.", + type: ParameterType.Map, + map: EmitStrategy, + defaultValue: "docs", + }); options.addDeclaration({ name: "theme", - help: - "Specify the path to the theme that should be used, or 'default' or 'minimal' to use built-in themes. " + - "Note: Not resolved according to the config file location, always resolved according to cwd.", + help: "Specify the theme name to render the documentation with", type: ParameterType.String, defaultValue: "default", }); @@ -223,7 +187,18 @@ export function addTypeDocOptions(options: Pick) { help: "Path to a custom CSS file to for the theme to import.", type: ParameterType.Path, }); - + options.addDeclaration({ + name: "markedOptions", + help: "Specify the options passed to Marked, the Markdown parser used by TypeDoc.", + type: ParameterType.Mixed, + validate(value) { + if (!Validation.validate({}, value)) { + throw new Error( + "The 'markedOptions' option must be a non-array object." + ); + } + }, + }); options.addDeclaration({ name: "name", help: "Set the name of the project that will be used in the header of the template.", @@ -233,10 +208,23 @@ export function addTypeDocOptions(options: Pick) { help: "Add the package version to the project name.", type: ParameterType.Boolean, }); + options.addDeclaration({ + name: "disableSources", + help: "Disable setting the source of a reflection when documenting it.", + type: ParameterType.Boolean, + }); options.addDeclaration({ name: "excludeTags", - help: "Remove the listed tags from doc comments.", + help: "Remove the listed block/modifier tags from doc comments.", type: ParameterType.Array, + defaultValue: ["@override", "@virtual", "@privateRemarks"], + validate(value) { + if (!Validation.validate([Array, Validation.isTagString], value)) { + throw new Error( + `excludeTags must be an array of valid tag names.` + ); + } + }, }); options.addDeclaration({ name: "readme", @@ -244,15 +232,96 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Path, }); options.addDeclaration({ - name: "defaultCategory", - help: "Specify the default category for reflections without a category.", - defaultValue: "Other", + name: "cname", + help: "Set the CNAME file text, it's useful for custom domains on GitHub Pages.", }); options.addDeclaration({ - name: "categoryOrder", - help: "Specify the order in which categories appear. * indicates the relative order for categories not in the list.", + name: "gitRevision", + help: "Use specified revision instead of the last revision for linking to GitHub/Bitbucket source files.", + }); + options.addDeclaration({ + name: "gitRemote", + help: "Use the specified remote for linking to GitHub/Bitbucket source files.", + defaultValue: "origin", + }); + options.addDeclaration({ + name: "githubPages", + help: "Generate a .nojekyll file to prevent 404 errors in GitHub Pages. Defaults to `true`.", + type: ParameterType.Boolean, + defaultValue: true, + }); + options.addDeclaration({ + name: "gaID", + help: "Set the Google Analytics tracking ID and activate tracking code.", + }); + options.addDeclaration({ + name: "hideGenerator", + help: "Do not print the TypeDoc link at the end of the page.", + type: ParameterType.Boolean, + }); + options.addDeclaration({ + name: "cleanOutputDir", + help: "If set, TypeDoc will remove the output directory before writing output.", + type: ParameterType.Boolean, + defaultValue: true, + }); + + /////////////////////////// + ///// Comment Options ///// + /////////////////////////// + + options.addDeclaration({ + name: "commentStyle", + help: "Determines how TypeDoc searches for comments.", + type: ParameterType.Map, + map: CommentStyle, + defaultValue: CommentStyle.JSDoc, + }); + + options.addDeclaration({ + name: "blockTags", + help: "Block tags which TypeDoc should recognize when parsing comments.", + type: ParameterType.Array, + defaultValue: blockTags, + validate(value) { + if (!Validation.validate([Array, Validation.isTagString], value)) { + throw new Error( + `blockTags must be an array of valid tag names.` + ); + } + }, + }); + options.addDeclaration({ + name: "inlineTags", + help: "Inline tags which TypeDoc should recognize when parsing comments.", type: ParameterType.Array, + defaultValue: inlineTags, + validate(value) { + if (!Validation.validate([Array, Validation.isTagString], value)) { + throw new Error( + `inlineTags must be an array of valid tag names.` + ); + } + }, }); + options.addDeclaration({ + name: "modifierTags", + help: "Modifier tags which TypeDoc should recognize when parsing comments.", + type: ParameterType.Array, + defaultValue: modifierTags, + validate(value) { + if (!Validation.validate([Array, Validation.isTagString], value)) { + throw new Error( + `modifierTags must be an array of valid tag names.` + ); + } + }, + }); + + /////////////////////////// + // Organization Options /// + /////////////////////////// + options.addDeclaration({ name: "categorizeByGroup", help: "Specify whether categorization will be done at the group level.", @@ -260,8 +329,14 @@ export function addTypeDocOptions(options: Pick) { defaultValue: true, }); options.addDeclaration({ - name: "cname", - help: "Set the CNAME file text, it's useful for custom domains on GitHub Pages.", + name: "defaultCategory", + help: "Specify the default category for reflections without a category.", + defaultValue: "Other", + }); + options.addDeclaration({ + name: "categoryOrder", + help: "Specify the order in which categories appear. * indicates the relative order for categories not in the list.", + type: ParameterType.Array, }); options.addDeclaration({ name: "sort", @@ -288,44 +363,91 @@ export function addTypeDocOptions(options: Pick) { }, }); options.addDeclaration({ - name: "gitRevision", - help: "Use specified revision instead of the last revision for linking to GitHub/Bitbucket source files.", - }); - options.addDeclaration({ - name: "gitRemote", - help: "Use the specified remote for linking to GitHub/Bitbucket source files.", - defaultValue: "origin", - }); - options.addDeclaration({ - name: "gaID", - help: "Set the Google Analytics tracking ID and activate tracking code.", - }); - options.addDeclaration({ - name: "gaSite", - help: "Set the site name for Google Analytics. Defaults to `auto`.", - defaultValue: "auto", + name: "visibilityFilters", + help: "Specify the default visibility for builtin filters and additional filters according to modifier tags.", + type: ParameterType.Mixed, + defaultValue: { + protected: false, + private: false, + inherited: true, + external: false, + }, + validate(value) { + const knownKeys = ["protected", "private", "inherited", "external"]; + if (!value || typeof value !== "object") { + throw new Error("visibilityFilters must be an object."); + } + + for (const [key, val] of Object.entries(value)) { + if (!key.startsWith("@") && !knownKeys.includes(key)) { + throw new Error( + `visibilityFilters can only include the following non-@ keys: ${knownKeys.join( + ", " + )}` + ); + } + + if (typeof val !== "boolean") { + throw new Error( + `All values of visibilityFilters must be booleans.` + ); + } + } + }, }); + options.addDeclaration({ - name: "githubPages", - help: "Generate a .nojekyll file to prevent 404 errors in GitHub Pages. Defaults to `true`.", - type: ParameterType.Boolean, - defaultValue: true, + name: "searchCategoryBoosts", + help: "Configure search to give a relevance boost to selected categories", + type: ParameterType.Mixed, + defaultValue: {}, + validate(value) { + if (!isObject(value)) { + throw new Error( + "The 'searchCategoryBoosts' option must be a non-array object." + ); + } + + if (Object.values(value).some((x) => typeof x !== "number")) { + throw new Error( + "All values of 'searchCategoryBoosts' must be numbers." + ); + } + }, }); options.addDeclaration({ - name: "hideGenerator", - help: "Do not print the TypeDoc link at the end of the page.", - type: ParameterType.Boolean, + name: "searchGroupBoosts", + help: 'Configure search to give a relevance boost to selected kinds (eg "class")', + type: ParameterType.Mixed, + defaultValue: {}, + validate(value: unknown) { + if (!isObject(value)) { + throw new Error( + "The 'searchGroupBoosts' option must be a non-array object." + ); + } + + if (Object.values(value).some((x) => typeof x !== "number")) { + throw new Error( + "All values of 'searchGroupBoosts' must be numbers." + ); + } + }, }); + + /////////////////////////// + ///// General Options ///// + /////////////////////////// + options.addDeclaration({ - name: "hideLegend", - help: "Do not print the Legend for icons at the end of the page.", + name: "watch", + help: "Watch files for changes and rebuild docs on change.", type: ParameterType.Boolean, }); options.addDeclaration({ - name: "cleanOutputDir", - help: "If set, TypeDoc will remove the output directory before writing output.", + name: "preserveWatchOutput", + help: "If set, TypeDoc will not clear the screen between compilation runs.", type: ParameterType.Boolean, - defaultValue: true, }); options.addDeclaration({ @@ -361,41 +483,12 @@ export function addTypeDocOptions(options: Pick) { map: LogLevel, defaultValue: LogLevel.Info, }); - options.addDeclaration({ - name: "markedOptions", - help: "Specify the options passed to Marked, the Markdown parser used by TypeDoc.", - type: ParameterType.Mixed, - validate(value) { - if (!isObject(value)) { - throw new Error( - "The 'markedOptions' option must be a non-array object." - ); - } - }, - }); - options.addDeclaration({ - name: "compilerOptions", - help: "Selectively override the TypeScript compiler options used by TypeDoc.", - type: ParameterType.Mixed, - validate(value) { - if (!isObject(value)) { - throw new Error( - "The 'compilerOptions' option must be a non-array object." - ); - } - }, - }); options.addDeclaration({ name: "treatWarningsAsErrors", help: "If set, warnings will be treated as errors.", type: ParameterType.Boolean, }); - options.addDeclaration({ - name: "listInvalidSymbolLinks", - help: "Emit a list of broken symbol {@link navigation} links after documentation generation, DEPRECATED, prefer validation.invalidLink instead.", - type: ParameterType.Boolean, - }); options.addDeclaration({ name: "intentionallyNotExported", help: "A list of types which should not produce 'referenced but not documented' warnings.", @@ -441,7 +534,7 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Flags, defaults: { notExported: true, - invalidLink: false, + invalidLink: true, notDocumented: false, }, }); diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts new file mode 100644 index 000000000..3cb561b7f --- /dev/null +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -0,0 +1,55 @@ +// If updating these lists, also see .config/typedoc-default.tsdoc.json + +export const tsdocBlockTags = [ + "@deprecated", + "@param", + "@remarks", + "@returns", + "@throws", + "@privateRemarks", + "@defaultValue", + "@typeParam", +] as const; + +export const blockTags = [ + ...tsdocBlockTags, + "@module", + "@inheritDoc", + "@group", + "@category", + // Alias for @typeParam + "@template", + // Because TypeScript is important! + "@type", + "@typedef", + "@callback", + "@prop", + "@property", +] as const; + +export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; +export const inlineTags = [...tsdocInlineTags, "@linkcode", "@linkplain"]; + +export const tsdocModifierTags = [ + "@public", + "@private", + "@protected", + "@internal", + "@readonly", + "@packageDocumentation", + "@eventProperty", + "@alpha", + "@beta", + "@experimental", + "@sealed", + "@override", + "@virtual", +] as const; + +export const modifierTags = [ + ...tsdocModifierTags, + "@hidden", + "@ignore", + "@enum", + "@event", +] as const; diff --git a/src/lib/utils/package-manifest.ts b/src/lib/utils/package-manifest.ts index 467d8aaeb..e19d87e47 100644 --- a/src/lib/utils/package-manifest.ts +++ b/src/lib/utils/package-manifest.ts @@ -1,11 +1,9 @@ // Utilities to support the inspection of node package "manifests" -import glob = require("glob"); import { dirname, join, resolve } from "path"; import { existsSync } from "fs"; -import { flatMap } from "./array"; -import { normalizePath, readFile } from "./fs"; +import { readFile, glob } from "./fs"; import type { Logger } from "./loggers"; /** @@ -66,19 +64,6 @@ function getPackagePaths( return undefined; } -/** - * Should produce the same results as the equivalent code in Yarn - * https://github.com/yarnpkg/yarn/blob/a4708b29ac74df97bac45365cba4f1d62537ceb7/src/config.js#L799 - */ -function globPackages(workspacePath: string, packageJsonDir: string): string[] { - return glob.sync( - normalizePath(resolve(packageJsonDir, workspacePath, "package.json")), - { - ignore: resolve(packageJsonDir, workspacePath, "node_modules"), - } - ); -} - /** * Given a list of (potentially wildcarded) package paths, * return all the actual package folders found. @@ -93,9 +78,12 @@ export function expandPackages( // to the root of a workspace tree in our params and so we could here // be dealing with either a root or a leaf. So let's do this recursively, // as it actually is simpler from an implementation perspective anyway. - return flatMap(workspaces, (workspace) => { - const globbedPackageJsonPaths = globPackages(workspace, packageJsonDir); - return flatMap(globbedPackageJsonPaths, (packageJsonPath) => { + return workspaces.flatMap((workspace) => { + const globbedPackageJsonPaths = glob( + resolve(packageJsonDir, workspace, "package.json"), + resolve(packageJsonDir) + ); + return globbedPackageJsonPaths.flatMap((packageJsonPath) => { const packageJson = loadPackageManifest(logger, packageJsonPath); if (packageJson === undefined) { logger.error(`Failed to load ${packageJsonPath}`); @@ -145,7 +133,7 @@ function getTsSourceFromJsSource( resolvedSourceMapURL = jsPath; sourceMap = JSON.parse( Buffer.from( - sourceMapURL.substr(sourceMapURL.indexOf(",") + 1), + sourceMapURL.substring(sourceMapURL.indexOf(",") + 1), "base64" ).toString() ); @@ -237,7 +225,10 @@ export function getTsEntryPointForPackage( // Pass an empty `paths` as node_modules locations do not need to be examined try { entryPointPath = require.resolve(entryPointPath, { paths: [] }); - if (/\.tsx?$/.test(entryPointPath) && existsSync(entryPointPath)) { + if ( + /\.([cm]ts|tsx?)$/.test(entryPointPath) && + existsSync(entryPointPath) + ) { return entryPointPath; } } catch (e: any) { @@ -249,7 +240,10 @@ export function getTsEntryPointForPackage( "..", packageTypes ?? packageMain ); - if (/\.tsx?$/.test(entryPointPath) && existsSync(entryPointPath)) { + if ( + /\.([cm][tj]s|tsx?)$/.test(entryPointPath) && + existsSync(entryPointPath) + ) { return entryPointPath; } else { logger.warn( diff --git a/src/lib/utils/perf.ts b/src/lib/utils/perf.ts new file mode 100644 index 000000000..4a050ec94 --- /dev/null +++ b/src/lib/utils/perf.ts @@ -0,0 +1,70 @@ +/* eslint-disable no-console */ + +import { performance } from "perf_hooks"; + +const benchmarks: { name: string; calls: number; time: number }[] = []; + +export function bench(fn: T, name = fn.name): T { + const timer = { + name, + calls: 0, + time: 0, + }; + benchmarks.push(timer); + + return function bench(this: any, ...args: any) { + timer.calls++; + const start = performance.now(); + let result: any; + try { + result = fn.apply(this, args); + } finally { + timer.time += performance.now() - start; + } + return result; + } as any; +} + +export function Bench(): MethodDecorator { + return function (target: any, key, descriptor) { + const rawMethod = descriptor.value as unknown as Function; + const name = `${target.name ?? target.constructor.name}.${String(key)}`; + descriptor.value = bench(rawMethod, name) as any; + }; +} + +const anon = { name: "measure()", calls: 0, time: 0 }; +export function measure(cb: () => T): T { + if (anon.calls === 0) { + benchmarks.unshift(anon); + } + + anon.calls++; + const start = performance.now(); + let result: T; + try { + result = cb(); + } finally { + anon.time += performance.now() - start; + } + return result; +} + +process.on("beforeExit", () => { + if (!benchmarks.length) return; + + const width = benchmarks.reduce((a, b) => Math.max(a, b.name.length), 11); + console.log("=".repeat(width + 20)); + console.log(`${"Benchmarked".padEnd(width)} | Calls | Time`); + console.log("=".repeat(width + 20)); + + for (const { name, calls, time } of benchmarks) { + console.log( + `${name.padEnd(width)} | ${calls + .toString() + .padEnd(5)} | ${time.toFixed(2)}ms` + ); + } + + console.log("=".repeat(width + 20)); +}); diff --git a/src/lib/utils/plugins.ts b/src/lib/utils/plugins.ts index df3cfe6f4..e7ebf8a64 100644 --- a/src/lib/utils/plugins.ts +++ b/src/lib/utils/plugins.ts @@ -131,7 +131,7 @@ function isPlugin(info: any): boolean { function getPluginDisplayName(plugin: string) { const path = nicePath(plugin); if (path.startsWith("./node_modules/")) { - return path.substr("./node_modules/".length); + return path.substring("./node_modules/".length); } return plugin; } diff --git a/src/lib/utils/sort.ts b/src/lib/utils/sort.ts index d012a137f..650ea6193 100644 --- a/src/lib/utils/sort.ts +++ b/src/lib/utils/sort.ts @@ -120,7 +120,6 @@ const sorts: Record< ReflectionKind.TypeAlias, ReflectionKind.Constructor, - ReflectionKind.Event, ReflectionKind.Property, ReflectionKind.Variable, ReflectionKind.Function, diff --git a/src/lib/utils/validation.ts b/src/lib/utils/validation.ts new file mode 100644 index 000000000..9c060185a --- /dev/null +++ b/src/lib/utils/validation.ts @@ -0,0 +1,130 @@ +export type Infer = T extends Optional + ? Infer + : T extends Guard + ? U + : T extends typeof String + ? string + : T extends typeof Number + ? number + : T extends typeof Boolean + ? boolean + : T extends readonly string[] + ? T[number] + : T extends readonly [typeof Array, Schema] + ? Array> + : { + -readonly [K in OptionalKeys]?: Infer< + Extract + >; + } & { + -readonly [K in Exclude< + keyof T, + OptionalKeys | typeof additionalProperties + >]: Infer>; + }; + +export type Optional = Record; +export type Guard = (x: unknown) => x is T; + +type OptionalKeys = keyof { + [K in keyof T as T[K] extends Optional ? K : never]: 1; +}; + +const opt = Symbol(); + +/** + * Symbol that may be placed on a schema object to define how additional properties are handled. + * By default, additional properties are not checked. + */ +export const additionalProperties = Symbol(); + +export type Schema = + | typeof String + | typeof Number + | typeof Boolean + | readonly string[] + | readonly [typeof Array, Schema] + | { readonly [k: string]: Schema; [additionalProperties]?: boolean } + | Guard + | Optional + | Optional + | Optional + | Optional + | Optional + | Optional<{ + readonly [k: string]: Schema; + [additionalProperties]?: boolean; + }> + | Optional>; + +/** + * Straightforward, fairly dumb, validation helper. + * @param schema + * @param obj + */ +export function validate( + schema: T, + obj: unknown +): obj is Infer; +export function validate(schema: Schema, obj: any): boolean { + let type: any = schema; + if (opt in schema) { + if (obj == null) { + return true; + } + type = (schema as Optional)[opt]; + } + + if (type === String) { + return typeof obj === "string"; + } + + if (type === Number) { + return typeof obj === "number"; + } + + if (type === Boolean) { + return typeof obj === "boolean"; + } + + if (typeof type === "function") { + return type(obj); + } + + if (Array.isArray(type)) { + if (type[0] === Array) { + return ( + Array.isArray(obj) && + obj.every((item) => validate(type[1], item)) + ); + } + + return type.includes(obj); + } + + if ( + additionalProperties in schema && + !(schema as any)[additionalProperties] + ) { + if (Object.keys(obj).some((key) => !(key in schema))) { + return false; + } + } + + return ( + !!obj && + typeof obj === "object" && + !Array.isArray(obj) && + Object.entries(type).every(([key, prop]) => + validate(prop, obj[key]) + ) + ); +} + +export function optional(x: T): Optional { + return { [opt]: x }; +} + +export function isTagString(x: unknown): x is `@${string}` { + return typeof x === "string" && /^@[a-zA-Z][a-zA-Z0-9]*$/.test(x); +} diff --git a/src/lib/validation/exports.ts b/src/lib/validation/exports.ts index 947285a51..9d05a3131 100644 --- a/src/lib/validation/exports.ts +++ b/src/lib/validation/exports.ts @@ -1,4 +1,3 @@ -import { relative } from "path"; import * as ts from "typescript"; import { ContainerReflection, @@ -10,7 +9,7 @@ import { SignatureReflection, TypeParameterReflection, } from "../models"; -import { Logger, normalizePath } from "../utils"; +import type { Logger } from "../utils"; function makeIntentionallyExportedHelper( intentional: readonly string[], @@ -96,18 +95,12 @@ export function validateExports( ) { warned.add(symbol); const decl = symbol.declarations![0]; - const { line } = ts.getLineAndCharacterOfPosition( - decl.getSourceFile(), - decl.getStart() - ); - const file = normalizePath( - relative(process.cwd(), decl.getSourceFile().fileName) - ); logger.warn( - `${type.name}, defined at ${file}:${ - line + 1 - }, is referenced by ${current!.getFullName()} but not included in the documentation.` + `${ + type.name + } is referenced by ${current!.getFullName()} but not included in the documentation.`, + decl ); } } diff --git a/src/lib/validation/links.ts b/src/lib/validation/links.ts new file mode 100644 index 000000000..740aaae42 --- /dev/null +++ b/src/lib/validation/links.ts @@ -0,0 +1,36 @@ +import type { Comment, CommentDisplayPart, ProjectReflection } from "../models"; +import type { Logger } from "../utils"; + +const linkTags = ["@link", "@linkcode", "@linkplain"]; + +function getBrokenLinks(comment: Comment | undefined) { + const links: string[] = []; + + function processPart(part: CommentDisplayPart) { + if ( + part.kind === "inline-tag" && + linkTags.includes(part.tag) && + !part.target + ) { + links.push(part.text); + } + } + + comment?.summary.forEach(processPart); + comment?.blockTags.forEach((tag) => tag.content.forEach(processPart)); + + return links; +} + +export function validateLinks( + project: ProjectReflection, + logger: Logger +): void { + for (const reflection of Object.values(project.reflections)) { + for (const broken of getBrokenLinks(reflection.comment)) { + logger.warn( + `Failed to resolve link to "${broken}" in comment for ${reflection.getFullName()}` + ); + } + } +} diff --git a/src/test/SourceLinkPlugin.test.ts b/src/test/Repository.test.ts similarity index 98% rename from src/test/SourceLinkPlugin.test.ts rename to src/test/Repository.test.ts index 6834288d1..d1e2067dc 100644 --- a/src/test/SourceLinkPlugin.test.ts +++ b/src/test/Repository.test.ts @@ -1,4 +1,4 @@ -import { Repository } from "../lib/converter/plugins/SourceLinkPlugin"; +import { Repository } from "../lib/converter/utils/repository"; import { RepositoryType } from "../lib/models"; import { strictEqual as equal } from "assert"; diff --git a/src/test/TestLogger.ts b/src/test/TestLogger.ts index aa62239b5..18134e28d 100644 --- a/src/test/TestLogger.ts +++ b/src/test/TestLogger.ts @@ -1,5 +1,7 @@ import { Logger, LogLevel, removeIf } from "../lib/utils"; import { deepStrictEqual as equal, fail } from "assert"; +import * as ts from "typescript"; +import { resolve } from "path"; const levelMap: Record = { [LogLevel.Error]: "error: ", @@ -11,12 +13,19 @@ const levelMap: Record = { export class TestLogger extends Logger { messages: string[] = []; + reset() { + this.resetErrors(); + this.resetWarnings(); + this.messages = []; + } + discardDebugMessages() { removeIf(this.messages, (msg) => msg.startsWith("debug")); } expectMessage(message: string) { - const index = this.messages.indexOf(message); + const regex = createRegex(message); + const index = this.messages.findIndex((m) => regex.test(m)); if (index === -1) { const messages = this.messages.join("\n\t") || "(none logged)"; fail( @@ -30,8 +39,37 @@ export class TestLogger extends Logger { equal(this.messages, [], "Expected no other messages to be logged."); } + override diagnostic(diagnostic: ts.Diagnostic): void { + const output = ts.formatDiagnostic(diagnostic, { + getCanonicalFileName: resolve, + getCurrentDirectory: () => process.cwd(), + getNewLine: () => ts.sys.newLine, + }); + + switch (diagnostic.category) { + case ts.DiagnosticCategory.Error: + this.log(output, LogLevel.Error); + break; + case ts.DiagnosticCategory.Warning: + this.log(output, LogLevel.Warn); + break; + case ts.DiagnosticCategory.Message: + this.log(output, LogLevel.Info); + } + } + override log(message: string, level: LogLevel): void { super.log(message, level); this.messages.push(levelMap[level] + message); } } + +function createRegex(s: string) { + return new RegExp( + [ + "^", + s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[\\s\\S]*"), + "$", + ].join("") + ); +} diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index bc005bffe..a70e5c27a 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -1,10 +1,19 @@ import { deepStrictEqual as equal, ok } from "assert"; +import type { Application } from "../lib/application"; import { DeclarationReflection, LiteralType, ProjectReflection, ReflectionKind, + Comment, + CommentDisplayPart, + CommentTag, + Reflection, + SignatureReflection, } from "../lib/models"; +import { Chars, filterMap } from "../lib/utils"; +import { CommentStyle } from "../lib/utils/options/declaration"; +import type { TestLogger } from "./TestLogger"; function query(project: ProjectReflection, name: string) { const reflection = project.getChildByName(name); @@ -12,10 +21,15 @@ function query(project: ProjectReflection, name: string) { return reflection; } -export const behaviorTests: Record< - string, - (project: ProjectReflection) => void -> = { +type Letters = Chars<"abcdefghijklmnopqrstuvwxyz">; + +export const behaviorTests: { + [issue: `_${string}`]: (app: Application) => void; + [issue: `${Letters}${string}`]: ( + project: ProjectReflection, + logger: TestLogger + ) => void; +} = { asConstEnum(project) { const SomeEnumLike = query(project, "SomeEnumLike"); equal(SomeEnumLike.kind, ReflectionKind.Variable, "SomeEnumLike"); @@ -27,7 +41,7 @@ export const behaviorTests: Record< ); const A = query(project, "SomeEnumLikeTagged.a"); equal(A.type, new LiteralType("a")); - equal(A.defaultValue, '"a"'); + equal(A.defaultValue, undefined); const ManualEnum = query(project, "ManualEnum"); equal(ManualEnum.kind, ReflectionKind.Enum, "ManualEnum"); @@ -59,7 +73,7 @@ export const behaviorTests: Record< ); const B = query(project, "SomeEnumLikeTaggedNumeric.b"); equal(B.type, new LiteralType(1)); - equal(B.defaultValue, "1"); + equal(B.defaultValue, undefined); const ManualEnumNumeric = query(project, "ManualEnumNumeric"); equal(ManualEnumNumeric.kind, ReflectionKind.Enum, "ManualEnumNumeric"); @@ -99,6 +113,20 @@ export const behaviorTests: Record< ); }, + _blockComment(app) { + app.options.setValue("commentStyle", CommentStyle.Block); + }, + blockComment(project) { + const a = query(project, "a"); + const b = query(project, "b"); + + equal(Comment.combineDisplayParts(a.comment?.summary), "jsdoc block"); + equal( + Comment.combineDisplayParts(b.comment?.summary), + "block, but not jsdoc" + ); + }, + declareGlobal(project) { equal( project.children?.map((c) => c.name), @@ -106,6 +134,31 @@ export const behaviorTests: Record< ); }, + deprecatedBracketLinks(project, logger) { + const a = query(project, "alpha"); + const b = query(project, "beta"); + + const aTag = a.comment?.summary.find((p) => p.kind === "inline-tag") as + | Extract + | undefined; + equal(aTag?.tag, "@link"); + equal(aTag?.text, "beta"); + equal(aTag.target, b); + logger.expectMessage( + "warn: alpha: Comment [[target]] style links are deprecated and will be removed in 0.24" + ); + + const bTag = b.comment?.summary.find((p) => p.kind === "inline-tag") as + | Extract + | undefined; + equal(bTag?.tag, "@link"); + equal(bTag?.text, "bracket links"); + equal(bTag.target, a); + logger.expectMessage( + "warn: beta: Comment [[target]] style links are deprecated and will be removed in 0.24" + ); + }, + duplicateHeritageClauses(project) { const b = query(project, "B"); equal(b.extendedTypes?.map(String), ["A"]); @@ -121,26 +174,334 @@ export const behaviorTests: Record< ]); }, - instantiationExpressions(project) { - const ss = query(project, "StringSet"); - equal(ss.kind, ReflectionKind.Variable); + exampleTags(project) { + const foo = query(project, "foo"); + const tags = foo.comment?.blockTags.map((tag) => tag.content); + + equal(tags, [ + [{ kind: "code", text: "```ts\n// JSDoc style\ncodeHere();\n```" }], + [ + { kind: "text", text: "JSDoc specialness\n" }, + { + kind: "code", + text: "```ts\n// JSDoc style\ncodeHere();\n```", + }, + ], + [{ kind: "code", text: "```ts\n// TSDoc style\ncodeHere();\n```" }], + ]); }, - overloads(project) { + exportComments(project) { + const abc = query(project, "abc"); + equal(abc.kind, ReflectionKind.Variable); + equal(Comment.combineDisplayParts(abc.comment?.summary), "abc"); + + const abcRef = query(project, "abcRef"); + equal(abcRef.kind, ReflectionKind.Reference); + equal( + Comment.combineDisplayParts(abcRef.comment?.summary), + "export abc" + ); + const foo = query(project, "foo"); - equal(foo.signatures?.length, 2); + equal(Comment.combineDisplayParts(foo.comment?.summary), "export foo"); + }, + + groupTag(project) { + const A = query(project, "A"); + const B = query(project, "B"); + const C = query(project, "C"); + + equal( + project.groups?.map((g) => g.title), + ["A", "B", "With Spaces"] + ); + + equal( + project.groups.map((g) => g.children), + [[A, B], [B], [C]] + ); + }, + + inheritDocBasic(project) { + const target = query(project, "InterfaceTarget"); + const comment = new Comment( + [{ kind: "text", text: "Summary" }], + [new CommentTag("@remarks", [{ kind: "text", text: "Remarks" }])] + ); + equal(target.comment, comment); + + equal( + Comment.combineDisplayParts( + target.typeParameters?.[0].comment?.summary + ), + "Type parameter" + ); + + const prop = query(project, "InterfaceTarget.property"); + equal( + Comment.combineDisplayParts(prop.comment?.summary), + "Property description" + ); + + const meth = query(project, "InterfaceTarget.someMethod"); + const methodComment = new Comment( + [{ kind: "text", text: "Method description" }], + [ + new CommentTag("@example", [ + { kind: "text", text: "This should still be present\n" }, + { kind: "code", text: "```ts\nsomeMethod(123)\n```" }, + ]), + ] + ); + equal(meth.signatures?.[0].comment, methodComment); + }, + + inheritDocJsdoc(project) { + const fooComment = query(project, "Foo").comment; + const fooMemberComment = query(project, "Foo.member").signatures?.[0] + .comment; + const xComment = query(project, "Foo.member").signatures?.[0] + .parameters?.[0].comment; + + ok(fooComment, "Foo"); + ok(fooMemberComment, "Foo.member"); + ok(xComment, "Foo.member.x"); + + for (const name of ["Bar", "Baz"]) { + equal(query(project, name).comment, fooComment, name); + } + + for (const name of ["Bar.member", "Baz.member"]) { + const refl = query(project, name); + equal(refl.signatures?.length, 1, name); + + equal( + refl.signatures[0].comment, + fooMemberComment, + `${name} signature` + ); + equal( + refl.signatures[0].parameters?.[0].comment, + xComment, + `${name} parameter` + ); + } + }, + + inheritDocRecursive(project, logger) { + const a = query(project, "A"); + equal(a.comment?.getTag("@inheritDoc")?.name, "B"); + + const b = query(project, "B"); + equal(b.comment?.getTag("@inheritDoc")?.name, "C"); + + const c = query(project, "C"); + equal(c.comment?.getTag("@inheritDoc")?.name, "A"); + + logger.expectMessage( + "warn: @inheritDoc specifies a circular inheritance chain: B -> C -> A -> B" + ); + }, + + inheritDocWarnings(project, logger) { + const target1 = query(project, "target1"); + equal(Comment.combineDisplayParts(target1.comment?.summary), "Source"); + equal( + Comment.combineDisplayParts( + target1.comment?.getTag("@remarks")?.content + ), + "Remarks" + ); + logger.expectMessage( + "warn: Content in the summary section will be overwritten by the @inheritDoc tag in comment at ./src/test/converter2/behavior/inheritDocWarnings.ts:9." + ); + + const target2 = query(project, "target2"); + equal(Comment.combineDisplayParts(target2.comment?.summary), "Source"); + equal( + Comment.combineDisplayParts( + target2.comment?.getTag("@remarks")?.content + ), + "Remarks" + ); + logger.expectMessage( + "warn: Content in the @remarks block will be overwritten by the @inheritDoc tag in comment at ./src/test/converter2/behavior/inheritDocWarnings.ts:15." + ); + + const target3 = query(project, "target3"); + ok(target3.comment?.getTag("@inheritDoc")); + logger.expectMessage( + 'warn: Failed to find "doesNotExist" to inherit the comment from in the comment for target3' + ); + + const target4 = query(project, "target4"); + ok(target4.comment?.getTag("@inheritDoc")); + logger.expectMessage( + "warn: target4 tried to copy a comment from source2 with @inheritDoc, but the source has no associated comment." + ); + + logger.expectMessage( + "warn: Declaration reference in @inheritDoc for badParse was not fully parsed and may resolve incorrectly." + ); + + logger.discardDebugMessages(); + logger.expectNoOtherMessages(); + }, + + _lineComment(app) { + app.options.setValue("commentStyle", CommentStyle.Line); + }, + lineComment(project) { + const a = query(project, "a"); + const b = query(project, "b"); + const c = query(project, "c"); + + equal(Comment.combineDisplayParts(a.comment?.summary), "docs"); + equal( + Comment.combineDisplayParts(b.comment?.summary), + "docs\nwith multiple lines" + ); + equal(Comment.combineDisplayParts(c.comment?.summary), ""); + }, + + _linkResolution(app) { + app.options.setValue("sort", ["source-order"]); + }, + linkResolution(project) { + function getLinks(refl: Reflection) { + ok(refl.comment); + return filterMap(refl.comment.summary, (p) => { + if (p.kind === "inline-tag" && p.tag === "@link") { + if (typeof p.target === "string") { + return p.target; + } + if (p.target instanceof SignatureReflection) { + return [ + p.target.getFullName(), + p.target.parent.signatures?.indexOf(p.target), + ]; + } + return [p.target?.kind, p.target?.getFullName()]; + } + }); + } + + for (const [refl, target] of [ + ["Scoping.abc", "Scoping.abc"], + ["Scoping.Foo", "Scoping.Foo.abc"], + ["Scoping.Foo.abc", "Scoping.Foo.abc"], + ["Scoping.Bar", "Scoping.abc"], + ["Scoping.Bar.abc", "Scoping.abc"], + ] as const) { + equal( + getLinks(query(project, refl)).map((x) => x[1]), + [query(project, target).getFullName()] + ); + } + + const links = getLinks(query(project, "Meanings")); + equal(links, [ + [ReflectionKind.Enum, "Meanings.A"], + [ReflectionKind.Namespace, "Meanings.A"], + [ReflectionKind.Enum, "Meanings.A"], + + [undefined, undefined], + [ReflectionKind.Class, "Meanings.B"], + + [ReflectionKind.Interface, "Meanings.C"], + [ReflectionKind.TypeAlias, "Meanings.D"], + ["Meanings.E.E", 0], + [ReflectionKind.Variable, "Meanings.F"], + + ["Meanings.B.constructor.new B", 0], + ["Meanings.B.constructor.new B", 0], + ["Meanings.B.constructor.new B", 1], + + [ReflectionKind.EnumMember, "Meanings.A.A"], + [undefined, undefined], - equal(foo.signatures[0].comment?.shortText, "Implementation comment"); - equal(foo.signatures[0].comment?.tags, []); + ["Meanings.E.E", 0], + ["Meanings.E.E", 1], + + ["Meanings.B.constructor.new B", 0], + ["Meanings.B.constructor.new B", 1], + + ["Meanings.B.__index", undefined], + [ReflectionKind.Interface, "Meanings.G"], + + ["Meanings.E.E", 1], + [ReflectionKind.Class, "Meanings.B"], + ]); + + equal(getLinks(query(project, "URLS")), [ + "https://example.com", + "ftp://example.com", + ]); - equal(foo.signatures[1].comment?.shortText, "Overrides summary"); - equal(foo.signatures[1].comment?.tags, []); equal( - foo.signatures[1].parameters?.[0].comment?.shortText.trim(), - "docs for x" + getLinks(query(project, "Globals.A")).map((x) => x[1]), + ["URLS", "A", "Globals.A"] ); + equal(getLinks(query(project, "Navigation")), [ + [ReflectionKind.Method, "Navigation.Child.foo"], + [ReflectionKind.Property, "Navigation.Child.foo"], + [undefined, undefined], + ]); + + const foo = query(project, "Navigation.Child.foo").signatures![0]; + equal(getLinks(foo), [[ReflectionKind.Method, "Navigation.Child.foo"]]); + }, + + mergedDeclarations(project, logger) { + const a = query(project, "SingleCommentMultiDeclaration"); + equal( + Comment.combineDisplayParts(a.comment?.summary), + "Comment on second declaration" + ); + + const b = query(project, "MultiCommentMultiDeclaration"); + equal(Comment.combineDisplayParts(b.comment?.summary), "Comment 1"); + + logger.expectMessage( + "warn: MultiCommentMultiDeclaration has multiple declarations with a comment. An arbitrary comment will be used." + ); + }, + + overloads(project, logger) { + const foo = query(project, "foo"); + const fooComments = foo.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) + ); + equal(fooComments, ["No arg comment\n", "No arg comment\n"]); equal(foo.comment, undefined); + + equal( + foo.signatures?.map((s) => s.label), + ["NO_ARGS", "WITH_X"] + ); + + const bar = query(project, "bar"); + const barComments = bar.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) + ); + equal(barComments, ["Implementation comment", "Custom comment"]); + equal(bar.comment, undefined); + + logger.expectMessage( + 'warn: The label "bad" for badLabel cannot be referenced with a declaration reference. Labels may only contain A-Z, 0-9, and _, and may not start with a number.' + ); + logger.discardDebugMessages(); + logger.expectNoOtherMessages(); + }, + + readonlyTag(project) { + const title = query(project, "Book.title"); + const author = query(project, "Book.author"); + + ok(!title.setSignature); + ok(author.flags.isReadonly); }, removeReflection(project) { @@ -151,4 +512,67 @@ export const behaviorTests: Record< ["typedoc"] ); }, + + seeTags(project) { + const foo = query(project, "foo"); + equal( + Comment.combineDisplayParts(foo.comment?.getTag("@see")?.content), + " - Double tag\n - Second tag\n" + ); + + const bar = query(project, "bar"); + equal( + Comment.combineDisplayParts(bar.comment?.getTag("@see")?.content), + "Single tag" + ); + }, + + _searchCategoryBoosts(app) { + app.options.setValue("searchCategoryBoosts", { + Cat0: 0, + Cat1: 2.0, + Cat2: 1.5, + CatUnused: 999, + }); + }, + searchCategoryBoosts(project, logger) { + const a = query(project, "A"); + const b = query(project, "B"); + const c = query(project, "C"); + equal(a.relevanceBoost, 3.0); + equal(b.relevanceBoost, 0.0); + equal(c.relevanceBoost, 2.0); + logger.expectMessage( + "warn: Not all categories specified in searchCategoryBoosts were used in the documentation." + + " The unused categories were:\n\tCatUnused" + ); + logger.discardDebugMessages(); + logger.expectNoOtherMessages(); + }, + + _searchGroupBoosts(app) { + app.options.setValue("searchGroupBoosts", { + Group0: 0, + Group1: 2.0, + Group2: 1.5, + GroupUnused: 999, + Interfaces: 0.5, + }); + }, + searchGroupBoosts(project, logger) { + const a = query(project, "A"); + const b = query(project, "B"); + const c = query(project, "C"); + const d = query(project, "D"); + equal(a.relevanceBoost, 3.0); + equal(b.relevanceBoost, 0.0); + equal(c.relevanceBoost, 2.0); + equal(d.relevanceBoost, 0.5); + logger.expectMessage( + "warn: Not all groups specified in searchGroupBoosts were used in the documentation." + + " The unused groups were:\n\tGroupUnused" + ); + logger.discardDebugMessages(); + logger.expectNoOtherMessages(); + }, }; diff --git a/src/test/capture-screenshots.ts b/src/test/capture-screenshots.ts index 6c9a582a7..eb303b801 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -1,9 +1,8 @@ import * as fs from "fs"; -import { sync as glob } from "glob"; import { platform } from "os"; -import { resolve, join, dirname } from "path"; +import { resolve, join, dirname, relative } from "path"; import { Application, TSConfigReader, EntryPointStrategy } from ".."; -import { remove } from "../lib/utils"; +import { glob } from "../lib/utils/fs"; // The @types package plays badly with non-dom packages. // eslint-disable-next-line @typescript-eslint/no-var-requires @@ -13,7 +12,6 @@ const concurrency = 10; const src = join(__dirname, "../../src/test/renderer/testProject/src"); const baseDirectory = join(__dirname, "../../dist/tmp/capture"); const outputDirectory = join(__dirname, "../../dist/tmp/__screenshots__"); -const globPattern = "**/*.html"; const viewport = { width: 1024, height: 768 }; class PQueue { @@ -63,9 +61,7 @@ export async function captureRegressionScreenshots() { app.bootstrap({ logger: "console", readme: join(src, "..", "README.md"), - gaSite: "foo.com", // verify theme option without modifying output name: "typedoc", - disableSources: true, cleanOutputDir: true, tsconfig: join(src, "..", "tsconfig.json"), plugin: [], @@ -74,7 +70,7 @@ export async function captureRegressionScreenshots() { }); const project = app.convert(); if (!project) throw new Error("Failed to convert."); - await remove(outputDirectory); + await fs.promises.rm(outputDirectory, { recursive: true, force: true }); await app.generateDocs(project, baseDirectory); await captureScreenshots(baseDirectory, outputDirectory); @@ -92,12 +88,12 @@ export async function captureScreenshots( }); const queue = new PQueue(concurrency); - for (const file of glob(globPattern, { cwd: baseDirectory })) { + for (const file of glob("**/*.html", baseDirectory)) { queue.add(async () => { const absPath = resolve(baseDirectory, file); const outputPath = resolve( outputDirectory, - file.replace(".html", "") + relative(baseDirectory, file).replace(".html", "") ); fs.mkdirSync(dirname(outputPath), { recursive: true }); @@ -130,6 +126,7 @@ export async function captureScreenshots( if (require.main == module) { captureRegressionScreenshots().catch((err) => { + // eslint-disable-next-line no-console console.error(err); process.exit(1); }); diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts new file mode 100644 index 000000000..de83d894b --- /dev/null +++ b/src/test/comments.test.ts @@ -0,0 +1,1220 @@ +import { deepStrictEqual as equal, fail } from "assert"; +import * as ts from "typescript"; +import type { CommentParserConfig } from "../lib/converter/comments"; + +import { lexBlockComment } from "../lib/converter/comments/blockLexer"; +import { lexLineComments } from "../lib/converter/comments/lineLexer"; +import { Token, TokenSyntaxKind } from "../lib/converter/comments/lexer"; +import { parseComment } from "../lib/converter/comments/parser"; +import { lexCommentString } from "../lib/converter/comments/rawLexer"; +import { Comment, CommentTag } from "../lib/models"; + +function dedent(text: string) { + const lines = text.split(/\r?\n/); + while (lines.length && lines[0].search(/\S/) === -1) { + lines.shift(); + } + while (lines.length && lines[lines.length - 1].search(/\S/) === -1) { + lines.pop(); + } + + const minIndent = lines.reduce( + (indent, line) => + line.length ? Math.min(indent, line.search(/\S/)) : indent, + Infinity + ); + + return lines.map((line) => line.substring(minIndent)).join("\n"); +} + +describe("Dedent test helper", () => { + it("Works on empty string", () => { + equal(dedent(""), ""); + }); + + it("Works with indented text", () => { + equal( + dedent(` + Text here + `), + "Text here" + ); + }); + + it("Works with multiple lines", () => { + equal( + dedent(` + Text here + More indented + `), + "Text here\n More indented" + ); + }); +}); + +describe("Block Comment Lexer", () => { + function lex(text: string): Token[] { + return Array.from(lexBlockComment(text)); + } + + it("Should handle an empty comment", () => { + const tokens = lex("/**/"); + equal(tokens, []); + + const tokens2 = lex("/***/"); + equal(tokens2, []); + + const tokens3 = lex("/** */"); + equal(tokens3, []); + }); + + it("Should handle a trivial comment", () => { + const tokens = lex("/** Comment */"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Comment" }]); + }); + + it("Should handle a multiline comment without stars", () => { + const tokens = lex("/* Comment\nNext line */"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Comment" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Next line" }, + ]); + }); + + it("Should handle a multiline comment with stars", () => { + const tokens = lex("/*\n * Comment\n * Next line */"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Comment" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Next line" }, + ]); + }); + + it("Should handle an indented comment with stars", () => { + const tokens = lex(`/** + * Text + */`); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Text" }]); + }); + + it("Should handle an indented comment without stars", () => { + const tokens = lex(`/* + Text + */`); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Text" }]); + }); + + it("Should handle a list within a comment without stars", () => { + const tokens = lex( + dedent(` + /* + Comment start + * This is a list item + */ + `) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Comment start" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: " * This is a list item" }, + ]); + }); + + it("Should handle higher detected indentation than the rest of the comment", () => { + const tokens = lex( + dedent(` + /* + A + B + */ + `) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "A" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "B" }, + ]); + }); + + it("Should handle a comment with stars missing a space", () => { + const tokens = lex( + dedent(` + /* + * A + *B + */ + `) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "A" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "B" }, + ]); + }); + + it("Should handle braces", () => { + const tokens = lex("/* {} */"); + + equal(tokens, [ + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); + + it("Should handle escaping braces", () => { + const tokens = lex("/* \\{\\} */"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "{}" }]); + }); + + it("Should allow escaping slashes", () => { + const tokens = lex("/* Text *\\/ */"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Text */" }]); + }); + + it("Should allow escaping slashes in code blocks", () => { + const tokens = lex( + dedent(` + /** + * \`\`\`ts + * /* inner block comment *\\/ + * \`\`\` + */ + `) + ); + + equal(tokens, [ + { + kind: TokenSyntaxKind.Code, + text: "```ts\n/* inner block comment */\n```", + }, + ]); + }); + + it("Should pass through unknown escapes", () => { + const tokens = lex("/* \\\\ \\n */"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "\\\\ \\n" }]); + }); + + it("Should recognize tags", () => { + const tokens = lex("/* @tag @a @abc234 */"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@tag" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@a" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@abc234" }, + ]); + }); + + it("Should not indiscriminately create tags", () => { + const tokens = lex("/* @123 @@ @ */"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "@123 @@ @" }]); + }); + + it("Should allow escaping @ to prevent a tag creation", () => { + const tokens = lex("/* not a \\@tag */"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "not a @tag" }]); + }); + + it("Should not mistake an email for a modifier tag", () => { + const tokens = lex("/* test@example.com */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow escaping @ in an email", () => { + const tokens = lex("/* test\\@example.com */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow inline code", () => { + const tokens = lex("/* test `code` after */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`code`" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should allow inline code with multiple ticks", () => { + const tokens = lex("/* test ```not ```` closed``` after */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "```not ```` closed```" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should allow escaping ticks", () => { + const tokens = lex("/* test `\\`` after */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`\\``" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should handle stars within code", () => { + const tokens = lex( + dedent(` + /** + * \`\`\`ts + * test() + * \`\`\` + */`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Code, text: "```ts\n test()\n```" }, + ]); + }); + + it("Should indent code without stars", () => { + const tokens = lex( + dedent(` + /** + \`\`\`ts + test() + \`\`\` + */`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Code, text: "```ts\n test()\n```" }, + ]); + }); + + it("Should treat unclosed inline code as text", () => { + const tokens = lex("/* text ` still text */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "text ` still text" }, + ]); + }); + + it("Should treat unclosed code blocks as code", () => { + const tokens = lex( + dedent(` + /* + * Text + * \`\`\`ts + * foo(); + */`) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Code, text: "```ts\nfoo();" }, + ]); + }); + + it("Should handle tags after unclosed code", () => { + const tokens = lex( + dedent(` + /* + * Text + * code? \`\` fake + * @blockTag text + */`) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "code? `` fake" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@blockTag" }, + { kind: TokenSyntaxKind.Text, text: " text" }, + ]); + }); + + it("Should handle text on the first line of a comment", () => { + let tokens = lex( + dedent(` + /* Text + * Text2 + */`) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Text2" }, + ]); + + tokens = lex( + dedent(` + /** Text + * Text2 + */`) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Text2" }, + ]); + }); + + it("Should handle a full comment", () => { + const tokens = lex( + dedent(` + /** + * This is a summary. + * + * @remarks + * Detailed text here with a {@link Inline | inline link} + * + * @alpha @beta + */`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "This is a summary." }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@remarks" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Detailed text here with a " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " Inline | inline link" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@alpha" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@beta" }, + ]); + }); + + it("Should handle starred comments without an end tag in code", () => { + const tokens = lex( + dedent(` + /** + *Text + *\`\`\` + *Text + */`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Code, text: "```\nText" }, + ]); + }); + + it("Should handle type annotations after tags at the start of a line", () => { + const tokens = lex( + dedent(` + /** + * @param {string} foo + */`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{string}" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + ]); + }); + + it("Should handle type annotations containing string literals", () => { + const tokens = lex( + dedent(` + /** + * @param {"{{}}"} + * @param {\`\${"{}"}\`} + * @param {"text\\"more {}"} + * @param {'{'} + * EOF + */`) + ); + + const expectedAnnotations = [ + '{"{{}}"}', + '{`${"{}"}`}', + '{"text\\"more {}"}', + "{'{'}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle type annotations with object literals", () => { + const tokens = lex( + dedent(` + /** + * @param {{ a: string }} + * @param {{ a: string; b: { c: { d: string }} }} + * EOF + */`) + ); + + const expectedAnnotations = [ + "{{ a: string }}", + "{{ a: string; b: { c: { d: string }} }}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle unclosed type annotations", () => { + const tokens = lex("/** @type {oops */"); + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@type" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{oops" }, + ]); + }); + + it("Should not parse inline tags as types", () => { + const tokens = lex("/** @param {@link foo} */"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); +}); + +describe("Line Comment Lexer", () => { + function lex(text: string): Token[] { + return Array.from( + lexLineComments(text, [ + { + kind: ts.SyntaxKind.SingleLineCommentTrivia, + pos: 0, + end: text.length, + }, + ]) + ); + } + + it("Should handle an empty string", () => { + equal(lex("//"), []); + + equal(lex("// "), []); + }); + + it("Should handle a trivial comment", () => { + const tokens = lex("// Comment "); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Comment" }]); + }); + + it("Should handle a multiline comment", () => { + const tokens = lex("// Comment\n // Next line "); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Comment" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Next line" }, + ]); + }); + + it("Should handle braces", () => { + const tokens = lex("// {}"); + + equal(tokens, [ + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); + + it("Should handle escaping braces", () => { + const tokens = lex("// \\{\\}"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "{}" }]); + }); + + it("Should pass through unknown escapes", () => { + const tokens = lex("// \\\\ \\n"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "\\\\ \\n" }]); + equal(lex("// *\\/"), [{ kind: TokenSyntaxKind.Text, text: "*\\/" }]); + }); + + it("Should recognize tags", () => { + const tokens = lex("// @tag @a @abc234"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@tag" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@a" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@abc234" }, + ]); + }); + + it("Should not indiscriminately create tags", () => { + const tokens = lex("// @123 @@ @"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "@123 @@ @" }]); + }); + + it("Should allow escaping @ to prevent a tag creation", () => { + const tokens = lex("// not a \\@tag"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "not a @tag" }]); + }); + + it("Should not mistake an email for a modifier tag", () => { + const tokens = lex("// test@example.com"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow escaping @ in an email", () => { + const tokens = lex("// test\\@example.com"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow inline code", () => { + const tokens = lex("// test `code` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`code`" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should allow inline code with multiple ticks", () => { + const tokens = lex("// test ```not ```` closed``` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "```not ```` closed```" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should allow escaping ticks", () => { + const tokens = lex("// test `\\`` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`\\``" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should treat unclosed inline code as text", () => { + const tokens = lex("// text ` still text"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "text ` still text" }, + ]); + }); + + it("Should handle tags after unclosed code", () => { + const tokens = lex( + dedent(` + // Text + // code? \`\` fake + // @blockTag text + `) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "code? `` fake" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@blockTag" }, + { kind: TokenSyntaxKind.Text, text: " text" }, + ]); + }); + + it("Should handle a full comment", () => { + const tokens = lex( + dedent(` + // This is a summary. + // + // @remarks + // Detailed text here with a {@link Inline | inline link} + // + // @alpha @beta + `) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "This is a summary." }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@remarks" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Detailed text here with a " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " Inline | inline link" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@alpha" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@beta" }, + ]); + }); + + it("Should handle unclosed code blocks", () => { + const tokens = lex( + dedent(` + // Text + // \`\`\` + // Text`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Code, text: "```\nText" }, + ]); + }); + + it("Should handle type annotations after tags at the start of a line", () => { + const tokens = lex(`// @param {string} foo`); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{string}" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + ]); + }); + + it("Should handle type annotations containing string literals", () => { + const tokens = lex( + dedent(` + // @param {"{{}}"} + // @param {\`\${"{}"}\`} + // @param {"text\\"more {}"} + // @param {'{'} + // EOF + `) + ); + + const expectedAnnotations = [ + '{"{{}}"}', + '{`${"{}"}`}', + '{"text\\"more {}"}', + "{'{'}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle type annotations with object literals", () => { + const tokens = lex( + dedent(` + // @param {{ a: string }} + // @param {{ a: string; b: { c: { d: string }} }} + // EOF + `) + ); + + const expectedAnnotations = [ + "{{ a: string }}", + "{{ a: string; b: { c: { d: string }} }}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle unclosed type annotations", () => { + const tokens = lex("// @type {oops"); + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@type" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{oops" }, + ]); + }); + + it("Should not parse inline tags as types", () => { + const tokens = lex("// @param { @link foo}"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); +}); + +describe("Raw Lexer", () => { + function lex(text: string): Token[] { + return Array.from(lexCommentString(text)); + } + + it("Should handle an empty string", () => { + equal(lex(""), []); + + equal(lex(" \n "), []); + }); + + it("Should handle a trivial comment", () => { + const tokens = lex(" Comment "); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "Comment" }]); + }); + + it("Should handle a multiline comment", () => { + const tokens = lex(" Comment\nNext line "); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Comment" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Next line" }, + ]); + }); + + it("Should handle braces", () => { + const tokens = lex("{}"); + + equal(tokens, [ + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); + + it("Should handle escaping braces", () => { + const tokens = lex("\\{\\}"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "{}" }]); + }); + + it("Should pass through unknown escapes", () => { + const tokens = lex("\\\\ \\n"); + + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "\\\\ \\n" }]); + equal(lex("*\\/"), [{ kind: TokenSyntaxKind.Text, text: "*\\/" }]); + }); + + it("Should recognize tags", () => { + const tokens = lex("@tag @a @abc234"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@tag" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@a" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@abc234" }, + ]); + }); + + it("Should not indiscriminately create tags", () => { + const tokens = lex("@123 @@ @"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "@123 @@ @" }]); + }); + + it("Should allow escaping @ to prevent a tag creation", () => { + const tokens = lex("not a \\@tag"); + equal(tokens, [{ kind: TokenSyntaxKind.Text, text: "not a @tag" }]); + }); + + it("Should not mistake an email for a modifier tag", () => { + const tokens = lex("test@example.com"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow escaping @ in an email", () => { + const tokens = lex("test\\@example.com"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test@example.com" }, + ]); + }); + + it("Should allow inline code", () => { + const tokens = lex("test `code` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`code`" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + // https://github.com/TypeStrong/typedoc/issues/1922#issuecomment-1166278275 + it("Should handle code blocks ending a string", () => { + const tokens = lex("`code`"); + + equal(tokens, [ + { + kind: "code", + text: "`code`", + }, + ]); + }); + + it("Should allow inline code with multiple ticks", () => { + const tokens = lex("test ```not ```` closed``` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "```not ```` closed```" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should allow escaping ticks", () => { + const tokens = lex("test `\\`` after"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "test " }, + { kind: TokenSyntaxKind.Code, text: "`\\``" }, + { kind: TokenSyntaxKind.Text, text: " after" }, + ]); + }); + + it("Should treat unclosed inline code as text", () => { + const tokens = lex("text ` still text"); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "text ` still text" }, + ]); + }); + + it("Should handle tags after unclosed code", () => { + const tokens = lex( + dedent(` + Text + code? \`\` fake + @blockTag text + `) + ); + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "code? `` fake" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@blockTag" }, + { kind: TokenSyntaxKind.Text, text: " text" }, + ]); + }); + + it("Should handle a full comment", () => { + const tokens = lex( + dedent(` + This is a summary. + + @remarks + Detailed text here with a {@link Inline | inline link} + + @alpha @beta + `) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "This is a summary." }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@remarks" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Text, text: "Detailed text here with a " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " Inline | inline link" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Tag, text: "@alpha" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@beta" }, + ]); + }); + + it("Should handle unclosed code blocks", () => { + const tokens = lex( + dedent(` + Text + \`\`\` + Text`) + ); + + equal(tokens, [ + { kind: TokenSyntaxKind.Text, text: "Text" }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + { kind: TokenSyntaxKind.Code, text: "```\nText" }, + ]); + }); + + it("Should handle type annotations after tags at the start of a line", () => { + const tokens = lex(`@param {string} foo`); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{string}" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + ]); + }); + + it("Should handle type annotations containing string literals", () => { + const tokens = lex( + dedent(` + @param {"{{}}"} + @param {\`\${"{}"}\`} + @param {"text\\"more {}"} + @param {'{'} + EOF + `) + ); + + const expectedAnnotations = [ + '{"{{}}"}', + '{`${"{}"}`}', + '{"text\\"more {}"}', + "{'{'}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle type annotations with object literals", () => { + const tokens = lex( + dedent(` + @param {{ a: string }} + @param {{ a: string; b: { c: { d: string }} }} + EOF + `) + ); + + const expectedAnnotations = [ + "{{ a: string }}", + "{{ a: string; b: { c: { d: string }} }}", + ]; + + const expectedTokens = expectedAnnotations.flatMap((text) => [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text }, + { kind: TokenSyntaxKind.NewLine, text: "\n" }, + ]); + expectedTokens.push({ kind: TokenSyntaxKind.Text, text: "EOF" }); + + equal(tokens, expectedTokens); + }); + + it("Should handle unclosed type annotations", () => { + const tokens = lex("@type {oops"); + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@type" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.TypeAnnotation, text: "{oops" }, + ]); + }); + + it("Should not parse inline tags as types", () => { + const tokens = lex("@param { @link foo}"); + + equal(tokens, [ + { kind: TokenSyntaxKind.Tag, text: "@param" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.OpenBrace, text: "{" }, + { kind: TokenSyntaxKind.Text, text: " " }, + { kind: TokenSyntaxKind.Tag, text: "@link" }, + { kind: TokenSyntaxKind.Text, text: " foo" }, + { kind: TokenSyntaxKind.CloseBrace, text: "}" }, + ]); + }); +}); + +describe("Comment Parser", () => { + const config: CommentParserConfig = { + blockTags: new Set(["@param", "@remarks", "@module"]), + inlineTags: new Set(["@link"]), + modifierTags: new Set([ + "@public", + "@private", + "@protected", + "@readonly", + "@enum", + "@event", + "@packageDocumentation", + ]), + }; + + it("Should rewrite @inheritdoc to @inheritDoc", () => { + let calls = 0; + function warning(msg: string) { + equal(msg, "The @inheritDoc tag should be properly capitalized"); + calls++; + } + const content = lexBlockComment("/** @inheritdoc */"); + const comment = parseComment(content, config, warning); + + equal(calls, 1); + equal(comment, new Comment([], [new CommentTag("@inheritDoc", [])])); + }); + + function test(name: string, text: string, cb: (comment: Comment) => void) { + it(name, () => { + const content = lexBlockComment(text); + const comment = parseComment(content, config, fail); + cb(comment); + }); + } + + test("Simple summary", "/** Summary! */", (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary!" }]); + equal(comment.blockTags, []); + equal(comment.modifierTags, new Set()); + }); + + test( + "Summary with remarks", + `/** + * Summary + * @remarks Remarks + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + equal(comment.blockTags, [ + new CommentTag("@remarks", [{ kind: "text", text: "Remarks" }]), + ]); + equal(comment.modifierTags, new Set()); + } + ); + + test( + "Parameter without content", + `/** + * Summary + * @param + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + const tag = new CommentTag("@param", []); + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); + + test( + "Parameter name", + `/** + * Summary + * @param T Param text + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + const tag = new CommentTag("@param", [ + { kind: "text", text: "Param text" }, + ]); + tag.name = "T"; + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); + + test( + "Parameter name with no content", + `/** + * Summary + * @param T + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + const tag = new CommentTag("@param", []); + tag.name = "T"; + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); + + test( + "Parameter name with dash", + `/** + * Summary + * @param T - Param text + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + const tag = new CommentTag("@param", [ + { kind: "text", text: "Param text" }, + ]); + tag.name = "T"; + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); + + test( + "Parameter name with type annotation", + `/** + * Summary + * @param {string} T - Param text + */`, + (comment) => { + equal(comment.summary, [{ kind: "text", text: "Summary" }]); + const tag = new CommentTag("@param", [ + { kind: "text", text: "Param text" }, + ]); + tag.name = "T"; + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); +}); diff --git a/src/test/converter.test.ts b/src/test/converter.test.ts index 4052bad1d..f86a6f7c2 100644 --- a/src/test/converter.test.ts +++ b/src/test/converter.test.ts @@ -77,7 +77,7 @@ describe("Converter", function () { FS.readFileSync(specsFile, "utf-8") ); let data = JSON.stringify( - app.serializer.toObject(result), + result && app.serializer.toObject(result), null, " " ); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 670e60960..2bf65bb0c 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -12,9 +12,22 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Conditional types from TS2.8" + "summary": [ + { + "kind": "text", + "text": "Conditional types from TS2.8" + } + ] }, - "typeParameter": [ + "sources": [ + { + "fileName": "alias.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L14" + } + ], + "typeParameters": [ { "id": 9, "name": "T", @@ -51,9 +64,22 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Extracts the type of a promise." + "summary": [ + { + "kind": "text", + "text": "Extracts the type of a promise." + } + ] }, - "typeParameter": [ + "sources": [ + { + "fileName": "alias.ts", + "line": 19, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L19" + } + ], + "typeParameters": [ { "id": 11, "name": "T", @@ -77,9 +103,9 @@ "name": "U" } ], + "name": "PromiseLike", "qualifiedName": "PromiseLike", - "package": "typescript", - "name": "PromiseLike" + "package": "typescript" }, "trueType": { "type": "reference", @@ -98,7 +124,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "alias.ts", + "line": 4, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" + } + ], + "typeParameters": [ { "id": 6, "name": "T", @@ -115,6 +149,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "alias.ts", + "line": 4, + "character": 34, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" + } + ], "signatures": [ { "id": 3, @@ -123,7 +165,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A type that describes a compare function, e.g. for array.sort()." + "summary": [ + { + "kind": "text", + "text": "A type that describes a compare function, e.g. for array.sort()." + } + ] }, "parameters": [ { @@ -167,8 +214,21 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "A type for IDs." + "summary": [ + { + "kind": "text", + "text": "A type for IDs." + } + ] }, + "sources": [ + { + "fileName": "alias.ts", + "line": 9, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L9" + } + ], "type": { "type": "union", "types": [ @@ -187,7 +247,6 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 8, 10, @@ -195,5 +254,13 @@ 7 ] } + ], + "sources": [ + { + "fileName": "alias.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" + } ] } diff --git a/src/test/converter/class/class.ts b/src/test/converter/class/class.ts index 4197392dd..731546286 100644 --- a/src/test/converter/class/class.ts +++ b/src/test/converter/class/class.ts @@ -3,7 +3,7 @@ * * TestClass comment text. * - * @see [[TestClass]] @ fixtures + * @see {@link TestClass} @ fixtures */ export class TestClass { /** diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 694fcfcb3..09e844248 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -20,7 +20,12 @@ "isPrivate": true }, "comment": { - "shortText": "A class that is documented as being private." + "summary": [ + { + "kind": "text", + "text": "A class that is documented as being private." + } + ] }, "children": [ { @@ -32,8 +37,21 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 34, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L34" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -48,8 +66,21 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 40, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L40" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -64,19 +95,25 @@ "isPrivate": true, "isStatic": true }, - "getSignature": [ + "sources": [ { - "id": 10, - "name": "privateStaticGetter", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "number" - } + "fileName": "access.ts", + "line": 59, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L59" } - ] + ], + "getSignature": { + "id": 10, + "name": "privateStaticGetter", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "number" + } + } }, { "id": 15, @@ -86,6 +123,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 46, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L46" + } + ], "signatures": [ { "id": 16, @@ -96,7 +141,12 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -113,6 +163,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 52, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L52" + } + ], "signatures": [ { "id": 18, @@ -123,7 +181,12 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -140,6 +203,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 54, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L54" + } + ], "signatures": [ { "id": 20, @@ -158,7 +229,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 13, 14 @@ -166,20 +236,26 @@ }, { "title": "Accessors", - "kind": 262144, "children": [ 9 ] }, { "title": "Methods", - "kind": 2048, "children": [ 15, 17, 19 ] } + ], + "sources": [ + { + "fileName": "access.ts", + "line": 29, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L29" + } ] }, { @@ -192,8 +268,21 @@ "isConst": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 5, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" + } + ], "type": { "type": "literal", "value": "test" @@ -210,8 +299,21 @@ "isConst": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 11, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L11" + } + ], "type": { "type": "literal", "value": "test" @@ -226,6 +328,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 17, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L17" + } + ], "signatures": [ { "id": 3, @@ -236,7 +346,12 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -253,6 +368,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 23, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L23" + } + ], "signatures": [ { "id": 5, @@ -263,7 +386,12 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -276,14 +404,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8 ] }, { "title": "Variables", - "kind": 32, "children": [ 6, 7 @@ -291,12 +417,19 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 4 ] } + ], + "sources": [ + { + "fileName": "access.ts", + "line": 5, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" + } ] }, { @@ -319,6 +452,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 108, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L108" + } + ], "signatures": [ { "id": 61, @@ -327,7 +468,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -340,11 +486,30 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 60 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 61, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" + }, + { + "fileName": "class.ts", + "line": 97, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" + }, + { + "fileName": "class.ts", + "line": 104, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" + } ] }, { @@ -385,6 +550,14 @@ "flags": { "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 126, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L126" + } + ], "signatures": [ { "id": 89, @@ -403,18 +576,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 86 ] }, { "title": "Methods", - "kind": 2048, "children": [ 88 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 125, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L125" + } ] }, { @@ -451,6 +630,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 114, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L114" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -463,6 +650,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 115, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L115" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -475,6 +670,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 116, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L116" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -487,6 +690,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 117, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L117" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -497,14 +708,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 75 ] }, { "title": "Properties", - "kind": 1024, "children": [ 79, 80, @@ -512,6 +721,14 @@ 78 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 113, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L113" + } ] }, { @@ -552,6 +769,14 @@ "flags": { "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 86, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L86" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -566,6 +791,14 @@ "isProtected": true, "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 88, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L88" + } + ], "signatures": [ { "id": 67, @@ -584,26 +817,31 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 63 ] }, { "title": "Properties", - "kind": 1024, "children": [ 65 ] }, { "title": "Methods", - "kind": 2048, "children": [ 66 ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 85, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L85" + } + ], "extendedBy": [ { "type": "reference", @@ -656,6 +894,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 92, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L92" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -674,6 +920,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 94, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L94" + } + ], "signatures": [ { "id": 73, @@ -702,26 +956,31 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 69 ] }, { "title": "Properties", - "kind": 1024, "children": [ 71 ] }, { "title": "Methods", - "kind": 2048, "children": [ 72 ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 91, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L91" + } + ], "extendedTypes": [ { "type": "reference", @@ -737,12 +996,27 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] } ] }, @@ -753,6 +1027,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 27, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L27" + } + ], "signatures": [ { "id": 27, @@ -761,7 +1043,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "type": { "type": "reference", @@ -780,8 +1067,21 @@ "isPrivate": true }, "comment": { - "shortText": "privateProperty short text." + "summary": [ + { + "kind": "text", + "text": "privateProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 17, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L17" + } + ], "type": { "type": "array", "elementType": { @@ -799,8 +1099,21 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 12, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -815,8 +1128,21 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 22, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" + } + ], "type": { "type": "reference", "id": 22, @@ -829,6 +1155,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 58, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" + } + ], "signatures": [ { "id": 37, @@ -837,7 +1171,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -854,6 +1193,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 48, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L48" + } + ], "signatures": [ { "id": 35, @@ -862,7 +1209,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "privateMethod short text." + "summary": [ + { + "kind": "text", + "text": "privateMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -879,6 +1231,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 41, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L41" + } + ], "signatures": [ { "id": 33, @@ -887,7 +1247,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -904,6 +1269,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 34, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L34" + } + ], "signatures": [ { "id": 31, @@ -912,7 +1285,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -929,6 +1307,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 53, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" + } + ], "signatures": [ { "id": 25, @@ -937,7 +1323,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -950,14 +1341,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 26 ] }, { "title": "Properties", - "kind": 1024, "children": [ 29, 28, @@ -966,7 +1355,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 36, 34, @@ -1004,6 +1392,14 @@ ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" + } + ], "extendedBy": [ { "type": "reference", @@ -1018,6 +1414,31 @@ "kind": 128, "kindString": "Class", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] + } + ] + }, "children": [ { "id": 42, @@ -1025,6 +1446,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "signatures": [ { "id": 43, @@ -1033,7 +1462,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "parameters": [ { @@ -1043,7 +1477,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor param" + "summary": [ + { + "kind": "text", + "text": "Constructor param" + } + ] }, "type": { "type": "intrinsic", @@ -1057,7 +1496,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Private string property" + "summary": [ + { + "kind": "text", + "text": "Private string property" + } + ] }, "type": { "type": "intrinsic", @@ -1071,7 +1515,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public number property" + "summary": [ + { + "kind": "text", + "text": "Public number property" + } + ] }, "type": { "type": "intrinsic", @@ -1085,7 +1534,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public implicit any property\n" + "summary": [ + { + "kind": "text", + "text": "Public implicit any property" + } + ] }, "type": { "type": "intrinsic", @@ -1119,6 +1573,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 47, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1132,6 +1594,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 66, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -1146,8 +1616,21 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 12, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1167,8 +1650,21 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 22, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" + } + ], "type": { "type": "reference", "id": 22, @@ -1186,6 +1682,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 58, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" + } + ], "signatures": [ { "id": 58, @@ -1194,7 +1698,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -1219,6 +1728,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 101, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L101" + } + ], "signatures": [ { "id": 55, @@ -1227,7 +1744,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "mergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "mergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1244,6 +1766,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 70, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L70" + } + ], "signatures": [ { "id": 51, @@ -1252,7 +1782,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1279,6 +1814,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 65, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L65" + } + ], "signatures": [ { "id": 49, @@ -1287,7 +1830,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1314,6 +1862,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 53, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" + } + ], "signatures": [ { "id": 41, @@ -1322,7 +1878,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1345,14 +1906,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 42 ] }, { "title": "Properties", - "kind": 1024, "children": [ 52, 53, @@ -1362,7 +1921,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 57, 54, @@ -1372,6 +1930,26 @@ ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 61, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" + }, + { + "fileName": "class.ts", + "line": 97, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" + }, + { + "fileName": "class.ts", + "line": 104, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" + } + ], "extendedTypes": [ { "type": "reference", @@ -1417,8 +1995,21 @@ "isPrivate": true }, "comment": { - "shortText": "Docs" + "summary": [ + { + "kind": "text", + "text": "Docs" + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 122, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L122" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1429,18 +2020,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 84 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 120, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L120" + } ] }, { @@ -1449,6 +2046,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" + } + ], "type": { "type": "reflection", "declaration": { @@ -1457,6 +2062,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 25, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" + } + ], "signatures": [ { "id": 92, @@ -1480,14 +2093,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 59 ] }, { "title": "Classes", - "kind": 128, "children": [ 85, 74, @@ -1500,11 +2111,18 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 90 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" + } ] }, { @@ -1521,7 +2139,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with constructor properties." + } + ] }, "children": [ { @@ -1530,6 +2153,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "signatures": [ { "id": 96, @@ -1537,7 +2168,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 97, @@ -1546,7 +2176,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": [ + { + "kind": "text", + "text": "X component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1560,7 +2195,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Y component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1574,7 +2214,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": [ + { + "kind": "text", + "text": "Vector name" + } + ] }, "type": { "type": "intrinsic", @@ -1598,6 +2243,14 @@ "flags": { "isReadonly": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 61, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1611,6 +2264,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1624,6 +2285,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1633,14 +2302,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 95 ] }, { "title": "Properties", - "kind": 1024, "children": [ 102, 100, @@ -1648,6 +2315,14 @@ ] } ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 4, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" + } + ], "extendedBy": [ { "type": "reference", @@ -1663,7 +2338,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with inherited and overwritten constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with inherited and overwritten constructor properties." + } + ] }, "children": [ { @@ -1672,6 +2352,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 23, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L23" + } + ], "signatures": [ { "id": 105, @@ -1679,7 +2367,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 106, @@ -1688,7 +2375,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": [ + { + "kind": "text", + "text": "X component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1702,7 +2394,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Y component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1716,7 +2413,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Z component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Z component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1730,7 +2432,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": [ + { + "kind": "text", + "text": "Vector name" + } + ] }, "type": { "type": "intrinsic", @@ -1764,6 +2471,14 @@ "flags": { "isReadonly": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 27, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L27" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1782,6 +2497,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1800,6 +2523,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 25, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L25" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1818,6 +2549,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 26, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L26" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1827,14 +2566,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 104 ] }, { "title": "Properties", - "kind": 1024, "children": [ 112, 113, @@ -1843,6 +2580,14 @@ ] } ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 16, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L16" + } + ], "extendedTypes": [ { "type": "reference", @@ -1855,12 +2600,19 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 94, 103 ] } + ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" + } ] }, { @@ -1877,21 +2629,13 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A decorated class." - }, - "decorators": [ - { - "name": "decoratorWithOptions", - "type": { - "type": "reference", - "id": 123, - "name": "decoratorWithOptions" - }, - "arguments": { - "options": "{\n name: \"Name of class\",\n}" + "summary": [ + { + "kind": "text", + "text": "A decorated class." } - } - ], + ] + }, "children": [ { "id": 129, @@ -1920,25 +2664,12 @@ "kind": 2048, "kindString": "Method", "flags": {}, - "decorators": [ - { - "name": "decoratorAtom", - "type": { - "type": "reference", - "id": 115, - "name": "decoratorAtom" - } - }, + "sources": [ { - "name": "decoratorWithParam", - "type": { - "type": "reference", - "id": 120, - "name": "decoratorWithParam" - }, - "arguments": { - "value": "false" - } + "fileName": "decorators.ts", + "line": 13, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L13" } ], "signatures": [ @@ -1949,7 +2680,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorated method." + "summary": [ + { + "kind": "text", + "text": "A decorated method." + } + ] }, "type": { "type": "intrinsic", @@ -1962,18 +2698,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 129 ] }, { "title": "Methods", - "kind": 2048, "children": [ 131 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 7, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L7" + } ] }, { @@ -1982,11 +2724,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 131, - "name": "decoratedMethod" + "fileName": "decorators.ts", + "line": 19, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L19" } ], "signatures": [ @@ -1997,7 +2740,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with no options." + "summary": [ + { + "kind": "text", + "text": "A decorator with no options." + } + ] }, "parameters": [ { @@ -2008,9 +2756,9 @@ "flags": {}, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -2047,9 +2795,9 @@ "name": "any" } ], + "name": "TypedPropertyDescriptor", "qualifiedName": "TypedPropertyDescriptor", - "package": "typescript", - "name": "TypedPropertyDescriptor" + "package": "typescript" } } ], @@ -2066,11 +2814,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 128, - "name": "DecoratedClass" + "fileName": "decorators.ts", + "line": 48, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ], "signatures": [ @@ -2081,7 +2830,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator consuming an options object." + "summary": [ + { + "kind": "text", + "text": "A decorator consuming an options object." + } + ] }, "parameters": [ { @@ -2091,7 +2845,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The options object of this decorator." + "summary": [ + { + "kind": "text", + "text": "The options object of this decorator." + } + ] }, "type": { "type": "reflection", @@ -2109,8 +2868,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A property on the options object of this decorator.\n" + "summary": [ + { + "kind": "text", + "text": "A property on the options object of this decorator." + } + ] }, + "sources": [ + { + "fileName": "decorators.ts", + "line": 49, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L49" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2120,11 +2892,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 127 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 48, + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" + } ] } } @@ -2132,9 +2911,9 @@ ], "type": { "type": "reference", + "name": "ClassDecorator", "qualifiedName": "ClassDecorator", - "package": "typescript", - "name": "ClassDecorator" + "package": "typescript" } } ] @@ -2145,11 +2924,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 131, - "name": "decoratedMethod" + "fileName": "decorators.ts", + "line": 32, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L32" } ], "signatures": [ @@ -2160,7 +2940,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with a parameter." + "summary": [ + { + "kind": "text", + "text": "A decorator with a parameter." + } + ] }, "parameters": [ { @@ -2170,7 +2955,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The parameter of this decorator.\n" + "summary": [ + { + "kind": "text", + "text": "The parameter of this decorator." + } + ] }, "type": { "type": "intrinsic", @@ -2180,9 +2970,9 @@ ], "type": { "type": "reference", + "name": "MethodDecorator", "qualifiedName": "MethodDecorator", - "package": "typescript", - "name": "MethodDecorator" + "package": "typescript" } } ] @@ -2191,20 +2981,26 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 128 ] }, { "title": "Functions", - "kind": 64, "children": [ 115, 123, 120 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L4" + } ] }, { @@ -2245,14 +3041,27 @@ { "id": 162, "name": "EVENT_CLICK", - "kind": 8388608, - "kindString": "Event", + "kind": 1024, + "kindString": "Property", "flags": { "isStatic": true }, "comment": { - "shortText": "This is an event documentation." + "summary": [ + { + "kind": "text", + "text": "This is an event documentation." + } + ] }, + "sources": [ + { + "fileName": "events.ts", + "line": 6, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L6" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2263,29 +3072,42 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 163 ] }, { "title": "Events", - "kind": 8388608, "children": [ 162 ] } + ], + "sources": [ + { + "fileName": "events.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 161 ] } + ], + "sources": [ + { + "fileName": "events.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" + } ] }, { @@ -2302,11 +3124,21 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates some information for background http transfers.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "https://github.com/TypeStrong/typedoc/issues/136\n" + "kind": "text", + "text": "Encapsulates some information for background http transfers." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "https://github.com/TypeStrong/typedoc/issues/136" + } + ] } ] }, @@ -2314,18 +3146,49 @@ { "id": 135, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 2048, + "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 14, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" + }, + { + "fileName": "events-overloads.ts", + "line": 23, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" + }, + { + "fileName": "events-overloads.ts", + "line": 32, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" + }, + { + "fileName": "events-overloads.ts", + "line": 41, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" + } + ], "signatures": [ { "id": 136, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for a general event by name." + "summary": [ + { + "kind": "text", + "text": "Subscribe for a general event by name." + } + ] }, "parameters": [ { @@ -2335,7 +3198,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "intrinsic", @@ -2349,7 +3217,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The handler called when the event occurs.\n" + "summary": [ + { + "kind": "text", + "text": "The handler called when the event occurs." + } + ] }, "type": { "type": "reflection", @@ -2359,6 +3232,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 14, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" + } + ], "signatures": [ { "id": 140, @@ -2397,11 +3278,16 @@ { "id": 142, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for error notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for error notifications." + } + ] }, "parameters": [ { @@ -2411,7 +3297,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2425,7 +3316,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive the error details\n" + "summary": [ + { + "kind": "text", + "text": "A handler that will receive the error details" + } + ] }, "type": { "type": "reflection", @@ -2435,6 +3331,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 23, + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" + } + ], "signatures": [ { "id": 146, @@ -2473,11 +3377,16 @@ { "id": 148, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for progress notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for progress notifications." + } + ] }, "parameters": [ { @@ -2487,7 +3396,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2501,7 +3415,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive a progress event with the current and expected total bytes\n" + "summary": [ + { + "kind": "text", + "text": "A handler that will receive a progress event with the current and expected total bytes" + } + ] }, "type": { "type": "reflection", @@ -2511,6 +3430,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 32, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" + } + ], "signatures": [ { "id": 152, @@ -2549,11 +3476,16 @@ { "id": 154, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for success notification." + "summary": [ + { + "kind": "text", + "text": "Subscribe for success notification." + } + ] }, "parameters": [ { @@ -2563,7 +3495,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2577,7 +3514,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A function that will be called with general event data upon successful completion\n" + "summary": [ + { + "kind": "text", + "text": "A function that will be called with general event data upon successful completion" + } + ] }, "type": { "type": "reflection", @@ -2587,6 +3529,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 41, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" + } + ], "signatures": [ { "id": 158, @@ -2628,22 +3578,36 @@ "groups": [ { "title": "Events", - "kind": 8388608, "children": [ 135 ] } + ], + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 6, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" + } ] } ], "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 134 ] } + ], + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" + } ] }, { @@ -2660,7 +3624,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "GenericClass short text." + "summary": [ + { + "kind": "text", + "text": "GenericClass short text." + } + ] }, "children": [ { @@ -2669,6 +3638,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" + } + ], "signatures": [ { "id": 168, @@ -2677,7 +3654,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "typeParameter": [ { @@ -2696,7 +3678,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Constructor parameter." + } + ] }, "type": { "type": "reference", @@ -2729,8 +3716,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 9, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" + } + ], "type": { "type": "reference", "id": 169, @@ -2746,8 +3746,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 14, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" + } + ], "type": { "type": "array", "elementType": { @@ -2763,6 +3776,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" + } + ], "signatures": [ { "id": 174, @@ -2771,8 +3792,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", - "returns": "Return value comment.\n" + "summary": [ + { + "kind": "text", + "text": "getValue short text." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Return value comment." + } + ] + } + ] }, "type": { "type": "reference", @@ -2786,14 +3822,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 167 ] }, { "title": "Properties", - "kind": 1024, "children": [ 171, 172 @@ -2801,13 +3835,20 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 173 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "generic-class.ts", + "line": 5, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" + } + ], + "typeParameters": [ { "id": 175, "name": "T", @@ -2815,7 +3856,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Generic parameter." + } + ] } } ], @@ -2834,7 +3880,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "NonGenericClass short text." + "summary": [ + { + "kind": "text", + "text": "NonGenericClass short text." + } + ] }, "children": [ { @@ -2843,6 +3894,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" + } + ], "signatures": [ { "id": 178, @@ -2851,7 +3910,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "parameters": [ { @@ -2861,7 +3925,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Constructor parameter." + } + ] }, "type": { "type": "intrinsic", @@ -2896,8 +3965,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 9, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2917,8 +3999,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 14, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" + } + ], "type": { "type": "array", "elementType": { @@ -2938,6 +4033,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" + } + ], "signatures": [ { "id": 183, @@ -2946,8 +4049,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", - "returns": "Return value comment.\n" + "summary": [ + { + "kind": "text", + "text": "getValue short text." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Return value comment." + } + ] + } + ] }, "type": { "type": "intrinsic", @@ -2970,14 +4088,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 177 ] }, { "title": "Properties", - "kind": 1024, "children": [ 180, 181 @@ -2985,12 +4101,19 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 182 ] } ], + "sources": [ + { + "fileName": "generic-class.ts", + "line": 36, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L36" + } + ], "extendedTypes": [ { "type": "reference", @@ -3009,12 +4132,19 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 166, 176 ] } + ], + "sources": [ + { + "fileName": "generic-class.ts", + "line": 5, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" + } ] }, { @@ -3060,6 +4190,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 2, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L2" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -3071,45 +4209,55 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "getSignature": [ + "sources": [ { - "id": 190, - "name": "name", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 4, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L4" + }, + { + "fileName": "getter-setter.ts", + "line": 7, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], - "setSignature": [ - { - "id": 191, - "name": "name", - "kind": 1048576, - "kindString": "Set signature", - "flags": {}, - "parameters": [ - { - "id": 192, - "name": "value", - "kind": 32768, - "kindString": "Parameter", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "getSignature": { + "id": 190, + "name": "name", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + }, + "setSignature": { + "id": 191, + "name": "name", + "kind": 1048576, + "kindString": "Set signature", + "flags": {}, + "parameters": [ + { + "id": 192, + "name": "value", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ], - "type": { - "type": "intrinsic", - "name": "void" } + ], + "type": { + "type": "intrinsic", + "name": "void" } - ] + } }, { "id": 193, @@ -3117,19 +4265,25 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "getSignature": [ + "sources": [ { - "id": 194, - "name": "readOnlyName", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 11, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L11" } - ] + ], + "getSignature": { + "id": 194, + "name": "readOnlyName", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } }, { "id": 195, @@ -3137,69 +4291,87 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "setSignature": [ + "sources": [ { - "id": 196, - "name": "writeOnlyName", - "kind": 1048576, - "kindString": "Set signature", - "flags": {}, - "parameters": [ - { - "id": 197, - "name": "value", - "kind": 32768, - "kindString": "Parameter", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 15, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L15" + } + ], + "setSignature": { + "id": 196, + "name": "writeOnlyName", + "kind": 1048576, + "kindString": "Set signature", + "flags": {}, + "parameters": [ + { + "id": 197, + "name": "value", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ], - "type": { - "type": "intrinsic", - "name": "void" } + ], + "type": { + "type": "intrinsic", + "name": "void" } - ] + } } ], "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 186 ] }, { "title": "Properties", - "kind": 1024, "children": [ 188 ] }, { "title": "Accessors", - "kind": 262144, "children": [ 189, 193, 195 ] } + ], + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 185 ] } + ], + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" + } ] }, { @@ -3216,8 +4388,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "ChainClass comment short text.", - "text": "ChainClass comment text.\n" + "summary": [ + { + "kind": "text", + "text": "ChainClass comment short text.\n\nChainClass comment text." + } + ] }, "children": [ { @@ -3249,6 +4425,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "this.ts", + "line": 10, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L10" + } + ], "signatures": [ { "id": 203, @@ -3257,7 +4441,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Chain method that returns this." + "summary": [ + { + "kind": "text", + "text": "Chain method that returns this." + } + ] }, "type": { "type": "reference", @@ -3271,29 +4460,42 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 200 ] }, { "title": "Methods", - "kind": 2048, "children": [ 202 ] } + ], + "sources": [ + { + "fileName": "this.ts", + "line": 6, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 199 ] } + ], + "sources": [ + { + "fileName": "this.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" + } ] }, { @@ -3362,6 +4564,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 14, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L14" + } + ], "type": { "type": "reference", "id": 213, @@ -3372,20 +4582,26 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 211 ] }, { "title": "Properties", - "kind": 1024, "children": [ 214 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "type-operator.ts", + "line": 13, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" + } + ], + "typeParameters": [ { "id": 215, "name": "T", @@ -3411,12 +4627,27 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 205 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] } ] }, @@ -3448,6 +4679,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 9, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L9" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -3459,6 +4698,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -3468,38 +4715,50 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 206 ] }, { "title": "Properties", - "kind": 1024, "children": [ 208, 209 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 210, 205 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 21, diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 0cb5cd958..f1b092a15 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -20,7 +20,12 @@ "isPrivate": true }, "comment": { - "shortText": "A class that is documented as being private." + "summary": [ + { + "kind": "text", + "text": "A class that is documented as being private." + } + ] }, "children": [ { @@ -32,8 +37,21 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 34, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L34" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -48,8 +66,21 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 40, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L40" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -64,19 +95,25 @@ "isPrivate": true, "isStatic": true }, - "getSignature": [ + "sources": [ { - "id": 10, - "name": "privateStaticGetter", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "number" - } + "fileName": "access.ts", + "line": 59, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L59" } - ] + ], + "getSignature": { + "id": 10, + "name": "privateStaticGetter", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "number" + } + } }, { "id": 15, @@ -86,6 +123,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 46, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L46" + } + ], "signatures": [ { "id": 16, @@ -96,7 +141,12 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -113,6 +163,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 52, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L52" + } + ], "signatures": [ { "id": 18, @@ -123,7 +181,12 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -140,6 +203,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 54, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L54" + } + ], "signatures": [ { "id": 20, @@ -158,7 +229,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 13, 14 @@ -166,20 +236,26 @@ }, { "title": "Accessors", - "kind": 262144, "children": [ 9 ] }, { "title": "Methods", - "kind": 2048, "children": [ 15, 17, 19 ] } + ], + "sources": [ + { + "fileName": "access.ts", + "line": 29, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L29" + } ] }, { @@ -192,8 +268,21 @@ "isConst": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 5, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" + } + ], "type": { "type": "literal", "value": "test" @@ -210,8 +299,21 @@ "isConst": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, + "sources": [ + { + "fileName": "access.ts", + "line": 11, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L11" + } + ], "type": { "type": "literal", "value": "test" @@ -226,6 +328,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 17, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L17" + } + ], "signatures": [ { "id": 3, @@ -236,7 +346,12 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -253,6 +368,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "access.ts", + "line": 23, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L23" + } + ], "signatures": [ { "id": 5, @@ -263,7 +386,12 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -276,14 +404,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8 ] }, { "title": "Variables", - "kind": 32, "children": [ 6, 7 @@ -291,12 +417,19 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 4 ] } + ], + "sources": [ + { + "fileName": "access.ts", + "line": 5, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" + } ] }, { @@ -319,6 +452,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 108, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L108" + } + ], "signatures": [ { "id": 61, @@ -327,7 +468,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -340,11 +486,30 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 60 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 61, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" + }, + { + "fileName": "class.ts", + "line": 97, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" + }, + { + "fileName": "class.ts", + "line": 104, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" + } ] }, { @@ -385,6 +550,14 @@ "flags": { "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 126, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L126" + } + ], "signatures": [ { "id": 89, @@ -403,18 +576,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 86 ] }, { "title": "Methods", - "kind": 2048, "children": [ 88 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 125, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L125" + } ] }, { @@ -451,6 +630,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 114, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L114" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -463,6 +650,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 115, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L115" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -475,6 +670,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 116, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L116" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -487,6 +690,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 117, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L117" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -497,14 +708,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 75 ] }, { "title": "Properties", - "kind": 1024, "children": [ 79, 80, @@ -512,6 +721,14 @@ 78 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 113, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L113" + } ] }, { @@ -552,6 +769,14 @@ "flags": { "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 86, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L86" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -566,6 +791,14 @@ "isProtected": true, "isAbstract": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 88, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L88" + } + ], "signatures": [ { "id": 67, @@ -584,26 +817,31 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 63 ] }, { "title": "Properties", - "kind": 1024, "children": [ 65 ] }, { "title": "Methods", - "kind": 2048, "children": [ 66 ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 85, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L85" + } + ], "extendedBy": [ { "type": "reference", @@ -656,6 +894,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 92, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L92" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -674,6 +920,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 94, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L94" + } + ], "signatures": [ { "id": 73, @@ -702,26 +956,31 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 69 ] }, { "title": "Properties", - "kind": 1024, "children": [ 71 ] }, { "title": "Methods", - "kind": 2048, "children": [ 72 ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 91, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L91" + } + ], "extendedTypes": [ { "type": "reference", @@ -737,12 +996,27 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] } ] }, @@ -753,6 +1027,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 27, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L27" + } + ], "signatures": [ { "id": 27, @@ -761,7 +1043,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "type": { "type": "reference", @@ -780,8 +1067,21 @@ "isPrivate": true }, "comment": { - "shortText": "privateProperty short text." + "summary": [ + { + "kind": "text", + "text": "privateProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 17, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L17" + } + ], "type": { "type": "array", "elementType": { @@ -799,8 +1099,21 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 12, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -815,8 +1128,21 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 22, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" + } + ], "type": { "type": "reference", "id": 22, @@ -829,6 +1155,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 58, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" + } + ], "signatures": [ { "id": 37, @@ -837,7 +1171,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -854,6 +1193,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 48, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L48" + } + ], "signatures": [ { "id": 35, @@ -862,7 +1209,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "privateMethod short text." + "summary": [ + { + "kind": "text", + "text": "privateMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -879,6 +1231,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 41, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L41" + } + ], "signatures": [ { "id": 33, @@ -887,7 +1247,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -904,6 +1269,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 34, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L34" + } + ], "signatures": [ { "id": 31, @@ -912,7 +1285,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -929,6 +1307,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 53, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" + } + ], "signatures": [ { "id": 25, @@ -937,7 +1323,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -950,14 +1341,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 26 ] }, { "title": "Properties", - "kind": 1024, "children": [ 29, 28, @@ -966,7 +1355,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 36, 34, @@ -1000,6 +1388,14 @@ ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" + } + ], "extendedBy": [ { "type": "reference", @@ -1014,6 +1410,31 @@ "kind": 128, "kindString": "Class", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] + } + ] + }, "children": [ { "id": 42, @@ -1021,6 +1442,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "signatures": [ { "id": 43, @@ -1029,7 +1458,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "parameters": [ { @@ -1039,7 +1473,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor param" + "summary": [ + { + "kind": "text", + "text": "Constructor param" + } + ] }, "type": { "type": "intrinsic", @@ -1053,7 +1492,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Private string property" + "summary": [ + { + "kind": "text", + "text": "Private string property" + } + ] }, "type": { "type": "intrinsic", @@ -1067,7 +1511,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public number property" + "summary": [ + { + "kind": "text", + "text": "Public number property" + } + ] }, "type": { "type": "intrinsic", @@ -1081,7 +1530,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public implicit any property\n" + "summary": [ + { + "kind": "text", + "text": "Public implicit any property" + } + ] }, "type": { "type": "intrinsic", @@ -1115,6 +1569,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 47, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1128,6 +1590,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 80, + "character": 66, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -1142,8 +1612,21 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 12, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1163,8 +1646,21 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 22, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" + } + ], "type": { "type": "reference", "id": 22, @@ -1182,6 +1678,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 58, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" + } + ], "signatures": [ { "id": 58, @@ -1190,7 +1694,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -1215,6 +1724,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 101, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L101" + } + ], "signatures": [ { "id": 55, @@ -1223,7 +1740,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "mergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "mergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1240,6 +1762,14 @@ "flags": { "isProtected": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 70, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L70" + } + ], "signatures": [ { "id": 51, @@ -1248,7 +1778,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1275,6 +1810,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 65, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L65" + } + ], "signatures": [ { "id": 49, @@ -1283,7 +1826,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1310,6 +1858,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "class.ts", + "line": 53, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" + } + ], "signatures": [ { "id": 41, @@ -1318,7 +1874,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1341,14 +1902,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 42 ] }, { "title": "Properties", - "kind": 1024, "children": [ 52, 53, @@ -1358,7 +1917,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 57, 54, @@ -1368,6 +1926,26 @@ ] } ], + "sources": [ + { + "fileName": "class.ts", + "line": 61, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" + }, + { + "fileName": "class.ts", + "line": 97, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" + }, + { + "fileName": "class.ts", + "line": 104, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" + } + ], "extendedTypes": [ { "type": "reference", @@ -1413,8 +1991,21 @@ "isPrivate": true }, "comment": { - "shortText": "Docs" + "summary": [ + { + "kind": "text", + "text": "Docs" + } + ] }, + "sources": [ + { + "fileName": "class.ts", + "line": 122, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L122" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1425,18 +2016,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 84 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 120, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L120" + } ] }, { @@ -1445,6 +2042,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" + } + ], "type": { "type": "reflection", "declaration": { @@ -1453,6 +2058,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 25, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" + } + ], "signatures": [ { "id": 92, @@ -1476,14 +2089,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 59 ] }, { "title": "Classes", - "kind": 128, "children": [ 85, 74, @@ -1496,11 +2107,18 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 90 ] } + ], + "sources": [ + { + "fileName": "class.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" + } ] }, { @@ -1517,7 +2135,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with constructor properties." + } + ] }, "children": [ { @@ -1526,6 +2149,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "signatures": [ { "id": 96, @@ -1533,7 +2164,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 97, @@ -1542,7 +2172,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": [ + { + "kind": "text", + "text": "X component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1556,7 +2191,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Y component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1570,7 +2210,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": [ + { + "kind": "text", + "text": "Vector name" + } + ] }, "type": { "type": "intrinsic", @@ -1594,6 +2239,14 @@ "flags": { "isReadonly": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 61, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1607,6 +2260,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1620,6 +2281,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1629,14 +2298,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 95 ] }, { "title": "Properties", - "kind": 1024, "children": [ 102, 100, @@ -1644,6 +2311,14 @@ ] } ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 4, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" + } + ], "extendedBy": [ { "type": "reference", @@ -1659,7 +2334,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with inherited and overwritten constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with inherited and overwritten constructor properties." + } + ] }, "children": [ { @@ -1668,6 +2348,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 23, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L23" + } + ], "signatures": [ { "id": 105, @@ -1675,7 +2363,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 106, @@ -1684,7 +2371,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": [ + { + "kind": "text", + "text": "X component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1698,7 +2390,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Y component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1712,7 +2409,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Z component of the Vector" + "summary": [ + { + "kind": "text", + "text": "Z component of the Vector" + } + ] }, "type": { "type": "intrinsic", @@ -1726,7 +2428,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": [ + { + "kind": "text", + "text": "Vector name" + } + ] }, "type": { "type": "intrinsic", @@ -1760,6 +2467,14 @@ "flags": { "isReadonly": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 27, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L27" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1778,6 +2493,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 10, + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1796,6 +2519,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 25, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L25" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1814,6 +2545,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 26, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L26" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1823,14 +2562,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 104 ] }, { "title": "Properties", - "kind": 1024, "children": [ 112, 113, @@ -1839,6 +2576,14 @@ ] } ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 16, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L16" + } + ], "extendedTypes": [ { "type": "reference", @@ -1851,12 +2596,19 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 94, 103 ] } + ], + "sources": [ + { + "fileName": "constructor-properties.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" + } ] }, { @@ -1873,21 +2625,13 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A decorated class." - }, - "decorators": [ - { - "name": "decoratorWithOptions", - "type": { - "type": "reference", - "id": 123, - "name": "decoratorWithOptions" - }, - "arguments": { - "options": "{\n name: \"Name of class\",\n}" + "summary": [ + { + "kind": "text", + "text": "A decorated class." } - } - ], + ] + }, "children": [ { "id": 129, @@ -1916,25 +2660,12 @@ "kind": 2048, "kindString": "Method", "flags": {}, - "decorators": [ - { - "name": "decoratorAtom", - "type": { - "type": "reference", - "id": 115, - "name": "decoratorAtom" - } - }, + "sources": [ { - "name": "decoratorWithParam", - "type": { - "type": "reference", - "id": 120, - "name": "decoratorWithParam" - }, - "arguments": { - "value": "false" - } + "fileName": "decorators.ts", + "line": 13, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L13" } ], "signatures": [ @@ -1945,7 +2676,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorated method." + "summary": [ + { + "kind": "text", + "text": "A decorated method." + } + ] }, "type": { "type": "intrinsic", @@ -1958,18 +2694,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 129 ] }, { "title": "Methods", - "kind": 2048, "children": [ 131 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 7, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L7" + } ] }, { @@ -1978,11 +2720,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 131, - "name": "decoratedMethod" + "fileName": "decorators.ts", + "line": 19, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L19" } ], "signatures": [ @@ -1993,7 +2736,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with no options." + "summary": [ + { + "kind": "text", + "text": "A decorator with no options." + } + ] }, "parameters": [ { @@ -2004,9 +2752,9 @@ "flags": {}, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -2043,9 +2791,9 @@ "name": "any" } ], + "name": "TypedPropertyDescriptor", "qualifiedName": "TypedPropertyDescriptor", - "package": "typescript", - "name": "TypedPropertyDescriptor" + "package": "typescript" } } ], @@ -2062,11 +2810,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 128, - "name": "DecoratedClass" + "fileName": "decorators.ts", + "line": 48, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ], "signatures": [ @@ -2077,7 +2826,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator consuming an options object." + "summary": [ + { + "kind": "text", + "text": "A decorator consuming an options object." + } + ] }, "parameters": [ { @@ -2087,7 +2841,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The options object of this decorator." + "summary": [ + { + "kind": "text", + "text": "The options object of this decorator." + } + ] }, "type": { "type": "reflection", @@ -2105,8 +2864,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A property on the options object of this decorator.\n" + "summary": [ + { + "kind": "text", + "text": "A property on the options object of this decorator." + } + ] }, + "sources": [ + { + "fileName": "decorators.ts", + "line": 49, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L49" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2116,11 +2888,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 127 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 48, + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" + } ] } } @@ -2128,9 +2907,9 @@ ], "type": { "type": "reference", + "name": "ClassDecorator", "qualifiedName": "ClassDecorator", - "package": "typescript", - "name": "ClassDecorator" + "package": "typescript" } } ] @@ -2141,11 +2920,12 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ + "sources": [ { - "type": "reference", - "id": 131, - "name": "decoratedMethod" + "fileName": "decorators.ts", + "line": 32, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L32" } ], "signatures": [ @@ -2156,7 +2936,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with a parameter." + "summary": [ + { + "kind": "text", + "text": "A decorator with a parameter." + } + ] }, "parameters": [ { @@ -2166,7 +2951,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The parameter of this decorator.\n" + "summary": [ + { + "kind": "text", + "text": "The parameter of this decorator." + } + ] }, "type": { "type": "intrinsic", @@ -2176,9 +2966,9 @@ ], "type": { "type": "reference", + "name": "MethodDecorator", "qualifiedName": "MethodDecorator", - "package": "typescript", - "name": "MethodDecorator" + "package": "typescript" } } ] @@ -2187,20 +2977,26 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 128 ] }, { "title": "Functions", - "kind": 64, "children": [ 115, 123, 120 ] } + ], + "sources": [ + { + "fileName": "decorators.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L4" + } ] }, { @@ -2241,14 +3037,27 @@ { "id": 162, "name": "EVENT_CLICK", - "kind": 8388608, - "kindString": "Event", + "kind": 1024, + "kindString": "Property", "flags": { "isStatic": true }, "comment": { - "shortText": "This is an event documentation." + "summary": [ + { + "kind": "text", + "text": "This is an event documentation." + } + ] }, + "sources": [ + { + "fileName": "events.ts", + "line": 6, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L6" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2259,29 +3068,42 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 163 ] }, { "title": "Events", - "kind": 8388608, "children": [ 162 ] } + ], + "sources": [ + { + "fileName": "events.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 161 ] } + ], + "sources": [ + { + "fileName": "events.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" + } ] }, { @@ -2298,11 +3120,21 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates some information for background http transfers.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "https://github.com/TypeStrong/typedoc/issues/136\n" + "kind": "text", + "text": "Encapsulates some information for background http transfers." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "https://github.com/TypeStrong/typedoc/issues/136" + } + ] } ] }, @@ -2310,18 +3142,49 @@ { "id": 135, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 2048, + "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 14, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" + }, + { + "fileName": "events-overloads.ts", + "line": 23, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" + }, + { + "fileName": "events-overloads.ts", + "line": 32, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" + }, + { + "fileName": "events-overloads.ts", + "line": 41, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" + } + ], "signatures": [ { "id": 136, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for a general event by name." + "summary": [ + { + "kind": "text", + "text": "Subscribe for a general event by name." + } + ] }, "parameters": [ { @@ -2331,7 +3194,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "intrinsic", @@ -2345,7 +3213,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The handler called when the event occurs.\n" + "summary": [ + { + "kind": "text", + "text": "The handler called when the event occurs." + } + ] }, "type": { "type": "reflection", @@ -2355,6 +3228,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 14, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" + } + ], "signatures": [ { "id": 140, @@ -2393,11 +3274,16 @@ { "id": 142, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for error notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for error notifications." + } + ] }, "parameters": [ { @@ -2407,7 +3293,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2421,7 +3312,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive the error details\n" + "summary": [ + { + "kind": "text", + "text": "A handler that will receive the error details" + } + ] }, "type": { "type": "reflection", @@ -2431,6 +3327,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 23, + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" + } + ], "signatures": [ { "id": 146, @@ -2469,11 +3373,16 @@ { "id": 148, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for progress notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for progress notifications." + } + ] }, "parameters": [ { @@ -2483,7 +3392,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2497,7 +3411,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive a progress event with the current and expected total bytes\n" + "summary": [ + { + "kind": "text", + "text": "A handler that will receive a progress event with the current and expected total bytes" + } + ] }, "type": { "type": "reflection", @@ -2507,6 +3426,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 32, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" + } + ], "signatures": [ { "id": 152, @@ -2545,11 +3472,16 @@ { "id": 154, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Subscribe for success notification." + "summary": [ + { + "kind": "text", + "text": "Subscribe for success notification." + } + ] }, "parameters": [ { @@ -2559,7 +3491,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] }, "type": { "type": "literal", @@ -2573,7 +3510,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A function that will be called with general event data upon successful completion\n" + "summary": [ + { + "kind": "text", + "text": "A function that will be called with general event data upon successful completion" + } + ] }, "type": { "type": "reflection", @@ -2583,6 +3525,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 41, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" + } + ], "signatures": [ { "id": 158, @@ -2624,22 +3574,36 @@ "groups": [ { "title": "Events", - "kind": 8388608, "children": [ 135 ] } + ], + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 6, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" + } ] } ], "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 134 ] } + ], + "sources": [ + { + "fileName": "events-overloads.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" + } ] }, { @@ -2656,7 +3620,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "GenericClass short text." + "summary": [ + { + "kind": "text", + "text": "GenericClass short text." + } + ] }, "children": [ { @@ -2665,6 +3634,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" + } + ], "signatures": [ { "id": 168, @@ -2673,7 +3650,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "typeParameter": [ { @@ -2692,7 +3674,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Constructor parameter." + } + ] }, "type": { "type": "reference", @@ -2725,8 +3712,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 9, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" + } + ], "type": { "type": "reference", "id": 169, @@ -2742,8 +3742,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 14, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" + } + ], "type": { "type": "array", "elementType": { @@ -2759,6 +3772,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" + } + ], "signatures": [ { "id": 174, @@ -2767,8 +3788,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", - "returns": "Return value comment.\n" + "summary": [ + { + "kind": "text", + "text": "getValue short text." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Return value comment." + } + ] + } + ] }, "type": { "type": "reference", @@ -2782,14 +3818,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 167 ] }, { "title": "Properties", - "kind": 1024, "children": [ 171, 172 @@ -2797,13 +3831,20 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 173 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "generic-class.ts", + "line": 5, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" + } + ], + "typeParameters": [ { "id": 175, "name": "T", @@ -2811,7 +3852,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Generic parameter." + } + ] } } ], @@ -2830,7 +3876,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "NonGenericClass short text." + "summary": [ + { + "kind": "text", + "text": "NonGenericClass short text." + } + ] }, "children": [ { @@ -2839,6 +3890,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" + } + ], "signatures": [ { "id": 178, @@ -2847,7 +3906,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": [ + { + "kind": "text", + "text": "Constructor short text." + } + ] }, "parameters": [ { @@ -2857,7 +3921,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": [ + { + "kind": "text", + "text": "Constructor parameter." + } + ] }, "type": { "type": "intrinsic", @@ -2892,8 +3961,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 9, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -2913,8 +3995,21 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 14, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" + } + ], "type": { "type": "array", "elementType": { @@ -2934,6 +4029,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" + } + ], "signatures": [ { "id": 183, @@ -2942,8 +4045,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", - "returns": "Return value comment.\n" + "summary": [ + { + "kind": "text", + "text": "getValue short text." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Return value comment." + } + ] + } + ] }, "type": { "type": "intrinsic", @@ -2966,14 +4084,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 177 ] }, { "title": "Properties", - "kind": 1024, "children": [ 180, 181 @@ -2981,12 +4097,19 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 182 ] } ], + "sources": [ + { + "fileName": "generic-class.ts", + "line": 36, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L36" + } + ], "extendedTypes": [ { "type": "reference", @@ -3005,12 +4128,19 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 166, 176 ] } + ], + "sources": [ + { + "fileName": "generic-class.ts", + "line": 5, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" + } ] }, { @@ -3056,6 +4186,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 2, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L2" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -3067,45 +4205,55 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "getSignature": [ + "sources": [ { - "id": 190, - "name": "name", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 4, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L4" + }, + { + "fileName": "getter-setter.ts", + "line": 7, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], - "setSignature": [ - { - "id": 191, - "name": "name", - "kind": 1048576, - "kindString": "Set signature", - "flags": {}, - "parameters": [ - { - "id": 192, - "name": "value", - "kind": 32768, - "kindString": "Parameter", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "getSignature": { + "id": 190, + "name": "name", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + }, + "setSignature": { + "id": 191, + "name": "name", + "kind": 1048576, + "kindString": "Set signature", + "flags": {}, + "parameters": [ + { + "id": 192, + "name": "value", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ], - "type": { - "type": "intrinsic", - "name": "void" } + ], + "type": { + "type": "intrinsic", + "name": "void" } - ] + } }, { "id": 193, @@ -3113,19 +4261,25 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "getSignature": [ + "sources": [ { - "id": 194, - "name": "readOnlyName", - "kind": 524288, - "kindString": "Get signature", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 11, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L11" } - ] + ], + "getSignature": { + "id": 194, + "name": "readOnlyName", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } }, { "id": 195, @@ -3133,69 +4287,87 @@ "kind": 262144, "kindString": "Accessor", "flags": {}, - "setSignature": [ + "sources": [ { - "id": 196, - "name": "writeOnlyName", - "kind": 1048576, - "kindString": "Set signature", - "flags": {}, - "parameters": [ - { - "id": 197, - "name": "value", - "kind": 32768, - "kindString": "Parameter", - "flags": {}, - "type": { - "type": "intrinsic", - "name": "string" - } + "fileName": "getter-setter.ts", + "line": 15, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L15" + } + ], + "setSignature": { + "id": 196, + "name": "writeOnlyName", + "kind": 1048576, + "kindString": "Set signature", + "flags": {}, + "parameters": [ + { + "id": 197, + "name": "value", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ], - "type": { - "type": "intrinsic", - "name": "void" } + ], + "type": { + "type": "intrinsic", + "name": "void" } - ] + } } ], "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 186 ] }, { "title": "Properties", - "kind": 1024, "children": [ 188 ] }, { "title": "Accessors", - "kind": 262144, "children": [ 189, 193, 195 ] } + ], + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 185 ] } + ], + "sources": [ + { + "fileName": "getter-setter.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" + } ] }, { @@ -3212,8 +4384,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "ChainClass comment short text.", - "text": "ChainClass comment text.\n" + "summary": [ + { + "kind": "text", + "text": "ChainClass comment short text.\n\nChainClass comment text." + } + ] }, "children": [ { @@ -3245,6 +4421,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "this.ts", + "line": 10, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L10" + } + ], "signatures": [ { "id": 203, @@ -3253,7 +4437,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Chain method that returns this." + "summary": [ + { + "kind": "text", + "text": "Chain method that returns this." + } + ] }, "type": { "type": "reference", @@ -3267,29 +4456,42 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 200 ] }, { "title": "Methods", - "kind": 2048, "children": [ 202 ] } + ], + "sources": [ + { + "fileName": "this.ts", + "line": 6, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 199 ] } + ], + "sources": [ + { + "fileName": "this.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" + } ] }, { @@ -3358,6 +4560,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 14, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L14" + } + ], "type": { "type": "reference", "id": 213, @@ -3368,20 +4578,26 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 211 ] }, { "title": "Properties", - "kind": 1024, "children": [ 214 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "type-operator.ts", + "line": 13, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" + } + ], + "typeParameters": [ { "id": 215, "name": "T", @@ -3407,12 +4623,27 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 205 + }, + { + "kind": "text", + "text": " @ fixtures" + } + ] } ] }, @@ -3444,6 +4675,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 9, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L9" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -3455,6 +4694,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -3464,38 +4711,50 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 206 ] }, { "title": "Properties", - "kind": 1024, "children": [ 208, 209 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 210, 205 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 21, diff --git a/src/test/converter/class/type-operator.ts b/src/test/converter/class/type-operator.ts index 3edd1f3ad..a9fb7aa12 100644 --- a/src/test/converter/class/type-operator.ts +++ b/src/test/converter/class/type-operator.ts @@ -3,7 +3,7 @@ * * TestClass comment text. * - * @see [[TestClass]] @ fixtures + * @see {@link TestClass} @ fixtures */ export class TestClass { a: string; diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index 08cc145d0..8b5ec6e22 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -10,9 +10,6 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": { - "shortText": "This is a module doc comment with legacy behavior." - }, "children": [ { "id": 2, @@ -21,16 +18,29 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A Comment for a class", - "text": "## Some Markup\n**with more markup**\n\nAn example with decorators that should not parse to tag\n```\n@myDecorator\n@FactoryDecorator('a', 'b', 'c')\nexport class CommentedClass {\n myProp: string = 'myProp';\n\n @PropDecorator() decoratedProp: string;\n\n constructor(@ParamDecorator public param: string) { }\n\n myMethod() { }\n}\n```", - "tags": [ + "summary": [ { - "tag": "deprecated", - "text": "" + "kind": "text", + "text": "A Comment for a class\n\n## Some Markup\n**with more markup**\n\nAn example with decorators that should not parse to tag\n" }, { - "tag": "todo", - "text": "something\n" + "kind": "code", + "text": "```\n@myDecorator\n@FactoryDecorator('a', 'b', 'c')\nexport class CommentedClass {\n myProp: string = 'myProp';\n\n @PropDecorator() decoratedProp: string;\n\n constructor(@ParamDecorator public param: string) { }\n\n myMethod() { }\n}\n```" + } + ], + "blockTags": [ + { + "tag": "@deprecated", + "content": [] + }, + { + "tag": "@todo", + "content": [ + { + "kind": "text", + "text": "something" + } + ] } ] }, @@ -63,8 +73,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "The main prop" + "summary": [ + { + "kind": "text", + "text": "The main prop" + } + ] }, + "sources": [ + { + "fileName": "comment.ts", + "line": 37, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L37" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -84,7 +107,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Mixed hidden 2" + "summary": [ + { + "kind": "text", + "text": "Mixed hidden 2" + } + ] }, "parameters": [ { @@ -121,36 +149,48 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] }, { "title": "Properties", - "kind": 1024, "children": [ 5 ] }, { "title": "Methods", - "kind": 2048, "children": [ 19 ] } + ], + "sources": [ + { + "fileName": "comment.ts", + "line": 33, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L33" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2 ] } + ], + "sources": [ + { + "fileName": "comment.ts", + "line": 5, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L5" + } ] }, { @@ -160,7 +200,20 @@ "kindString": "Module", "flags": {}, "comment": { - "shortText": "This is a module doc with the packageDocumentation tag to mark it as documentation\nfor the whole module. It is *not* documentation for the `multiply` function." + "summary": [ + { + "kind": "text", + "text": "This is a module doc with the packageDocumentation tag to mark it as documentation\nfor the whole module. It is *not* documentation for the " + }, + { + "kind": "code", + "text": "`multiply`" + }, + { + "kind": "text", + "text": " function." + } + ] }, "children": [ { @@ -169,6 +222,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "comment2.ts", + "line": 8, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment2.ts#L8" + } + ], "signatures": [ { "id": 28, @@ -176,6 +237,25 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a module doc with the packageDocumentation tag to mark it as documentation\nfor the whole module. It is *not* documentation for the " + }, + { + "kind": "code", + "text": "`multiply`" + }, + { + "kind": "text", + "text": " function." + } + ], + "modifierTags": [ + "@packageDocumentation" + ] + }, "parameters": [ { "id": 29, @@ -211,11 +291,18 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 27 ] } + ], + "sources": [ + { + "fileName": "comment2.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment2.ts#L8" + } ] }, { @@ -225,7 +312,20 @@ "kindString": "Module", "flags": {}, "comment": { - "shortText": "This is a module doc with the module tag to mark it as documentation\nfor the whole module. It is *not* documentation for the `multiply` function." + "summary": [ + { + "kind": "text", + "text": "This is a module doc with the module tag to mark it as documentation\nfor the whole module. It is *not* documentation for the " + }, + { + "kind": "code", + "text": "`multiply`" + }, + { + "kind": "text", + "text": " function." + } + ] }, "children": [ { @@ -234,6 +334,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "comment3.ts", + "line": 8, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment3.ts#L8" + } + ], "signatures": [ { "id": 33, @@ -241,6 +349,28 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a module doc with the module tag to mark it as documentation\nfor the whole module. It is *not* documentation for the " + }, + { + "kind": "code", + "text": "`multiply`" + }, + { + "kind": "text", + "text": " function." + } + ], + "blockTags": [ + { + "tag": "@module", + "content": [] + } + ] + }, "parameters": [ { "id": 34, @@ -276,11 +406,18 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 32 ] } + ], + "sources": [ + { + "fileName": "comment3.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment3.ts#L8" + } ] }, { @@ -290,7 +427,16 @@ "kindString": "Module", "flags": {}, "comment": { - "shortText": "This is a comment containing a multiline code block\n```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" + "summary": [ + { + "kind": "text", + "text": "This is a comment containing a multiline code block\n" + }, + { + "kind": "code", + "text": "```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" + } + ] }, "children": [ { @@ -299,6 +445,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "comment4.ts", + "line": 11, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment4.ts#L11" + } + ], "signatures": [ { "id": 38, @@ -306,6 +460,24 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a comment containing a multiline code block\n" + }, + { + "kind": "code", + "text": "```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" + } + ], + "blockTags": [ + { + "tag": "@module", + "content": [] + } + ] + }, "parameters": [ { "id": 39, @@ -341,18 +513,24 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 37 ] } + ], + "sources": [ + { + "fileName": "comment4.ts", + "line": 11, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment4.ts#L11" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 26, diff --git a/src/test/converter/declaration/specs.json b/src/test/converter/declaration/specs.json index 9c0eb4ff5..ffe21ba1d 100644 --- a/src/test/converter/declaration/specs.json +++ b/src/test/converter/declaration/specs.json @@ -45,6 +45,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "declaration.d.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L2" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -54,18 +62,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] }, { "title": "Properties", - "kind": 1024, "children": [ 5 ] } + ], + "sources": [ + { + "fileName": "declaration.d.ts", + "line": 1, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L1" + } ] }, { @@ -76,6 +90,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "declaration.d.ts", + "line": 5, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L5" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -85,18 +107,24 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2 ] }, { "title": "Variables", - "kind": 32, "children": [ 6 ] } + ], + "sources": [ + { + "fileName": "declaration.d.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L1" + } ] }, { @@ -138,11 +166,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 9 ] } + ], + "sources": [ + { + "fileName": "export-declaration.d.ts", + "line": 1, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L1" + } ] }, { @@ -177,23 +212,37 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 12 ] } + ], + "sources": [ + { + "fileName": "export-declaration.d.ts", + "line": 3, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L3" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8, 11 ] } + ], + "sources": [ + { + "fileName": "export-declaration.d.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L1" + } ] }, { @@ -211,29 +260,43 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "external.d.ts", + "line": 3, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/external.d.ts#L3" + } + ], "type": { "type": "reference", + "name": "ts.server.ActionSet", "qualifiedName": "ts.server.ActionSet", - "package": "typescript", - "name": "ts.server.ActionSet" + "package": "typescript" } } ], "groups": [ { "title": "Variables", - "kind": 32, "children": [ 15 ] } + ], + "sources": [ + { + "fileName": "external.d.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/external.d.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 7, diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index 979f859bc..bedf333e7 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -12,7 +12,12 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is a module extending an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a module extending an enumeration." + } + ] }, "children": [ { @@ -22,8 +27,21 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This is a variable appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a variable appended to an enumeration." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 48, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L48" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -35,6 +53,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 53, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L53" + } + ], "signatures": [ { "id": 11, @@ -43,7 +69,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a function appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -56,18 +87,30 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 12 ] }, { "title": "Functions", - "kind": 64, "children": [ 10 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 24, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" + }, + { + "fileName": "enum.ts", + "line": 44, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" + } ] }, { @@ -79,7 +122,12 @@ "isConst": true }, "comment": { - "shortText": "This is a const enum." + "summary": [ + { + "kind": "text", + "text": "This is a const enum." + } + ] }, "children": [ { @@ -88,11 +136,18 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 60, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L60" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 15, @@ -100,22 +155,36 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 61, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L61" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 14, 15 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 59, + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L59" + } ] }, { @@ -125,7 +194,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is an enumeration extended by a module." + "summary": [ + { + "kind": "text", + "text": "This is an enumeration extended by a module." + } + ] }, "children": [ { @@ -135,13 +209,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L28" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 7, @@ -150,13 +236,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 33, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L33" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 8, @@ -165,25 +263,50 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 38, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L38" + } + ], "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 6, 7, 8 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 24, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" + }, + { + "fileName": "enum.ts", + "line": 44, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" + } ] }, { @@ -193,7 +316,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is a simple enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a simple enumeration." + } + ] }, "children": [ { @@ -203,13 +331,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 8, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L8" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 3, @@ -218,13 +358,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 13, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L13" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 4, @@ -233,44 +385,69 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 18, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L18" + } + ], "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 2, 3, 4 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 4, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" + } ] } ], "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 9 ] }, { "title": "Enumerations", - "kind": 8, "children": [ 13, 5, 1 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" + } ] } diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index 979f859bc..bedf333e7 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -12,7 +12,12 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is a module extending an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a module extending an enumeration." + } + ] }, "children": [ { @@ -22,8 +27,21 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This is a variable appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a variable appended to an enumeration." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 48, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L48" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -35,6 +53,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 53, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L53" + } + ], "signatures": [ { "id": 11, @@ -43,7 +69,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a function appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -56,18 +87,30 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 12 ] }, { "title": "Functions", - "kind": 64, "children": [ 10 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 24, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" + }, + { + "fileName": "enum.ts", + "line": 44, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" + } ] }, { @@ -79,7 +122,12 @@ "isConst": true }, "comment": { - "shortText": "This is a const enum." + "summary": [ + { + "kind": "text", + "text": "This is a const enum." + } + ] }, "children": [ { @@ -88,11 +136,18 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 60, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L60" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 15, @@ -100,22 +155,36 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "enum.ts", + "line": 61, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L61" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 14, 15 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 59, + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L59" + } ] }, { @@ -125,7 +194,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is an enumeration extended by a module." + "summary": [ + { + "kind": "text", + "text": "This is an enumeration extended by a module." + } + ] }, "children": [ { @@ -135,13 +209,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L28" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 7, @@ -150,13 +236,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 33, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L33" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 8, @@ -165,25 +263,50 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 38, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L38" + } + ], "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 6, 7, 8 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 24, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" + }, + { + "fileName": "enum.ts", + "line": 44, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" + } ] }, { @@ -193,7 +316,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is a simple enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a simple enumeration." + } + ] }, "children": [ { @@ -203,13 +331,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 8, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L8" + } + ], "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 3, @@ -218,13 +358,25 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 13, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L13" + } + ], "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 4, @@ -233,44 +385,69 @@ "kindString": "Enumeration Member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, + "sources": [ + { + "fileName": "enum.ts", + "line": 18, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L18" + } + ], "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 2, 3, 4 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 4, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" + } ] } ], "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 9 ] }, { "title": "Enumerations", - "kind": 8, "children": [ 13, 5, 1 ] } + ], + "sources": [ + { + "fileName": "enum.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" + } ] } diff --git a/src/test/converter/exports/no-doc-members.ts b/src/test/converter/exports/no-doc-members.ts new file mode 100644 index 000000000..274f79d65 --- /dev/null +++ b/src/test/converter/exports/no-doc-members.ts @@ -0,0 +1,6 @@ +/** + * This module has documentation, but no exported members do. + * @see https://github.com/TypeStrong/typedoc/issues/1948 + * @module + */ +export const abc = 123; diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index dd42d5c32..1ab1fdc2f 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -12,73 +12,147 @@ "flags": {}, "children": [ { - "id": 46, + "id": 48, "name": "GH1453Helper", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 42, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L42" + } + ], "target": 35 }, { - "id": 39, + "id": 41, "name": "Mod", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 5, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" + } + ], "target": 29 }, { - "id": 41, + "id": 43, "name": "Mod2", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { - "shortText": "This is a comment for Mod that overwrites the one specified in \"mod\"" + "summary": [ + { + "kind": "text", + "text": "This is a comment for Mod that overwrites the one specified in \"mod\"" + } + ] }, + "sources": [ + { + "fileName": "export.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L14" + } + ], "target": 29 }, { - "id": 40, + "id": 42, "name": "ModDefault", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 5, + "character": 27, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" + } + ], "target": 36 }, { - "id": 45, + "id": 47, "name": "ThisModule", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 40, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L40" + } + ], "target": 34 }, { - "id": 42, + "id": 44, "name": "a", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" + } + ], "target": 30 }, { - "id": 43, + "id": 45, "name": "b", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export of a local under a different name." + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] }, + "sources": [ + { + "fileName": "mod.ts", + "line": 13, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" + } + ], "target": 31 }, { - "id": 38, + "id": 40, "name": "c", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 5, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" + } + ], "target": 30 }, { @@ -94,6 +168,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 31, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L31" + } + ], "type": { "type": "reference", "id": 29, @@ -108,6 +190,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export.ts", + "line": 28, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L28" + } + ], "type": { "type": "literal", "value": 1 @@ -122,6 +212,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export.ts", + "line": 26, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L26" + } + ], "type": { "type": "reference", "id": 29, @@ -137,6 +235,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export.ts", + "line": 29, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L29" + } + ], "type": { "type": "reference", "id": 29, @@ -152,6 +258,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export.ts", + "line": 27, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L27" + } + ], "type": { "type": "reference", "id": 29, @@ -163,14 +277,12 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 25 ] }, { "title": "Variables", - "kind": 32, "children": [ 23, 21, @@ -178,6 +290,14 @@ 22 ] } + ], + "sources": [ + { + "fileName": "export.ts", + "line": 25, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L25" + } ] }, { @@ -186,6 +306,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 7, + "character": 9, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L7" + } + ], "signatures": [ { "id": 16, @@ -230,6 +358,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "export.ts", + "line": 18, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L18" + } + ], "signatures": [ { "id": 27, @@ -261,33 +397,38 @@ "groups": [ { "title": "References", - "kind": 16777216, "children": [ - 46, - 39, + 48, 41, - 40, - 45, - 42, 43, - 38 + 42, + 47, + 44, + 45, + 40 ] }, { "title": "Namespaces", - "kind": 4, "children": [ 20 ] }, { "title": "Functions", - "kind": 64, "children": [ 15, 26 ] } + ], + "sources": [ + { + "fileName": "export.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L1" + } ] }, { @@ -303,6 +444,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "export-assignment.ts", + "line": 1, + "character": 9, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-assignment.ts#L1" + } + ], "signatures": [ { "id": 3, @@ -345,11 +494,18 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 2 ] } + ], + "sources": [ + { + "fileName": "export-assignment.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-assignment.ts#L1" + } ] }, { @@ -367,6 +523,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export-default.ts", + "line": 1, + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-default.ts#L1" + } + ], "type": { "type": "literal", "value": 5 @@ -377,11 +541,18 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 7 ] } + ], + "sources": [ + { + "fileName": "export-default.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-default.ts#L1" + } ] }, { @@ -399,6 +570,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "export-with-local.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L1" + } + ], "type": { "type": "literal", "value": 5 @@ -411,6 +590,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "export-with-local.ts", + "line": 6, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L6" + } + ], "signatures": [ { "id": 10, @@ -453,18 +640,24 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 13 ] }, { "title": "Functions", - "kind": 64, "children": [ 9 ] } + ], + "sources": [ + { + "fileName": "export-with-local.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L1" + } ] }, { @@ -473,38 +666,69 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": { - "shortText": "Doc comment for Mod" - }, "children": [ { "id": 34, "name": "ThisModule", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 40, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L40" + } + ], "target": 29 }, { "id": 31, "name": "b", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export of a local under a different name." + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] }, + "sources": [ + { + "fileName": "mod.ts", + "line": 13, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" + } + ], "target": 30 }, { "id": 32, "name": "c", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export with a module specifier that comes from this file." + "summary": [ + { + "kind": "text", + "text": "An export with a module specifier that comes from this file." + } + ] }, + "sources": [ + { + "fileName": "mod.ts", + "line": 18, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L18" + } + ], "target": 30 }, { @@ -513,6 +737,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 42, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L42" + } + ], "type": { "type": "literal", "value": "1" @@ -527,8 +759,21 @@ "isConst": true }, "comment": { - "shortText": "A simple named export that will be exported from export.ts" + "summary": [ + { + "kind": "text", + "text": "Doc comment for Mod" + } + ] }, + "sources": [ + { + "fileName": "mod.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" + } + ], "type": { "type": "literal", "value": 1 @@ -541,6 +786,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 23, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L23" + } + ], "signatures": [ { "id": 37, @@ -549,7 +802,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Will not be re-exported from export.ts using export * from..." + "summary": [ + { + "kind": "text", + "text": "Will not be re-exported from export.ts using export * from..." + } + ] }, "type": { "type": "intrinsic", @@ -562,7 +820,6 @@ "groups": [ { "title": "References", - "kind": 16777216, "children": [ 34, 31, @@ -571,38 +828,109 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 35 ] }, { "title": "Variables", - "kind": 32, "children": [ 30 ] }, { "title": "Functions", - "kind": 64, "children": [ 36 ] } + ], + "sources": [ + { + "fileName": "mod.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" + } + ] + }, + { + "id": 38, + "name": "no-doc-members", + "kind": 2, + "kindString": "Module", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This module has documentation, but no exported members do." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "https://github.com/TypeStrong/typedoc/issues/1948" + } + ] + } + ] + }, + "children": [ + { + "id": 39, + "name": "abc", + "kind": 32, + "kindString": "Variable", + "flags": { + "isConst": true + }, + "sources": [ + { + "fileName": "no-doc-members.ts", + "line": 6, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/no-doc-members.ts#L6" + } + ], + "type": { + "type": "literal", + "value": 123 + }, + "defaultValue": "123" + } + ], + "groups": [ + { + "title": "Variables", + "children": [ + 39 + ] + } + ], + "sources": [ + { + "fileName": "no-doc-members.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/no-doc-members.ts#L6" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 14, 1, 6, 8, - 29 + 29, + 38 ] } ] diff --git a/src/test/converter/exports/specs.nodoc.json b/src/test/converter/exports/specs.nodoc.json new file mode 100644 index 000000000..3698dffe5 --- /dev/null +++ b/src/test/converter/exports/specs.nodoc.json @@ -0,0 +1,278 @@ +{ + "id": 0, + "name": "typedoc", + "kind": 1, + "flags": {}, + "children": [ + { + "id": 14, + "name": "export", + "kind": 2, + "kindString": "Module", + "flags": {}, + "children": [ + { + "id": 43, + "name": "Mod2", + "kind": 8388608, + "kindString": "Reference", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a comment for Mod that overwrites the one specified in \"mod\"" + } + ] + }, + "sources": [ + { + "fileName": "export.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L14" + } + ], + "target": 29 + }, + { + "id": 45, + "name": "b", + "kind": 8388608, + "kindString": "Reference", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] + }, + "sources": [ + { + "fileName": "mod.ts", + "line": 13, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" + } + ], + "target": 31 + } + ], + "groups": [ + { + "title": "References", + "children": [ + 43, + 45 + ] + } + ], + "sources": [ + { + "fileName": "export.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L1" + } + ] + }, + { + "id": 29, + "name": "mod", + "kind": 2, + "kindString": "Module", + "flags": {}, + "children": [ + { + "id": 31, + "name": "b", + "kind": 8388608, + "kindString": "Reference", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] + }, + "sources": [ + { + "fileName": "mod.ts", + "line": 13, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" + } + ], + "target": 30 + }, + { + "id": 32, + "name": "c", + "kind": 8388608, + "kindString": "Reference", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export with a module specifier that comes from this file." + } + ] + }, + "sources": [ + { + "fileName": "mod.ts", + "line": 18, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L18" + } + ], + "target": 30 + }, + { + "id": 30, + "name": "a", + "kind": 32, + "kindString": "Variable", + "flags": { + "isConst": true + }, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Doc comment for Mod" + } + ] + }, + "sources": [ + { + "fileName": "mod.ts", + "line": 8, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" + } + ], + "type": { + "type": "literal", + "value": 1 + }, + "defaultValue": "1" + }, + { + "id": 36, + "name": "default", + "kind": 64, + "kindString": "Function", + "flags": {}, + "sources": [ + { + "fileName": "mod.ts", + "line": 23, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L23" + } + ], + "signatures": [ + { + "id": 37, + "name": "default", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Will not be re-exported from export.ts using export * from..." + } + ] + }, + "type": { + "type": "intrinsic", + "name": "void" + } + } + ] + } + ], + "groups": [ + { + "title": "References", + "children": [ + 31, + 32 + ] + }, + { + "title": "Variables", + "children": [ + 30 + ] + }, + { + "title": "Functions", + "children": [ + 36 + ] + } + ], + "sources": [ + { + "fileName": "mod.ts", + "line": 8, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" + } + ] + }, + { + "id": 38, + "name": "no-doc-members", + "kind": 2, + "kindString": "Module", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This module has documentation, but no exported members do." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "https://github.com/TypeStrong/typedoc/issues/1948" + } + ] + } + ] + }, + "sources": [ + { + "fileName": "no-doc-members.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/no-doc-members.ts#L6" + } + ] + } + ], + "groups": [ + { + "title": "Modules", + "children": [ + 14, + 29, + 38 + ] + } + ] +} diff --git a/src/test/converter/function/function.ts b/src/test/converter/function/function.ts index 827e35b74..e897da786 100644 --- a/src/test/converter/function/function.ts +++ b/src/test/converter/function/function.ts @@ -13,10 +13,10 @@ export function exportedFunction(): void {} * @param paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * const value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * * @returns This is the return value of the function. */ @@ -90,10 +90,10 @@ export function functionWithRest(...rest: string[]): string { * @param destructuredParam.paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * const value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * * @returns This is the return value of the function. */ @@ -121,10 +121,10 @@ export function functionWithADestructuredParameter({ * @param destructuredParam.paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * const value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * * @returns This is the return value of the function. */ @@ -156,10 +156,10 @@ export function functionWithADestructuredParameterAndExtraParameters( * @param destructuredParam.paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * const value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * * @returns This is the return value of the function. */ diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 084d19e94..ee92e7b76 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -24,6 +24,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 305, + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" + } + ], "signatures": [ { "id": 82, @@ -42,11 +50,24 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 81 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 304, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L304" + }, + { + "fileName": "function.ts", + "line": 305, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" + } ] }, { @@ -56,7 +77,12 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is the module extending the function moduleFunction()." + "summary": [ + { + "kind": "text", + "text": "This is the module extending the function moduleFunction()." + } + ] }, "children": [ { @@ -66,8 +92,21 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This variable is appended to a function." + "summary": [ + { + "kind": "text", + "text": "This variable is appended to a function." + } + ] }, + "sources": [ + { + "fileName": "function.ts", + "line": 264, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L264" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -79,6 +118,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 269, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L269" + } + ], "signatures": [ { "id": 57, @@ -87,7 +134,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This function is appended to another function." + "summary": [ + { + "kind": "text", + "text": "This function is appended to another function." + } + ] }, "type": { "type": "intrinsic", @@ -102,6 +154,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 274, + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L274" + } + ], "signatures": [ { "id": 59, @@ -110,7 +170,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This function is appended to another function." + "summary": [ + { + "kind": "text", + "text": "This function is appended to another function." + } + ] }, "type": { "type": "intrinsic", @@ -123,19 +188,31 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 60 ] }, { "title": "Functions", - "kind": 64, "children": [ 56, 58 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 218, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L218" + }, + { + "fileName": "function.ts", + "line": 260, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L260" + } ] }, { @@ -172,6 +249,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 285, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L285" + } + ], "signatures": [ { "id": 98, @@ -197,6 +282,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 281, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L281" + } + ], "signatures": [ { "id": 96, @@ -224,6 +317,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "function.ts", + "line": 284, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L284" + } + ], "signatures": [ { "id": 91, @@ -260,6 +361,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "function.ts", + "line": 278, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L278" + } + ], "signatures": [ { "id": 88, @@ -296,14 +405,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 93 ] }, { "title": "Methods", - "kind": 2048, "children": [ 97, 95, @@ -311,6 +418,14 @@ 87 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 277, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L277" + } ] }, { @@ -319,6 +434,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 293, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L293" + } + ], "signatures": [ { "id": 100, @@ -326,10 +449,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "Returns true if fn returns true for every item in the iterator", - "text": "Returns true if the iterator is empty\n" - }, "typeParameter": [ { "id": 101, @@ -354,6 +473,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 294, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L294" + } + ], "signatures": [ { "id": 104, @@ -399,9 +526,9 @@ "name": "T" } ], + "name": "Iterable", "qualifiedName": "Iterable", - "package": "typescript", - "name": "Iterable" + "package": "typescript" } } ], @@ -416,10 +543,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "Returns true if fn returns true for every item in the iterator", - "text": "Returns true if the iterator is empty\n" - }, "typeParameter": [ { "id": 108, @@ -444,6 +567,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 295, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L295" + } + ], "signatures": [ { "id": 111, @@ -483,6 +614,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 295, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L295" + } + ], "signatures": [ { "id": 114, @@ -506,9 +645,9 @@ "name": "T" } ], + "name": "Iterable", "qualifiedName": "Iterable", - "package": "typescript", - "name": "Iterable" + "package": "typescript" } } ], @@ -529,6 +668,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 241, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L241" + } + ], "signatures": [ { "id": 68, @@ -537,7 +684,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Asserts that an argument is not null." + "summary": [ + { + "kind": "text", + "text": "Asserts that an argument is not null." + } + ] }, "typeParameter": [ { @@ -555,9 +707,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "\n" - }, "type": { "type": "union", "types": [ @@ -597,6 +746,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 227, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L227" + } + ], "signatures": [ { "id": 62, @@ -605,7 +762,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is an assertion function." + "summary": [ + { + "kind": "text", + "text": "This is an assertion function." + } + ] }, "parameters": [ { @@ -615,7 +777,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The condition that is asserted to be true when this function returns.\n" + "summary": [ + { + "kind": "text", + "text": "The condition that is asserted to be true when this function returns." + } + ] }, "type": { "type": "intrinsic", @@ -637,6 +804,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 298, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L298" + } + ], "signatures": [ { "id": 76, @@ -679,6 +854,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 233, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L233" + } + ], "signatures": [ { "id": 65, @@ -687,7 +870,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Assertion function with a type." + "summary": [ + { + "kind": "text", + "text": "Assertion function with a type." + } + ] }, "parameters": [ { @@ -696,9 +884,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "\n" - }, "type": { "type": "intrinsic", "name": "any" @@ -723,6 +908,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 4, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L4" + } + ], "signatures": [ { "id": 3, @@ -731,7 +924,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a simple exported function." + "summary": [ + { + "kind": "text", + "text": "This is a simple exported function." + } + ] }, "type": { "type": "intrinsic", @@ -746,6 +944,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 100, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L100" + } + ], "signatures": [ { "id": 24, @@ -754,8 +960,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a destructured parameter.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with a destructured parameter." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -765,7 +986,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is the parameter that is destructured." + "summary": [ + { + "kind": "text", + "text": "This is the parameter that is destructured." + } + ] }, "originalName": "__namedParameters", "type": { @@ -784,13 +1010,30 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "\n This is a **parameter** pointing to an interface.\n\n ~~~\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ~~~\n" + "summary": [ + { + "kind": "text", + "text": "This is a **parameter** pointing to an interface.\n\n " + }, + { + "kind": "code", + "text": "```\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ```" + } + ] }, + "sources": [ + { + "fileName": "function.ts", + "line": 107, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L107" + } + ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -800,8 +1043,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" + "summary": [ + { + "kind": "text", + "text": "This is a parameter flagged with any.\n This sentence is placed in the next line." + } + ] }, + "sources": [ + { + "fileName": "function.ts", + "line": 106, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L106" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -814,8 +1070,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "This is a string parameter." + "summary": [ + { + "kind": "text", + "text": "This is a string parameter." + } + ] }, + "sources": [ + { + "fileName": "function.ts", + "line": 105, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L105" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -825,13 +1094,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 29, 28, 27 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 104, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L104" + } ] } } @@ -850,6 +1126,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 166, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L166" + } + ], "signatures": [ { "id": 39, @@ -858,8 +1142,39 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a destructured parameter and an extra `@param` directive with no corresponding parameter.\nThe `@param` directives are ignored because we cannot be certain which corresponds to the real parameter.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with a destructured parameter and an extra " + }, + { + "kind": "code", + "text": "`@param`" + }, + { + "kind": "text", + "text": " directive with no corresponding parameter.\nThe " + }, + { + "kind": "code", + "text": "`@param`" + }, + { + "kind": "text", + "text": " directives are ignored because we cannot be certain which corresponds to the real parameter." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -883,11 +1198,19 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 173, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L173" + } + ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -896,6 +1219,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 172, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L172" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -907,6 +1238,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 171, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L171" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -916,13 +1255,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 44, 43, 42 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 170, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L170" + } ] } } @@ -941,6 +1287,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 131, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L131" + } + ], "signatures": [ { "id": 31, @@ -949,8 +1303,31 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a destructured parameter and additional undocumented parameters.\nThe `@param` directives are ignored because we cannot be certain which parameter they refer to.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with a destructured parameter and additional undocumented parameters.\nThe " + }, + { + "kind": "code", + "text": "`@param`" + }, + { + "kind": "text", + "text": " directives are ignored because we cannot be certain which parameter they refer to." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -974,11 +1351,19 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 139, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L139" + } + ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -987,6 +1372,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 138, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L138" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -998,6 +1391,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 137, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L137" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1007,13 +1408,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 36, 35, 34 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 136, + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L136" + } ] } } @@ -1043,6 +1451,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 62, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L62" + } + ], "signatures": [ { "id": 14, @@ -1051,8 +1467,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a parameter that has a default value.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with a parameter that has a default value." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -1062,7 +1493,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default string value." + "summary": [ + { + "kind": "text", + "text": "A parameter with a default string value." + } + ] }, "type": { "type": "intrinsic", @@ -1077,7 +1513,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default numeric value." + "summary": [ + { + "kind": "text", + "text": "A parameter with a default numeric value." + } + ] }, "type": { "type": "intrinsic", @@ -1092,7 +1533,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default NaN value." + "summary": [ + { + "kind": "text", + "text": "A parameter with a default NaN value." + } + ] }, "type": { "type": "intrinsic", @@ -1107,7 +1553,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default boolean value." + "summary": [ + { + "kind": "text", + "text": "A parameter with a default boolean value." + } + ] }, "type": { "type": "intrinsic", @@ -1122,7 +1573,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default null value." + "summary": [ + { + "kind": "text", + "text": "A parameter with a default null value." + } + ] }, "type": { "type": "intrinsic", @@ -1144,6 +1600,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 47, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L47" + } + ], "signatures": [ { "id": 10, @@ -1152,7 +1616,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a parameter that is optional." + "summary": [ + { + "kind": "text", + "text": "This is a function with a parameter that is optional." + } + ] }, "parameters": [ { @@ -1162,7 +1631,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A normal parameter." + "summary": [ + { + "kind": "text", + "text": "A normal parameter." + } + ] }, "type": { "type": "intrinsic", @@ -1178,7 +1652,12 @@ "isOptional": true }, "comment": { - "shortText": "An optional parameter.\n" + "summary": [ + { + "kind": "text", + "text": "An optional parameter." + } + ] }, "type": { "type": "intrinsic", @@ -1199,6 +1678,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 23, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L23" + } + ], "signatures": [ { "id": 5, @@ -1207,8 +1694,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with multiple arguments and a return value.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with multiple arguments and a return value." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -1218,7 +1720,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is a string parameter." + "summary": [ + { + "kind": "text", + "text": "This is a string parameter." + } + ] }, "type": { "type": "intrinsic", @@ -1232,7 +1739,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" + "summary": [ + { + "kind": "text", + "text": "This is a parameter flagged with any.\n This sentence is placed in the next line." + } + ] }, "type": { "type": "intrinsic", @@ -1246,13 +1758,22 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n This is a **parameter** pointing to an interface.\n\n ~~~\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ~~~\n" + "summary": [ + { + "kind": "text", + "text": "This is a **parameter** pointing to an interface.\n\n " + }, + { + "kind": "code", + "text": "```\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ```" + } + ] }, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } } ], @@ -1269,6 +1790,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 78, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L78" + } + ], "signatures": [ { "id": 21, @@ -1277,8 +1806,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with rest parameter.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is a function with rest parameter." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This is the return value of the function." + } + ] + } + ] }, "parameters": [ { @@ -1290,7 +1834,12 @@ "isRest": true }, "comment": { - "shortText": "The rest parameter." + "summary": [ + { + "kind": "text", + "text": "The rest parameter." + } + ] }, "type": { "type": "array", @@ -1314,6 +1863,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 253, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L253" + } + ], "signatures": [ { "id": 72, @@ -1322,7 +1879,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Checks that an argument is not null." + "summary": [ + { + "kind": "text", + "text": "Checks that an argument is not null." + } + ] }, "typeParameter": [ { @@ -1340,9 +1902,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "\n" - }, "type": { "type": "union", "types": [ @@ -1382,6 +1941,20 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 304, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L304" + }, + { + "fileName": "function.ts", + "line": 305, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" + } + ], "signatures": [ { "id": 79, @@ -1402,6 +1975,20 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 218, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L218" + }, + { + "fileName": "function.ts", + "line": 260, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L260" + } + ], "signatures": [ { "id": 53, @@ -1410,7 +1997,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function that is extended by a module." + "summary": [ + { + "kind": "text", + "text": "This is a function that is extended by a module." + } + ] }, "parameters": [ { @@ -1420,7 +2012,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "An argument.\n" + "summary": [ + { + "kind": "text", + "text": "An argument." + } + ] }, "type": { "type": "intrinsic", @@ -1441,6 +2038,26 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 183, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L183" + }, + { + "fileName": "function.ts", + "line": 191, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" + }, + { + "fileName": "function.ts", + "line": 201, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L201" + } + ], "signatures": [ { "id": 46, @@ -1449,8 +2066,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is the first signature of a function with multiple signatures.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is the first signature of a function with multiple signatures." + } + ] }, "parameters": [ { @@ -1460,7 +2081,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name value.\n" + "summary": [ + { + "kind": "text", + "text": "The name value." + } + ] }, "type": { "type": "intrinsic", @@ -1480,8 +2106,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is the second signature of a function with multiple signatures.", - "returns": "This is the return value of the function.\n" + "summary": [ + { + "kind": "text", + "text": "This is the second signature of a function with multiple signatures." + } + ] }, "parameters": [ { @@ -1491,7 +2121,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "An object containing the name value." + "summary": [ + { + "kind": "text", + "text": "An object containing the name value." + } + ] }, "type": { "type": "reflection", @@ -1509,8 +2144,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A value of the object.\n" + "summary": [ + { + "kind": "text", + "text": "A value of the object." + } + ] }, + "sources": [ + { + "fileName": "function.ts", + "line": 191, + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1520,11 +2168,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 51 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 191, + "character": 42, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" + } ] } } @@ -1543,6 +2198,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "function.ts", + "line": 37, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L37" + } + ], "signatures": [ { "id": 84, @@ -1550,10 +2213,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "This is a function that is assigned to a variable.", - "returns": "This is the return value of the function.\n" - }, "parameters": [ { "id": 85, @@ -1561,9 +2220,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "This is some numeric parameter." - }, "type": { "type": "intrinsic", "name": "number" @@ -1581,7 +2237,6 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 80, 55 @@ -1589,14 +2244,12 @@ }, { "title": "Classes", - "kind": 128, "children": [ 86 ] }, { "title": "Functions", - "kind": 64, "children": [ 99, 67, @@ -1618,6 +2271,14 @@ 83 ] } + ], + "sources": [ + { + "fileName": "function.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L4" + } ] }, { @@ -1633,6 +2294,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "generic-function.ts", + "line": 18, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L18" + } + ], "signatures": [ { "id": 122, @@ -1641,8 +2310,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A function with a generic type array parameter.", - "returns": "A generic array.\n" + "summary": [ + { + "kind": "text", + "text": "A function with a generic type array parameter." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "A generic array." + } + ] + } + ] }, "typeParameter": [ { @@ -1661,7 +2345,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A generic parameter." + "summary": [ + { + "kind": "text", + "text": "A generic parameter." + } + ] }, "type": { "type": "reference", @@ -1676,7 +2365,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A generic array parameter." + "summary": [ + { + "kind": "text", + "text": "A generic array parameter." + } + ] }, "type": { "type": "array", @@ -1705,6 +2399,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "generic-function.ts", + "line": 29, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L29" + } + ], "signatures": [ { "id": 127, @@ -1712,7 +2414,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "typeParameter": [ { "id": 128, @@ -1721,7 +2422,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "this describes T\n" + "summary": [ + { + "kind": "text", + "text": "this describes T" + } + ] } } ], @@ -1733,7 +2439,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "this describes param" + "summary": [ + { + "kind": "text", + "text": "this describes param" + } + ] }, "type": { "type": "reference", @@ -1756,6 +2467,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "generic-function.ts", + "line": 7, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L7" + } + ], "signatures": [ { "id": 118, @@ -1764,8 +2483,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Generic function short text.", - "returns": "Generic function return value.\n" + "summary": [ + { + "kind": "text", + "text": "Generic function short text." + } + ], + "blockTags": [ + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Generic function return value." + } + ] + } + ] }, "typeParameter": [ { @@ -1775,13 +2509,18 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic function type parameter." + "summary": [ + { + "kind": "text", + "text": "Generic function type parameter." + } + ] }, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } } ], @@ -1793,7 +2532,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Generic function parameter." + "summary": [ + { + "kind": "text", + "text": "Generic function parameter." + } + ] }, "type": { "type": "reference", @@ -1814,13 +2558,20 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 121, 126, 117 ] } + ], + "sources": [ + { + "fileName": "generic-function.ts", + "line": 7, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L7" + } ] }, { @@ -1843,6 +2594,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 3, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L3" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1854,6 +2613,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L2" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1863,12 +2630,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 141, 140 ] } + ], + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L1" + } ] }, { @@ -1877,6 +2651,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 14, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L14" + } + ], "signatures": [ { "id": 132, @@ -1899,6 +2681,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 9, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L9" + } + ], "type": { "type": "reference", "id": 139, @@ -1911,6 +2701,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 8, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L8" + } + ], "type": { "type": "reference", "id": 139, @@ -1923,6 +2721,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 7, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L7" + } + ], "type": { "type": "reference", "id": 139, @@ -1935,6 +2741,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L10" + } + ], "type": { "type": "reference", "id": 139, @@ -1947,6 +2761,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 11, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L11" + } + ], "type": { "type": "reference", "id": 139, @@ -1957,7 +2779,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 136, 135, @@ -1966,6 +2787,14 @@ 138 ] } + ], + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 6, + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L6" + } ] } } @@ -1976,25 +2805,30 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 139 ] }, { "title": "Functions", - "kind": 64, "children": [ 131 ] } + ], + "sources": [ + { + "fileName": "implicit-types.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 116, diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index 968d0f64b..a3ee632ed 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -39,6 +39,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 11, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L11" + } + ], "signatures": [ { "id": 10, @@ -46,7 +54,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 11, @@ -55,7 +62,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": [ + { + "kind": "text", + "text": "Parameter A." + } + ] }, "type": { "type": "intrinsic", @@ -69,7 +81,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": [ + { + "kind": "text", + "text": "Parameter B." + } + ] }, "type": { "type": "intrinsic", @@ -98,19 +115,25 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 7 ] }, { "title": "Methods", - "kind": 2048, "children": [ 9 ] } ], + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 9, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L9" + } + ], "implementedTypes": [ { "type": "reference", @@ -153,6 +176,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L20" + } + ], "signatures": [ { "id": 17, @@ -160,7 +191,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 18, @@ -169,7 +199,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Custom parameter A doc.\n" + "summary": [ + { + "kind": "text", + "text": "Custom parameter A doc." + } + ] }, "type": { "type": "intrinsic", @@ -183,7 +218,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": [ + { + "kind": "text", + "text": "Parameter B." + } + ] }, "type": { "type": "intrinsic", @@ -212,19 +252,25 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 14 ] }, { "title": "Methods", - "kind": 2048, "children": [ 16 ] } ], + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 14, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L14" + } + ], "implementedTypes": [ { "type": "reference", @@ -267,6 +313,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 29, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L29" + } + ], "signatures": [ { "id": 24, @@ -274,7 +328,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 25, @@ -283,7 +336,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": [ + { + "kind": "text", + "text": "Parameter A." + } + ] }, "type": { "type": "intrinsic", @@ -297,7 +355,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Custom second parameter doc with name change.\n" + "summary": [ + { + "kind": "text", + "text": "Custom second parameter doc with name change." + } + ] }, "type": { "type": "intrinsic", @@ -326,19 +389,25 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 21 ] }, { "title": "Methods", - "kind": 2048, "children": [ 23 ] } ], + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 23, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L23" + } + ], "implementedTypes": [ { "type": "reference", @@ -360,6 +429,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L6" + } + ], "signatures": [ { "id": 3, @@ -367,7 +444,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 4, @@ -376,7 +452,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": [ + { + "kind": "text", + "text": "Parameter A." + } + ] }, "type": { "type": "intrinsic", @@ -390,7 +471,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": [ + { + "kind": "text", + "text": "Parameter B." + } + ] }, "type": { "type": "intrinsic", @@ -409,12 +495,19 @@ "groups": [ { "title": "Methods", - "kind": 2048, "children": [ 2 ] } ], + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L1" + } + ], "implementedBy": [ { "type": "reference", @@ -437,7 +530,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 6, 13, @@ -446,10 +538,17 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 1 ] } + ], + "sources": [ + { + "fileName": "inherit-param-doc.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L1" + } ] } diff --git a/src/test/converter/inheritance/inherit-doc.ts b/src/test/converter/inheritance/inherit-doc.ts index 9b6a34e90..aca0bba88 100644 --- a/src/test/converter/inheritance/inherit-doc.ts +++ b/src/test/converter/inheritance/inherit-doc.ts @@ -46,7 +46,7 @@ export interface InterfaceTarget { * * Remarks will be inherited * - * @example + * @customBlock * * This part of the commentary will not be inherited * diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 9b224c8e8..7cf03133f 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -18,7 +18,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Source interface summary" + "summary": [ + { + "kind": "text", + "text": "Source interface summary" + } + ] }, "children": [ { @@ -28,15 +33,33 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Source interface property description", - "tags": [ + "summary": [ { - "tag": "typeparam", - "text": "Source interface type parameter\n", - "param": "T" + "kind": "text", + "text": "Source interface property description" + } + ], + "blockTags": [ + { + "tag": "@typeParam", + "name": "T", + "content": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ] } ] }, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 12, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L12" + } + ], "type": { "type": "reference", "id": 19, @@ -49,6 +72,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 19, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L19" + } + ], "signatures": [ { "id": 17, @@ -57,7 +88,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "summary": [ + { + "kind": "text", + "text": "Source interface method description" + } + ] }, "parameters": [ { @@ -66,9 +102,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "\n" - }, "type": { "type": "intrinsic", "name": "number" @@ -87,20 +120,26 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 15 ] }, { "title": "Methods", - "kind": 2048, "children": [ 16 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 6, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L6" + } + ], + "typeParameters": [ { "id": 19, "name": "T", @@ -108,7 +147,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Source interface type parameter\n" + "summary": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ] } } ] @@ -120,7 +164,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Source interface summary" + "summary": [ + { + "kind": "text", + "text": "Source interface summary" + } + ] }, "children": [ { @@ -130,8 +179,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Source interface property description" + "summary": [ + { + "kind": "text", + "text": "Source interface property description" + } + ] }, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 30, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L30" + } + ], "type": { "type": "reference", "id": 25, @@ -144,6 +206,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 37, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L37" + } + ], "signatures": [ { "id": 23, @@ -152,18 +222,20 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "summary": [ + { + "kind": "text", + "text": "Source interface method description" + } + ] }, "parameters": [ { - "id": 18, + "id": 24, "name": "arg", "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "shortText": "\n" - }, "type": { "type": "intrinsic", "name": "number" @@ -182,28 +254,39 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 21 ] }, { "title": "Methods", - "kind": 2048, "children": [ 22 ] } ], - "typeParameter": [ + "sources": [ { - "id": 19, + "fileName": "inherit-doc.ts", + "line": 26, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L26" + } + ], + "typeParameters": [ + { + "id": 25, "name": "T", "kind": 131072, "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Source interface type parameter\n" + "summary": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ] } } ] @@ -214,6 +297,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 58, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L58" + } + ], "signatures": [ { "id": 3, @@ -222,17 +313,39 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", - "returns": "Stringified sum or concatenation of numeric arguments\n", - "tags": [ + "summary": [ + { + "kind": "text", + "text": "Function summary\n\nThis part of the commentary will be inherited by other entities" + } + ], + "blockTags": [ { - "tag": "remarks", - "text": "\n\nRemarks will be inherited\n" + "tag": "@remarks", + "content": [ + { + "kind": "text", + "text": "Remarks will be inherited" + } + ] }, { - "tag": "example", - "text": "\n\nThis part of the commentary will not be inherited\n" + "tag": "@customBlock", + "content": [ + { + "kind": "text", + "text": "This part of the commentary will not be inherited" + } + ] + }, + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Stringified sum or concatenation of numeric arguments" + } + ] } ] }, @@ -244,7 +357,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "Type of arguments" + } + ] } } ], @@ -256,7 +374,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "First argument" + } + ] }, "type": { "type": "reference", @@ -271,7 +394,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "Second argument" + } + ] }, "type": { "type": "reference", @@ -293,6 +421,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 68, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L68" + } + ], "signatures": [ { "id": 8, @@ -301,11 +437,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "tags": [ + "summary": [], + "blockTags": [ { - "tag": "inheritdoc", - "text": "\n", - "param": "SubClassA.printName" + "tag": "@inheritDoc", + "name": "SubClassA.printName", + "content": [] } ] }, @@ -322,6 +459,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 85, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L85" + } + ], "signatures": [ { "id": 10, @@ -330,60 +475,114 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", - "returns": "This will be inherited\n\n", - "tags": [ + "summary": [ + { + "kind": "text", + "text": "Function summary\n\nThis part of the commentary will be inherited by other entities" + } + ], + "blockTags": [ + { + "tag": "@remarks", + "content": [ + { + "kind": "text", + "text": "Remarks will be inherited" + } + ] + }, { - "tag": "example", - "text": "\n\nThis function inherited commentary from the `functionSource` function\n" + "tag": "@example", + "content": [ + { + "kind": "text", + "text": "This function inherited commentary from the " + }, + { + "kind": "code", + "text": "`functionSource`" + }, + { + "kind": "text", + "text": " function" + } + ] }, { - "tag": "remarks", - "text": "\n\nRemarks will be inherited\n" + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "This will be inherited" + } + ] + }, + { + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Stringified sum or concatenation of numeric arguments" + } + ] } ] }, "typeParameter": [ { - "id": 4, + "id": 11, "name": "T", "kind": 131072, "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "Type of arguments" + } + ] } } ], "parameters": [ { - "id": 5, + "id": 12, "name": "arg1", "kind": 32768, "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "First argument" + } + ] }, "type": { "type": "reference", - "id": 4, + "id": 11, "name": "T" } }, { - "id": 6, + "id": 13, "name": "arg2", "kind": 32768, "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "Second argument" + } + ] }, "type": { "type": "reference", - "id": 4, + "id": 11, "name": "T" } } @@ -399,7 +598,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 14, 20 @@ -407,13 +605,20 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 7, 9 ] } + ], + "sources": [ + { + "fileName": "inherit-doc.ts", + "line": 6, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L6" + } ] }, { @@ -436,6 +641,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 3, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L3" + } + ], "signatures": [ { "id": 37, @@ -465,6 +678,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 7, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L7" + } + ], "type": { "type": "literal", "value": 1 @@ -482,6 +703,14 @@ "flags": { "isStatic": true }, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L2" + } + ], "type": { "type": "literal", "value": 1 @@ -495,20 +724,26 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 36 ] }, { "title": "Properties", - "kind": 1024, "children": [ 38, 35 ] } ], + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 12, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L12" + } + ], "extendedTypes": [ { "type": "reference", @@ -530,6 +765,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 7, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L7" + } + ], "type": { "type": "literal", "value": 1 @@ -539,11 +782,24 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 33 ] } + ], + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 6, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L6" + }, + { + "fileName": "mergable-class.ts", + "line": 10, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L10" + } ] }, { @@ -559,6 +815,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" + } + ], "signatures": [ { "id": 30, @@ -580,6 +844,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L2" + } + ], "type": { "type": "literal", "value": 1 @@ -589,18 +861,24 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 29 ] }, { "title": "Properties", - "kind": 1024, "children": [ 28 ] } + ], + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" + } ] }, { @@ -609,6 +887,20 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 6, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L6" + }, + { + "fileName": "mergable-class.ts", + "line": 10, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L10" + } + ], "type": { "type": "reference", "id": 27, @@ -626,14 +918,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 34 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 32, 27 @@ -641,18 +931,24 @@ }, { "title": "Variables", - "kind": 32, "children": [ 31 ] } + ], + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 26 diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index 7e174be85..88f73abc0 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -24,6 +24,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-type.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" + } + ], "signatures": [ { "id": 4, @@ -138,11 +146,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] } + ], + "sources": [ + { + "fileName": "constructor-type.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" + } ] }, { @@ -150,18 +165,33 @@ "name": "Instance", "kind": 256, "kindString": "Interface", - "flags": {} + "flags": {}, + "sources": [ + { + "fileName": "constructor-type.ts", + "line": 12, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L12" + } + ] } ], "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 2, 13 ] } + ], + "sources": [ + { + "fileName": "constructor-type.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" + } ] }, { @@ -177,6 +207,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 10, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L10" + } + ], "indexSignature": { "id": 22, "name": "__index", @@ -207,6 +245,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 5, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L5" + } + ], "indexSignature": { "id": 19, "name": "__index", @@ -237,6 +283,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L1" + } + ], "indexSignature": { "id": 16, "name": "__index", @@ -267,6 +321,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 15, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L15" + } + ], "type": { "type": "reflection", "declaration": { @@ -275,6 +337,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 15, + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L15" + } + ], "indexSignature": { "id": 26, "name": "__index", @@ -305,7 +375,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 21, 18, @@ -314,11 +383,18 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 24 ] } + ], + "sources": [ + { + "fileName": "index-signature.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L1" + } ] }, { @@ -335,7 +411,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class implementing an empty interface." + "summary": [ + { + "kind": "text", + "text": "A class implementing an empty interface." + } + ] }, "children": [ { @@ -367,6 +448,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "interface-empty.ts", + "line": 10, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L10" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -380,6 +469,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "interface-empty.ts", + "line": 11, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L11" + } + ], "signatures": [ { "id": 35, @@ -398,26 +495,31 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 31 ] }, { "title": "Properties", - "kind": 1024, "children": [ 33 ] }, { "title": "Methods", - "kind": 2048, "children": [ 34 ] } ], + "sources": [ + { + "fileName": "interface-empty.ts", + "line": 9, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L9" + } + ], "implementedTypes": [ { "type": "reference", @@ -433,8 +535,21 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "An empty interface" + "summary": [ + { + "kind": "text", + "text": "An empty interface" + } + ] }, + "sources": [ + { + "fileName": "interface-empty.ts", + "line": 4, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L4" + } + ], "implementedBy": [ { "type": "reference", @@ -447,18 +562,24 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 30 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 29 ] } + ], + "sources": [ + { + "fileName": "interface-empty.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L4" + } ] }, { @@ -482,11 +603,21 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Implementation of IEventDispatcher", - "tags": [ + "summary": [ { - "tag": "see", - "text": "IEventDispatcher\n" + "kind": "text", + "text": "Implementation of IEventDispatcher" + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "IEventDispatcher" + } + ] } ] }, @@ -536,6 +667,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 57, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L57" + } + ], "type": { "type": "array", "elementType": { @@ -558,6 +697,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 59, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L59" + } + ], "signatures": [ { "id": 87, @@ -641,6 +788,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 73, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L73" + } + ], "signatures": [ { "id": 98, @@ -671,6 +826,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 69, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L69" + } + ], "signatures": [ { "id": 95, @@ -715,6 +878,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 75, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L75" + } + ], "signatures": [ { "id": 100, @@ -745,6 +916,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 67, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L67" + } + ], "signatures": [ { "id": 92, @@ -794,21 +973,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 85 ] }, { "title": "Methods", - "kind": 2048, "children": [ 86, 97, @@ -818,7 +994,15 @@ ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 56, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L56" + } + ], + "typeParameters": [ { "id": 101, "name": "T", @@ -848,6 +1032,14 @@ "kind": 128, "kindString": "Class", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" + } + ] + }, "children": [ { "id": 50, @@ -855,6 +1047,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 25, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L25" + } + ], "signatures": [ { "id": 51, @@ -956,6 +1156,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 29, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L29" + } + ], "type": { "type": "reference", "id": 81, @@ -977,6 +1185,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 27, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L27" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -995,6 +1211,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 26, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L26" + } + ], "type": { "type": "reference", "id": 38, @@ -1021,6 +1245,14 @@ "flags": { "isPublic": true }, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 28, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L28" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1037,6 +1269,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 32, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L32" + } + ], "signatures": [ { "id": 62, @@ -1045,7 +1285,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Remove this subscription from its dispatcher" + "summary": [ + { + "kind": "text", + "text": "Remove this subscription from its dispatcher" + } + ] }, "type": { "type": "intrinsic", @@ -1068,14 +1313,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 50 ] }, { "title": "Properties", - "kind": 1024, "children": [ 60, 58, @@ -1085,13 +1328,20 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 61 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 24, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L24" + } + ], + "typeParameters": [ { "id": 63, "name": "V", @@ -1122,7 +1372,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "The main interface of the event system.\nAn IEventDispatcher is an object that keeps a list of listeners, and sends dispatches events of a certain type to them.\nThis might otherwise be known as a Signal." + "summary": [ + { + "kind": "text", + "text": "The main interface of the event system.\nAn IEventDispatcher is an object that keeps a list of listeners, and sends dispatches events of a certain type to them.\nThis might otherwise be known as a Signal." + } + ] }, "children": [ { @@ -1131,6 +1386,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 41, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L41" + } + ], "signatures": [ { "id": 66, @@ -1206,6 +1469,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 48, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L48" + } + ], "signatures": [ { "id": 77, @@ -1226,6 +1497,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 47, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L47" + } + ], "signatures": [ { "id": 74, @@ -1260,6 +1539,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 49, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L49" + } + ], "signatures": [ { "id": 79, @@ -1280,6 +1567,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 46, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L46" + } + ], "signatures": [ { "id": 71, @@ -1319,7 +1614,6 @@ "groups": [ { "title": "Methods", - "kind": 2048, "children": [ 65, 76, @@ -1329,7 +1623,15 @@ ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 40, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L40" + } + ], + "typeParameters": [ { "id": 80, "name": "U", @@ -1352,7 +1654,15 @@ "kind": 256, "kindString": "Interface", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 5, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L5" + } + ], + "typeParameters": [ { "id": 39, "name": "T", @@ -1368,9 +1678,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "Function signature of an event listener callback" - }, "parameters": [ { "id": 41, @@ -1379,7 +1686,12 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "param text" + "summary": [ + { + "kind": "text", + "text": "param text" + } + ] }, "type": { "type": "reference", @@ -1402,7 +1714,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" + "summary": [ + { + "kind": "text", + "text": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" + } + ] }, "children": [ { @@ -1411,6 +1728,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 16, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L16" + } + ], "type": { "type": "intrinsic", "name": "any" @@ -1422,6 +1747,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 14, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L14" + } + ], "type": { "type": "reference", "id": 38, @@ -1441,6 +1774,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 15, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L15" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1452,6 +1793,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 21, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L21" + } + ], "signatures": [ { "id": 47, @@ -1460,7 +1809,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Remove this subscription from its dispatcher" + "summary": [ + { + "kind": "text", + "text": "Remove this subscription from its dispatcher" + } + ] }, "type": { "type": "intrinsic", @@ -1473,7 +1827,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 45, 43, @@ -1482,13 +1835,20 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 46 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 13, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L13" + } + ], + "typeParameters": [ { "id": 48, "name": "T", @@ -1509,7 +1869,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 81, 49 @@ -1517,24 +1876,38 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 64, 38, 42 ] } + ], + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 1, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L1" + } ] } ], "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 37 ] } + ], + "sources": [ + { + "fileName": "interface-implementation.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L1" + } ] }, { @@ -1557,6 +1930,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" + } + ], "type": { "type": "literal", "value": 1 @@ -1566,12 +1947,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 104 ] } ], + "sources": [ + { + "fileName": "merging.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L1" + } + ], "extendedBy": [ { "type": "reference", @@ -1598,6 +1986,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" + } + ], "type": { "type": "literal", "value": 2 @@ -1607,12 +2003,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 106 ] } ], + "sources": [ + { + "fileName": "merging.ts", + "line": 5, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L5" + } + ], "extendedBy": [ { "type": "reference", @@ -1634,6 +2037,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" + } + ], "type": { "type": "literal", "value": 1 @@ -1650,6 +2061,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" + } + ], "type": { "type": "literal", "value": 2 @@ -1666,6 +2085,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L10" + } + ], "type": { "type": "literal", "value": 1 @@ -1677,6 +2104,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 15, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L15" + } + ], "type": { "type": "literal", "value": 2 @@ -1686,7 +2121,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 110, 111, @@ -1695,6 +2129,20 @@ ] } ], + "sources": [ + { + "fileName": "merging.ts", + "line": 9, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L9" + }, + { + "fileName": "merging.ts", + "line": 14, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L14" + } + ], "extendedTypes": [ { "type": "reference", @@ -1728,6 +2176,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 2, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" + } + ], "type": { "type": "literal", "value": 1 @@ -1744,6 +2200,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" + } + ], "type": { "type": "literal", "value": 2 @@ -1760,6 +2224,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L10" + } + ], "type": { "type": "literal", "value": 1 @@ -1776,6 +2248,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 19, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L19" + } + ], "type": { "type": "literal", "value": 1 @@ -1787,6 +2267,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "merging.ts", + "line": 15, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L15" + } + ], "type": { "type": "literal", "value": 2 @@ -1801,7 +2289,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 116, 117, @@ -1811,6 +2298,14 @@ ] } ], + "sources": [ + { + "fileName": "merging.ts", + "line": 18, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L18" + } + ], "extendedTypes": [ { "type": "reference", @@ -1828,7 +2323,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 103, 105, @@ -1836,13 +2330,20 @@ 112 ] } + ], + "sources": [ + { + "fileName": "merging.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 14, diff --git a/src/test/converter/js/index.js b/src/test/converter/js/index.js index 3f03f11bf..a325b7569 100644 --- a/src/test/converter/js/index.js +++ b/src/test/converter/js/index.js @@ -54,7 +54,9 @@ /** @type {Foo} */ export const usedFoo = () => 1; -/** @enum {string} */ +/** + * @enum {string} enum comment + */ export const ColumnType = { STRING: "string", NUMBER: "number", diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index 792d270b9..d5ce36c11 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -10,7 +10,6 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": {}, "children": [ { "id": 5, @@ -18,6 +17,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "export-eq-type.js", + "line": 1, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L1" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -29,6 +36,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "export-eq-type.js", + "line": 4, + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L4" + } + ], "signatures": [ { "id": 3, @@ -36,7 +51,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 4, @@ -44,7 +58,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": {}, "type": { "type": "intrinsic", "name": "string" @@ -62,18 +75,24 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 5 ] }, { "title": "Functions", - "kind": 64, "children": [ 2 ] } + ], + "sources": [ + { + "fileName": "export-eq-type.js", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L4" + } ] }, { @@ -82,7 +101,6 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": {}, "children": [ { "id": 10, @@ -90,7 +108,14 @@ "kind": 8, "kindString": "Enumeration", "flags": {}, - "comment": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "enum comment" + } + ] + }, "children": [ { "id": 12, @@ -98,6 +123,14 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 62, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L62" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -109,6 +142,14 @@ "kind": 16, "kindString": "Enumeration Member", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 61, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L61" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -118,12 +159,25 @@ "groups": [ { "title": "Enumeration Members", - "kind": 16, "children": [ 12, 11 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 60, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L60" + }, + { + "fileName": "index.js", + "line": 58, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L58" + } ] }, { @@ -133,7 +187,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "docs for interface" + "summary": [ + { + "kind": "text", + "text": "docs for interface" + } + ] }, "children": [ { @@ -142,9 +201,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "shortText": "can also use prop tag" - }, + "sources": [ + { + "fileName": "index.js", + "line": 13, + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L13" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -156,9 +220,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "shortText": "docs for property" - }, + "sources": [ + { + "fileName": "index.js", + "line": 12, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L12" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -168,12 +237,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 17, 16 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 11, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L11" + } ] }, { @@ -189,9 +265,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "shortText": "docs for property\nmore docs for property" - }, + "sources": [ + { + "fileName": "index.js", + "line": 6, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L6" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -201,11 +282,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 14 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 5, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L5" + } ] }, { @@ -214,6 +302,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 49, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L49" + } + ], "type": { "type": "reflection", "declaration": { @@ -222,6 +318,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 49, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L49" + } + ], "signatures": [ { "id": 44, @@ -262,6 +366,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 27, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L27" + } + ], "type": { "type": "reflection", "declaration": { @@ -270,6 +382,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 27, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L27" + } + ], "signatures": [ { "id": 30, @@ -293,9 +413,22 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "comment on alias" + "summary": [ + { + "kind": "text", + "text": "comment on alias" + } + ] }, - "typeParameter": [ + "sources": [ + { + "fileName": "index.js", + "line": 45, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L45" + } + ], + "typeParameters": [ { "id": 41, "name": "T", @@ -303,7 +436,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "comment on template" + "summary": [ + { + "kind": "text", + "text": "comment on template" + } + ] } } ], @@ -319,7 +457,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "index.js", + "line": 33, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L33" + } + ], + "typeParameters": [ { "id": 35, "name": "T", @@ -336,6 +482,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 33, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L33" + } + ], "signatures": [ { "id": 33, @@ -374,8 +528,21 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "docs for alias" + "summary": [ + { + "kind": "text", + "text": "docs for alias" + } + ] }, + "sources": [ + { + "fileName": "index.js", + "line": 22, + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" + } + ], "type": { "type": "intersection", "types": [ @@ -394,6 +561,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 22, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -403,11 +578,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 22 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 22, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" + } ] } }, @@ -426,6 +608,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 22, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -435,11 +625,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 24 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 22, + "character": 29, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" + } ] } } @@ -452,6 +649,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 26, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L26" + } + ], "type": { "type": "reflection", "declaration": { @@ -460,6 +665,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 26, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L26" + } + ], "signatures": [ { "id": 27, @@ -467,6 +680,14 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "even though in the same comment block" + } + ] + }, "type": { "type": "intrinsic", "name": "any" @@ -483,13 +704,26 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "type alias since it doesn't have a property tag" + "summary": [ + { + "kind": "text", + "text": "type alias since it doesn't have a property tag" + } + ] }, + "sources": [ + { + "fileName": "index.js", + "line": 17, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L17" + } + ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -498,6 +732,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 39, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L39" + } + ], "type": { "type": "reflection", "declaration": { @@ -506,6 +748,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 39, + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L39" + } + ], "signatures": [ { "id": 38, @@ -522,6 +772,14 @@ "flags": { "isOptional": true }, + "comment": { + "summary": [ + { + "kind": "text", + "text": "an optional argument" + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -544,8 +802,21 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "docs for alias" + "summary": [ + { + "kind": "text", + "text": "docs for alias" + } + ] }, + "sources": [ + { + "fileName": "index.js", + "line": 21, + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L21" + } + ], "type": { "type": "union", "types": [ @@ -566,6 +837,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "index.js", + "line": 55, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L55" + } + ], "signatures": [ { "id": 8, @@ -573,7 +852,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 9, @@ -603,14 +881,12 @@ "groups": [ { "title": "Enumerations", - "kind": 8, "children": [ 10 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 15, 13 @@ -618,7 +894,6 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 42, 28, @@ -633,18 +908,24 @@ }, { "title": "Functions", - "kind": 64, "children": [ 7 ] } + ], + "sources": [ + { + "fileName": "index.js", + "line": 55, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L55" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 6 diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index da6cf603f..8ba5e8c41 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -12,7 +12,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Base class" + "summary": [ + { + "kind": "text", + "text": "Base class" + } + ] }, "children": [ { @@ -42,6 +47,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -54,6 +67,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 22, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" + } + ], "signatures": [ { "id": 18, @@ -72,25 +93,30 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 14 ] }, { "title": "Properties", - "kind": 1024, "children": [ 16 ] }, { "title": "Methods", - "kind": 2048, "children": [ 17 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 19, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L19" + } ] }, { @@ -100,7 +126,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class that inherits from Base and consumes Mixin1 and Mixin2, in order." + "summary": [ + { + "kind": "text", + "text": "Class that inherits from Base and consumes Mixin1 and Mixin2, in order." + } + ] }, "children": [ { @@ -138,6 +169,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -154,6 +193,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 86, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L86" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -166,6 +213,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 35, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -182,6 +237,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 55, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L55" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -198,6 +261,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 22, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" + } + ], "signatures": [ { "id": 76, @@ -226,6 +297,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 88, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L88" + } + ], "signatures": [ { "id": 65, @@ -246,6 +325,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 37, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" + } + ], "signatures": [ { "id": 72, @@ -295,6 +382,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 57, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L57" + } + ], "signatures": [ { "id": 68, @@ -336,14 +431,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 61 ] }, { "title": "Properties", - "kind": 1024, "children": [ 74, 63, @@ -353,7 +446,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 75, 64, @@ -362,6 +454,14 @@ ] } ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 85, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L85" + } + ], "extendedTypes": [ { "type": "intersection", @@ -404,11 +504,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 60 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 34, + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L34" + } ] } }, @@ -470,7 +577,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "The \"instance type\" of the Mixin1 using the interface notation (supports recursive type definition)" + "summary": [ + { + "kind": "text", + "text": "The \"instance type\" of the Mixin1 using the interface notation (supports recursive type definition)" + } + ] }, "children": [ { @@ -479,6 +591,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -495,6 +615,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 35, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -511,6 +639,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 22, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" + } + ], "signatures": [ { "id": 32, @@ -539,6 +675,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 37, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" + } + ], "signatures": [ { "id": 28, @@ -586,7 +730,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 30, 26 @@ -594,13 +737,20 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 31, 27 ] } ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 45, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L45" + } + ], "extendedTypes": [ { "type": "reference", @@ -626,7 +776,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "The \"instance type\" of the Mixin2 using the interface notation (supports recursive type definition)" + "summary": [ + { + "kind": "text", + "text": "The \"instance type\" of the Mixin2 using the interface notation (supports recursive type definition)" + } + ] }, "children": [ { @@ -635,6 +790,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -651,6 +814,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 35, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -667,6 +838,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 55, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L55" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -683,6 +862,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 22, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" + } + ], "signatures": [ { "id": 50, @@ -711,6 +898,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 37, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" + } + ], "signatures": [ { "id": 46, @@ -760,6 +955,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 57, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L57" + } + ], "signatures": [ { "id": 42, @@ -801,7 +1004,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 48, 44, @@ -810,7 +1012,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 49, 45, @@ -818,6 +1019,14 @@ ] } ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 65, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L65" + } + ], "extendedTypes": [ { "type": "reference", @@ -842,7 +1051,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "mixin.ts", + "line": 9, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L9" + } + ], + "typeParameters": [ { "id": 10, "name": "A", @@ -863,6 +1080,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 9, + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L9" + } + ], "signatures": [ { "id": 8, @@ -871,7 +1096,12 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Any constructor function" + "summary": [ + { + "kind": "text", + "text": "Any constructor function" + } + ] }, "parameters": [ { @@ -907,7 +1137,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "mixin.ts", + "line": 4, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" + } + ], + "typeParameters": [ { "id": 5, "name": "A", @@ -928,6 +1166,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 4, + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" + } + ], "signatures": [ { "id": 3, @@ -936,7 +1182,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Any function" + "summary": [ + { + "kind": "text", + "text": "Any function" + } + ] }, "parameters": [ { @@ -973,9 +1224,22 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Mixin type helper" + "summary": [ + { + "kind": "text", + "text": "Mixin type helper" + } + ] }, - "typeParameter": [ + "sources": [ + { + "fileName": "mixin.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L14" + } + ], + "typeParameters": [ { "id": 12, "name": "T", @@ -1001,14 +1265,14 @@ "name": "T" } ], + "name": "ReturnType", "qualifiedName": "ReturnType", - "package": "typescript", - "name": "ReturnType" + "package": "typescript" } ], + "name": "InstanceType", "qualifiedName": "InstanceType", - "package": "typescript", - "name": "InstanceType" + "package": "typescript" }, "extendedBy": [ { @@ -1030,8 +1294,27 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "The \"instance type\" of the Mixin3 using the regular type notation (does not work well for recursive type definition)\nIs not well supported by the TypeDoc" + "summary": [ + { + "kind": "text", + "text": "The \"instance type\" of the Mixin3 using the regular type notation (does not work well for recursive type definition)\nIs not well supported by the TypeDoc" + } + ] }, + "sources": [ + { + "fileName": "mixin.ts", + "line": 70, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L70" + }, + { + "fileName": "mixin.ts", + "line": 80, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L80" + } + ], "type": { "type": "reference", "id": 11, @@ -1054,6 +1337,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 30, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L30" + } + ], "signatures": [ { "id": 20, @@ -1061,9 +1352,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "The \"mixin function\" of the Mixin1" - }, "typeParameter": [ { "id": 21, @@ -1133,11 +1421,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 24 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 34, + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L34" + } ] } }, @@ -1157,6 +1452,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 50, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L50" + } + ], "signatures": [ { "id": 34, @@ -1164,9 +1467,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "The \"mixin function\" of the Mixin2" - }, "typeParameter": [ { "id": 35, @@ -1246,11 +1546,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 38 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 54, + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L54" + } ] } }, @@ -1270,6 +1577,20 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 70, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L70" + }, + { + "fileName": "mixin.ts", + "line": 80, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L80" + } + ], "signatures": [ { "id": 52, @@ -1277,9 +1598,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "shortText": "The \"mixin function\" of the Mixin3" - }, "typeParameter": [ { "id": 53, @@ -1348,11 +1666,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 56 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 74, + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L74" + } ] } }, @@ -1370,7 +1695,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 13, 58 @@ -1378,7 +1702,6 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 25, 39 @@ -1386,7 +1709,6 @@ }, { "title": "Type Aliases", - "kind": 4194304, "children": [ 6, 1, @@ -1396,12 +1718,19 @@ }, { "title": "Functions", - "kind": 64, "children": [ 19, 33, 51 ] } + ], + "sources": [ + { + "fileName": "mixin.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" + } ] } diff --git a/src/test/converter/react/specs.json b/src/test/converter/react/specs.json index df6f1898a..8a3d1b30c 100644 --- a/src/test/converter/react/specs.json +++ b/src/test/converter/react/specs.json @@ -18,6 +18,14 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "react.tsx", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L20" + } + ], "signatures": [ { "id": 6, @@ -55,6 +63,14 @@ "flags": { "isPrivate": true }, + "sources": [ + { + "fileName": "react.tsx", + "line": 18, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L18" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -66,6 +82,14 @@ "kind": 2048, "kindString": "Method", "flags": {}, + "sources": [ + { + "fileName": "react.tsx", + "line": 25, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L25" + } + ], "signatures": [ { "id": 10, @@ -84,25 +108,30 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 5 ] }, { "title": "Properties", - "kind": 1024, "children": [ 8 ] }, { "title": "Methods", - "kind": 2048, "children": [ 9 ] } + ], + "sources": [ + { + "fileName": "react.tsx", + "line": 17, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L17" + } ] }, { @@ -118,6 +147,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "react.tsx", + "line": 14, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L14" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -129,6 +166,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "react.tsx", + "line": 13, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L13" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -138,29 +183,42 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 3, 2 ] } + ], + "sources": [ + { + "fileName": "react.tsx", + "line": 12, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L12" + } ] } ], "groups": [ { "title": "Classes", - "kind": 128, "children": [ 4 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 1 ] } + ], + "sources": [ + { + "fileName": "react.tsx", + "line": 2, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L2" + } ] } diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index 566f951bf..33710b84c 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -17,6 +17,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "general.ts", + "line": 12, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L12" + } + ], "type": { "type": "intrinsic", "name": "bigint" @@ -28,6 +36,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "general.ts", + "line": 3, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L3" + } + ], "type": { "type": "literal", "value": { @@ -42,7 +58,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "general.ts", + "line": 17, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L17" + } + ], + "typeParameters": [ { "id": 12, "name": "T", @@ -104,6 +128,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "general.ts", + "line": 6, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L6" + } + ], "type": { "type": "literal", "value": { @@ -118,6 +150,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "general.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L14" + } + ], "type": { "type": "literal", "value": -1 @@ -129,6 +169,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "general.ts", + "line": 9, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L9" + } + ], "type": { "type": "array", "elementType": { @@ -145,6 +193,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "general.ts", + "line": 4, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L4" + } + ], "type": { "type": "literal", "value": { @@ -162,6 +218,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "general.ts", + "line": 7, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L7" + } + ], "type": { "type": "literal", "value": { @@ -179,6 +243,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "general.ts", + "line": 15, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L15" + } + ], "type": { "type": "literal", "value": -1 @@ -193,6 +265,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "general.ts", + "line": 10, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L10" + } + ], "type": { "type": "array", "elementType": { @@ -206,7 +286,6 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 8, 2, @@ -218,7 +297,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 3, 5, @@ -226,6 +304,14 @@ 7 ] } + ], + "sources": [ + { + "fileName": "general.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L1" + } ] }, { @@ -241,6 +327,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 5, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L5" + } + ], "indexSignature": { "id": 18, "name": "__index", @@ -280,6 +374,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 1, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L1" + } + ], "indexSignature": { "id": 15, "name": "__index", @@ -310,6 +412,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "sources": [ + { + "fileName": "index-signature.ts", + "line": 9, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L9" + } + ], "indexSignature": { "id": 21, "name": "__index", @@ -347,13 +457,20 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 17, 14, 20 ] } + ], + "sources": [ + { + "fileName": "index-signature.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L1" + } ] }, { @@ -369,7 +486,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "mapped.ts", + "line": 7, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L7" + } + ], + "typeParameters": [ { "id": 35, "name": "T", @@ -439,7 +564,15 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "typeParameter": [ + "sources": [ + { + "fileName": "mapped.ts", + "line": 5, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L5" + } + ], + "typeParameters": [ { "id": 33, "name": "T", @@ -480,6 +613,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mapped.ts", + "line": 9, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L9" + } + ], "signatures": [ { "id": 29, @@ -559,6 +700,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "mapped.ts", + "line": 1, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L1" + } + ], "signatures": [ { "id": 25, @@ -623,7 +772,6 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 34, 32 @@ -631,12 +779,19 @@ }, { "title": "Functions", - "kind": 64, "children": [ 28, 24 ] } + ], + "sources": [ + { + "fileName": "mapped.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L1" + } ] }, { @@ -652,6 +807,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "parens.ts", + "line": 3, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" + } + ], "type": { "type": "intersection", "types": [ @@ -674,6 +837,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "parens.ts", + "line": 3, + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -683,11 +854,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 39 ] } + ], + "sources": [ + { + "fileName": "parens.ts", + "line": 3, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" + } ] } } @@ -698,11 +876,18 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 37 ] } + ], + "sources": [ + { + "fileName": "parens.ts", + "line": 3, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" + } ] }, { @@ -718,6 +903,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "query.ts", + "line": 3, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L3" + } + ], "type": { "type": "query", "queryType": { @@ -735,6 +928,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "query.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L1" + } + ], "type": { "type": "literal", "value": 1 @@ -745,18 +946,24 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 42 ] }, { "title": "Variables", - "kind": 32, "children": [ 41 ] } + ], + "sources": [ + { + "fileName": "query.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L1" + } ] }, { @@ -772,6 +979,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "tuple.ts", + "line": 14, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L14" + } + ], "type": { "type": "tuple", "elements": [ @@ -798,6 +1013,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "tuple.ts", + "line": 1, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L1" + } + ], "type": { "type": "tuple", "elements": [ @@ -828,6 +1051,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "tuple.ts", + "line": 11, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L11" + } + ], "type": { "type": "tuple", "elements": [ @@ -858,6 +1089,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "tuple.ts", + "line": 5, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L5" + } + ], "type": { "type": "tuple", "elements": [ @@ -884,6 +1123,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "tuple.ts", + "line": 8, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L8" + } + ], "type": { "type": "tuple", "elements": [ @@ -919,6 +1166,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "tuple.ts", + "line": 16, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L16" + } + ], "type": { "type": "tuple", "elements": [ @@ -948,6 +1203,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "tuple.ts", + "line": 3, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L3" + } + ], "type": { "type": "tuple", "elements": [ @@ -981,6 +1244,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "tuple.ts", + "line": 12, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L12" + } + ], "type": { "type": "tuple", "elements": [ @@ -1014,6 +1285,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "tuple.ts", + "line": 6, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L6" + } + ], "type": { "type": "tuple", "elements": [ @@ -1043,6 +1322,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "tuple.ts", + "line": 9, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L9" + } + ], "type": { "type": "tuple", "elements": [ @@ -1078,7 +1365,6 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 52, 44, @@ -1089,7 +1375,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 53, 45, @@ -1098,6 +1383,14 @@ 49 ] } + ], + "sources": [ + { + "fileName": "tuple.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L1" + } ] }, { @@ -1113,6 +1406,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 2, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L2" + } + ], "type": { "type": "typeOperator", "operator": "readonly", @@ -1131,6 +1432,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 3, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L3" + } + ], "type": { "type": "reflection", "declaration": { @@ -1146,6 +1455,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 4, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L4" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1157,6 +1474,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 5, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L5" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1166,12 +1491,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 59, 60 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 3, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L3" + } ] } } @@ -1182,6 +1514,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 7, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L7" + } + ], "type": { "type": "typeOperator", "operator": "keyof", @@ -1200,6 +1540,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "type-operator.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L1" + } + ], "type": { "type": "typeOperator", "operator": "unique", @@ -1214,7 +1562,6 @@ "groups": [ { "title": "Type Aliases", - "kind": 4194304, "children": [ 56, 57, @@ -1223,11 +1570,18 @@ }, { "title": "Variables", - "kind": 32, "children": [ 55 ] } + ], + "sources": [ + { + "fileName": "type-operator.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L1" + } ] }, { @@ -1244,7 +1598,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "First type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "First type for union or intersection type tests." + } + ] }, "children": [ { @@ -1254,8 +1613,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Property of first type." + "summary": [ + { + "kind": "text", + "text": "Property of first type." + } + ] }, + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 8, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L8" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1265,11 +1637,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 64 ] } + ], + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 4, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L4" + } ] }, { @@ -1279,7 +1658,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Second type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "Second type for union or intersection type tests." + } + ] }, "children": [ { @@ -1289,8 +1673,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Property of second type." + "summary": [ + { + "kind": "text", + "text": "Property of second type." + } + ] }, + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 18, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L18" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1300,11 +1697,18 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 66 ] } + ], + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 14, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L14" + } ] }, { @@ -1314,7 +1718,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Third type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "Third type for union or intersection type tests." + } + ] }, "children": [ { @@ -1324,8 +1733,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Complex Property of third type." + "summary": [ + { + "kind": "text", + "text": "Complex Property of third type." + } + ] }, + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 38, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L38" + } + ], "type": { "type": "array", "elementType": { @@ -1364,8 +1786,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Intersection Property of third type." + "summary": [ + { + "kind": "text", + "text": "Intersection Property of third type." + } + ] }, + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 33, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L33" + } + ], "type": { "type": "intersection", "types": [ @@ -1389,8 +1824,21 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Union Property of third type." + "summary": [ + { + "kind": "text", + "text": "Union Property of third type." + } + ] }, + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L28" + } + ], "type": { "type": "union", "types": [ @@ -1411,33 +1859,46 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 70, 69, 68 ] } + ], + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 24, + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L24" + } ] } ], "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 63, 65, 67 ] } + ], + "sources": [ + { + "fileName": "union-or-intersection.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L4" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 13, diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 0992984f6..dcfc30e50 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -18,7 +18,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A custom array class." + "summary": [ + { + "kind": "text", + "text": "A custom array class." + } + ] }, "children": [ { @@ -62,13 +67,20 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] } ], - "typeParameter": [ + "sources": [ + { + "fileName": "array.ts", + "line": 4, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" + } + ], + "typeParameters": [ { "id": 6, "name": "T", @@ -92,7 +104,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class array class item" + "summary": [ + { + "kind": "text", + "text": "Class array class item" + } + ] }, "children": [ { @@ -120,11 +137,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 10 ] } + ], + "sources": [ + { + "fileName": "array.ts", + "line": 19, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L19" + } ] }, { @@ -134,7 +158,12 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Custom list class" + "summary": [ + { + "kind": "text", + "text": "Custom list class" + } + ] }, "children": [ { @@ -172,12 +201,19 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 13 ] } ], + "sources": [ + { + "fileName": "array.ts", + "line": 24, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L24" + } + ], "extendedTypes": [ { "type": "reference", @@ -202,8 +238,21 @@ "isConst": true }, "comment": { - "shortText": "A const of a complex type." + "summary": [ + { + "kind": "text", + "text": "A const of a complex type." + } + ] }, + "sources": [ + { + "fileName": "array.ts", + "line": 9, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L9" + } + ], "type": { "type": "array", "elementType": { @@ -259,8 +308,21 @@ "isConst": true }, "comment": { - "shortText": "An exported const of the custom array type." + "summary": [ + { + "kind": "text", + "text": "An exported const of the custom array type." + } + ] }, + "sources": [ + { + "fileName": "array.ts", + "line": 14, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L14" + } + ], "type": { "type": "reference", "id": 2, @@ -278,7 +340,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2, 9, @@ -287,12 +348,19 @@ }, { "title": "Variables", - "kind": 32, "children": [ 7, 8 ] } + ], + "sources": [ + { + "fileName": "array.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" + } ] }, { @@ -308,6 +376,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 13, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -319,6 +395,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 13, + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -330,6 +414,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 13, + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" + } + ], "type": { "type": "union", "types": [ @@ -351,6 +443,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 31, + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L31" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -362,6 +462,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 31, + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L31" + } + ], "type": { "type": "tuple", "elements": [ @@ -382,6 +490,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 25, + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L25" + } + ], "type": { "type": "tuple", "elements": [ @@ -402,6 +518,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 23, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L23" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -413,6 +537,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 24, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L24" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -424,6 +556,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 4, + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -435,6 +575,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 4, + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -446,6 +594,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 4, + "character": 49, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -457,6 +613,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 38, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L38" + } + ], "signatures": [ { "id": 17, @@ -465,7 +629,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Destructuring function parameters." + "summary": [ + { + "kind": "text", + "text": "Destructuring function parameters." + } + ] }, "parameters": [ { @@ -491,7 +660,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 22, 23, @@ -508,11 +676,18 @@ }, { "title": "Functions", - "kind": 64, "children": [ 16 ] } + ], + "sources": [ + { + "fileName": "destructuring.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" + } ] }, { @@ -530,6 +705,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "literal.ts", + "line": 43, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L43" + } + ], "type": { "type": "reflection", "declaration": { @@ -545,6 +728,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 48, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" + } + ], "type": { "type": "reflection", "declaration": { @@ -553,6 +744,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 48, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" + } + ], "signatures": [ { "id": 60, @@ -575,6 +774,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 48, + "character": 27, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" + } + ], "signatures": [ { "id": 63, @@ -608,6 +815,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 52, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" + } + ], "type": { "type": "reflection", "declaration": { @@ -616,6 +831,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 52, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" + } + ], "signatures": [ { "id": 66, @@ -638,6 +861,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 52, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" + } + ], "signatures": [ { "id": 69, @@ -671,6 +902,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 44, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" + } + ], "type": { "type": "reflection", "declaration": { @@ -679,6 +918,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 44, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" + } + ], "signatures": [ { "id": 54, @@ -701,6 +948,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 44, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" + } + ], "signatures": [ { "id": 57, @@ -732,13 +987,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 58, 64, 52 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 43, + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L43" + } ] } }, @@ -753,8 +1015,21 @@ "isConst": true }, "comment": { - "shortText": "An object literal." + "summary": [ + { + "kind": "text", + "text": "An object literal." + } + ] }, + "sources": [ + { + "fileName": "literal.ts", + "line": 5, + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" + } + ], "type": { "type": "reflection", "declaration": { @@ -770,6 +1045,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 19, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L19" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -782,6 +1065,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L20" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -794,6 +1085,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 21, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L21" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -806,6 +1105,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 17, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L17" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -818,6 +1125,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 18, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L18" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -830,6 +1145,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" + } + ], "type": { "type": "reflection", "declaration": { @@ -845,6 +1168,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 15, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L15" + } + ], "type": { "type": "array", "elementType": { @@ -860,6 +1191,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 12, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" + } + ], "type": { "type": "reflection", "declaration": { @@ -868,6 +1207,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 12, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" + } + ], "signatures": [ { "id": 81, @@ -903,6 +1250,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -915,6 +1270,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -925,12 +1288,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 84, 85 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } ] } } @@ -946,6 +1316,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 11, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L11" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -956,13 +1334,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 86, 79, 78 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 10, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" + } ] } }, @@ -974,6 +1359,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 7, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" + } + ], "type": { "type": "reflection", "declaration": { @@ -982,6 +1375,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 7, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" + } + ], "signatures": [ { "id": 75, @@ -1005,6 +1406,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L6" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1015,7 +1424,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 89, 90, @@ -1027,6 +1435,14 @@ 72 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 5, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" + } ] } }, @@ -1039,8 +1455,21 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A typed literal without an initializer." + "summary": [ + { + "kind": "text", + "text": "A typed literal without an initializer." + } + ] }, + "sources": [ + { + "fileName": "literal.ts", + "line": 27, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" + } + ], "type": { "type": "reflection", "declaration": { @@ -1058,6 +1487,14 @@ "flags": { "isOptional": true }, + "sources": [ + { + "fileName": "literal.ts", + "line": 35, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L35" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1071,6 +1508,14 @@ "flags": { "isOptional": true }, + "sources": [ + { + "fileName": "literal.ts", + "line": 36, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L36" + } + ], "type": { "type": "intrinsic", "name": "boolean" @@ -1082,6 +1527,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 30, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" + } + ], "type": { "type": "reflection", "declaration": { @@ -1097,6 +1550,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 33, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L33" + } + ], "type": { "type": "array", "elementType": { @@ -1111,6 +1572,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], "type": { "type": "reflection", "declaration": { @@ -1119,6 +1588,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], "signatures": [ { "id": 42, @@ -1154,6 +1631,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 33, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1165,6 +1650,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1174,12 +1667,19 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 45, 46 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } ] } } @@ -1194,6 +1694,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 31, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L31" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1203,13 +1711,20 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 47, 40, 39 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 30, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" + } ] } } @@ -1220,6 +1735,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 29, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" + } + ], "type": { "type": "reflection", "declaration": { @@ -1228,6 +1751,14 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 29, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" + } + ], "signatures": [ { "id": 36, @@ -1250,6 +1781,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L28" + } + ], "type": { "type": "intrinsic", "name": "string" @@ -1259,7 +1798,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 48, 49, @@ -1268,6 +1806,14 @@ 33 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 27, + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" + } ] } } @@ -1276,13 +1822,20 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 50, 70, 31 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L1" + } ] }, { @@ -1300,6 +1853,14 @@ "flags": { "isConst": true }, + "sources": [ + { + "fileName": "variable.ts", + "line": 1, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L1" + } + ], "type": { "type": "literal", "value": 15 @@ -1312,6 +1873,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "variable.ts", + "line": 2, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L2" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1324,6 +1893,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "variable.ts", + "line": 3, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L3" + } + ], "type": { "type": "intrinsic", "name": "number" @@ -1336,6 +1913,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "variable.ts", + "line": 5, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L5" + } + ], "type": { "type": "intrinsic", "name": "object" @@ -1347,6 +1932,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "variable.ts", + "line": 6, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L6" + } + ], "type": { "type": "reference", "typeArguments": [ @@ -1355,9 +1948,9 @@ "name": "string" } ], + "name": "Promise", "qualifiedName": "Promise", - "package": "typescript", - "name": "Promise" + "package": "typescript" } }, { @@ -1366,6 +1959,14 @@ "kind": 32, "kindString": "Variable", "flags": {}, + "sources": [ + { + "fileName": "variable.ts", + "line": 7, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L7" + } + ], "type": { "type": "reference", "typeArguments": [ @@ -1374,16 +1975,15 @@ "name": "object" } ], + "name": "Promise", "qualifiedName": "Promise", - "package": "typescript", - "name": "Promise" + "package": "typescript" } } ], "groups": [ { "title": "Variables", - "kind": 32, "children": [ 93, 94, @@ -1393,13 +1993,20 @@ 98 ] } + ], + "sources": [ + { + "fileName": "variable.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 15, diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index 532968927..423f4542a 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -18,57 +18,22 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A custom array class." + "summary": [ + { + "kind": "text", + "text": "A custom array class." + } + ] }, - "children": [ + "sources": [ { - "id": 3, - "name": "constructor", - "kind": 512, - "kindString": "Constructor", - "flags": {}, - "signatures": [ - { - "id": 4, - "name": "new Array", - "kind": 16384, - "kindString": "Constructor signature", - "flags": {}, - "typeParameter": [ - { - "id": 5, - "name": "T", - "kind": 131072, - "kindString": "Type parameter", - "flags": {} - } - ], - "type": { - "type": "reference", - "id": 2, - "typeArguments": [ - { - "type": "reference", - "id": 5, - "name": "T" - } - ], - "name": "Array" - } - } - ] + "fileName": "array.ts", + "line": 4, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ], - "groups": [ - { - "title": "Constructors", - "kind": 512, - "children": [ - 3 - ] - } - ], - "typeParameter": [ + "typeParameters": [ { "id": 6, "name": "T", @@ -92,38 +57,19 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class array class item" + "summary": [ + { + "kind": "text", + "text": "Class array class item" + } + ] }, - "children": [ - { - "id": 10, - "name": "constructor", - "kind": 512, - "kindString": "Constructor", - "flags": {}, - "signatures": [ - { - "id": 11, - "name": "new Foo", - "kind": 16384, - "kindString": "Constructor signature", - "flags": {}, - "type": { - "type": "reference", - "id": 9, - "name": "Foo" - } - } - ] - } - ], - "groups": [ + "sources": [ { - "title": "Constructors", - "kind": 512, - "children": [ - 10 - ] + "fileName": "array.ts", + "line": 19, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L19" } ] }, @@ -134,48 +80,19 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Custom list class" - }, - "children": [ - { - "id": 13, - "name": "constructor", - "kind": 512, - "kindString": "Constructor", - "flags": {}, - "signatures": [ - { - "id": 14, - "name": "new FooList", - "kind": 16384, - "kindString": "Constructor signature", - "flags": {}, - "type": { - "type": "reference", - "id": 12, - "name": "FooList" - }, - "inheritedFrom": { - "type": "reference", - "id": 4, - "name": "Array.constructor" - } - } - ], - "inheritedFrom": { - "type": "reference", - "id": 3, - "name": "Array.constructor" + "summary": [ + { + "kind": "text", + "text": "Custom list class" } - } - ], - "groups": [ + ] + }, + "sources": [ { - "title": "Constructors", - "kind": 512, - "children": [ - 13 - ] + "fileName": "array.ts", + "line": 24, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L24" } ], "extendedTypes": [ @@ -202,8 +119,21 @@ "isConst": true }, "comment": { - "shortText": "A const of a complex type." + "summary": [ + { + "kind": "text", + "text": "A const of a complex type." + } + ] }, + "sources": [ + { + "fileName": "array.ts", + "line": 9, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L9" + } + ], "type": { "type": "array", "elementType": { @@ -259,8 +189,21 @@ "isConst": true }, "comment": { - "shortText": "An exported const of the custom array type." + "summary": [ + { + "kind": "text", + "text": "An exported const of the custom array type." + } + ] }, + "sources": [ + { + "fileName": "array.ts", + "line": 14, + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L14" + } + ], "type": { "type": "reference", "id": 2, @@ -278,7 +221,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2, 9, @@ -287,12 +229,19 @@ }, { "title": "Variables", - "kind": 32, "children": [ 7, 8 ] } + ], + "sources": [ + { + "fileName": "array.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" + } ] }, { @@ -308,6 +257,14 @@ "kind": 64, "kindString": "Function", "flags": {}, + "sources": [ + { + "fileName": "destructuring.ts", + "line": 38, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L38" + } + ], "signatures": [ { "id": 17, @@ -316,7 +273,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Destructuring function parameters." + "summary": [ + { + "kind": "text", + "text": "Destructuring function parameters." + } + ] }, "parameters": [ { @@ -342,22 +304,29 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 16 ] } + ], + "sources": [ + { + "fileName": "destructuring.ts", + "line": 4, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" + } ] }, { - "id": 19, + "id": 30, "name": "literal", "kind": 2, "kindString": "Module", "flags": {}, "children": [ { - "id": 22, + "id": 70, "name": "objectLiteral", "kind": 32, "kindString": "Variable", @@ -365,37 +334,806 @@ "isConst": true }, "comment": { - "shortText": "An object literal." + "summary": [ + { + "kind": "text", + "text": "An object literal." + } + ] }, + "sources": [ + { + "fileName": "literal.ts", + "line": 5, + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" + } + ], "type": { "type": "reflection", "declaration": { - "id": 23, + "id": 71, "name": "__type", "kind": 65536, "kindString": "Type literal", - "flags": {} + "flags": {}, + "children": [ + { + "id": 89, + "name": "[toStringTag]", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 19, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L19" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "\"computed\"" + }, + { + "id": 90, + "name": "literal", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 20, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L20" + } + ], + "type": { + "type": "intrinsic", + "name": "boolean" + }, + "defaultValue": "true" + }, + { + "id": 91, + "name": "literal2", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 21, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L21" + } + ], + "type": { + "type": "intrinsic", + "name": "boolean" + }, + "defaultValue": "true" + }, + { + "id": 87, + "name": "valueA", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 17, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L17" + } + ], + "type": { + "type": "intrinsic", + "name": "number" + }, + "defaultValue": "100" + }, + { + "id": 88, + "name": "valueB", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 18, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L18" + } + ], + "type": { + "type": "intrinsic", + "name": "boolean" + }, + "defaultValue": "true" + }, + { + "id": 76, + "name": "valueX", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 10, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 77, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "children": [ + { + "id": 86, + "name": "valueA", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 15, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L15" + } + ], + "type": { + "type": "array", + "elementType": { + "type": "intrinsic", + "name": "number" + } + }, + "defaultValue": "..." + }, + { + "id": 79, + "name": "valueY", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 12, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 80, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 12, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" + } + ], + "signatures": [ + { + "id": 81, + "name": "__type", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "parameters": [ + { + "id": 82, + "name": "z", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 83, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "children": [ + { + "id": 84, + "name": "a", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "\"test\"" + }, + { + "id": 85, + "name": "b", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "z" + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 84, + 85 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 13, + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" + } + ] + } + } + } + ] + } + }, + "defaultValue": "..." + }, + { + "id": 78, + "name": "valueZ", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 11, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L11" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "\"foo\"" + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 86, + 79, + 78 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 10, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" + } + ] + } + }, + "defaultValue": "..." + }, + { + "id": 73, + "name": "valueY", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 7, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 74, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 7, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" + } + ], + "signatures": [ + { + "id": 75, + "name": "__type", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } + ] + } + }, + "defaultValue": "..." + }, + { + "id": 72, + "name": "valueZ", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 6, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L6" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "\"foo\"" + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 89, + 90, + 91, + 87, + 88, + 76, + 73, + 72 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 5, + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" + } + ] } }, "defaultValue": "..." }, { - "id": 20, + "id": 31, "name": "typeLiteral", "kind": 32, "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A typed literal without an initializer." + "summary": [ + { + "kind": "text", + "text": "A typed literal without an initializer." + } + ] }, + "sources": [ + { + "fileName": "literal.ts", + "line": 27, + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" + } + ], "type": { "type": "reflection", "declaration": { - "id": 21, + "id": 32, "name": "__type", "kind": 65536, "kindString": "Type literal", - "flags": {} + "flags": {}, + "children": [ + { + "id": 48, + "name": "valueA", + "kind": 1024, + "kindString": "Property", + "flags": { + "isOptional": true + }, + "sources": [ + { + "fileName": "literal.ts", + "line": 35, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L35" + } + ], + "type": { + "type": "intrinsic", + "name": "number" + } + }, + { + "id": 49, + "name": "valueB", + "kind": 1024, + "kindString": "Property", + "flags": { + "isOptional": true + }, + "sources": [ + { + "fileName": "literal.ts", + "line": 36, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L36" + } + ], + "type": { + "type": "intrinsic", + "name": "boolean" + } + }, + { + "id": 37, + "name": "valueX", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 30, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 38, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "children": [ + { + "id": 47, + "name": "valueA", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 33, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L33" + } + ], + "type": { + "type": "array", + "elementType": { + "type": "intrinsic", + "name": "number" + } + } + }, + { + "id": 40, + "name": "valueY", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 41, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], + "signatures": [ + { + "id": 42, + "name": "__type", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "parameters": [ + { + "id": 43, + "name": "z", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 44, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "children": [ + { + "id": 45, + "name": "a", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 33, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + } + }, + { + "id": 46, + "name": "b", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + } + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 45, + 46 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 32, + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" + } + ] + } + } + } + ] + } + } + }, + { + "id": 39, + "name": "valueZ", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 31, + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L31" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + } + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 47, + 40, + 39 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 30, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" + } + ] + } + } + }, + { + "id": 34, + "name": "valueY", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 29, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" + } + ], + "type": { + "type": "reflection", + "declaration": { + "id": 35, + "name": "__type", + "kind": 65536, + "kindString": "Type literal", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 29, + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" + } + ], + "signatures": [ + { + "id": 36, + "name": "__type", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" + } + } + ] + } + } + }, + { + "id": 33, + "name": "valueZ", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "sources": [ + { + "fileName": "literal.ts", + "line": 28, + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L28" + } + ], + "type": { + "type": "intrinsic", + "name": "string" + } + } + ], + "groups": [ + { + "title": "Properties", + "children": [ + 48, + 49, + 37, + 34, + 33 + ] + } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 27, + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" + } + ] } } } @@ -403,23 +1141,29 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ - 22, - 20 + 70, + 31 ] } + ], + "sources": [ + { + "fileName": "literal.ts", + "line": 1, + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L1" + } ] } ], "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 15, - 19 + 30 ] } ] diff --git a/src/test/converter2.test.ts b/src/test/converter2.test.ts index 7e6ece66a..ab29aa4af 100644 --- a/src/test/converter2.test.ts +++ b/src/test/converter2.test.ts @@ -1,6 +1,7 @@ import { ok } from "assert"; import { existsSync } from "fs"; import { join } from "path"; +import type { Application } from "../lib/application"; import type { ProjectReflection } from "../lib/models"; import { behaviorTests } from "./behaviorTests"; import { issueTests } from "./issueTests"; @@ -16,6 +17,7 @@ const app = getConverter2App(); function runTest( title: string, + pre: ((app: Application) => void) | undefined, entry: string, check: (project: ProjectReflection, logger: TestLogger) => void ) { @@ -34,7 +36,11 @@ function runTest( const sourceFile = program.getSourceFile(entryPoint); ok(sourceFile, `No source file found for ${entryPoint}`); - app.logger = new TestLogger(); + const snap = app.options.snapshot(); + + const logger = new TestLogger(); + app.logger = logger; + pre?.(app); app.options.setValue("entryPoints", [entryPoint]); const project = app.converter.convert([ { @@ -43,7 +49,9 @@ function runTest( sourceFile, }, ]); - check(project, app.logger as TestLogger); + + app.options.restore(snap); + check(project, logger); }); } @@ -53,23 +61,52 @@ describe("Converter2", () => { }); for (const [entry, check] of Object.entries(issueTests)) { - const link = `https://github.com/TypeStrong/typedoc/issues/${entry.substr( - 2 + if (entry.startsWith("pre")) continue; + + const link = `https://github.com/TypeStrong/typedoc/issues/${entry.replace( + /[^\d]/g, + "" )}`; - runTest( - `Issue ${entry.substr(2).padEnd(4)} (${link})`, - join("issues", entry), - check - ); + const name = `Issue ${entry + .replace("_skip", "") + .substring(2) + .padEnd(4)} (${link})`; + + if (entry.endsWith("_skip")) { + it.skip(name); + } else { + runTest( + name, + issueTests[`pre${entry}`], + join("issues", entry), + check as ( + project: ProjectReflection, + logger: TestLogger + ) => void + ); + } } for (const [entry, check] of Object.entries(behaviorTests)) { - const title = `Handles ${entry.replace( - /([a-z][A-Z])/g, - (x) => `${x[0]} ${x[1].toLowerCase()}` - )}`; + const title = `Handles ${entry + .replace(/([a-z][A-Z])/g, (x) => `${x[0]} ${x[1].toLowerCase()}`) + .replace("_skip", "")}`; + + if (entry.startsWith("_")) continue; - runTest(title, join("behavior", entry), check); + if (entry.endsWith("_skip")) { + it.skip(entry); + } else { + runTest( + title, + behaviorTests[`_${entry}`], + join("behavior", entry), + check as ( + project: ProjectReflection, + logger: TestLogger + ) => void + ); + } } }); diff --git a/src/test/converter2/behavior/blockComment.ts b/src/test/converter2/behavior/blockComment.ts new file mode 100644 index 000000000..1a8dcb286 --- /dev/null +++ b/src/test/converter2/behavior/blockComment.ts @@ -0,0 +1,5 @@ +/** jsdoc block */ +export const a = 123; + +/* block, but not jsdoc */ +export const b = 123; diff --git a/src/test/converter2/behavior/deprecatedBracketLinks.ts b/src/test/converter2/behavior/deprecatedBracketLinks.ts new file mode 100644 index 000000000..dcb8c05f9 --- /dev/null +++ b/src/test/converter2/behavior/deprecatedBracketLinks.ts @@ -0,0 +1,9 @@ +/** + * Supports [[beta]] basic bracket links. + */ +export const alpha = 123; + +/** + * Supports [[alpha | bracket links]] with text. + */ +export const beta = 456; diff --git a/src/test/converter2/behavior/exampleTags.ts b/src/test/converter2/behavior/exampleTags.ts new file mode 100644 index 000000000..2da630194 --- /dev/null +++ b/src/test/converter2/behavior/exampleTags.ts @@ -0,0 +1,21 @@ +/** + * The example tag is problematic. + * JSDoc expects it to have no code ticks: https://jsdoc.app/tags-example.html + * TSDoc does not: https://tsdoc.org/pages/tags/example/ + * VSCode says it's code if it does not include a code block: https://github.com/Microsoft/vscode/blob/1.64.2/extensions/typescript-language-features/src/utils/previewer.ts#L52-L60 + * + * @example + * // JSDoc style + * codeHere(); + * + * @example JSDoc specialness + * // JSDoc style + * codeHere(); + * + * @example + * ```ts + * // TSDoc style + * codeHere(); + * ``` + */ +export const foo = 123; diff --git a/src/test/converter2/behavior/exportComments.ts b/src/test/converter2/behavior/exportComments.ts new file mode 100644 index 000000000..03af8b78e --- /dev/null +++ b/src/test/converter2/behavior/exportComments.ts @@ -0,0 +1,13 @@ +/** abc */ +const abc = 123; + +/** export abc */ +export { abc, abc as abcRef }; + +/** foo */ +namespace foo { + export const abc = 123; +} + +/** export foo */ +export { foo }; diff --git a/src/test/converter2/behavior/groupTag.ts b/src/test/converter2/behavior/groupTag.ts new file mode 100644 index 000000000..7f49a4ead --- /dev/null +++ b/src/test/converter2/behavior/groupTag.ts @@ -0,0 +1,15 @@ +/** + * @group A + */ +export const A = 123; + +/** + * @group A + * @group B + */ +export const B = 123; + +/** + * @group With Spaces + */ +export const C = 123; diff --git a/src/test/converter2/behavior/inheritDocBasic.ts b/src/test/converter2/behavior/inheritDocBasic.ts new file mode 100644 index 000000000..3316f6045 --- /dev/null +++ b/src/test/converter2/behavior/inheritDocBasic.ts @@ -0,0 +1,37 @@ +/** + * Summary + * @remarks Remarks + * @typeParam T - Type parameter + */ +export interface InterfaceSource { + /** + * Property description + */ + property: T; + + /** + * Method description + * @param arg arg description + */ + someMethod(arg: number): T; +} + +/** + * @inheritDoc InterfaceSource + */ +export interface InterfaceTarget { + /** + * @inheritDoc InterfaceSource.property + */ + property: T; + + /** + * @inheritDoc InterfaceSource.someMethod + * + * @example This should still be present + * ```ts + * someMethod(123) + * ``` + */ + someMethod(arg: number): T; +} diff --git a/src/test/converter2/behavior/inheritDocJsdoc.ts b/src/test/converter2/behavior/inheritDocJsdoc.ts new file mode 100644 index 000000000..a4c3575d6 --- /dev/null +++ b/src/test/converter2/behavior/inheritDocJsdoc.ts @@ -0,0 +1,19 @@ +/** Foo */ +export class Foo { + /** + * Foo.member + * @param x Foo.member.x + */ + member(x: number) {} +} + +/** @inheritdoc */ +export class Bar implements Foo { + /** @inheritdoc */ + member(x: number) {} +} + +export class Baz extends Foo { + /** @inheritdoc */ + override member(x: number): void {} +} diff --git a/src/test/converter2/behavior/inheritDocRecursive.ts b/src/test/converter2/behavior/inheritDocRecursive.ts new file mode 100644 index 000000000..f8541b9fe --- /dev/null +++ b/src/test/converter2/behavior/inheritDocRecursive.ts @@ -0,0 +1,14 @@ +/** @inheritDoc B */ +export interface A { + a: string; +} + +/** @inheritDoc C */ +export interface B { + b: string; +} + +/** @inheritDoc A */ +export interface C { + c: string; +} diff --git a/src/test/converter2/behavior/inheritDocWarnings.ts b/src/test/converter2/behavior/inheritDocWarnings.ts new file mode 100644 index 000000000..609a1e21e --- /dev/null +++ b/src/test/converter2/behavior/inheritDocWarnings.ts @@ -0,0 +1,34 @@ +/** + * Source + * @remarks Remarks + */ +export const source = 123; + +export const source2 = 123; + +/** + * Target summary + * @inheritDoc source + */ +export const target1 = 123; + +/** + * @inheritDoc source + * @remarks Target remarks + */ +export const target2 = 123; + +/** + * @inheritDoc doesNotExist + */ +export const target3 = 123; + +/** + * @inheritDoc source2 + */ +export const target4 = 123; + +/** + * {@inheritDoc source:bad_label} + */ +export const badParse = 456; diff --git a/src/test/converter2/behavior/lineComment.ts b/src/test/converter2/behavior/lineComment.ts new file mode 100644 index 000000000..7563433b2 --- /dev/null +++ b/src/test/converter2/behavior/lineComment.ts @@ -0,0 +1,9 @@ +// docs +export const a = 123; + +///// docs +// with multiple lines +export const b = 123; + +/** no docs */ +export const c = 123; diff --git a/src/test/converter2/behavior/linkResolution.ts b/src/test/converter2/behavior/linkResolution.ts new file mode 100644 index 000000000..602ae774e --- /dev/null +++ b/src/test/converter2/behavior/linkResolution.ts @@ -0,0 +1,123 @@ +export namespace Scoping { + // TypeScript / TypeDoc + /** {@link abc | def} */ + export type abc = 1; + + /** {@link abc} 2/2 */ + export namespace Foo { + /** {@link abc} 2/2 */ + export type abc = 2; + + export function bar(): undefined; + export function bar(x: number): number; + export function bar(x?: number): number | undefined { + return x; + } + } + + /** {@link abc} 1/1 */ + export interface Bar { + /** {@link abc} 1/1 */ + abc: 3; + } +} + +/** + * {@link Meanings!A} + * {@link Meanings!A:namespace} + * {@link Meanings!A:enum} + * + * {@link A:class} doesn't exist + * {@link B:class} + * + * {@link C:interface} + * {@link D:type} + * {@link E:function} + * {@link F:var} + * + * {@link B:constructor} + * {@link B:constructor(0)} + * {@link B:constructor(1)} + * + * {@link A.A:member} + * {@link B.prop:event} Don't use this. It doesn't work but is required by the grammar. + * + * {@link E:call} + * {@link E:call(1)} + * + * {@link B:new} + * {@link B:new(1)} + * + * {@link B:index} + * {@link G:complex} + * + * {@link E:1} + * {@link B:0} Weird, but technically ok + */ +export namespace Meanings { + export enum A { + A, + B, + } + export namespace A { + export const a = 123; + } + + export class B { + constructor(); + constructor(x: number); + constructor(_?: number) {} + + /** @event */ + prop = 1; + + [x: string]: number; + } + + export interface C {} + + export type D = 123; + + export function E(): void; + export function E(x: number): number; + export function E(x?: number) { + return x; + } + + export const F = 123; + + export interface G {} + export namespace G {} +} + +/** + * {@link https://example.com} + * {@link ftp://example.com} + */ +export namespace URLS {} + +export const A = 1; + +export namespace Globals { + /** + * {@link URLS!} + * {@link !A} + * {@link A} + */ + export const A = 2; +} + +/** + * {@link Navigation~Child.foo} + * {@link Navigation.Child#foo} + * {@link Child~foo} bad + */ +export namespace Navigation { + export class Child { + /** + * {@link foo} Child.foo, not Child#foo + */ + static foo() {} + foo = 456; + } +} diff --git a/src/test/converter2/behavior/mergedDeclarations.ts b/src/test/converter2/behavior/mergedDeclarations.ts new file mode 100644 index 000000000..cad2337ea --- /dev/null +++ b/src/test/converter2/behavior/mergedDeclarations.ts @@ -0,0 +1,8 @@ +export namespace SingleCommentMultiDeclaration {} +/** Comment on second declaration */ +export namespace SingleCommentMultiDeclaration {} + +/** Comment 1 */ +export namespace MultiCommentMultiDeclaration {} +/** Comment 2 */ +export namespace MultiCommentMultiDeclaration {} diff --git a/src/test/converter2/behavior/overloads.ts b/src/test/converter2/behavior/overloads.ts index 9442d0e96..aa152361a 100644 --- a/src/test/converter2/behavior/overloads.ts +++ b/src/test/converter2/behavior/overloads.ts @@ -1,13 +1,31 @@ +/** + * No arg comment + * {@label NO_ARGS} + */ export function foo(): string; /** - * Overrides summary + * {@inheritDoc foo:NO_ARGS} + * {@label WITH_X} + * @param x docs for x */ export function foo(x: string): number; +export function foo(x?: string): string | number { + return x == null ? "" : x.length; +} +export function bar(): string; +/** + * Custom comment + */ +export function bar(x: string): string; /** * Implementation comment - * @param x docs for x */ -export function foo(x?: string): string | number { - return x == null ? "" : x.length; +export function bar(x?: string) { + return x || ""; } + +/** + * {@label bad} + */ +export function badLabel() {} diff --git a/src/test/converter2/behavior/readonlyTag.ts b/src/test/converter2/behavior/readonlyTag.ts new file mode 100644 index 000000000..26f74249b --- /dev/null +++ b/src/test/converter2/behavior/readonlyTag.ts @@ -0,0 +1,20 @@ +export class Book { + /** + * Technically property has a setter, but for documentation purposes it should + * be presented as readonly. + * @readonly + */ + get title(): string { + return "hah"; + } + + set title(_value: string) { + throw new Error("This property is read-only!"); + } + + /** + * Should be documented as readonly because no consumer should change it. + * @readonly + */ + author!: string; +} diff --git a/src/test/converter2/behavior/searchCategoryBoosts.ts b/src/test/converter2/behavior/searchCategoryBoosts.ts new file mode 100644 index 000000000..40bc8fe7a --- /dev/null +++ b/src/test/converter2/behavior/searchCategoryBoosts.ts @@ -0,0 +1,13 @@ +/** + * @category Cat1 + * @category Cat2 + */ +export interface A {} +/** + * @category Cat0 + */ +export interface B {} +/** + * @category Cat1 + */ +export interface C {} diff --git a/src/test/converter2/behavior/searchGroupBoosts.ts b/src/test/converter2/behavior/searchGroupBoosts.ts new file mode 100644 index 000000000..cabf09dca --- /dev/null +++ b/src/test/converter2/behavior/searchGroupBoosts.ts @@ -0,0 +1,17 @@ +/** + * @group Group1 + * @group Group2 + */ +export interface A {} +/** + * @group Group0 + */ +export interface B {} +/** + * @group Group1 + */ +export interface C {} +/** + * No group, implicitly in the "Interfaces" group + */ +export interface D {} diff --git a/src/test/converter2/behavior/seeTags.ts b/src/test/converter2/behavior/seeTags.ts new file mode 100644 index 000000000..12659e0ca --- /dev/null +++ b/src/test/converter2/behavior/seeTags.ts @@ -0,0 +1,10 @@ +/** + * @see Double tag + * @see Second tag + */ +export const foo = 123; + +/** + * @see Single tag + */ +export const bar = 123; diff --git a/src/test/converter2/issues/gh1580.ts b/src/test/converter2/issues/gh1580.ts index 2caef2c83..4463fa0d1 100644 --- a/src/test/converter2/issues/gh1580.ts +++ b/src/test/converter2/issues/gh1580.ts @@ -1,3 +1,5 @@ +// Export order matters here. We want TypeDoc to process `B` before `A` so that the +// implements plugin has to defer handling of `B` export { B, A }; class A { diff --git a/src/test/converter2/issues/gh1770.ts b/src/test/converter2/issues/gh1770.ts new file mode 100644 index 000000000..7ee8b4bc6 --- /dev/null +++ b/src/test/converter2/issues/gh1770.ts @@ -0,0 +1,18 @@ +const api = (): { + sym1: () => number; + sym2: number; +} => { + return null!; +}; + +export const { + /** + * Docs for Sym1 + */ + sym1, + + /** + * Docs for Sym2 + */ + sym2, +} = api(); diff --git a/src/test/converter2/issues/gh1771.ts b/src/test/converter2/issues/gh1771.ts new file mode 100644 index 000000000..086c945df --- /dev/null +++ b/src/test/converter2/issues/gh1771.ts @@ -0,0 +1,10 @@ +export class Test { + method() {} +} + +export { Test as Test2 }; + +/** + * {@link Test2.method} + */ +export const check = 123; diff --git a/src/test/converter2/issues/gh1804.js b/src/test/converter2/issues/gh1804.js new file mode 100644 index 000000000..35dedaad3 --- /dev/null +++ b/src/test/converter2/issues/gh1804.js @@ -0,0 +1,4 @@ +/** + * @param {number} [arg] + */ +export function foo(arg) {} diff --git a/src/test/converter2/issues/gh1896.js b/src/test/converter2/issues/gh1896.js new file mode 100644 index 000000000..551a787c9 --- /dev/null +++ b/src/test/converter2/issues/gh1896.js @@ -0,0 +1,16 @@ +/** + * Before tag + * @callback Type1 On Tag + * @param {number} one Param 1 + * @param {number} two Param 2 + * @returns {number} Ret + */ + +/** + * Before tag + * @typedef {{(one: number, two: number) => number}} Type2 + * + * Some type 2. + */ + +export const answer = 42; diff --git a/src/test/converter2/issues/gh1913.js b/src/test/converter2/issues/gh1913.js new file mode 100644 index 000000000..835b12e80 --- /dev/null +++ b/src/test/converter2/issues/gh1913.js @@ -0,0 +1,4 @@ +/** + * @returns {[{ [key1: string]: number }, { [key2: string]: string }]} ret + */ +exports.fn = () => [{ a: 42 }, { b: "42" }]; diff --git a/src/test/converter2/issues/gh1927.ts b/src/test/converter2/issues/gh1927.ts new file mode 100644 index 000000000..2ada03393 --- /dev/null +++ b/src/test/converter2/issues/gh1927.ts @@ -0,0 +1,15 @@ +export abstract class Base { + /** + * Base + */ + abstract get getter(): string; +} + +export class Derived extends Base { + /** + * @inheritdoc + */ + public get getter() { + return ""; + } +} diff --git a/src/test/converter2/issues/gh567.ts b/src/test/converter2/issues/gh567.ts new file mode 100644 index 000000000..c620e1ed3 --- /dev/null +++ b/src/test/converter2/issues/gh567.ts @@ -0,0 +1,4 @@ +/** + * @param [x] JSDoc style param name + */ +export function foo(x?: string) {} diff --git a/src/test/converter2/issues/gh671.js b/src/test/converter2/issues/gh671.js new file mode 100644 index 000000000..0b4150017 --- /dev/null +++ b/src/test/converter2/issues/gh671.js @@ -0,0 +1,7 @@ +/** + * @param {string} x the string to parse as a number + * @param {boolean} [int=true] whether to parse as an integer or float + */ +export function toNumber(x, int = true) { + return int ? parseInt(x) : parseFloat(x); +} diff --git a/src/test/declarationReference.test.ts b/src/test/declarationReference.test.ts new file mode 100644 index 000000000..a835d2246 --- /dev/null +++ b/src/test/declarationReference.test.ts @@ -0,0 +1,222 @@ +import { deepStrictEqual as equal } from "assert"; +import { + parseComponent, + parseComponentPath, + parseDeclarationReference, + parseMeaning, + parseModuleSource, + parseString, + parseSymbolReference, +} from "../lib/converter/comments/declarationReference"; + +describe("Declaration References", () => { + describe("String parsing", () => { + const parse = (s: string) => parseString(s, 0, s.length)?.[0]; + + it("Fails if string does not start with a double quote", () => { + equal(parse("x"), undefined); + }); + + it("Fails if string includes a line terminator", () => { + equal(parse('"a\nb"'), undefined); + }); + + it("Fails if string is unclosed", () => { + equal(parse('"abc'), undefined); + }); + + it("Bails on bad escapes", () => { + equal(parse('"\\123"'), undefined); + equal(parse('"\\xZZ"'), undefined); + equal(parse('"\\uAAAZ"'), undefined); + equal(parse('"\\u4"'), undefined); + equal(parse('"\\u{41"'), undefined); + equal(parse('"\\uZ"'), undefined); + equal(parse('"\\u{FFFFFFFFFFFFFFFFFFFFFFF}"'), undefined); + }); + + it("Parses successfully", () => { + equal(parse('"abc\\x41\\u0041\\u{42}z\\n\\a\\0"'), "abcAABz\na\0"); + }); + }); + + describe("Component parsing", () => { + const parse = (s: string) => parseComponent(s, 0, s.length)?.[0]; + + it("Fails if it is an invalid string", () => { + equal(parse('"asdf'), undefined); + }); + + it("Fails if there is no valid string", () => { + equal(parse(""), undefined); + equal(parse("\n"), undefined); + }); + + it("Reads valid component", () => { + equal(parse("abc"), "abc"); + equal(parse('"abc"'), "abc"); + }); + }); + + describe("Component Path parsing", () => { + const parse = (s: string) => parseComponentPath(s, 0, s.length)?.[0]; + + it("Fails if it is an invalid string", () => { + equal(parse('"asdf'), undefined); + }); + + it("Fails if a later part of the path fails to parse", () => { + equal(parse('a."asdf'), undefined); + }); + + it("Parses a path", () => { + equal(parse("a.b"), [ + { navigation: ".", path: "a" }, + { navigation: ".", path: "b" }, + ]); + equal(parse('a#"b"'), [ + { navigation: ".", path: "a" }, + { navigation: "#", path: "b" }, + ]); + }); + }); + + describe("Meaning parsing", () => { + const parse = (s: string) => { + const meaning = parseMeaning(s, 0, s.length); + if (meaning) { + equal( + meaning[1], + s.length, + "Parse did not consume full string" + ); + } + return meaning?.[0]; + }; + + it("Fails if string does not start with :", () => { + equal(parse("class"), undefined); + }); + + it("Parses a bare keyword", () => { + equal(parse(":class"), { keyword: "class" }); + }); + + it("Parses a keyword with index", () => { + equal(parse(":class(123)"), { keyword: "class", index: 123 }); + }); + + it("Does not parse index if invalid", () => { + const input = ":class(123"; + const meaning = parseMeaning(input, 0, input.length); + equal(meaning, [{ keyword: "class" }, ":class".length]); + }); + + it("Parses an index", () => { + equal(parse(":(123)"), { keyword: undefined, index: 123 }); + }); + + it("Parses a bare index", () => { + equal(parse(":123"), { index: 123 }); + }); + + it("Parses a user identifier", () => { + equal(parse(":USER_IDENT"), { label: "USER_IDENT" }); + }); + }); + + describe("Symbol reference parsing", () => { + const parse = (s: string) => parseSymbolReference(s, 0, s.length)?.[0]; + + it("Fails if both parses fail", () => { + equal(parse(":bad"), undefined); + }); + + it("Succeeds if path succeeds", () => { + equal(parse("a"), { + path: [{ navigation: ".", path: "a" }], + meaning: undefined, + }); + }); + + it("Succeeds if meaning succeeds", () => { + equal(parse(":class"), { + path: undefined, + meaning: { keyword: "class" }, + }); + }); + + it("Succeeds both succeed", () => { + equal(parse("a:class(1)"), { + path: [{ navigation: ".", path: "a" }], + meaning: { keyword: "class", index: 1 }, + }); + }); + }); + + describe("Module source parsing", () => { + const parse = (s: string) => parseModuleSource(s, 0, s.length)?.[0]; + + it("Fails if empty", () => { + equal(parse(""), undefined); + equal(parse("!"), undefined); + }); + + it("Parses strings", () => { + equal(parse('"ab"'), "ab"); + }); + + it("Parses module source characters", () => { + equal(parse("abc.def"), "abc.def"); + }); + }); + + describe("Full reference parsing", () => { + const parse = (s: string) => + parseDeclarationReference(s, 0, s.length)?.[0]; + + it("Parses module if there is one", () => { + equal(parse("abc!"), { + moduleSource: "abc", + resolutionStart: "global", + symbolReference: undefined, + }); + }); + + it("Does not parse module if there is not one", () => { + equal(parse("abc#def"), { + moduleSource: undefined, + resolutionStart: "local", + symbolReference: { + path: [ + { navigation: ".", path: "abc" }, + { navigation: "#", path: "def" }, + ], + meaning: undefined, + }, + }); + }); + + it("Supports referencing global symbols", () => { + equal(parse("!abc#def"), { + moduleSource: undefined, + resolutionStart: "global", + symbolReference: { + path: [ + { navigation: ".", path: "abc" }, + { navigation: "#", path: "def" }, + ], + meaning: undefined, + }, + }); + }); + + it("Doesn't crash with an empty reference", () => { + equal(parse(""), { + moduleSource: undefined, + resolutionStart: "local", + symbolReference: undefined, + }); + }); + }); +}); diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index ead65d591..0791c0e33 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -1,4 +1,5 @@ import { deepStrictEqual as equal, ok } from "assert"; +import type { Application } from "../lib/application"; import { DeclarationReflection, ProjectReflection, @@ -12,6 +13,7 @@ import { LiteralType, IntrinsicType, } from "../lib/models"; +import type { InlineTagDisplayPart } from "../lib/models/comments/comment"; import { getConverter2App } from "./programs"; import type { TestLogger } from "./TestLogger"; @@ -22,8 +24,39 @@ function query(project: ProjectReflection, name: string) { } export const issueTests: { - [issue: string]: (project: ProjectReflection, logger: TestLogger) => void; + [issue: `pre${string}`]: (app: Application) => void; + [issue: `gh${string}`]: ( + project: ProjectReflection, + logger: TestLogger + ) => void; } = { + gh567(project) { + const foo = query(project, "foo"); + const sig = foo.signatures?.[0]; + ok(sig, "Missing signature"); + ok(sig.comment, "No comment for signature"); + const param = sig.parameters?.[0]; + equal(param?.name, "x"); + equal( + Comment.combineDisplayParts(param.comment?.summary), + "JSDoc style param name" + ); + }, + + gh671(project) { + const toNumber = query(project, "toNumber"); + const sig = toNumber.signatures?.[0]; + ok(sig, "Missing signatures"); + + const paramComments = sig.parameters?.map((param) => + Comment.combineDisplayParts(param.comment?.summary) + ); + equal(paramComments, [ + "the string to parse as a number", + "whether to parse as an integer or float", + ]); + }, + gh869(project) { const classFoo = project.children?.find( (r) => r.name === "Foo" && r.kind === ReflectionKind.Class @@ -58,10 +91,16 @@ export const issueTests: { gh1164(project) { const refl = query(project, "gh1164"); equal( - refl.signatures?.[0]?.parameters?.[0]?.comment?.shortText, + Comment.combineDisplayParts( + refl.signatures?.[0]?.parameters?.[0]?.comment?.summary + ), "{@link CommentedClass} Test description." ); - equal(refl.signatures?.[0]?.comment?.returns, "Test description.\n"); + const tag = refl.signatures?.[0]?.comment?.blockTags.find( + (x) => x.tag === "@returns" + ); + ok(tag); + equal(Comment.combineDisplayParts(tag.content), "Test description."); }, gh1215(project) { @@ -72,7 +111,7 @@ export const issueTests: { gh1255(project) { const foo = query(project, "C.foo"); - equal(foo.comment?.shortText, "Docs!"); + equal(Comment.combineDisplayParts(foo.comment?.summary), "Docs!"); }, gh1330(project) { @@ -125,15 +164,23 @@ export const issueTests: { equal(prop.type?.toString(), "number"); // Would be nice to get this to work someday - equal(prop.comment?.shortText, void 0); + equal(prop.comment?.summary, void 0); const method = query(project, "METHOD"); - equal(method.signatures?.[0].comment?.shortText, "method docs"); + equal( + Comment.combineDisplayParts( + method.signatures?.[0].comment?.summary + ), + "method docs" + ); }, gh1481(project) { const signature = query(project, "GH1481.static").signatures?.[0]; - equal(signature?.comment?.shortText, "static docs"); + equal( + Comment.combineDisplayParts(signature?.comment?.summary), + "static docs" + ); equal(signature?.type?.toString(), "void"); }, @@ -150,7 +197,10 @@ export const issueTests: { gh1490(project) { const refl = query(project, "GH1490.optionalMethod"); - equal(refl.signatures?.[0]?.comment?.shortText, "With comment"); + equal( + Comment.combineDisplayParts(refl.signatures?.[0]?.comment?.summary), + "With comment" + ); }, gh1509(project) { @@ -209,7 +259,7 @@ export const issueTests: { gh1578(project) { ok(query(project, "notIgnored")); ok( - !project.findReflectionByName("ignored"), + !project.getChildByName("ignored"), "Symbol re-exported from ignored file is ignored." ); }, @@ -246,9 +296,13 @@ export const issueTests: { gh1733(project) { const alias = query(project, "Foo"); - equal(alias.typeParameters?.[0].comment?.shortText.trim(), "T docs"); + equal(alias.typeParameters?.[0].comment?.summary, [ + { kind: "text", text: "T docs" }, + ]); const cls = query(project, "Bar"); - equal(cls.typeParameters?.[0].comment?.shortText.trim(), "T docs"); + equal(cls.typeParameters?.[0].comment?.summary, [ + { kind: "text", text: "T docs" }, + ]); }, gh1734(project) { @@ -257,36 +311,60 @@ export const issueTests: { ok(type instanceof ReflectionType); const expectedComment = new Comment(); - expectedComment.returns = undefined; - expectedComment.tags = [ - new CommentTag("asdf", void 0, "Some example text\n"), + expectedComment.blockTags = [ + new CommentTag("@asdf", [ + { kind: "text", text: "Some example text" }, + ]), ]; equal(type.declaration.signatures?.[0].comment, expectedComment); }, gh1745(project) { const Foo = query(project, "Foo"); - ok(Foo.type instanceof ReflectionType); + ok(Foo.type instanceof ReflectionType, "invalid type"); - const group = project.groups?.find( - (g) => g.kind === ReflectionKind.TypeAlias - ); - ok(group); + const group = project.groups?.find((g) => g.title === "Type Aliases"); + ok(group, "missing group"); const cat = group.categories?.find( (cat) => cat.title === "My category" ); - ok(cat); + ok(cat, "missing cat"); - ok(cat.children.includes(Foo)); - ok(!Foo.comment?.hasTag("category")); - ok(!Foo.type.declaration.comment?.hasTag("category")); + ok(cat.children.includes(Foo), "not included in cat"); + ok(!Foo.comment?.getTag("@category"), "has cat tag"); + ok(!Foo.type.declaration.comment?.getTag("@category"), "has cat tag 2"); ok( !Foo.type.declaration.signatures?.some((s) => - s.comment?.hasTag("category") - ) + s.comment?.getTag("@category") + ), + "has cat tag 3" + ); + }, + + gh1770(project) { + const sym1 = query(project, "sym1"); + equal( + Comment.combineDisplayParts(sym1.signatures?.[0].comment?.summary), + "Docs for Sym1" + ); + + const sym2 = query(project, "sym2"); + equal( + Comment.combineDisplayParts(sym2.comment?.summary), + "Docs for Sym2" ); }, + gh1771(project) { + const check = query(project, "check"); + const tag = check.comment?.summary[0] as + | InlineTagDisplayPart + | undefined; + equal(tag?.kind, "inline-tag"); + equal(tag.text, "Test2.method"); + equal(tag.target, query(project, "Test.method")); + }, + gh1795(project) { equal( project.children?.map((c) => c.name), @@ -296,6 +374,15 @@ export const issueTests: { ok(project.children![1].kind !== ReflectionKind.Reference); }, + gh1804(project) { + const foo = query(project, "foo"); + const sig = foo.signatures?.[0]; + ok(sig); + const param = sig.parameters?.[0]; + ok(param); + ok(param.flags.isOptional); + }, + gh1875(project) { const test = query(project, "test"); equal( @@ -317,9 +404,11 @@ export const issueTests: { ok(fooSig.type instanceof UnionType); ok(fooSig.type.types[1] instanceof ReflectionType); equal( - fooSig.type.types[1].declaration.getChildByName("min")?.comment - ?.shortText, - "Nested\n" + Comment.combineDisplayParts( + fooSig.type.types[1].declaration.getChildByName("min")?.comment + ?.summary + ), + "Nested" ); const bar = query(project, "bar"); @@ -329,14 +418,18 @@ export const issueTests: { ok(barSig.type.types[0] instanceof ReflectionType); ok(barSig.type.types[1] instanceof ReflectionType); equal( - barSig.type.types[0].declaration.getChildByName("min")?.comment - ?.shortText, - "Nested\n" + Comment.combineDisplayParts( + barSig.type.types[0].declaration.getChildByName("min")?.comment + ?.summary + ), + "Nested" ); equal( - barSig.type.types[1].declaration.getChildByName("min")?.comment - ?.shortText, - "Nested\n" + Comment.combineDisplayParts( + barSig.type.types[1].declaration.getChildByName("min")?.comment + ?.summary + ), + "Nested" ); }, @@ -349,6 +442,22 @@ export const issueTests: { ok(auto.hasComment(), "Missing @enum member comment"); }, + gh1896(project) { + const Type1 = query(project, "Type1"); + const Type2 = query(project, "Type2"); + equal(Type1.type?.type, "reflection" as const); + equal(Type2.type?.type, "reflection" as const); + + equal( + Type1.type.declaration.signatures?.[0].comment, + new Comment([{ kind: "text", text: "On Tag" }]) + ); + equal( + Type2.type.declaration.signatures?.[0].comment, + new Comment([{ kind: "text", text: "Some type 2." }]) + ); + }, + gh1898(project, logger) { const app = getConverter2App(); app.validate(project); @@ -381,6 +490,27 @@ export const issueTests: { logger.expectNoOtherMessages(); }, + gh1913(project) { + const fn = query(project, "fn"); + + equal( + fn.signatures?.[0].comment, + new Comment( + [], + [new CommentTag("@returns", [{ kind: "text", text: "ret" }])] + ) + ); + }, + + gh1927(project) { + const ref = query(project, "Derived.getter"); + + equal( + ref.getSignature?.comment, + new Comment([{ kind: "text", text: "Base" }]) + ); + }, + gh1942(project) { equal(query(project, "Foo.A").type, new LiteralType(0)); equal(query(project, "Foo.B").type, new IntrinsicType("number")); diff --git a/src/test/legend-builder.test.ts b/src/test/legend-builder.test.ts deleted file mode 100644 index 9c6a8a2d4..000000000 --- a/src/test/legend-builder.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { deepStrictEqual as equal } from "assert"; -import { LegendBuilder } from "../lib/output/plugins/LegendPlugin"; - -describe("LegendBuilder", function () { - it("returns empty items when no css classes are registered", function () { - const builder = new LegendBuilder(); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, []); - }); - - it("returns single item list when common css classes are registered", function () { - const builder = new LegendBuilder(); - builder.registerCssClasses(["tsd-kind-namespace"]); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, [["Namespace"]]); - }); - - it("returns single item list with multiple items when common css classes are registered", function () { - const builder = new LegendBuilder(); - builder.registerCssClasses(["tsd-kind-namespace"]); - builder.registerCssClasses(["tsd-kind-function"]); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, [["Namespace", "Function"]]); - }); - - it("returns single item list with multiple items when multiple css classes are registered", function () { - const builder = new LegendBuilder(); - builder.registerCssClasses(["tsd-kind-namespace"]); - builder.registerCssClasses(["tsd-kind-function"]); - builder.registerCssClasses([ - "tsd-kind-function", - "tsd-has-type-parameter", - ]); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, [ - ["Namespace", "Function", "Function with type parameter"], - ]); - }); - - it("returns multiple item list when common css classes are registered from different groups", function () { - const builder = new LegendBuilder(); - builder.registerCssClasses(["tsd-kind-namespace"]); - builder.registerCssClasses([ - "tsd-kind-accessor", - "tsd-parent-kind-class", - "tsd-is-inherited", - ]); - builder.registerCssClasses([ - "tsd-kind-property", - "tsd-parent-kind-class", - "tsd-is-private", - ]); - builder.registerCssClasses([ - "tsd-kind-accessor", - "tsd-parent-kind-class", - "tsd-is-private", - ]); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, [ - ["Namespace"], - ["Inherited accessor"], - ["Private property", "Private accessor"], - ]); - }); - - it("returns single item when includes ignored classes", function () { - const builder = new LegendBuilder(); - builder.registerCssClasses([ - "tsd-kind-class", - "tsd-parent-kind-module", - ]); - const results = builder - .build() - .map((items) => items.map((item) => item.name)); - - equal(results, [["Class"]]); - }); -}); diff --git a/src/test/packages.test.ts b/src/test/packages.test.ts index b1fc784ad..18847691f 100644 --- a/src/test/packages.test.ts +++ b/src/test/packages.test.ts @@ -1,24 +1,88 @@ -import { deepStrictEqual as equal, ok } from "assert"; +import { deepStrictEqual as equal } from "assert"; import { readFileSync } from "fs"; import { join } from "path"; -import { Logger, normalizePath } from "../lib/utils"; +import { normalizePath } from "../lib/utils"; import { expandPackages, getTsEntryPointForPackage, } from "../lib/utils/package-manifest"; +import { tempdirProject } from "@typestrong/fs-fixture-builder"; +import { TestLogger } from "./TestLogger"; + describe("Packages support", () => { + let project: ReturnType; + + beforeEach(() => { + project = tempdirProject(); + }); + + afterEach(() => { + project.rm(); + }); + it("handles monorepos", () => { - const base = join(__dirname, "packages", "multi-package"); - const logger = new Logger(); - const packages = expandPackages(logger, ".", [base]); + project.addJsonFile("tsconfig.json", { + compilerOptions: { + strict: true, + sourceMap: true, + }, + exclude: ["node_modules", "dist"], + }); + const childTsconfig = { + extends: "../../tsconfig.json", + compilerOptions: { + outDir: "dist", + }, + }; + project.addJsonFile("package.json", { + name: "typedoc-multi-package-example", + main: "dist/index.js", + workspaces: ["packages/*"], + }); + + // Bar, types entry point + project.addFile( + "packages/bar/index.d.ts", + "export function bar(): void;" + ); + project.addJsonFile("packages/bar/package.json", { + name: "typedoc-multi-package-bar", + version: "1.0.0", + types: "index.d.ts", + }); + project.addJsonFile("packages/bar/tsconfig.json", childTsconfig); + + // Baz, TypeScript "main" entry point + project.addFile("packages/baz/index.ts", "export function baz(): {}"); + project.addJsonFile("packages/baz/package.json", { + name: "typedoc-multi-package-baz", + version: "1.0.0", + main: "index.ts", + }); + project.addJsonFile("packages/baz/tsconfig.json", childTsconfig); + + // Foo, entry point with "typedocMain" + project.addFile("packages/foo/dist/index.js", "module.exports = 123"); + project.addFile("packages/foo/index.ts", "export function foo() {}"); + project.addJsonFile("packages/foo/package.json", { + name: "typedoc-multi-package-foo", + version: "1.0.0", + main: "dist/index", + typedocMain: "index.ts", + }); + project.addJsonFile("packages/foo/tsconfig.json", childTsconfig); + + project.write(); + const logger = new TestLogger(); + const packages = expandPackages(logger, project.cwd, [project.cwd]); equal( packages, [ - join(base, "packages/bar"), - join(base, "packages/baz"), - join(base, "packages/foo"), + join(project.cwd, "packages/bar"), + join(project.cwd, "packages/baz"), + join(project.cwd, "packages/foo"), ].map(normalizePath) ); @@ -32,19 +96,82 @@ describe("Packages support", () => { }); equal(entries, [ - join(base, "packages/bar/index.d.ts"), - join(base, "packages/baz/index.ts"), - join(base, "packages/foo/index.ts"), + join(project.cwd, "packages/bar/index.d.ts"), + join(project.cwd, "packages/baz/index.ts"), + join(project.cwd, "packages/foo/index.ts"), ]); - ok(!logger.hasErrors() && !logger.hasWarnings()); + logger.discardDebugMessages(); + logger.expectNoOtherMessages(); }); it("handles single packages", () => { - const base = join(__dirname, "packages", "single-package"); - const logger = new Logger(); - const packages = expandPackages(logger, ".", [base]); + project.addJsonFile("tsconfig.json", { + compilerOptions: { + outDir: "dist", + sourceMap: true, + strict: true, + }, + include: ["src"], + }); + project.addJsonFile("package.json", { + name: "typedoc-single-package", + main: "dist/index.js", + }); + project.addFile("dist/index.js", `//# sourceMappingURL=index.js.map`); + project.addJsonFile("dist/index.js.map", { + version: 3, + file: "index.js", + sourceRoot: "", + sources: ["../src/index.ts"], + names: [], + mappings: "", + }); + project.addFile( + "src/index.ts", + `export function helloWorld() { return "Hello World!"; }` + ); + project.write(); + + const logger = new TestLogger(); + const packages = expandPackages(logger, project.cwd, [project.cwd]); + + logger.expectNoOtherMessages(); + equal(packages, [normalizePath(project.cwd)]); + }); + + it("Handles TS 4.7 extensions", () => { + project.addJsonFile("tsconfig.json", { + compilerOptions: { + outDir: "dist", + sourceMap: true, + strict: true, + }, + include: ["src"], + }); + project.addJsonFile("package.json", { + name: "typedoc-single-package", + main: "dist/index.cjs", + }); + project.addFile("dist/index.cjs", `//# sourceMappingURL=index.cjs.map`); + project.addJsonFile("dist/index.cjs.map", { + version: 3, + file: "index.cjs", + sourceRoot: "", + sources: ["../src/index.cts"], + names: [], + mappings: "", + }); + project.addFile( + "src/index.cts", + `export function helloWorld() { return "Hello World!"; }` + ); + project.write(); + + const logger = new TestLogger(); + const packages = expandPackages(logger, project.cwd, [project.cwd]); - equal(packages, [normalizePath(base)]); + logger.expectNoOtherMessages(); + equal(packages, [normalizePath(project.cwd)]); }); }); diff --git a/src/test/packages/README.md b/src/test/packages/README.md deleted file mode 100644 index 4441385e0..000000000 --- a/src/test/packages/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Example repos for "packages" mode - -This folder contains examples for the testing of the "packages" mode. -Note: If you change any of the source files, you must manually rebuild the packages before running tests. diff --git a/src/test/packages/multi-package/package.json b/src/test/packages/multi-package/package.json deleted file mode 100644 index ec732dce0..000000000 --- a/src/test/packages/multi-package/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "typedoc-multi-package-example", - "version": "1.0.0", - "description": "An example of using typedoc with multiple packages", - "private": true, - "main": "dist/index.js", - "workspaces": [ - "packages/*" - ] -} diff --git a/src/test/packages/multi-package/packages/bar/index.d.ts b/src/test/packages/multi-package/packages/bar/index.d.ts deleted file mode 100644 index d8850a0b6..000000000 --- a/src/test/packages/multi-package/packages/bar/index.d.ts +++ /dev/null @@ -1 +0,0 @@ -export function bar(): void; diff --git a/src/test/packages/multi-package/packages/bar/package.json b/src/test/packages/multi-package/packages/bar/package.json deleted file mode 100644 index 36cd1509e..000000000 --- a/src/test/packages/multi-package/packages/bar/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "typedoc-multi-package-bar", - "version": "1.0.0", - "types": "index.d.ts" -} diff --git a/src/test/packages/multi-package/packages/bar/tsconfig.json b/src/test/packages/multi-package/packages/bar/tsconfig.json deleted file mode 100644 index 2cb17e7b0..000000000 --- a/src/test/packages/multi-package/packages/bar/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist" - } -} diff --git a/src/test/packages/multi-package/packages/baz/index.ts b/src/test/packages/multi-package/packages/baz/index.ts deleted file mode 100644 index bb93e5892..000000000 --- a/src/test/packages/multi-package/packages/baz/index.ts +++ /dev/null @@ -1 +0,0 @@ -export function baz() {} diff --git a/src/test/packages/multi-package/packages/baz/package.json b/src/test/packages/multi-package/packages/baz/package.json deleted file mode 100644 index 10518cb7f..000000000 --- a/src/test/packages/multi-package/packages/baz/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "typedoc-multi-package-baz", - "version": "1.0.0", - "main": "index.ts" -} diff --git a/src/test/packages/multi-package/packages/baz/tsconfig.json b/src/test/packages/multi-package/packages/baz/tsconfig.json deleted file mode 100644 index 614afc5c7..000000000 --- a/src/test/packages/multi-package/packages/baz/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "sourceMap": false, - "inlineSourceMap": true - } -} diff --git a/src/test/packages/multi-package/packages/foo/dist/index.js b/src/test/packages/multi-package/packages/foo/dist/index.js deleted file mode 100644 index 74eb37c38..000000000 --- a/src/test/packages/multi-package/packages/foo/dist/index.js +++ /dev/null @@ -1,2 +0,0 @@ -// This file simulates a file that was produced from another non-tsc build tool. -// It therefore cannot be directly mapped back to the original TS source. diff --git a/src/test/packages/multi-package/packages/foo/index.ts b/src/test/packages/multi-package/packages/foo/index.ts deleted file mode 100644 index f99d42777..000000000 --- a/src/test/packages/multi-package/packages/foo/index.ts +++ /dev/null @@ -1 +0,0 @@ -export function foo() {} diff --git a/src/test/packages/multi-package/packages/foo/package.json b/src/test/packages/multi-package/packages/foo/package.json deleted file mode 100644 index 2d5ca817d..000000000 --- a/src/test/packages/multi-package/packages/foo/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "typedoc-multi-package-foo", - "version": "1.0.0", - "main": "dist/index", - "typedocMain": "index.ts" -} diff --git a/src/test/packages/multi-package/packages/foo/tsconfig.json b/src/test/packages/multi-package/packages/foo/tsconfig.json deleted file mode 100644 index 614afc5c7..000000000 --- a/src/test/packages/multi-package/packages/foo/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "sourceMap": false, - "inlineSourceMap": true - } -} diff --git a/src/test/packages/multi-package/tsconfig.json b/src/test/packages/multi-package/tsconfig.json deleted file mode 100644 index b497380d5..000000000 --- a/src/test/packages/multi-package/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "compilerOptions": { - "strict": true, - "sourceMap": true - }, - "exclude": ["node_modules", "dist"] -} diff --git a/src/test/packages/single-package/dist/index.js b/src/test/packages/single-package/dist/index.js deleted file mode 100644 index 921912f48..000000000 --- a/src/test/packages/single-package/dist/index.js +++ /dev/null @@ -1,8 +0,0 @@ -"use strict"; -exports.__esModule = true; -exports.helloWorld = void 0; -function helloWorld() { - return "Hello World!"; -} -exports.helloWorld = helloWorld; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/src/test/packages/single-package/dist/index.js.map b/src/test/packages/single-package/dist/index.js.map deleted file mode 100644 index 88be091eb..000000000 --- a/src/test/packages/single-package/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,SAAgB,UAAU;IACtB,OAAO,cAAc,CAAC;AAC1B,CAAC;AAFD,gCAEC"} \ No newline at end of file diff --git a/src/test/packages/single-package/package.json b/src/test/packages/single-package/package.json deleted file mode 100644 index 8ae9b5b51..000000000 --- a/src/test/packages/single-package/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "typedoc-single-package", - "version": "1.0.0", - "description": "An example of using typedoc with a single package", - "private": true, - "main": "dist/index.js" -} diff --git a/src/test/packages/single-package/src/index.ts b/src/test/packages/single-package/src/index.ts deleted file mode 100644 index 40578e1c2..000000000 --- a/src/test/packages/single-package/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function helloWorld() { - return "Hello World!"; -} diff --git a/src/test/packages/single-package/tsconfig.json b/src/test/packages/single-package/tsconfig.json deleted file mode 100644 index 5d24a80d0..000000000 --- a/src/test/packages/single-package/tsconfig.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "compilerOptions": { - "outDir": "dist", - "sourceMap": true, - "strict": true - }, - "include": ["src"] -} diff --git a/src/test/programs.ts b/src/test/programs.ts index 739e7dc0a..639e5da07 100644 --- a/src/test/programs.ts +++ b/src/test/programs.ts @@ -9,7 +9,7 @@ let converter2App: Application | undefined; let converter2Program: ts.Program | undefined; export function getConverterBase() { - return join(__dirname, "converter"); + return join(process.cwd(), "src/test/converter"); } export function getConverterApp() { @@ -20,11 +20,12 @@ export function getConverterApp() { logger: "none", name: "typedoc", excludeExternals: true, - disableSources: true, + disableSources: false, tsconfig: join(getConverterBase(), "tsconfig.json"), externalPattern: ["**/node_modules/**"], plugin: [], entryPointStrategy: EntryPointStrategy.Expand, + gitRevision: "fake", }); } @@ -46,7 +47,7 @@ export function getConverterProgram() { } export function getConverter2Base() { - return join(__dirname, "converter2"); + return join(process.cwd(), "src/test/converter2"); } export function getConverter2App() { diff --git a/src/test/renderer/testProject/src/functions.ts b/src/test/renderer/testProject/src/functions.ts index aa0222e49..e5e105aa8 100644 --- a/src/test/renderer/testProject/src/functions.ts +++ b/src/test/renderer/testProject/src/functions.ts @@ -19,10 +19,10 @@ export function exportedFunction(): void {} * @param paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * var value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * */ export let variableFunction = function ( @@ -42,10 +42,10 @@ export let variableFunction = function ( * @param paramA * This is a **parameter** pointing to an interface. * - * ~~~ + * ``` * var value:BaseClass = new BaseClass('test'); * functionWithArguments('arg', 0, value); - * ~~~ + * ``` * */ export function functionWithArguments( diff --git a/src/test/renderer/testProject/src/generics.ts b/src/test/renderer/testProject/src/generics.ts index fa1442745..26b40d5e5 100644 --- a/src/test/renderer/testProject/src/generics.ts +++ b/src/test/renderer/testProject/src/generics.ts @@ -1,7 +1,7 @@ /** * A generic function * - * @typeparam T The generic type parameter. + * @typeParam T The generic type parameter. * @param value A generic parameter. * @returns A generic return value. */ @@ -49,7 +49,7 @@ export interface B { * A generic interface extending two other generic interfaces * and setting one of the type parameters. * - * @typeparam T The leftover generic type parameter. + * @typeParam T The leftover generic type parameter. */ export interface AB extends A, B {} diff --git a/src/test/renderer/testProject/src/modules.ts b/src/test/renderer/testProject/src/modules.ts index 5022cd8f5..f38d51a09 100644 --- a/src/test/renderer/testProject/src/modules.ts +++ b/src/test/renderer/testProject/src/modules.ts @@ -1,11 +1,3 @@ -/** - * This comment has a code block that is only marked by indentation. - * - * @thisIsADecorator - * class Foo {} - * @module - */ - /** * This is a module. */ diff --git a/src/test/renderer/testProject/src/single-export.ts b/src/test/renderer/testProject/src/single-export.ts index 61551327b..dd43c9e01 100644 --- a/src/test/renderer/testProject/src/single-export.ts +++ b/src/test/renderer/testProject/src/single-export.ts @@ -23,9 +23,9 @@ class NotExportedClass { /** * This class is exported by being assigned to ´export´. * - * ~~~ + * ``` * export = SingleExportedClass; - * ~~~ + * ``` */ class SingleExportedClass { /** diff --git a/src/test/slow/entry-point.test.ts b/src/test/slow/entry-point.test.ts index a7ed33528..5c1256dcf 100644 --- a/src/test/slow/entry-point.test.ts +++ b/src/test/slow/entry-point.test.ts @@ -1,18 +1,51 @@ +import { tempdirProject } from "@typestrong/fs-fixture-builder"; import { deepStrictEqual as equal, ok } from "assert"; import { join } from "path"; import { Application, EntryPointStrategy, TSConfigReader } from "../.."; -const root = join(__dirname, "entry-points"); +const fixture = tempdirProject(); +fixture.addJsonFile("tsconfig.json", { + include: ["."], +}); +fixture.addJsonFile("package.json", { + main: "index.ts", +}); +fixture.addFile("index.ts", "export function fromIndex() {}"); +fixture.addFile("extra.ts", "export function extra() {}"); describe("Entry Points", () => { + beforeEach(() => { + fixture.write(); + }); + + afterEach(() => { + fixture.rm(); + }); + const app = new Application(); - const tsconfig = join(root, "tsconfig.json"); + const tsconfig = join(fixture.cwd, "tsconfig.json"); app.options.addReader(new TSConfigReader()); it("Supports expanding existing paths", () => { app.bootstrap({ tsconfig, - entryPoints: [root], + entryPoints: [fixture.cwd], + entryPointStrategy: EntryPointStrategy.Expand, + }); + + const entryPoints = app.getEntryPoints(); + ok(entryPoints); + equal( + entryPoints.length, + 2, + "There are two files, so both should be expanded" + ); + }); + + it("Supports expanding globs in paths", () => { + app.bootstrap({ + tsconfig, + entryPoints: [`${fixture.cwd}/*.ts`], entryPointStrategy: EntryPointStrategy.Expand, }); @@ -28,7 +61,7 @@ describe("Entry Points", () => { it("Supports resolving directories", () => { app.bootstrap({ tsconfig, - entryPoints: [root], + entryPoints: [fixture.cwd], entryPointStrategy: EntryPointStrategy.Resolve, }); @@ -42,15 +75,14 @@ describe("Entry Points", () => { }); it("Supports resolving packages", () => { - const root = join(__dirname, "../packages/multi-package"); app.bootstrap({ - tsconfig: root, - entryPoints: [root], + tsconfig: tsconfig, + entryPoints: [fixture.cwd], entryPointStrategy: EntryPointStrategy.Packages, }); const entryPoints = app.getEntryPoints(); ok(entryPoints); - equal(entryPoints.length, 3); + equal(entryPoints.length, 1); }); }); diff --git a/src/test/slow/entry-points/extra.ts b/src/test/slow/entry-points/extra.ts deleted file mode 100644 index 3a30be6ae..000000000 --- a/src/test/slow/entry-points/extra.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function extra() { - // -} diff --git a/src/test/slow/entry-points/index.ts b/src/test/slow/entry-points/index.ts deleted file mode 100644 index d1f6b0a22..000000000 --- a/src/test/slow/entry-points/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function fromIndex() { - // -} diff --git a/src/test/slow/entry-points/tsconfig.json b/src/test/slow/entry-points/tsconfig.json deleted file mode 100644 index 82194fc7a..000000000 --- a/src/test/slow/entry-points/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "include": ["."] -} diff --git a/src/test/slow/visual.test.ts b/src/test/slow/visual.test.ts index 98dfe2ed0..8b8fd998f 100644 --- a/src/test/slow/visual.test.ts +++ b/src/test/slow/visual.test.ts @@ -1,4 +1,4 @@ -import { deepStrictEqual as equal } from "assert"; +import { deepStrictEqual as equal, ok } from "assert"; import { RegSuitCore } from "reg-suit-core"; import { captureRegressionScreenshots } from "../capture-screenshots"; @@ -19,12 +19,15 @@ describe("Visual Test", () => { await processor.getExpectedKey() ); + ok( + result.comparisonResult.passedItems.length > 1, + "No baselines compared. captureRegressionScreenshots is probably broken." + ); equal( result.comparisonResult.newItems, [], "Cannot run visual test without previously created baseline" ); - equal(result.comparisonResult.deletedItems, []); equal(result.comparisonResult.failedItems, []); }); diff --git a/src/test/utils/options/default-options.test.ts b/src/test/utils/options/default-options.test.ts index 750aac1c2..63badd718 100644 --- a/src/test/utils/options/default-options.test.ts +++ b/src/test/utils/options/default-options.test.ts @@ -85,7 +85,7 @@ describe("Default Options", () => { it("Should disallow non-numbers", () => { throws(() => opts.setValue("searchCategoryBoosts", { - cat: true, + cat: true as any as number, }) ); }); @@ -96,12 +96,12 @@ describe("Default Options", () => { throws(() => opts.setValue("searchGroupBoosts", null as never)); }); - it("Should disallow invalid kind names", () => { - throws(() => opts.setValue("searchGroupBoosts", { Enum2: 123 })); - }); - it("Should disallow non-numbers", () => { - throws(() => opts.setValue("searchGroupBoosts", { Enum: true })); + throws(() => + opts.setValue("searchGroupBoosts", { + Enum: true as any as number, + }) + ); }); it("Should allow groups", () => { diff --git a/src/test/utils/options/help.test.ts b/src/test/utils/options/help.test.ts index 544e22958..50fe4a7ac 100644 --- a/src/test/utils/options/help.test.ts +++ b/src/test/utils/options/help.test.ts @@ -10,7 +10,7 @@ import { getOptionsHelp } from "../../../lib/utils/options/help"; describe("Options - help", () => { const options = new Options(new Logger()); - options.addDeclarations([ + for (const decl of [ { name: "td-option", help: "help", type: ParameterType.String }, { name: "td-option2", help: "help" }, { name: "not displayed", help: "" }, @@ -19,7 +19,9 @@ describe("Options - help", () => { help: "help", hint: ParameterHint.File, }, - ]); + ]) { + options.addDeclaration(decl as never); + } it("Describes TypeDoc options", () => { const help = getOptionsHelp(options); diff --git a/src/test/utils/options/options.test.ts b/src/test/utils/options/options.test.ts index 91109fdce..2f62b45d7 100644 --- a/src/test/utils/options/options.test.ts +++ b/src/test/utils/options/options.test.ts @@ -12,17 +12,21 @@ import type { describe("Options", () => { const logger = new Logger(); - const options = new Options(logger) as Options & { + let options: Options & { addDeclaration(declaration: Readonly): void; getValue(name: string): unknown; }; - options.addDefaultDeclarations(); - options.addDeclaration({ - name: "mapped", - type: ParameterType.Map, - map: { a: 1 }, - defaultValue: 2, - help: "", + + beforeEach(() => { + options = new Options(logger); + options.addDefaultDeclarations(); + options.addDeclaration({ + name: "mapped", + type: ParameterType.Map, + map: { a: 1 }, + defaultValue: 2, + help: "", + }); }); it("Errors on duplicate declarations", () => { @@ -43,7 +47,6 @@ describe("Options", () => { defaultValue: 1, }; options.addDeclaration(declaration); - options.removeDeclarationByName(declaration.name); }); it("Does not throw if default value is out of range for number declaration", () => { @@ -56,7 +59,6 @@ describe("Options", () => { defaultValue: 0, }; options.addDeclaration(declaration); - options.removeDeclarationByName(declaration.name); }); it("Does not throw if a map declaration has a default value that is not part of the map of possible values", () => { @@ -71,18 +73,6 @@ describe("Options", () => { defaultValue: 0, }; options.addDeclaration(declaration); - options.removeDeclarationByName(declaration.name); - }); - - it("Supports removing a declaration by name", () => { - options.addDeclaration({ name: "not-an-option", help: "" }); - options.removeDeclarationByName("not-an-option"); - equal(options.getDeclaration("not-an-option"), undefined); - }); - - it("Ignores removal of non-existent declarations", () => { - options.removeDeclarationByName("not-an-option"); - equal(options.getDeclaration("not-an-option"), undefined); }); it("Throws on attempt to get an undeclared option", () => { @@ -172,7 +162,7 @@ describe("Options", () => { options.addDefaultDeclarations(); options.freeze(); - throws(() => options.setValue("emit", true)); + throws(() => options.setValue("categorizeByGroup", true)); throws(() => options.setCompilerOptions([], {}, [])); }); @@ -181,11 +171,12 @@ describe("Options", () => { options.addDefaultDeclarations(); options.setValue("entryPoints", ["x"]); - options.setValue("excludeTags", ["x"]); + const oldExcludeTags = options.getValue("excludeTags"); + options.setValue("excludeTags", ["@x"]); options.reset(); equal(options.getValue("entryPoints"), []); - equal(options.getValue("excludeTags"), []); + equal(options.getValue("excludeTags"), oldExcludeTags); }); it("Supports resetting a single value", () => { @@ -193,11 +184,12 @@ describe("Options", () => { options.addDefaultDeclarations(); options.setValue("name", "test"); - options.setValue("excludeTags", ["x"]); + const originalExclude = options.getValue("excludeTags"); + options.setValue("excludeTags", ["@x"]); options.reset("excludeTags"); equal(options.getValue("name"), "test"); - equal(options.getValue("excludeTags"), []); + equal(options.getValue("excludeTags"), originalExclude); }); it("Throws if resetting a single value which does not exist", () => { diff --git a/src/test/utils/options/readers/arguments.test.ts b/src/test/utils/options/readers/arguments.test.ts index c4d1768a8..4d91c7e69 100644 --- a/src/test/utils/options/readers/arguments.test.ts +++ b/src/test/utils/options/readers/arguments.test.ts @@ -14,7 +14,7 @@ describe("Options - ArgumentsReader", () => { // Note: We lie about the type of Options here since we want the less strict // behavior for tests. If TypeDoc ever gets a numeric option, then we can // exclusively use the builtin options for tests and this cast can go away. - const options = new Options(logger) as Options & { + let options: Options & { addDeclaration( declaration: Readonly & { name: "numOption"; @@ -28,18 +28,22 @@ describe("Options - ArgumentsReader", () => { getValue(name: "numOption"): number; getValue(name: "mapped"): number; }; - options.addDefaultDeclarations(); - options.addDeclaration({ - name: "numOption", - help: "", - type: ParameterType.Number, - }); - options.addDeclaration({ - name: "mapped", - type: ParameterType.Map, - help: "", - map: { a: 1, b: 2 }, - defaultValue: 3, + + beforeEach(() => { + options = new Options(logger); + options.addDefaultDeclarations(); + options.addDeclaration({ + name: "numOption", + help: "", + type: ParameterType.Number, + }); + options.addDeclaration({ + name: "mapped", + type: ParameterType.Map, + help: "", + map: { a: 1, b: 2 }, + defaultValue: 3, + }); }); function test(name: string, args: string[], cb: () => void) { @@ -51,7 +55,6 @@ describe("Options - ArgumentsReader", () => { options.addReader(reader); options.read(logger); cb(); - options.removeReaderByName(reader.name); }); } @@ -135,7 +138,6 @@ describe("Options - ArgumentsReader", () => { options.reset(); options.addReader(reader); options.read(new TestLogger()); - options.removeReaderByName(reader.name); equal(check, true, "Reader did not report an error."); }); @@ -152,7 +154,6 @@ describe("Options - ArgumentsReader", () => { options.reset(); options.addReader(reader); options.read(new TestLogger()); - options.removeReaderByName(reader.name); equal(check, true, "Reader did not report an error."); }); diff --git a/src/test/utils/options/readers/data/circular-extends.json b/src/test/utils/options/readers/data/circular-extends.json deleted file mode 100644 index c58ddc2d2..000000000 --- a/src/test/utils/options/readers/data/circular-extends.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": ["./circular-extends.json"] -} diff --git a/src/test/utils/options/readers/data/extends.json b/src/test/utils/options/readers/data/extends.json deleted file mode 100644 index a16a66171..000000000 --- a/src/test/utils/options/readers/data/extends.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "extends": "./valid.json", - "name": "extends" -} diff --git a/src/test/utils/options/readers/data/file.ts b/src/test/utils/options/readers/data/file.ts deleted file mode 100644 index a5e460907..000000000 --- a/src/test/utils/options/readers/data/file.ts +++ /dev/null @@ -1,2 +0,0 @@ -// This is referenced in valid.tsconfig.json -export const test = true; diff --git a/src/test/utils/options/readers/data/folder.json/tsconfig.json b/src/test/utils/options/readers/data/folder.json/tsconfig.json deleted file mode 100644 index 8dc142972..000000000 --- a/src/test/utils/options/readers/data/folder.json/tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "compilerOptions": { - "strict": true - } -} diff --git a/src/test/utils/options/readers/data/invalid.json b/src/test/utils/options/readers/data/invalid.json deleted file mode 100644 index 38de27a34..000000000 --- a/src/test/utils/options/readers/data/invalid.json +++ /dev/null @@ -1 +0,0 @@ -"Will cause an error" diff --git a/src/test/utils/options/readers/data/invalid.tsconfig.json b/src/test/utils/options/readers/data/invalid.tsconfig.json deleted file mode 100644 index 1a6110da5..000000000 --- a/src/test/utils/options/readers/data/invalid.tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "typedocOptions": "Will cause an error" -} diff --git a/src/test/utils/options/readers/data/options-file.tsconfig.json b/src/test/utils/options/readers/data/options-file.tsconfig.json deleted file mode 100644 index 9052c2b7c..000000000 --- a/src/test/utils/options/readers/data/options-file.tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "typedocOptions": { - "options": "any" - } -} diff --git a/src/test/utils/options/readers/data/stripInternal.tsconfig.json b/src/test/utils/options/readers/data/stripInternal.tsconfig.json deleted file mode 100644 index 9572a35d3..000000000 --- a/src/test/utils/options/readers/data/stripInternal.tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/tsconfig", - "compilerOptions": { - "stripInternal": true - } -} diff --git a/src/test/utils/options/readers/data/unknown.json b/src/test/utils/options/readers/data/unknown.json deleted file mode 100644 index f00158317..000000000 --- a/src/test/utils/options/readers/data/unknown.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "someOptionThatDoesNotExist": true -} diff --git a/src/test/utils/options/readers/data/unknown.tsconfig.json b/src/test/utils/options/readers/data/unknown.tsconfig.json deleted file mode 100644 index 408b38f53..000000000 --- a/src/test/utils/options/readers/data/unknown.tsconfig.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "typedocOptions": { - "someOptionThatDoesNotExist": true - } -} diff --git a/src/test/utils/options/readers/data/valid.json b/src/test/utils/options/readers/data/valid.json deleted file mode 100644 index 33431cb09..000000000 --- a/src/test/utils/options/readers/data/valid.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://typedoc.org/schema.json", - "gitRevision": "master" -} diff --git a/src/test/utils/options/readers/data/valid.tsconfig.json b/src/test/utils/options/readers/data/valid.tsconfig.json deleted file mode 100644 index 854836627..000000000 --- a/src/test/utils/options/readers/data/valid.tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "$schema": "http://json.schemastore.org/tsconfig", - "compilerOptions": { - "target": "ESNext" - }, - "files": [ - // This has to specify a file that exists or TS will drop it. - "./file.ts" - ], - "typedocOptions": { - "help": true - } -} diff --git a/src/test/utils/options/readers/tsconfig.test.ts b/src/test/utils/options/readers/tsconfig.test.ts index f4319edd7..b77a0ea0c 100644 --- a/src/test/utils/options/readers/tsconfig.test.ts +++ b/src/test/utils/options/readers/tsconfig.test.ts @@ -1,99 +1,289 @@ -import { join, resolve } from "path"; +import { basename, join } from "path"; import { deepStrictEqual as equal } from "assert"; import { TSConfigReader } from "../../../../lib/utils/options/readers"; import { Logger, Options } from "../../../../lib/utils"; +import { TestLogger } from "../../../TestLogger"; +import { tempdirProject, Project } from "@typestrong/fs-fixture-builder"; import { tmpdir } from "os"; describe("Options - TSConfigReader", () => { const options = new Options(new Logger()); options.addDefaultDeclarations(); options.addReader(new TSConfigReader()); + const logger = new TestLogger(); - function testError(name: string, file: string) { - it(name, () => { + function readWithProject(project: Project, reset = true) { + if (reset) { options.reset(); - options.setValue("tsconfig", file); - const logger = new Logger(); - options.read(logger); + } + logger.reset(); + options.setValue("tsconfig", project.cwd); + project.write(); + options.read(logger); + project.rm(); + } + + it("Errors if the file cannot be found", () => { + options.reset(); + logger.reset(); + + options.setValue( + "tsconfig", + join(tmpdir(), "typedoc/does-not-exist.json") + ); + options.read(logger); + logger.expectMessage("error: *"); + }); + + function testError(name: string, file: object) { + it(name, () => { + const project = tempdirProject(); + project.addJsonFile("tsconfig.json", file); + readWithProject(project); equal(logger.hasErrors(), true, "No error was logged"); }); } - testError( - "Errors if the file cannot be found", - join(tmpdir(), "typedoc/non-existent-file.json") - ); - testError( - "Errors if the data is invalid", - join(__dirname, "data/invalid.tsconfig.json") - ); - testError( - "Errors if any set option errors", - join(__dirname, "data/unknown.tsconfig.json") - ); - testError( - "Errors if tsconfig tries to set options file", - join(__dirname, "data/options-file.tsconfig.json") - ); + testError("Errors if the data is invalid", { + typedocOptions: "Will cause an error", + }); + + testError("Errors if any set option errors", { + typedocOptions: { + someOptionThatDoesNotExist: true, + }, + }); + + testError("Errors if tsconfig tries to set options file", { + typedocOptions: { + options: "any", + }, + }); + + testError("Errors if tsconfig tries to set tsconfig file", { + typedocOptions: { + tsconfig: "any", + }, + }); + + it("Errors if a tsconfig file cannot be parsed", () => { + const project = tempdirProject(); + project.addFile("tsconfig.json", '{"test}'); + readWithProject(project); + logger.expectMessage("error: *"); + }); it("Does not error if the option file cannot be found but was not set.", () => { + const logger = new Logger(); + const options = new (class LyingOptions extends Options { override isSet() { return false; } - })(new Logger()); + })(logger); options.addDefaultDeclarations(); options.setValue( "tsconfig", join(__dirname, "data/does_not_exist.json") ); - const logger = new Logger(); options.addReader(new TSConfigReader()); options.read(logger); equal(logger.hasErrors(), false); }); + function readTsconfig(tsconfig: object) { + const project = tempdirProject(); + project.addFile("file.ts", "export const abc = 123"); + project.addJsonFile("tsconfig.json", tsconfig); + + readWithProject(project); + logger.expectNoOtherMessages(); + } + it("Sets files for the program", () => { - options.reset(); - options.setValue( - "tsconfig", - join(__dirname, "data/valid.tsconfig.json") - ); - options.read(new Logger()); + readTsconfig({ + files: ["./file.ts"], + }); equal( - options.getFileNames().map((f) => resolve(f)), - [resolve(__dirname, "./data/file.ts")] + options.getFileNames().map((f) => basename(f)), + ["file.ts"] ); }); it("Allows stripInternal to set excludeInternal", () => { - options.reset(); - options.setValue( - "tsconfig", - join(__dirname, "data/stripInternal.tsconfig.json") - ); - options.read(new Logger()); + readTsconfig({ + compilerOptions: { + stripInternal: true, + }, + }); equal(options.getValue("excludeInternal"), true); }); it("Does not set excludeInternal by stripInternal if already set", () => { + const project = tempdirProject(); + project.addJsonFile("tsconfig.json", { + compilerOptions: { stripInternal: true }, + }); + options.reset(); - options.setValue( - "tsconfig", - join(__dirname, "data/stripInternal.tsconfig.json") - ); options.setValue("excludeInternal", false); - options.read(new Logger()); + readWithProject(project, false); equal(options.getValue("excludeInternal"), false); }); it("Correctly handles folder names ending with .json (#1712)", () => { - options.reset(); - options.setValue("tsconfig", join(__dirname, "data/folder.json")); - options.setCompilerOptions([], { strict: false }, void 0); - options.read(new Logger()); + const project = tempdirProject(); + project.addJsonFile("tsconfig.json", { + compilerOptions: { strict: true }, + }); + readWithProject(project); equal(options.getCompilerOptions().strict, true); }); + + function testTsdoc(tsdoc: object, cb?: () => void, reset = true) { + const project = tempdirProject(); + project.addFile("file.ts", "export const abc = 123"); + project.addJsonFile("tsconfig.json", {}); + project.addJsonFile("tsdoc.json", tsdoc); + + readWithProject(project, reset); + cb?.(); + logger.expectNoOtherMessages(); + } + + it("Handles failed tsdoc reads", () => { + testTsdoc([], () => { + logger.expectMessage( + "error: Failed to read tsdoc.json file at */tsdoc.json." + ); + }); + }); + + it("Handles invalid tsdoc files", () => { + testTsdoc( + { + doesNotMatchSchema: true, + }, + () => { + logger.expectMessage( + `error: The file */tsdoc.json is not a valid tsdoc.json file.` + ); + } + ); + }); + + it("Warns if an option will be overwritten", () => { + options.reset(); + options.setValue("blockTags", []); + options.setValue("modifierTags", []); + testTsdoc( + {}, + () => { + logger.expectMessage( + "warn: The blockTags, modifierTags defined in typedoc.json " + + "will be overwritten by configuration in tsdoc.json." + ); + }, + false + ); + }); + + it("Reads tsdoc.json", () => { + testTsdoc({ + noStandardTags: true, + tagDefinitions: [ + { + tagName: "@tag", + syntaxKind: "block", + }, + { + tagName: "@tag2", + syntaxKind: "inline", + }, + { + tagName: "@tag3", + syntaxKind: "modifier", + }, + ], + }); + + equal(options.getValue("blockTags"), ["@tag"]); + equal(options.getValue("inlineTags"), ["@tag2"]); + equal(options.getValue("modifierTags"), ["@tag3"]); + }); + + it("Handles extends in tsdoc.json", () => { + const project = tempdirProject(); + project.addFile("file.ts", "export const abc = 123"); + project.addJsonFile("tsconfig.json", {}); + project.addJsonFile("tsdoc.json", { extends: ["./tsdoc2.json"] }); + project.addJsonFile("tsdoc2.json", { + noStandardTags: true, + tagDefinitions: [ + { + tagName: "@tag", + syntaxKind: "block", + }, + ], + }); + + readWithProject(project); + equal(options.getValue("blockTags"), ["@tag"]); + logger.expectNoOtherMessages(); + }); + + it("Handles supportForTags in tsdoc.json", () => { + testTsdoc({ + noStandardTags: true, + tagDefinitions: [ + { + tagName: "@tag", + syntaxKind: "block", + }, + { + tagName: "@tag2", + syntaxKind: "inline", + }, + { + tagName: "@tag3", + syntaxKind: "modifier", + }, + ], + supportForTags: { + "@tag": true, + }, + }); + + equal(options.getValue("blockTags"), ["@tag"]); + equal(options.getValue("inlineTags"), []); + equal(options.getValue("modifierTags"), []); + }); + + it("Handles circular extends", () => { + testTsdoc( + { + extends: ["./tsdoc.json"], + }, + () => { + logger.expectMessage( + 'error: Circular reference encountered for "extends" field of */tsdoc.json' + ); + } + ); + }); + + it("Handles extends which reference invalid files", () => { + testTsdoc( + { + extends: ["typedoc/nope"], + }, + () => { + logger.expectMessage( + "error: Failed to resolve typedoc/nope to a file in */tsdoc.json" + ); + } + ); + }); }); diff --git a/src/test/utils/options/readers/typedoc.test.ts b/src/test/utils/options/readers/typedoc.test.ts index cb7f8f58e..7f3937ca4 100644 --- a/src/test/utils/options/readers/typedoc.test.ts +++ b/src/test/utils/options/readers/typedoc.test.ts @@ -1,53 +1,139 @@ -import { join } from "path"; import { deepStrictEqual as equal } from "assert"; +import { project as fsProject } from "@typestrong/fs-fixture-builder"; import { TypeDocReader } from "../../../../lib/utils/options/readers"; -import { Logger, Options, ConsoleLogger } from "../../../../lib/utils"; +import { Logger, Options } from "../../../../lib/utils"; +import { TestLogger } from "../../../TestLogger"; describe("Options - TypeDocReader", () => { const options = new Options(new Logger()); options.addDefaultDeclarations(); options.addReader(new TypeDocReader()); - function test(name: string, input: string, cb: () => void) { - it(name, () => { - options.reset(); - options.setValue("options", input); - options.read(new ConsoleLogger()); - cb(); + it("Supports comments in json", () => { + const project = fsProject("jsonc"); + project.addFile("typedoc.json", '//comment\n{"name": "comment"}'); + const logger = new TestLogger(); + + project.write(); + options.reset(); + options.setValue("options", project.cwd); + options.read(logger); + project.rm(); + + logger.expectNoOtherMessages(); + equal(options.getValue("name"), "comment"); + }); + + it("Supports extends", () => { + const project = fsProject("extends"); + project.addJsonFile("typedoc.json", { + extends: "./other.json", + name: "extends", }); - } + project.addJsonFile("other.json", { + gitRevision: "master", + }); + const logger = new TestLogger(); + + project.write(); + options.reset(); + options.setValue("options", project.cwd); + options.read(logger); + project.rm(); - test("Supports extends", join(__dirname, "data/extends.json"), () => { + logger.expectNoOtherMessages(); equal(options.getValue("name"), "extends"); equal(options.getValue("gitRevision"), "master"); }); - function testError(name: string, file: string) { + it("Supports js files", () => { + const project = fsProject("js"); + project.addFile("typedoc.js", "module.exports = { name: 'js' }"); + const logger = new TestLogger(); + + project.write(); + options.reset(); + options.setValue("options", project.cwd); + options.read(logger); + project.rm(); + + logger.expectNoOtherMessages(); + equal(options.getValue("name"), "js"); + }); + + it("Errors if the file cannot be found", () => { + options.reset(); + options.setValue("options", "./non-existent-file.json"); + const logger = new TestLogger(); + options.read(logger); + logger.expectMessage( + "error: The options file */non-existent-file.json does not exist." + ); + logger.expectNoOtherMessages(); + }); + + function testError( + name: string, + file: unknown, + message: string, + json = true + ) { it(name, () => { + const optionsFile = json ? "typedoc.json" : "typedoc.js"; + const project = fsProject(name.replace(/ /g, "_")); + if (typeof file === "string") { + project.addFile(optionsFile, file); + } else { + project.addJsonFile(optionsFile, file); + } + options.reset(); - options.setValue("options", file); - const logger = new Logger(); + options.setValue("options", project.cwd); + const logger = new TestLogger(); + project.write(); options.read(logger); - equal(logger.hasErrors(), true, "No error was logged"); + project.rm(); + logger.expectMessage(message); }); } testError( - "Errors if the file cannot be found", - join(__dirname, "data/non-existent-file.json") + "Errors if the data is invalid", + "Not valid json {}", + "error: Failed to parse */typedoc.json, ensure it exists and contains an object." ); testError( - "Errors if the data is invalid", - join(__dirname, "data/invalid.json") + "Errors if the data is not an object in a json file", + 123, + "error: Failed to parse */typedoc.json, ensure it exists and contains an object." + ); + testError( + "Errors if the data is not an object in a js file", + "module.exports = 123", + "error: The root value of */typedoc.js is not an object.", + false ); testError( "Errors if any set option errors", - join(__dirname, "data/unknown.json") + { + someOptionThatDoesNotExist: true, + }, + "error: Tried to set an option (someOptionThatDoesNotExist) that was not declared." ); testError( "Errors if extends results in a loop", - join(__dirname, "data/circular-extends.json") + { + extends: "./typedoc.json", + }, + "error: Tried to load the options file */typedoc.json multiple times." + ); + testError( + "Errors if the extended path cannot be found", + { + extends: "typedoc/nope", + }, + "error: Failed to resolve typedoc/nope to a file in */typedoc.json" ); it("Does not error if the option file cannot be found but was not set.", () => { diff --git a/src/test/utils/sort.test.ts b/src/test/utils/sort.test.ts index 3c89e78fd..d962f6a26 100644 --- a/src/test/utils/sort.test.ts +++ b/src/test/utils/sort.test.ts @@ -164,33 +164,32 @@ describe("Sort", () => { it("Should sort by kind", () => { const arr = [ new DeclarationReflection("1", ReflectionKind.Reference), - new DeclarationReflection("25", ReflectionKind.SetSignature), + new DeclarationReflection("24", ReflectionKind.SetSignature), new DeclarationReflection("3", ReflectionKind.Module), new DeclarationReflection("4", ReflectionKind.Namespace), new DeclarationReflection("5", ReflectionKind.Enum), new DeclarationReflection("6", ReflectionKind.EnumMember), - new DeclarationReflection("16", ReflectionKind.Method), + new DeclarationReflection("15", ReflectionKind.Method), new DeclarationReflection("8", ReflectionKind.Interface), new DeclarationReflection("9", ReflectionKind.TypeAlias), new DeclarationReflection("10", ReflectionKind.Constructor), - new DeclarationReflection("11", ReflectionKind.Event), new DeclarationReflection("2", ReflectionKind.Project), - new DeclarationReflection("24", ReflectionKind.GetSignature), - new DeclarationReflection("13", ReflectionKind.Variable), - new DeclarationReflection("14", ReflectionKind.Function), - new DeclarationReflection("15", ReflectionKind.Accessor), - new DeclarationReflection("12", ReflectionKind.Property), - new DeclarationReflection("20", ReflectionKind.TypeLiteral), - new DeclarationReflection("17", ReflectionKind.ObjectLiteral), - new DeclarationReflection("18", ReflectionKind.Parameter), - new DeclarationReflection("19", ReflectionKind.TypeParameter), - new DeclarationReflection("21", ReflectionKind.CallSignature), + new DeclarationReflection("23", ReflectionKind.GetSignature), + new DeclarationReflection("12", ReflectionKind.Variable), + new DeclarationReflection("13", ReflectionKind.Function), + new DeclarationReflection("14", ReflectionKind.Accessor), + new DeclarationReflection("11", ReflectionKind.Property), + new DeclarationReflection("19", ReflectionKind.TypeLiteral), + new DeclarationReflection("16", ReflectionKind.ObjectLiteral), + new DeclarationReflection("17", ReflectionKind.Parameter), + new DeclarationReflection("18", ReflectionKind.TypeParameter), + new DeclarationReflection("20", ReflectionKind.CallSignature), new DeclarationReflection("7", ReflectionKind.Class), new DeclarationReflection( - "22", + "21", ReflectionKind.ConstructorSignature ), - new DeclarationReflection("23", ReflectionKind.IndexSignature), + new DeclarationReflection("22", ReflectionKind.IndexSignature), ]; sortReflections(arr, ["kind"]); diff --git a/src/test/utils/validation.test.ts b/src/test/utils/validation.test.ts new file mode 100644 index 000000000..046f61d56 --- /dev/null +++ b/src/test/utils/validation.test.ts @@ -0,0 +1,80 @@ +import { ok } from "assert"; +import { Validation } from "../../lib/utils"; +import { additionalProperties } from "../../lib/utils/validation"; + +describe("Validation Utils", () => { + it("Should be able to validate optional values", () => { + ok(Validation.validate(Validation.optional(String), null)); + ok(Validation.validate(Validation.optional(String), undefined)); + ok(Validation.validate(Validation.optional(String), "")); + }); + + it("Should be able to validate a boolean", () => { + ok(Validation.validate(Boolean, false)); + ok(!Validation.validate(Boolean, 123)); + ok(!Validation.validate(Boolean, "")); + }); + + it("Should be able to validate a number", () => { + ok(!Validation.validate(Number, false)); + ok(Validation.validate(Number, 123)); + ok(!Validation.validate(Number, "")); + }); + + it("Should be able to validate a string", () => { + ok(!Validation.validate(String, false)); + ok(!Validation.validate(String, 123)); + ok(Validation.validate(String, "")); + }); + + it("Should be able to validate an array", () => { + ok(Validation.validate([Array, String], [])); + ok(Validation.validate([Array, String], ["a"])); + ok(!Validation.validate([Array, String], ["a", 1])); + }); + + it("Should be able to validate with a custom function", () => { + ok(Validation.validate(Validation.isTagString, "@foo")); + ok(!Validation.validate(Validation.isTagString, true)); + }); + + it("Should be able to validate a set of literals", () => { + ok(Validation.validate(["a", "b", "c"] as const, "a")); + ok(Validation.validate(["a", "b", "c"] as const, "c")); + ok(!Validation.validate(["a", "b", "c"] as const, "d")); + }); + + it("Should be able to validate an object", () => { + const schema = { + x: String, + y: Validation.optional(Number), + }; + + ok(Validation.validate(schema, { x: "" })); + ok(Validation.validate(schema, { x: "", y: 0 })); + ok(Validation.validate(schema, { x: "", y: 0, z: 123 })); + ok(!Validation.validate(schema, { y: 123 })); + ok(!Validation.validate(schema, null)); + ok(!Validation.validate(schema, true)); + }); + + it("Should support not checking for excess properties (default)", () => { + const schema = { + x: String, + [additionalProperties]: true, + }; + + ok(Validation.validate(schema, { x: "" })); + ok(Validation.validate(schema, { x: "", y: "" })); + }); + + it("Should support checking for excess properties", () => { + const schema = { + x: String, + [additionalProperties]: false, + }; + + ok(Validation.validate(schema, { x: "" })); + ok(!Validation.validate(schema, { x: "", y: "" })); + }); +}); diff --git a/src/test/validation.test.ts b/src/test/validation.test.ts index 6c50dedfb..14fe4eeae 100644 --- a/src/test/validation.test.ts +++ b/src/test/validation.test.ts @@ -1,6 +1,6 @@ import { equal, fail, ok } from "assert"; -import { join, relative } from "path"; -import { Logger, LogLevel, normalizePath } from ".."; +import { join } from "path"; +import { Logger, LogLevel } from ".."; import { validateDocumentation } from "../lib/validation/documentation"; import { validateExports } from "../lib/validation/exports"; import { getConverter2App, getConverter2Program } from "./programs"; @@ -36,7 +36,7 @@ function expectWarning( let sawWarning = false; const regex = - /(.*?), defined at (.*?):\d+, is referenced by (.*?) but not included in the documentation\./; + /(.*?) is referenced by (.*?) but not included in the documentation\./; class LoggerCheck extends Logger { override log(message: string, level: LogLevel) { @@ -46,16 +46,6 @@ function expectWarning( equal(match[1], typeName, "Missing type name is different."); equal( match[2], - normalizePath( - relative( - process.cwd(), - `${__dirname}/converter2/validation/${file}` - ) - ), - "Referencing file is different." - ); - equal( - match[3], referencingName, "Referencing name is different" ); diff --git a/static/icons.css b/static/icons.css deleted file mode 100644 index 776a3562d..000000000 --- a/static/icons.css +++ /dev/null @@ -1,1043 +0,0 @@ -.tsd-kind-icon { - display: block; - position: relative; - padding-left: 20px; - text-indent: -20px; -} -.tsd-kind-icon:before { - content: ""; - display: inline-block; - vertical-align: middle; - width: 17px; - height: 17px; - margin: 0 3px 2px 0; - background-image: url(./icons.png); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-kind-icon:before { - background-image: url(./icons@2x.png); - background-size: 238px 204px; - } -} - -.tsd-signature.tsd-kind-icon:before { - background-position: 0 -153px; -} - -.tsd-kind-object-literal > .tsd-kind-icon:before { - background-position: 0px -17px; -} -.tsd-kind-object-literal.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -17px; -} -.tsd-kind-object-literal.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -17px; -} - -.tsd-kind-class > .tsd-kind-icon:before { - background-position: 0px -34px; -} -.tsd-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -34px; -} -.tsd-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -34px; -} - -.tsd-kind-class.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -51px; -} -.tsd-kind-class.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -51px; -} - -.tsd-kind-interface > .tsd-kind-icon:before { - background-position: 0px -68px; -} -.tsd-kind-interface.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -68px; -} -.tsd-kind-interface.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -68px; -} - -.tsd-kind-interface.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -85px; -} -.tsd-kind-interface.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -85px; -} - -.tsd-kind-namespace > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-namespace.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-namespace.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-module > .tsd-kind-icon:before { - background-position: 0px -102px; -} -.tsd-kind-module.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -102px; -} -.tsd-kind-module.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -102px; -} - -.tsd-kind-enum > .tsd-kind-icon:before { - background-position: 0px -119px; -} -.tsd-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -119px; -} -.tsd-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -119px; -} - -.tsd-kind-enum-member > .tsd-kind-icon:before { - background-position: 0px -136px; -} -.tsd-kind-enum-member.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -136px; -} -.tsd-kind-enum-member.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -136px; -} - -.tsd-kind-signature > .tsd-kind-icon:before { - background-position: 0px -153px; -} -.tsd-kind-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -153px; -} -.tsd-kind-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -153px; -} - -.tsd-kind-type-alias > .tsd-kind-icon:before { - background-position: 0px -170px; -} -.tsd-kind-type-alias.tsd-is-protected > .tsd-kind-icon:before { - background-position: -17px -170px; -} -.tsd-kind-type-alias.tsd-is-private > .tsd-kind-icon:before { - background-position: -34px -170px; -} - -.tsd-kind-type-alias.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: 0px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -17px -187px; -} -.tsd-kind-type-alias.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -34px -187px; -} - -.tsd-kind-variable > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-variable.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-variable.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-variable.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-variable.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-variable.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-property > .tsd-kind-icon:before { - background-position: -136px -0px; -} -.tsd-kind-property.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -0px; -} -.tsd-kind-property.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -0px; -} -.tsd-kind-property.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -0px; -} -.tsd-kind-property.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -0px; -} -.tsd-kind-property.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -0px; -} - -.tsd-kind-get-signature > .tsd-kind-icon:before { - background-position: -136px -17px; -} -.tsd-kind-get-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -17px; -} -.tsd-kind-get-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -17px; -} -.tsd-kind-get-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -17px; -} - -.tsd-kind-set-signature > .tsd-kind-icon:before { - background-position: -136px -34px; -} -.tsd-kind-set-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -34px; -} -.tsd-kind-set-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -34px; -} -.tsd-kind-set-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -34px; -} - -.tsd-kind-accessor > .tsd-kind-icon:before { - background-position: -136px -51px; -} -.tsd-kind-accessor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -51px; -} -.tsd-kind-accessor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -51px; -} -.tsd-kind-accessor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -51px; -} - -.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-method.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -68px; -} -.tsd-kind-call-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -68px; -} -.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -68px; -} -.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -68px; -} - -.tsd-kind-function.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-function.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-method.tsd-has-type-parameter > .tsd-kind-icon:before { - background-position: -136px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -85px; -} -.tsd-kind-method.tsd-has-type-parameter.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -85px; -} - -.tsd-kind-constructor > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-constructor-signature > .tsd-kind-icon:before { - background-position: -136px -102px; -} -.tsd-kind-constructor-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -102px; -} -.tsd-kind-constructor-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -102px; -} -.tsd-kind-constructor-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -102px; -} - -.tsd-kind-index-signature > .tsd-kind-icon:before { - background-position: -136px -119px; -} -.tsd-kind-index-signature.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -119px; -} -.tsd-kind-index-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -119px; -} -.tsd-kind-index-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -119px; -} - -.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -136px; -} -.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -136px; -} -.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -136px; -} -.tsd-kind-event.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -136px; -} -.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -136px; -} -.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -136px; -} - -.tsd-is-static > .tsd-kind-icon:before { - background-position: -136px -153px; -} -.tsd-is-static.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -153px; -} -.tsd-is-static.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-inherited > .tsd-kind-icon:before { - background-position: -68px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected > .tsd-kind-icon:before { - background-position: -85px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -153px; -} -.tsd-is-static.tsd-parent-kind-class.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-protected > .tsd-kind-icon:before { - background-position: -187px -153px; -} -.tsd-is-static.tsd-parent-kind-enum.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -153px; -} -.tsd-is-static.tsd-parent-kind-interface > .tsd-kind-icon:before { - background-position: -204px -153px; -} -.tsd-is-static.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -153px; -} - -.tsd-is-static.tsd-kind-function > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-function.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-method > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-method.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-call-signature > .tsd-kind-icon:before { - background-position: -136px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -153px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class - > .tsd-kind-icon:before { - background-position: -51px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum - > .tsd-kind-icon:before { - background-position: -170px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -170px; -} -.tsd-is-static.tsd-kind-call-signature.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -170px; -} - -.tsd-is-static.tsd-kind-event > .tsd-kind-icon:before { - background-position: -136px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-protected > .tsd-kind-icon:before { - background-position: -153px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-is-private > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class > .tsd-kind-icon:before { - background-position: -51px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -68px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -85px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-protected.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -102px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-class.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum > .tsd-kind-icon:before { - background-position: -170px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-protected - > .tsd-kind-icon:before { - background-position: -187px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-enum.tsd-is-private - > .tsd-kind-icon:before { - background-position: -119px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface - > .tsd-kind-icon:before { - background-position: -204px -187px; -} -.tsd-is-static.tsd-kind-event.tsd-parent-kind-interface.tsd-is-inherited - > .tsd-kind-icon:before { - background-position: -221px -187px; -} diff --git a/static/icons.png b/static/icons.png deleted file mode 100644 index 3836d5fe4..000000000 Binary files a/static/icons.png and /dev/null differ diff --git a/static/icons@2x.png b/static/icons@2x.png deleted file mode 100644 index 5a209e2f6..000000000 Binary files a/static/icons@2x.png and /dev/null differ diff --git a/static/style.css b/static/style.css index 6127b27cd..88952e47e 100644 --- a/static/style.css +++ b/static/style.css @@ -1,155 +1,133 @@ -@import url("./icons.css"); - :root { /* Light */ - --light-color-background: #fcfcfc; - --light-color-secondary-background: #fff; + --light-color-background: #f2f4f8; + --light-color-background-secondary: #eff0f1; + --light-color-icon-background: var(--light-color-background); + --light-color-accent: #c5c7c9; --light-color-text: #222; --light-color-text-aside: #707070; --light-color-link: #4da6ff; - --light-color-menu-divider: #eee; - --light-color-menu-divider-focus: #000; - --light-color-menu-label: #707070; - --light-color-panel: var(--light-color-secondary-background); - --light-color-panel-divider: #eee; - --light-color-comment-tag: #707070; - --light-color-comment-tag-text: #fff; - --light-color-ts: #9600ff; - --light-color-ts-interface: #647f1b; - --light-color-ts-enum: #937210; - --light-color-ts-class: #0672de; + --light-color-ts: #db1373; + --light-color-ts-interface: #139d2c; + --light-color-ts-enum: #9c891a; + --light-color-ts-class: #2484e5; + --light-color-ts-function: #572be7; + --light-color-ts-namespace: #b111c9; --light-color-ts-private: #707070; - --light-color-toolbar: #fff; - --light-color-toolbar-text: #333; - --light-icon-filter: invert(0); + --light-color-ts-variable: #4d68ff; --light-external-icon: url("data:image/svg+xml;utf8,"); + --light-color-scheme: light; /* Dark */ - --dark-color-background: #36393f; - --dark-color-secondary-background: #2f3136; - --dark-color-text: #ffffff; - --dark-color-text-aside: #e6e4e4; + --dark-color-background: #2b2e33; + --dark-color-background-secondary: #1e2024; + --dark-color-icon-background: var(--dark-color-background-secondary); + --dark-color-accent: #9096a2; + --dark-color-text: #f5f5f5; + --dark-color-text-aside: #dddddd; --dark-color-link: #00aff4; - --dark-color-menu-divider: #eee; - --dark-color-menu-divider-focus: #000; - --dark-color-menu-label: #707070; - --dark-color-panel: var(--dark-color-secondary-background); - --dark-color-panel-divider: #818181; - --dark-color-comment-tag: #dcddde; - --dark-color-comment-tag-text: #2f3136; - --dark-color-ts: #c97dff; - --dark-color-ts-interface: #9cbe3c; - --dark-color-ts-enum: #d6ab29; - --dark-color-ts-class: #3695f3; + --dark-color-ts: #ff6492; + --dark-color-ts-interface: #6cff87; + --dark-color-ts-enum: #f4d93e; + --dark-color-ts-class: #61b0ff; + --dark-color-ts-function: #9772ff; + --dark-color-ts-namespace: #e14dff; --dark-color-ts-private: #e2e2e2; - --dark-color-toolbar: #34373c; - --dark-color-toolbar-text: #ffffff; - --dark-icon-filter: invert(1); + --dark-color-ts-variable: #4d68ff; --dark-external-icon: url("data:image/svg+xml;utf8,"); + --dark-color-scheme: dark; } @media (prefers-color-scheme: light) { :root { --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); --color-ts: var(--light-color-ts); --color-ts-interface: var(--light-color-ts-interface); --color-ts-enum: var(--light-color-ts-enum); --color-ts-class: var(--light-color-ts-class); + --color-ts-function: var(--light-color-ts-function); + --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); + --color-ts-variable: var(--light-color-ts-variable); --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); } } @media (prefers-color-scheme: dark) { :root { --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); --color-ts: var(--dark-color-ts); --color-ts-interface: var(--dark-color-ts-interface); --color-ts-enum: var(--dark-color-ts-enum); --color-ts-class: var(--dark-color-ts-class); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); + --color-ts-variable: var(--dark-color-ts-variable); --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); } } +html { + color-scheme: var(--color-scheme); +} + body { margin: 0; } -body.light { +:root[data-theme="light"] { --color-background: var(--light-color-background); - --color-secondary-background: var(--light-color-secondary-background); + --color-background-secondary: var(--light-color-background-secondary); + --color-icon-background: var(--light-color-icon-background); + --color-accent: var(--light-color-accent); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); --color-link: var(--light-color-link); - --color-menu-divider: var(--light-color-menu-divider); - --color-menu-divider-focus: var(--light-color-menu-divider-focus); - --color-menu-label: var(--light-color-menu-label); - --color-panel: var(--light-color-panel); - --color-panel-divider: var(--light-color-panel-divider); - --color-comment-tag: var(--light-color-comment-tag); - --color-comment-tag-text: var(--light-color-comment-tag-text); --color-ts: var(--light-color-ts); --color-ts-interface: var(--light-color-ts-interface); --color-ts-enum: var(--light-color-ts-enum); --color-ts-class: var(--light-color-ts-class); + --color-ts-function: var(--light-color-ts-function); + --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-private: var(--light-color-ts-private); - --color-toolbar: var(--light-color-toolbar); - --color-toolbar-text: var(--light-color-toolbar-text); - --icon-filter: var(--light-icon-filter); + --color-ts-variable: var(--light-color-ts-variable); --external-icon: var(--light-external-icon); + --color-scheme: var(--light-color-scheme); } -body.dark { +:root[data-theme="dark"] { --color-background: var(--dark-color-background); - --color-secondary-background: var(--dark-color-secondary-background); + --color-background-secondary: var(--dark-color-background-secondary); + --color-icon-background: var(--dark-color-icon-background); + --color-accent: var(--dark-color-accent); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); --color-link: var(--dark-color-link); - --color-menu-divider: var(--dark-color-menu-divider); - --color-menu-divider-focus: var(--dark-color-menu-divider-focus); - --color-menu-label: var(--dark-color-menu-label); - --color-panel: var(--dark-color-panel); - --color-panel-divider: var(--dark-color-panel-divider); - --color-comment-tag: var(--dark-color-comment-tag); - --color-comment-tag-text: var(--dark-color-comment-tag-text); --color-ts: var(--dark-color-ts); --color-ts-interface: var(--dark-color-ts-interface); --color-ts-enum: var(--dark-color-ts-enum); --color-ts-class: var(--dark-color-ts-class); + --color-ts-function: var(--dark-color-ts-function); + --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-private: var(--dark-color-ts-private); - --color-toolbar: var(--dark-color-toolbar); - --color-toolbar-text: var(--dark-color-toolbar-text); - --icon-filter: var(--dark-icon-filter); + --color-ts-variable: var(--dark-color-ts-variable); --external-icon: var(--dark-external-icon); + --color-scheme: var(--dark-color-scheme); } h1, @@ -162,34 +140,37 @@ h6 { } h1 { - font-size: 2em; - margin: 0.67em 0; + font-size: 1.875rem; + margin: 0.67rem 0; } h2 { - font-size: 1.5em; - margin: 0.83em 0; + font-size: 1.5rem; + margin: 0.83rem 0; } h3 { - font-size: 1.17em; - margin: 1em 0; + font-size: 1.25rem; + margin: 1rem 0; } -h4, -.tsd-index-panel h3 { - font-size: 1em; - margin: 1.33em 0; +h4 { + font-size: 1.05rem; + margin: 1.33rem 0; } h5 { - font-size: 0.83em; - margin: 1.67em 0; + font-size: 1rem; + margin: 1.5rem 0; } h6 { - font-size: 0.67em; - margin: 2.33em 0; + font-size: 0.875rem; + margin: 2.33rem 0; +} + +.uppercase { + text-transform: uppercase; } pre { @@ -210,45 +191,61 @@ dd { } .container { - max-width: 1200px; - margin: 0 auto; - padding: 0 40px; + max-width: 1600px; + padding: 0 2rem; +} + +@media (min-width: 640px) { + .container { + padding: 0 4rem; + } +} +@media (min-width: 1200px) { + .container { + padding: 0 8rem; + } } -@media (max-width: 640px) { +@media (min-width: 1600px) { .container { - padding: 0 20px; + padding: 0 12rem; } } -.container-main { - padding-bottom: 200px; +/* Footer */ +.tsd-generator { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; + max-height: 3.5rem; +} + +.tsd-generator > p { + margin-top: 0; + margin-bottom: 0; + padding: 0 1rem; } -.row { +.container-main { display: flex; + justify-content: space-between; position: relative; - margin: 0 -10px; -} -.row:after { - visibility: hidden; - display: block; - content: ""; - clear: both; - height: 0; + margin: 0 auto; } .col-4, .col-8 { box-sizing: border-box; float: left; - padding: 0 10px; + padding: 2rem 1rem; } .col-4 { - width: 33.3333333333%; + flex: 0 0 25%; } .col-8 { - width: 66.6666666667%; + flex: 1 0; + flex-wrap: wrap; + padding-left: 0; } ul.tsd-descriptions > li > :first-child, @@ -379,11 +376,13 @@ pre { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0.2em; margin: 0; - font-size: 14px; + font-size: 0.875rem; + border-radius: 0.8em; } pre { padding: 10px; + border: 0.1em solid var(--color-accent); } pre code { padding: 0; @@ -422,36 +421,26 @@ blockquote { margin: 1em 0; } -@media (min-width: 901px) and (max-width: 1024px) { - html .col-content { - width: 72%; - } - html .col-menu { - width: 28%; - } - html .tsd-navigation { - padding-left: 10px; - } -} -@media (max-width: 900px) { +@media (max-width: 1024px) { html .col-content { float: none; + max-width: 100%; width: 100%; + padding-top: 3rem; } html .col-menu { position: fixed !important; - overflow: auto; + overflow-y: auto; -webkit-overflow-scrolling: touch; z-index: 1024; top: 0 !important; bottom: 0 !important; left: auto !important; right: 0 !important; - width: 100%; - padding: 20px 20px 0 0; - max-width: 450px; + padding: 1.5rem 1.5rem 0 0; + max-width: 25rem; visibility: hidden; - background-color: var(--color-panel); + background-color: var(--color-background); transform: translate(100%, 0); } html .col-menu > *:last-child { @@ -507,24 +496,17 @@ blockquote { visibility: visible; transform: translate(0, 0); display: grid; + align-items: center; grid-template-rows: auto 1fr; + grid-gap: 1.5rem; max-height: 100vh; + padding: 1rem 2rem; } .has-menu .tsd-navigation { max-height: 100%; } } -.tsd-page-title { - padding: 70px 0 20px 0; - margin: 0 0 40px 0; - background: var(--color-panel); - box-shadow: 0 0 5px rgba(0, 0, 0, 0.35); -} -.tsd-page-title h1 { - margin: 0; -} - .tsd-breadcrumb { margin: 0; padding: 0; @@ -544,32 +526,44 @@ blockquote { content: " / "; } -dl.tsd-comment-tags { +.tsd-comment-tags { + display: flex; + flex-direction: column; +} +dl.tsd-comment-tag-group { + display: flex; + align-items: center; overflow: hidden; + margin: 0.5em 0; } -dl.tsd-comment-tags dt { - float: left; - padding: 1px 5px; - margin: 0 10px 0 0; - border-radius: 4px; - border: 1px solid var(--color-comment-tag); - color: var(--color-comment-tag); - font-size: 0.8em; +dl.tsd-comment-tag-group dt { + display: flex; + margin-right: 0.5em; + font-size: 0.875em; font-weight: normal; } -dl.tsd-comment-tags dd { - margin: 0 0 10px 0; +dl.tsd-comment-tag-group dd { + margin: 0; +} +code.tsd-tag { + padding: 0.25em 0.4em; + border: 0.1em solid var(--color-accent); + margin-right: 0.25em; + font-size: 70%; } -dl.tsd-comment-tags dd:before, -dl.tsd-comment-tags dd:after { - display: table; +h1 code.tsd-tag:first-of-type { + margin-left: 0.25em; +} + +dl.tsd-comment-tag-group dd:before, +dl.tsd-comment-tag-group dd:after { content: " "; } -dl.tsd-comment-tags dd pre, -dl.tsd-comment-tags dd:after { +dl.tsd-comment-tag-group dd pre, +dl.tsd-comment-tag-group dd:after { clear: both; } -dl.tsd-comment-tags p { +dl.tsd-comment-tag-group p { margin: 0; } @@ -582,153 +576,109 @@ dl.tsd-comment-tags p { margin-bottom: 0; } -.toggle-protected .tsd-is-private { - display: none; -} - -.toggle-public .tsd-is-private, -.toggle-public .tsd-is-protected, -.toggle-public .tsd-is-private-protected { - display: none; +.tsd-filter-visibility h4 { + font-size: 1rem; + padding-top: 0.75rem; + padding-bottom: 0.5rem; + margin: 0; } - -.toggle-inherited .tsd-is-inherited { - display: none; +.tsd-filter-item:not(:last-child) { + margin-bottom: 0.5rem; } - -.toggle-externals .tsd-is-external { - display: none; +.tsd-filter-input { + display: flex; + width: fit-content; + width: -moz-fit-content; + align-items: center; + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + cursor: pointer; } - -#tsd-filter { - position: relative; - display: inline-block; - height: 40px; - vertical-align: bottom; +.tsd-filter-input input[type="checkbox"] { + cursor: pointer; + position: absolute; + width: 1.5em; + height: 1.5em; + opacity: 0; } -.no-filter #tsd-filter { - display: none; +.tsd-filter-input input[type="checkbox"]:disabled { + pointer-events: none; } -#tsd-filter .tsd-filter-group { - display: inline-block; - height: 40px; - vertical-align: bottom; - white-space: nowrap; +.tsd-filter-input svg { + cursor: pointer; + width: 1.5em; + height: 1.5em; + margin-right: 0.5em; + border-radius: 0.33em; + /* Leaving this at full opacity breaks event listeners on Firefox. + Don't remove unless you know what you're doing. */ + opacity: 0.99; } -#tsd-filter input { - display: none; +.tsd-filter-input input[type="checkbox"]:focus + svg { + transform: scale(0.95); } -@media (max-width: 900px) { - #tsd-filter .tsd-filter-group { - display: block; - position: absolute; - top: 40px; - right: 20px; - height: auto; - background-color: var(--color-panel); - visibility: hidden; - transform: translate(50%, 0); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - } - .has-options #tsd-filter .tsd-filter-group { - visibility: visible; - } - .to-has-options #tsd-filter .tsd-filter-group { - animation: fade-in 0.2s; - } - .from-has-options #tsd-filter .tsd-filter-group { - animation: fade-out 0.2s; - } - #tsd-filter label, - #tsd-filter .tsd-select { - display: block; - padding-right: 20px; - } +.tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { + transform: scale(1); } - -footer { - border-top: 1px solid var(--color-panel-divider); - background-color: var(--color-panel); +.tsd-checkbox-background { + fill: var(--color-accent); } -footer:after { - content: ""; - display: table; +input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { + stroke: var(--color-text); } -footer.with-border-bottom { - border-bottom: 1px solid var(--color-panel-divider); +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { + fill: var(--color-background); + stroke: var(--color-accent); + stroke-width: 0.25rem; } -footer .tsd-legend-group { - font-size: 0; +.tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { + stroke: var(--color-accent); } -footer .tsd-legend { - display: inline-block; - width: 25%; - padding: 0; - font-size: 16px; - list-style: none; - line-height: 1.333em; - vertical-align: top; + +.tsd-theme-toggle { + padding-top: 0.75rem; } -@media (max-width: 900px) { - footer .tsd-legend { - width: 50%; - } +.tsd-theme-toggle > h4 { + display: inline; + vertical-align: middle; + margin-right: 0.75rem; } .tsd-hierarchy { list-style: square; - padding: 0 0 0 20px; margin: 0; } .tsd-hierarchy .target { font-weight: bold; } -.tsd-index-panel .tsd-index-content { - margin-bottom: -30px !important; -} -.tsd-index-panel .tsd-index-section { - margin-bottom: 30px !important; -} -.tsd-index-panel h3 { - margin: 0 -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 3; - -moz-column-count: 3; - -ms-column-count: 3; - -o-column-count: 3; - column-count: 3; - -webkit-column-gap: 20px; - -moz-column-gap: 20px; - -ms-column-gap: 20px; - -o-column-gap: 20px; - column-gap: 20px; - padding: 0; +.tsd-panel-group.tsd-index-group { + margin-bottom: 0; +} +.tsd-index-panel .tsd-index-list { list-style: none; line-height: 1.333em; -} -@media (max-width: 900px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 1; - -moz-column-count: 1; - -ms-column-count: 1; - -o-column-count: 1; - column-count: 1; + margin: 0; + padding: 0.25rem 0 0 0; + overflow: hidden; + display: grid; + grid-template-columns: repeat(3, 1fr); + column-gap: 1rem; + grid-template-rows: auto; +} +@media (max-width: 1024px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(2, 1fr); } } -@media (min-width: 901px) and (max-width: 1024px) { - .tsd-index-panel ul.tsd-index-list { - -webkit-column-count: 2; - -moz-column-count: 2; - -ms-column-count: 2; - -o-column-count: 2; - column-count: 2; +@media (max-width: 768px) { + .tsd-index-panel .tsd-index-list { + grid-template-columns: repeat(1, 1fr); } } -.tsd-index-panel ul.tsd-index-list li { +.tsd-index-panel .tsd-index-list li { -webkit-page-break-inside: avoid; -moz-page-break-inside: avoid; -ms-page-break-inside: avoid; @@ -736,31 +686,40 @@ footer .tsd-legend { page-break-inside: avoid; } .tsd-index-panel a, -.tsd-index-panel .tsd-parent-kind-module a { +.tsd-index-panel a.tsd-parent-kind-module { color: var(--color-ts); } -.tsd-index-panel .tsd-parent-kind-interface a { +.tsd-index-panel a.tsd-parent-kind-interface { color: var(--color-ts-interface); } -.tsd-index-panel .tsd-parent-kind-enum a { +.tsd-index-panel a.tsd-parent-kind-enum { color: var(--color-ts-enum); } -.tsd-index-panel .tsd-parent-kind-class a { +.tsd-index-panel a.tsd-parent-kind-class { color: var(--color-ts-class); } -.tsd-index-panel .tsd-kind-module a { - color: var(--color-ts); +.tsd-index-panel a.tsd-kind-module { + color: var(--color-ts-namespace); } -.tsd-index-panel .tsd-kind-interface a { +.tsd-index-panel a.tsd-kind-interface { color: var(--color-ts-interface); } -.tsd-index-panel .tsd-kind-enum a { +.tsd-index-panel a.tsd-kind-enum { color: var(--color-ts-enum); } -.tsd-index-panel .tsd-kind-class a { +.tsd-index-panel a.tsd-kind-class { color: var(--color-ts-class); } -.tsd-index-panel .tsd-is-private a { +.tsd-index-panel a.tsd-kind-function { + color: var(--color-ts-function); +} +.tsd-index-panel a.tsd-kind-namespace { + color: var(--color-ts-namespace); +} +.tsd-index-panel a.tsd-kind-variable { + color: var(--color-ts-variable); +} +.tsd-index-panel a.tsd-is-private { color: var(--color-ts-private); } @@ -785,6 +744,8 @@ footer .tsd-legend { position: relative; } .tsd-member .tsd-anchor + h3 { + display: flex; + align-items: center; margin-top: 0; margin-bottom: 0; border-bottom: none; @@ -805,13 +766,9 @@ footer .tsd-legend { color: var(--color-ts-private); } -.tsd-navigation { - margin: 0 0 0 40px; -} .tsd-navigation a { display: block; - padding-top: 2px; - padding-bottom: 2px; + margin: 0.4rem 0; border-left: 2px solid transparent; color: var(--color-text); text-decoration: none; @@ -829,110 +786,167 @@ footer .tsd-legend { padding: 0; } -.tsd-navigation.primary { - padding-bottom: 40px; +.tsd-navigation.primary .tsd-accordion-details > ul { + margin-top: 0.75rem; } .tsd-navigation.primary a { - display: block; - padding-top: 6px; - padding-bottom: 6px; + padding: 0.75rem 0.5rem; + margin: 0; } .tsd-navigation.primary ul li a { - padding-left: 5px; + margin-left: 0.5rem; } .tsd-navigation.primary ul li li a { - padding-left: 25px; + margin-left: 1.5rem; } .tsd-navigation.primary ul li li li a { - padding-left: 45px; + margin-left: 2.5rem; } .tsd-navigation.primary ul li li li li a { - padding-left: 65px; + margin-left: 3.5rem; } .tsd-navigation.primary ul li li li li li a { - padding-left: 85px; + margin-left: 4.5rem; } .tsd-navigation.primary ul li li li li li li a { - padding-left: 105px; -} -.tsd-navigation.primary > ul { - border-bottom: 1px solid var(--color-panel-divider); -} -.tsd-navigation.primary li { - border-top: 1px solid var(--color-panel-divider); + margin-left: 5.5rem; } .tsd-navigation.primary li.current > a { + border-left: 0.15rem var(--color-text) solid; +} +.tsd-navigation.primary li.selected > a { font-weight: bold; + border-left: 0.2rem var(--color-text) solid; } -.tsd-navigation.primary li.label span { - display: block; - padding: 20px 0 6px 5px; - color: var(--color-menu-label); +.tsd-navigation.primary ul li a:hover { + border-left: 0.2rem var(--color-text-aside) solid; } .tsd-navigation.primary li.globals + li > span, .tsd-navigation.primary li.globals + li > a { padding-top: 20px; } -.tsd-navigation.secondary { - max-height: calc(100vh - 1rem - 40px); - overflow: auto; - position: sticky; - top: calc(0.5rem + 40px); - transition: 0.3s; -} .tsd-navigation.secondary.tsd-navigation--toolbar-hide { max-height: calc(100vh - 1rem); top: 0.5rem; } -.tsd-navigation.secondary ul { +.tsd-navigation.secondary > ul { + display: inline; + padding-right: 0.5rem; transition: opacity 0.2s; } .tsd-navigation.secondary ul li a { - padding-left: 25px; + padding-left: 0; } .tsd-navigation.secondary ul li li a { - padding-left: 45px; + padding-left: 1.1rem; } .tsd-navigation.secondary ul li li li a { - padding-left: 65px; + padding-left: 2.2rem; } .tsd-navigation.secondary ul li li li li a { - padding-left: 85px; + padding-left: 3.3rem; } .tsd-navigation.secondary ul li li li li li a { - padding-left: 105px; + padding-left: 4.4rem; } .tsd-navigation.secondary ul li li li li li li a { - padding-left: 125px; + padding-left: 5.5rem; +} + +a.tsd-index-link { + margin: 0.25rem 0; + font-size: 1rem; + line-height: 1.25rem; + display: inline-flex; + align-items: center; +} +.tsd-accordion-summary > h1, +.tsd-accordion-summary > h2, +.tsd-accordion-summary > h3, +.tsd-accordion-summary > h4, +.tsd-accordion-summary > h5 { + display: inline-flex; + align-items: center; + vertical-align: middle; + margin-bottom: 0; + user-select: none; + -moz-user-select: none; + -webkit-user-select: none; + -ms-user-select: none; } -.tsd-navigation.secondary ul.current a { - border-left-color: var(--color-panel-divider); +.tsd-accordion-summary { + display: block; + cursor: pointer; } -.tsd-navigation.secondary li.focus > a, -.tsd-navigation.secondary ul.current li.focus > a { - border-left-color: var(--color-menu-divider-focus); +.tsd-accordion-summary > * { + margin-top: 0; + margin-bottom: 0; + padding-top: 0; + padding-bottom: 0; } -.tsd-navigation.secondary li.current { - margin-top: 20px; - margin-bottom: 20px; - border-left-color: var(--color-panel-divider); +.tsd-accordion-summary::-webkit-details-marker { + display: none; } -.tsd-navigation.secondary li.current > a { - font-weight: bold; +.tsd-index-accordion .tsd-accordion-summary svg { + margin-right: 0.25rem; +} +.tsd-index-content > :not(:first-child) { + margin-top: 0.75rem; +} +.tsd-index-heading { + margin-top: 1.5rem; + margin-bottom: 0.75rem; +} + +.tsd-kind-icon { + margin-right: 0.5rem; + width: 1.25rem; + height: 1.25rem; + min-width: 1.25rem; + min-height: 1.25rem; +} +.tsd-kind-icon path { + transform-origin: center; + transform: scale(1.1); +} +.tsd-signature > .tsd-kind-icon { + margin-right: 0.8rem; } -@media (min-width: 901px) { +@media (min-width: 1024px) { + .col-content { + margin: 2rem auto; + } + .menu-sticky-wrap { - position: static; + position: sticky; + height: calc(100vh - 2rem); + top: 4rem; + right: 0; + padding: 0 1.5rem; + padding-top: 1rem; + margin-top: 3rem; + transition: 0.3s ease-in-out; + transition-property: top, padding-top, padding, height; + overflow-y: auto; + } + .col-menu { + border-left: 1px solid var(--color-accent); + } + .col-menu--hide { + top: 1rem; + } + .col-menu .tsd-navigation:not(:last-child) { + padding-bottom: 1.75rem; } } .tsd-panel { - margin: 20px 0; - padding: 20px; - background-color: var(--color-panel); - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); + margin-bottom: 2.5rem; +} +.tsd-panel.tsd-member { + margin-bottom: 4rem; } .tsd-panel:empty { display: none; @@ -940,48 +954,24 @@ footer .tsd-legend { .tsd-panel > h1, .tsd-panel > h2, .tsd-panel > h3 { - margin: 1.5em -20px 10px -20px; - padding: 0 20px 10px 20px; - border-bottom: 1px solid var(--color-panel-divider); + margin: 1.5rem -1.5rem 0.75rem -1.5rem; + padding: 0 1.5rem 0.75rem 1.5rem; } .tsd-panel > h1.tsd-before-signature, .tsd-panel > h2.tsd-before-signature, .tsd-panel > h3.tsd-before-signature { margin-bottom: 0; - border-bottom: 0; -} -.tsd-panel table { - display: block; - width: 100%; - overflow: auto; - margin-top: 10px; - word-break: normal; - word-break: keep-all; - border-collapse: collapse; -} -.tsd-panel table th { - font-weight: bold; -} -.tsd-panel table th, -.tsd-panel table td { - padding: 6px 13px; - border: 1px solid var(--color-panel-divider); -} -.tsd-panel table tr { - background: var(--color-background); -} -.tsd-panel table tr:nth-child(even) { - background: var(--color-secondary-background); + border-bottom: none; } .tsd-panel-group { - margin: 60px 0; + margin: 4rem 0; } -.tsd-panel-group > h1, -.tsd-panel-group > h2, -.tsd-panel-group > h3 { - padding-left: 20px; - padding-right: 20px; +.tsd-panel-group.tsd-index-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group details { + margin: 4rem 0; } #tsd-search { @@ -995,8 +985,8 @@ footer .tsd-legend { position: absolute; left: 0; top: 0; - right: 40px; - height: 40px; + right: 2.5rem; + height: 100%; } #tsd-search .field input { box-sizing: border-box; @@ -1035,14 +1025,14 @@ footer .tsd-legend { background-color: var(--color-background); } #tsd-search .results li:nth-child(even) { - background-color: var(--color-panel); + background-color: var(--color-background-secondary); } #tsd-search .results li.state { display: none; } #tsd-search .results li.current, #tsd-search .results li:hover { - background-color: var(--color-panel-divider); + background-color: var(--color-accent); } #tsd-search .results a { display: block; @@ -1055,7 +1045,7 @@ footer .tsd-legend { font-weight: normal; } #tsd-search.has-focus { - background-color: var(--color-panel-divider); + background-color: var(--color-accent); } #tsd-search.has-focus .field input { top: 0; @@ -1076,31 +1066,16 @@ footer .tsd-legend { } .tsd-signature { - margin: 0 0 1em 0; - padding: 10px; - border: 1px solid var(--color-panel-divider); + margin: 0 0 1rem 0; + padding: 1rem 0.5rem; + border: 1px solid var(--color-accent); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; overflow-x: auto; } -.tsd-signature.tsd-kind-icon { - padding-left: 30px; -} -.tsd-signature.tsd-kind-icon:before { - top: 10px; - left: 10px; -} .tsd-panel > .tsd-signature { - margin-left: -20px; - margin-right: -20px; border-width: 1px 0; } -.tsd-panel > .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signature.tsd-kind-icon:before { - left: 20px; -} .tsd-signature-symbol { color: var(--color-text-aside); @@ -1115,7 +1090,7 @@ footer .tsd-legend { .tsd-signatures { padding: 0; margin: 0 0 1em 0; - border: 1px solid var(--color-panel-divider); + border: 1px solid var(--color-accent); } .tsd-signatures .tsd-signature { margin: 0; @@ -1126,22 +1101,14 @@ footer .tsd-legend { border-top-width: 0; } .tsd-signatures .tsd-signature.current { - background-color: var(--color-panel-divider); + background-color: var(--color-background-secondary); } .tsd-signatures.active > .tsd-signature { cursor: pointer; } .tsd-panel > .tsd-signatures { - margin-left: -20px; - margin-right: -20px; border-width: 1px 0; } -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon { - padding-left: 40px; -} -.tsd-panel > .tsd-signatures .tsd-signature.tsd-kind-icon:before { - left: 20px; -} .tsd-panel > a.anchor + .tsd-signatures { border-top-width: 0; margin-top: -20px; @@ -1179,40 +1146,30 @@ ul.tsd-descriptions .tsd-index-panel h3, margin: 1em 0 0.5em 0; } -ul.tsd-parameters, -ul.tsd-type-parameters { +ul.tsd-parameter-list, +ul.tsd-type-parameter-list { list-style: square; margin: 0; padding-left: 20px; } -ul.tsd-parameters > li.tsd-parameter-signature, -ul.tsd-type-parameters > li.tsd-parameter-signature { +ul.tsd-parameter-list > li.tsd-parameter-signature, +ul.tsd-type-parameter-list > li.tsd-parameter-signature { list-style: none; margin-left: -20px; } -ul.tsd-parameters h5, -ul.tsd-type-parameters h5 { +ul.tsd-parameter-list h5, +ul.tsd-type-parameter-list h5 { font-size: 16px; margin: 1em 0 0.5em 0; } -ul.tsd-parameters .tsd-comment, -ul.tsd-type-parameters .tsd-comment { - margin-top: -0.5em; -} - .tsd-sources { - font-size: 14px; - color: var(--color-text-aside); - margin: 0 0 1em 0; + margin-top: 1rem; + font-size: 0.875em; } .tsd-sources a { color: var(--color-text-aside); text-decoration: underline; } -.tsd-sources ul, -.tsd-sources p { - margin: 0 !important; -} .tsd-sources ul { list-style: none; padding: 0; @@ -1224,14 +1181,13 @@ ul.tsd-type-parameters .tsd-comment { top: 0; left: 0; width: 100%; - height: 40px; - color: var(--color-toolbar-text); - background: var(--color-toolbar); - border-bottom: 1px solid var(--color-panel-divider); - transition: transform 0.3s linear; + color: var(--color-text); + background: var(--color-background-secondary); + border-bottom: 1px var(--color-accent) solid; + transition: transform 0.3s ease-in-out; } .tsd-page-toolbar a { - color: var(--color-toolbar-text); + color: var(--color-text); text-decoration: none; } .tsd-page-toolbar a.title { @@ -1240,13 +1196,12 @@ ul.tsd-type-parameters .tsd-comment { .tsd-page-toolbar a.title:hover { text-decoration: underline; } -.tsd-page-toolbar .table-wrap { - display: table; - width: 100%; - height: 40px; +.tsd-page-toolbar .tsd-toolbar-contents { + display: flex; + justify-content: space-between; + height: 2.5rem; } .tsd-page-toolbar .table-cell { - display: table-cell; position: relative; white-space: nowrap; line-height: 40px; @@ -1259,29 +1214,6 @@ ul.tsd-type-parameters .tsd-comment { transform: translateY(-100%); } -.tsd-select .tsd-select-list li:before, -.tsd-select .tsd-select-label:before, -.tsd-widget:before { - content: ""; - display: inline-block; - width: 40px; - height: 40px; - margin: 0 -8px 0 0; - background-image: url(./widgets.png); - background-repeat: no-repeat; - text-indent: -1024px; - vertical-align: bottom; - filter: var(--icon-filter); -} -@media (-webkit-min-device-pixel-ratio: 1.5), (min-resolution: 144dpi) { - .tsd-select .tsd-select-list li:before, - .tsd-select .tsd-select-label:before, - .tsd-widget:before { - background-image: url(./widgets@2x.png); - background-size: 320px 40px; - } -} - .tsd-widget { display: inline-block; overflow: hidden; @@ -1296,7 +1228,7 @@ ul.tsd-type-parameters .tsd-comment { } .tsd-widget.active { opacity: 1; - background-color: var(--color-panel-divider); + background-color: var(--color-accent); } .tsd-widget.no-caption { width: 40px; @@ -1304,20 +1236,12 @@ ul.tsd-type-parameters .tsd-comment { .tsd-widget.no-caption:before { margin: 0; } -.tsd-widget.search:before { - background-position: 0 0; -} -.tsd-widget.menu:before { - background-position: -40px 0; -} -.tsd-widget.options:before { - background-position: -80px 0; -} + .tsd-widget.options, .tsd-widget.menu { display: none; } -@media (max-width: 900px) { +@media (max-width: 1024px) { .tsd-widget.options, .tsd-widget.menu { display: inline-block; @@ -1330,75 +1254,14 @@ input[type="checkbox"]:checked + .tsd-widget:before { background-position: -160px 0; } -.tsd-select { - position: relative; - display: inline-block; - height: 40px; - transition: opacity 0.1s, background-color 0.2s; - vertical-align: bottom; - cursor: pointer; -} -.tsd-select .tsd-select-label { - opacity: 0.6; - transition: opacity 0.2s; -} -.tsd-select .tsd-select-label:before { - background-position: -240px 0; -} -.tsd-select.active .tsd-select-label { - opacity: 0.8; -} -.tsd-select.active .tsd-select-list { - visibility: visible; - opacity: 1; - transition-delay: 0s; -} -.tsd-select .tsd-select-list { - position: absolute; - visibility: hidden; - top: 40px; - left: 0; - margin: 0; - padding: 0; - opacity: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - transition: visibility 0s 0.2s, opacity 0.2s; -} -.tsd-select .tsd-select-list li { - padding: 0 20px 0 0; - background-color: var(--color-background); -} -.tsd-select .tsd-select-list li:before { - background-position: 40px 0; -} -.tsd-select .tsd-select-list li:nth-child(even) { - background-color: var(--color-panel); -} -.tsd-select .tsd-select-list li:hover { - background-color: var(--color-panel-divider); -} -.tsd-select .tsd-select-list li.selected:before { - background-position: -200px 0; -} -@media (max-width: 900px) { - .tsd-select .tsd-select-list { - top: 0; - left: auto; - right: 100%; - margin-right: -5px; - } - .tsd-select .tsd-select-label:before { - background-position: -280px 0; - } -} - img { max-width: 100%; } .tsd-anchor-icon { - margin-left: 10px; + display: inline-flex; + align-items: center; + margin-left: 0.5rem; vertical-align: middle; color: var(--color-text); } @@ -1412,3 +1275,26 @@ img { .tsd-anchor-link:hover > .tsd-anchor-icon svg { visibility: visible; } + +.deprecated { + text-decoration: line-through; +} + +* { + scrollbar-width: thin; + scrollbar-color: var(--color-accent) var(--color-icon-background); +} + +*::-webkit-scrollbar { + width: 0.75rem; +} + +*::-webkit-scrollbar-track { + background: var(--color-icon-background); +} + +*::-webkit-scrollbar-thumb { + background-color: var(--color-accent); + border-radius: 999rem; + border: 0.25rem solid var(--color-icon-background); +} diff --git a/tsconfig.json b/tsconfig.json index 21a96d728..bdccdc0eb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,14 +1,16 @@ { "compilerOptions": { "module": "CommonJS", - "lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"], - "target": "es2019", + "lib": ["es2020"], + "target": "es2020", + // Add our `ts` internal types "typeRoots": ["node_modules/@types", "src/lib/types"], "types": ["node", "glob", "lunr", "marked", "minimatch", "mocha"], // Speed up dev compilation time "incremental": true, - "tsBuildInfoFile": "node_modules/.cache/.tsbuildinfo", + "tsBuildInfoFile": "dist/.tsbuildinfo", + "experimentalDecorators": true, "strict": true, "alwaysStrict": true, @@ -44,8 +46,7 @@ "src/test/module", "src/test/packages", "src/test/slow/entry-points", - "src/test/renderer/testProject", - "src/codegen" + "src/test/renderer/testProject" ], // We use ts-node to support mocha runner directly on files "ts-node": { diff --git a/tsdoc.json b/tsdoc.json new file mode 100644 index 000000000..8f2978b04 --- /dev/null +++ b/tsdoc.json @@ -0,0 +1,71 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": false, + "tagDefinitions": [ + { + "tagName": "@module", + "syntaxKind": "block" + }, + { + "tagName": "@typedef", + "syntaxKind": "block" + }, + { + "tagName": "@callback", + "syntaxKind": "block" + }, + { + "tagName": "@prop", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@property", + "syntaxKind": "block", + "allowMultiple": true + }, + // Don't include @inheritDoc, because the @microsoft/tsdoc-config parser blows up + // if the standard @inheritDoc inline tag is also defined here. + { + "tagName": "@group", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@category", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@hidden", + "syntaxKind": "modifier" + }, + { + "tagName": "@ignore", + "syntaxKind": "modifier" + }, + { + "tagName": "@enum", + "syntaxKind": "modifier" + }, + { + "tagName": "@event", + "syntaxKind": "modifier" + }, + { + "tagName": "@template", + "syntaxKind": "block", + "allowMultiple": true + }, + { + "tagName": "@linkcode", + "syntaxKind": "inline", + "allowMultiple": true + }, + { + "tagName": "@linkplain", + "syntaxKind": "block", + "allowMultiple": true + } + ] +}