diff --git a/package-lock.json b/package-lock.json index a4ce8b2b..cde07bb4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@microsoft/api-extractor": "^7.20.0", "@microsoft/api-extractor-model": "^7.16.0", "@microsoft/tsdoc": "^0.13.2", + "@rushstack/node-core-library": "^3.45.2", "@types/aws-lambda": "^8.10.92", "@types/body-parser": "^1.19.2", "@types/jest": "^27.4.0", @@ -1558,6 +1559,29 @@ "api-documenter": "bin/api-documenter" } }, + "node_modules/@microsoft/api-documenter/node_modules/@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "dependencies": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "node_modules/@microsoft/api-documenter/node_modules/@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, "node_modules/@microsoft/api-documenter/node_modules/colors": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", @@ -1567,6 +1591,20 @@ "node": ">=0.1.90" } }, + "node_modules/@microsoft/api-documenter/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/@microsoft/api-documenter/node_modules/js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -1626,6 +1664,87 @@ "@rushstack/node-core-library": "3.45.1" } }, + "node_modules/@microsoft/api-extractor-model/node_modules/@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "dependencies": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "node_modules/@microsoft/api-extractor-model/node_modules/@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, + "node_modules/@microsoft/api-extractor-model/node_modules/colors": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", + "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@microsoft/api-extractor-model/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@microsoft/api-extractor-model/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "dependencies": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "node_modules/@microsoft/api-extractor/node_modules/@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, "node_modules/@microsoft/api-extractor/node_modules/colors": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", @@ -1635,6 +1754,20 @@ "node": ">=0.1.90" } }, + "node_modules/@microsoft/api-extractor/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/@microsoft/api-extractor/node_modules/resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -1846,9 +1979,9 @@ } }, "node_modules/@rushstack/node-core-library": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", - "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "version": "3.45.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.2.tgz", + "integrity": "sha512-MJKdB6mxOoIkks3htGVCo7aiTzllm2I6Xua+KbTSb0cp7rBp8gTCOF/4d8R4HFMwpRdEdwzKgqMM6k9rAK73iw==", "dev": true, "dependencies": { "@types/node": "12.20.24", @@ -16453,12 +16586,46 @@ "resolve": "~1.17.0" }, "dependencies": { + "@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "requires": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, "colors": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", "dev": true }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "js-yaml": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", @@ -16500,12 +16667,46 @@ "typescript": "~4.5.2" }, "dependencies": { + "@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "requires": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, "colors": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", "dev": true }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, "resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", @@ -16526,6 +16727,57 @@ "@microsoft/tsdoc": "0.13.2", "@microsoft/tsdoc-config": "~0.15.2", "@rushstack/node-core-library": "3.45.1" + }, + "dependencies": { + "@rushstack/node-core-library": { + "version": "3.45.1", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", + "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "dev": true, + "requires": { + "@types/node": "12.20.24", + "colors": "~1.2.1", + "fs-extra": "~7.0.1", + "import-lazy": "~4.0.0", + "jju": "~1.4.0", + "resolve": "~1.17.0", + "semver": "~7.3.0", + "timsort": "~0.3.0", + "z-schema": "~5.0.2" + } + }, + "@types/node": { + "version": "12.20.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.24.tgz", + "integrity": "sha512-yxDeaQIAJlMav7fH5AQqPH1u8YIuhYJXYBzxaQ4PifsU0GDO38MSdmEDeRlIxrKbC6NbEaaEHDanWb+y30U8SQ==", + "dev": true + }, + "colors": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.2.5.tgz", + "integrity": "sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==", + "dev": true + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + } } }, "@microsoft/tsdoc": { @@ -16709,9 +16961,9 @@ } }, "@rushstack/node-core-library": { - "version": "3.45.1", - "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.1.tgz", - "integrity": "sha512-BwdssTNe007DNjDBxJgInHg8ePytIPyT0La7ZZSQZF9+rSkT42AygXPGvbGsyFfEntjr4X37zZSJI7yGzL16cQ==", + "version": "3.45.2", + "resolved": "https://registry.npmjs.org/@rushstack/node-core-library/-/node-core-library-3.45.2.tgz", + "integrity": "sha512-MJKdB6mxOoIkks3htGVCo7aiTzllm2I6Xua+KbTSb0cp7rBp8gTCOF/4d8R4HFMwpRdEdwzKgqMM6k9rAK73iw==", "dev": true, "requires": { "@types/node": "12.20.24", diff --git a/package.json b/package.json index c52722ec..b5ae89e9 100644 --- a/package.json +++ b/package.json @@ -16,9 +16,9 @@ "coverage": "codecov", "lint": "eslint ./src/ ./test/ --fix", "semantic-release": "semantic-release", - "docs:generate:api-pages": "ts-node scripts/apidoc.ts", - "docs:generate:api-pages-test": "ts-node scripts/apidoc-test.ts", - "docs:generate:api-pages-test-1": "ts-node scripts/apidoc-test-1.ts", + "docs:parse": "npm run build:docs && ts-node scripts/parse-docs.ts", + "docs:generate:markdown": "ts-node scripts/generate-markdown.ts", + "docs:generate:api-pages": "ts-node scripts/generate-api-pages.ts", "docs:typedoc": "npm run build:docs && npm run docs:typedoc:extract:local && npm run docs:typedoc:extract && npm run docs:typedoc:markdown", "docs:typedoc:extract:local": "npx @microsoft/api-extractor run --local", "docs:typedoc:extract": "npx @microsoft/api-extractor run", @@ -68,6 +68,7 @@ "@microsoft/api-extractor": "^7.20.0", "@microsoft/api-extractor-model": "^7.16.0", "@microsoft/tsdoc": "^0.13.2", + "@rushstack/node-core-library": "^3.45.2", "@types/aws-lambda": "^8.10.92", "@types/body-parser": "^1.19.2", "@types/jest": "^27.4.0", diff --git a/scripts/Formatter.ts b/scripts/Formatter.ts deleted file mode 100644 index acaece89..00000000 --- a/scripts/Formatter.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { DocExcerpt, DocNode } from '@microsoft/tsdoc'; - -/** - * This is a simplistic solution until we implement proper DocNode rendering APIs. - */ -export class Formatter { - public static renderDocNode(docNode: DocNode): string { - let result: string = ''; - if (docNode) { - if (docNode instanceof DocExcerpt) { - result += docNode.content.toString(); - } - for (const childNode of docNode.getChildNodes()) { - result += Formatter.renderDocNode(childNode); - } - } - return result; - } - - public static renderDocNodes(docNodes: ReadonlyArray): string { - let result: string = ''; - for (const docNode of docNodes) { - result += Formatter.renderDocNode(docNode); - } - return result; - } -} diff --git a/scripts/apidoc-test.ts b/scripts/apidoc-test.ts deleted file mode 100644 index 916e1ef4..00000000 --- a/scripts/apidoc-test.ts +++ /dev/null @@ -1,336 +0,0 @@ -import { - IMarkdownEmitterOptions, - MarkdownEmitter, -} from '@microsoft/api-documenter/lib/markdown/MarkdownEmitter'; -import * as tsdoc from '@microsoft/tsdoc'; -import { StringBuilder } from '@microsoft/tsdoc'; -import colors from 'colors'; -import * as os from 'os'; -import * as path from 'path'; -import * as ts from 'typescript'; - -/** - * Returns true if the specified SyntaxKind is part of a declaration form. - * - * Based on ts.isDeclarationKind() from the compiler. - * https://github.com/microsoft/TypeScript/blob/v3.0.3/src/compiler/utilities.ts#L6382 - */ -function isDeclarationKind(kind: ts.SyntaxKind): boolean { - return ( - kind === ts.SyntaxKind.ArrowFunction || - kind === ts.SyntaxKind.BindingElement || - kind === ts.SyntaxKind.ClassDeclaration || - kind === ts.SyntaxKind.ClassExpression || - kind === ts.SyntaxKind.Constructor || - kind === ts.SyntaxKind.EnumDeclaration || - kind === ts.SyntaxKind.EnumMember || - kind === ts.SyntaxKind.ExportSpecifier || - kind === ts.SyntaxKind.FunctionDeclaration || - kind === ts.SyntaxKind.FunctionExpression || - kind === ts.SyntaxKind.GetAccessor || - kind === ts.SyntaxKind.ImportClause || - kind === ts.SyntaxKind.ImportEqualsDeclaration || - kind === ts.SyntaxKind.ImportSpecifier || - kind === ts.SyntaxKind.InterfaceDeclaration || - kind === ts.SyntaxKind.JsxAttribute || - kind === ts.SyntaxKind.MethodDeclaration || - kind === ts.SyntaxKind.MethodSignature || - kind === ts.SyntaxKind.ModuleDeclaration || - kind === ts.SyntaxKind.NamespaceExportDeclaration || - kind === ts.SyntaxKind.NamespaceImport || - kind === ts.SyntaxKind.Parameter || - kind === ts.SyntaxKind.PropertyAssignment || - kind === ts.SyntaxKind.PropertyDeclaration || - kind === ts.SyntaxKind.PropertySignature || - kind === ts.SyntaxKind.SetAccessor || - kind === ts.SyntaxKind.ShorthandPropertyAssignment || - kind === ts.SyntaxKind.TypeAliasDeclaration || - kind === ts.SyntaxKind.TypeParameter || - kind === ts.SyntaxKind.VariableDeclaration || - kind === ts.SyntaxKind.JSDocTypedefTag || - kind === ts.SyntaxKind.JSDocCallbackTag || - kind === ts.SyntaxKind.JSDocPropertyTag - ); -} - -/** - * Retrieves the JSDoc-style comments associated with a specific AST node. - * - * Based on ts.getJSDocCommentRanges() from the compiler. - * https://github.com/microsoft/TypeScript/blob/v3.0.3/src/compiler/utilities.ts#L924 - */ -function getJSDocCommentRanges(node: ts.Node, text: string): ts.CommentRange[] { - const commentRanges: ts.CommentRange[] = []; - - switch (node.kind) { - case ts.SyntaxKind.Parameter: - case ts.SyntaxKind.TypeParameter: - case ts.SyntaxKind.FunctionExpression: - case ts.SyntaxKind.ArrowFunction: - case ts.SyntaxKind.ParenthesizedExpression: - commentRanges.push( - ...(ts.getTrailingCommentRanges(text, node.pos) || []), - ); - break; - } - commentRanges.push(...(ts.getLeadingCommentRanges(text, node.pos) || [])); - - // True if the comment starts with '/**' but not if it is '/**/' - return commentRanges.filter( - comment => - text.charCodeAt(comment.pos + 1) === - 0x2a /* ts.CharacterCodes.asterisk */ && - text.charCodeAt(comment.pos + 2) === - 0x2a /* ts.CharacterCodes.asterisk */ && - text.charCodeAt(comment.pos + 3) !== 0x2f /* ts.CharacterCodes.slash */, - ); -} - -interface IFoundComment { - compilerNode: ts.Node; - textRange: tsdoc.TextRange; -} - -function walkCompilerAstAndFindComments( - node: ts.Node, - indent: string, - foundComments: IFoundComment[], -): void { - // The TypeScript AST doesn't store code comments directly. If you want to find *every* comment, - // you would need to rescan the SourceFile tokens similar to how tsutils.forEachComment() works: - // https://github.com/ajafff/tsutils/blob/v3.0.0/util/util.ts#L453 - // - // However, for this demo we are modeling a tool that discovers declarations and then analyzes their doc comments, - // so we only care about TSDoc that would conventionally be associated with an interesting AST node. - - let foundCommentsSuffix: string = ''; - const buffer: string = node.getSourceFile().getFullText(); // don't use getText() here! - - // Only consider nodes that are part of a declaration form. Without this, we could discover - // the same comment twice (e.g. for a MethodDeclaration and its PublicKeyword). - if (isDeclarationKind(node.kind)) { - // Find "/** */" style comments associated with this node. - // Note that this reinvokes the compiler's scanner -- the result is not cached. - const comments: ts.CommentRange[] = getJSDocCommentRanges(node, buffer); - - if (comments.length > 0) { - if (comments.length === 1) { - foundCommentsSuffix = colors.cyan(` (FOUND 1 COMMENT)`); - } else { - foundCommentsSuffix = colors.cyan( - ` (FOUND ${comments.length} COMMENTS)`, - ); - } - - for (const comment of comments) { - foundComments.push({ - compilerNode: node, - textRange: tsdoc.TextRange.fromStringRange( - buffer, - comment.pos, - comment.end, - ), - }); - } - } - } - - console.log(`${indent}- ${ts.SyntaxKind[node.kind]}${foundCommentsSuffix}`); - - return node.forEachChild(child => - walkCompilerAstAndFindComments(child, indent + ' ', foundComments), - ); -} - -function dumpTSDocTree(docNode: tsdoc.DocNode, indent: string): void { - let dumpText: string = ''; - if (docNode instanceof tsdoc.DocExcerpt) { - const content: string = docNode.content.toString(); - dumpText += - colors.gray(`${indent}* ${docNode.excerptKind}=`) + - colors.cyan(JSON.stringify(content)); - } else { - dumpText += `${indent}- ${docNode.kind}`; - } - console.log(dumpText); - - for (const child of docNode.getChildNodes()) { - dumpTSDocTree(child, indent + ' '); - } -} - -function parseTSDoc(foundComment: IFoundComment): void { - console.log(os.EOL + colors.green('Comment to be parsed:') + os.EOL); - console.log(colors.gray('<<<<<<')); - console.log(foundComment.textRange.toString()); - console.log(colors.gray('>>>>>>')); - - const customConfiguration: tsdoc.TSDocConfiguration = - new tsdoc.TSDocConfiguration(); - - const customInlineDefinition: tsdoc.TSDocTagDefinition = - new tsdoc.TSDocTagDefinition({ - tagName: '@customInline', - syntaxKind: tsdoc.TSDocTagSyntaxKind.InlineTag, - allowMultiple: true, - }); - - // NOTE: Defining this causes a new DocBlock to be created under docComment.customBlocks. - // Otherwise, a simple DocBlockTag would appear inline in the @remarks section. - const customBlockDefinition: tsdoc.TSDocTagDefinition = - new tsdoc.TSDocTagDefinition({ - tagName: '@customBlock', - syntaxKind: tsdoc.TSDocTagSyntaxKind.BlockTag, - }); - - // NOTE: Defining this causes @customModifier to be removed from its section, - // and added to the docComment.modifierTagSet - const customModifierDefinition: tsdoc.TSDocTagDefinition = - new tsdoc.TSDocTagDefinition({ - tagName: '@customModifier', - syntaxKind: tsdoc.TSDocTagSyntaxKind.ModifierTag, - }); - - customConfiguration.addTagDefinitions([ - customInlineDefinition, - customBlockDefinition, - customModifierDefinition, - ]); - - console.log( - os.EOL + 'Invoking TSDocParser with custom configuration...' + os.EOL, - ); - const tsdocParser: tsdoc.TSDocParser = new tsdoc.TSDocParser( - customConfiguration, - ); - const parserContext: tsdoc.ParserContext = tsdocParser.parseRange( - foundComment.textRange, - ); - const docComment: tsdoc.DocComment = parserContext.docComment; - - const emitter = new MarkdownEmitter(); - const stringBuiler = new StringBuilder(); - const options: IMarkdownEmitterOptions = {}; - - console.log(emitter.emit(stringBuiler, docComment, options)); - - console.log(os.EOL + colors.green('Parser Log Messages:') + os.EOL); - - if (parserContext.log.messages.length === 0) { - console.log('No errors or warnings.'); - } else { - const sourceFile: ts.SourceFile = foundComment.compilerNode.getSourceFile(); - - for (const message of parserContext.log.messages) { - // Since we have the compiler's analysis, use it to calculate the line/column information, - // since this is currently faster than TSDoc's TextRange.getLocation() lookup. - const location: ts.LineAndCharacter = - sourceFile.getLineAndCharacterOfPosition(message.textRange.pos); - const formattedMessage: string = `${sourceFile.fileName}(${ - location.line + 1 - },${location.character + 1}): [TSDoc] ${message}`; - console.log(formattedMessage); - } - } - - if ( - parserContext.docComment.modifierTagSet.hasTag(customModifierDefinition) - ) { - console.log( - os.EOL + - colors.cyan( - `The ${customModifierDefinition.tagName} modifier was FOUND.`, - ), - ); - } else { - console.log( - os.EOL + - colors.cyan( - `The ${customModifierDefinition.tagName} modifier was NOT FOUND.`, - ), - ); - } - - console.log(os.EOL + colors.green("Visiting TSDoc's DocNode tree") + os.EOL); - dumpTSDocTree(docComment, ''); -} - -/** - * The advanced demo invokes the TypeScript compiler and extracts the comment from the AST. - * It also illustrates how to define custom TSDoc tags using TSDocConfiguration. - */ -export function advancedDemo(): void { - console.log( - colors.yellow('*** TSDoc API demo: Advanced Scenario ***') + os.EOL, - ); - - const inputFilename: string = path.resolve( - path.join(__dirname, '..', 'dist', 'serverless-adapter.d.ts'), - ); - const compilerOptions: ts.CompilerOptions = { - target: ts.ScriptTarget.ES5, - }; - - // Compile the input - console.log( - 'Invoking the TypeScript compiler to analyze assets/advanced-input.ts...', - ); - - const program: ts.Program = ts.createProgram( - [inputFilename], - compilerOptions, - ); - - // Report any compiler errors - const compilerDiagnostics: ReadonlyArray = - program.getSemanticDiagnostics(); - if (compilerDiagnostics.length > 0) { - for (const diagnostic of compilerDiagnostics) { - const message: string = ts.flattenDiagnosticMessageText( - diagnostic.messageText, - os.EOL, - ); - if (diagnostic.file) { - const location: ts.LineAndCharacter = - diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!); - const formattedMessage: string = - `${diagnostic.file.fileName}(${location.line + 1},${ - location.character + 1 - }):` + ` [TypeScript] ${message}`; - console.log(colors.red(formattedMessage)); - } else { - console.log(colors.red(message)); - } - } - } else { - console.log('No compiler errors or warnings.'); - } - - const sourceFile: ts.SourceFile | undefined = - program.getSourceFile(inputFilename); - if (!sourceFile) { - throw new Error('Error retrieving source file'); - } - - console.log( - os.EOL + - colors.green('Scanning compiler AST for first code comment...') + - os.EOL, - ); - - const foundComments: IFoundComment[] = []; - - walkCompilerAstAndFindComments(sourceFile, '', foundComments); - - if (foundComments.length === 0) { - console.log( - colors.red('Error: No code comments were found in the input file'), - ); - } else { - // For the purposes of this demo, only analyze the first comment that we found - - parseTSDoc(foundComments[0]); - } -} - -advancedDemo(); diff --git a/scripts/apidoc.ts b/scripts/apidoc.ts deleted file mode 100644 index 2629204a..00000000 --- a/scripts/apidoc.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'; -import { resolve } from 'path'; - -const outputFile = resolve('.', 'docs', '.vitepress', 'api-pages.ts'); -const apiExtractConfig = resolve('./api-extractor.json'); - -async function build(): Promise { - const config = ExtractorConfig.loadFileAndPrepare(apiExtractConfig); - - const extractorResult = Extractor.invoke(config, { - localBuild: true, - }); - - if (extractorResult.succeeded) { - console.log(`API Extractor completed successfully`); - process.exitCode = 0; - } else { - console.error( - `API Extractor completed with ${extractorResult.errorCount} errors` + - ` and ${extractorResult.warningCount} warnings`, - ); - process.exitCode = 1; - } - - // const members: APIDoc['members'] = serverlessAdapterApi.members[0] - // .members as unknown as APIDoc['members']; - // - // const adapters = members.filter( - // member => member.name.includes('Adapter') && member.kind === 'Class', - // ); - // const adapterGroup: SideBarGroup = { - // text: 'Adapters', - // link: './adapters', - // children: adapters.map(adapter => ({ - // text: adapter.name, - // link: `./api/serverless-adapter.${adapter.name.toLowerCase()}`, - // })), - // }; - // - // const pages: SideBarGroup[] = [adapterGroup]; - // - // writeFileSync(outputFile, `export const apiPages = ${JSON.stringify(pages)}`); -} - -build().catch(console.error); diff --git a/scripts/generate-api-pages.ts b/scripts/generate-api-pages.ts new file mode 100644 index 00000000..08611f58 --- /dev/null +++ b/scripts/generate-api-pages.ts @@ -0,0 +1,121 @@ +import { writeFileSync } from 'fs'; +import { resolve } from 'path'; +import { + ApiDocumentedItem, + ApiItem, + ApiModel, +} from '@microsoft/api-extractor-model'; +import { DocNodeKind, DocPlainText } from '@microsoft/tsdoc'; +import { DefaultTheme } from 'vitepress'; +import SideBarGroup = DefaultTheme.SideBarGroup; + +const apiModelPath = resolve('.', 'temp', 'serverless-adapter.api.json'); +const outputFile = resolve('.', 'docs', '.vitepress', 'api-pages.ts'); + +type BreadcumbItem = { + breadcumbs: string[]; + apiMember: ApiItem; +}; + +function getBreadcumbsWithApiItem(apiModel: ApiModel): BreadcumbItem[] { + const breadcumbs: BreadcumbItem[] = []; + + for (const apiPackage of apiModel.members) { + for (const apiEntrypoint of apiPackage.members) { + for (const apiMember of apiEntrypoint.members) { + const apiDocumentedItem = apiMember as ApiDocumentedItem; + + if (!apiDocumentedItem.tsdocComment) continue; + + const breadcumb = apiDocumentedItem.tsdocComment.customBlocks.find( + block => block.blockTag.tagName === '@breadcumb', + ); + + if (!breadcumb) continue; + + const breadcumbContent = breadcumb.content + .getChildNodes() + .filter(block => block.kind === DocNodeKind.Paragraph) + .reduce((acc, block) => [...acc, ...block.getChildNodes()], []) + .filter(block => block.kind === DocNodeKind.PlainText) + .map((plainText: DocPlainText) => plainText.text) + .join(''); + + breadcumbs.push({ + breadcumbs: breadcumbContent + .split('/') + .map(section => section.trimLeft().trimRight()), + apiMember, + }); + } + } + } + + return breadcumbs; +} + +function build(): void { + const apiModel = new ApiModel(); + + apiModel.loadPackage(apiModelPath); + + const breadcumbsWithApiItems = getBreadcumbsWithApiItem(apiModel); + + const pages: SideBarGroup[] = []; + + let level: number = 0; + + for (const breadcumbWithApiItem of breadcumbsWithApiItems) { + let lastPage: SideBarGroup | undefined; + + for (const breadcumb of breadcumbWithApiItem.breadcumbs) { + level++; + + const newPage: SideBarGroup = { + text: breadcumb, + collapsable: level > 1, + children: [], + }; + + if (lastPage) { + let subpage = lastPage.children.find( + page => page.text === breadcumb, + ) as SideBarGroup; + + if (!subpage) { + subpage = newPage; + + lastPage.children.push(subpage); + } + + lastPage = subpage; + } else { + const oldPage = pages.find(page => page.text === breadcumb); + + if (oldPage) lastPage = oldPage; + else { + lastPage = newPage; + + pages.push(lastPage); + } + } + } + + if (!lastPage) { + throw new Error( + `Breadcumb was configured incorrectly. Error found in ${breadcumbWithApiItem.apiMember.displayName}.`, + ); + } + + lastPage.children.push({ + text: breadcumbWithApiItem.apiMember.displayName, + link: `./api/${breadcumbWithApiItem.apiMember.displayName}`, + collapsable: false, + children: [], + }); + } + + writeFileSync(outputFile, `export const apiPages = ${JSON.stringify(pages)}`); +} + +build(); diff --git a/scripts/apidoc-test-1.ts b/scripts/generate-markdown.ts similarity index 66% rename from scripts/apidoc-test-1.ts rename to scripts/generate-markdown.ts index 642f694b..1fa5e1bb 100644 --- a/scripts/apidoc-test-1.ts +++ b/scripts/generate-markdown.ts @@ -1,11 +1,12 @@ -import { ApiModel } from '@microsoft/api-extractor-model'; import { resolve } from 'path'; +import { ApiModel } from '@microsoft/api-extractor-model'; import { CustomMarkdownDocumenter } from './libs/CustomMarkdownDocumenter'; -async function build(): Promise { +const apiModelPath = resolve('.', 'temp', 'serverless-adapter.api.json'); +const outputFolder = resolve('.', 'docs', 'api'); + +function build(): void { const apiModel = new ApiModel(); - const apiModelPath = resolve('.', 'temp', 'serverless-adapter.api.json'); - const outputFolder = resolve('.', 'docs', 'api'); apiModel.loadPackage(apiModelPath); @@ -18,4 +19,4 @@ async function build(): Promise { markdown.generateFiles(); } -build().catch(console.error); +build(); diff --git a/scripts/libs/CustomMarkdownDocumenter.ts b/scripts/libs/CustomMarkdownDocumenter.ts index 98fb904f..b3cfe336 100644 --- a/scripts/libs/CustomMarkdownDocumenter.ts +++ b/scripts/libs/CustomMarkdownDocumenter.ts @@ -1,5 +1,6 @@ -import { IMarkdownDocumenterFeatureOnBeforeWritePageArgs } from '@microsoft/api-documenter'; +import * as path from 'path'; import { + IMarkdownDocumenterFeatureOnBeforeWritePageArgs, MarkdownDocumenterAccessor, MarkdownDocumenterFeatureContext, } from '@microsoft/api-documenter/lib'; @@ -58,7 +59,6 @@ import { NewlineKind, PackageName, } from '@rushstack/node-core-library'; -import * as path from 'path'; import { CustomUtilities } from './CustomUtilities'; export interface IMarkdownDocumenterOptions { @@ -72,13 +72,6 @@ export interface IMarkdownDocumenterOptions { * For more info: https://en.wikipedia.org/wiki/Markdown */ export class CustomMarkdownDocumenter { - private readonly _apiModel: ApiModel; - private readonly _documenterConfig: DocumenterConfig | undefined; - private readonly _tsdocConfiguration: TSDocConfiguration; - private readonly _markdownEmitter: CustomMarkdownEmitter; - private readonly _outputFolder: string; - private readonly _pluginLoader: PluginLoader; - public constructor(options: IMarkdownDocumenterOptions) { this._apiModel = options.apiModel; this._documenterConfig = options.documenterConfig; @@ -89,6 +82,13 @@ export class CustomMarkdownDocumenter { this._pluginLoader = new PluginLoader(); } + private readonly _apiModel: ApiModel; + private readonly _documenterConfig: DocumenterConfig | undefined; + private readonly _tsdocConfiguration: TSDocConfiguration; + private readonly _markdownEmitter: CustomMarkdownEmitter; + private readonly _outputFolder: string; + private readonly _pluginLoader: PluginLoader; + public generateFiles(): void { if (this._documenterConfig) { this._pluginLoader.load(this._documenterConfig, () => { @@ -109,35 +109,36 @@ export class CustomMarkdownDocumenter { this._writeApiItemPage(this._apiModel); - if (this._pluginLoader.markdownDocumenterFeature) { + if (this._pluginLoader.markdownDocumenterFeature) this._pluginLoader.markdownDocumenterFeature.onFinished({}); - } } - private _writeApiItemPage(apiItem: ApiItem): void { + private _writeApiItemPage(apiItem: ApiItem, parentOutput?: DocSection): void { const configuration: TSDocConfiguration = this._tsdocConfiguration; - const output: DocSection = new DocSection({ - configuration: this._tsdocConfiguration, - }); + const output: DocSection = + parentOutput || + new DocSection({ + configuration: this._tsdocConfiguration, + }); - this._writeBreadcrumb(output, apiItem); + if (!parentOutput) this._writeBreadcrumb(output, apiItem); - const scopedName: string = apiItem.getScopedNameWithinPackage(); + const scopedName: string = apiItem.displayName; switch (apiItem.kind) { case ApiItemKind.Class: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} class` }), + new DocHeading({ configuration, title: `(class) ${scopedName}` }), ); break; case ApiItemKind.Enum: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} enum` }), + new DocHeading({ configuration, title: `(enum) ${scopedName}` }), ); break; case ApiItemKind.Interface: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} interface` }), + new DocHeading({ configuration, title: `(interface) ${scopedName}` }), ); break; case ApiItemKind.Constructor: @@ -147,22 +148,22 @@ export class CustomMarkdownDocumenter { case ApiItemKind.Method: case ApiItemKind.MethodSignature: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} method` }), + new DocHeading({ configuration, title: `(method) ${scopedName}` }), ); break; case ApiItemKind.Function: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} function` }), + new DocHeading({ configuration, title: `(function) ${scopedName}` }), ); break; case ApiItemKind.Model: output.appendNode( - new DocHeading({ configuration, title: `API Reference` }), + new DocHeading({ configuration, title: 'API Reference' }), ); break; case ApiItemKind.Namespace: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} namespace` }), + new DocHeading({ configuration, title: `(namespace) ${scopedName}` }), ); break; case ApiItemKind.Package: @@ -173,24 +174,24 @@ export class CustomMarkdownDocumenter { output.appendNode( new DocHeading({ configuration, - title: `${unscopedPackageName} package`, + title: `(package) ${unscopedPackageName}`, }), ); break; case ApiItemKind.Property: case ApiItemKind.PropertySignature: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} property` }), + new DocHeading({ configuration, title: `(property) ${scopedName}` }), ); break; case ApiItemKind.TypeAlias: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} type` }), + new DocHeading({ configuration, title: `(type) ${scopedName}e` }), ); break; case ApiItemKind.Variable: output.appendNode( - new DocHeading({ configuration, title: `${scopedName} variable` }), + new DocHeading({ configuration, title: `(variable) ${scopedName}` }), ); break; default: @@ -198,9 +199,8 @@ export class CustomMarkdownDocumenter { } if (ApiReleaseTagMixin.isBaseClassOf(apiItem)) { - if (apiItem.releaseTag === ReleaseTag.Beta) { + if (apiItem.releaseTag === ReleaseTag.Beta) this._writeBetaWarning(output); - } } const decoratorBlocks: DocBlock[] = []; @@ -264,9 +264,8 @@ export class CustomMarkdownDocumenter { ]), ]), ); - for (const decoratorBlock of decoratorBlocks) { + for (const decoratorBlock of decoratorBlocks) output.appendNodes(decoratorBlock.content.nodes); - } } let appendRemarks: boolean = true; @@ -315,12 +314,10 @@ export class CustomMarkdownDocumenter { case ApiItemKind.Variable: break; default: - throw new Error('Unsupported API item kind: ' + apiItem.kind); + throw new Error(`Unsupported API item kind: ${apiItem.kind}`); } - if (appendRemarks) { - this._writeRemarksSection(output, apiItem); - } + if (appendRemarks) this._writeRemarksSection(output, apiItem); const filename: string = path.join( this._outputFolder, @@ -354,6 +351,8 @@ export class CustomMarkdownDocumenter { if (apiItem.kind == ApiItemKind.Model) return; + if (parentOutput) return; + FileSystem.writeFile(filename, pageContent, { convertLineEndings: this._documenterConfig ? this._documenterConfig.newlineKind @@ -458,9 +457,8 @@ export class CustomMarkdownDocumenter { let needsComma: boolean = false; const visited: Set = new Set(); for (const ref of refs) { - if (visited.has(ref.text)) { - continue; - } + if (visited.has(ref.text)) continue; + visited.add(ref.text); if (needsComma) { @@ -541,9 +539,8 @@ export class CustomMarkdownDocumenter { }), ); - for (const throwsBlock of throwsBlocks) { + for (const throwsBlock of throwsBlocks) this._appendSection(output, throwsBlock.content); - } } } } @@ -774,6 +771,8 @@ export class CustomMarkdownDocumenter { headerTitles: ['Method', 'Modifiers', 'Description'], }); + const postApiMembers: ApiItem[] = []; + for (const apiMember of apiClass.members) { switch (apiMember.kind) { case ApiItemKind.Constructor: { @@ -785,7 +784,8 @@ export class CustomMarkdownDocumenter { ]), ); - this._writeApiItemPage(apiMember); + // this._writeApiItemPage(apiMember); + postApiMembers.push(apiMember); break; } case ApiItemKind.Method: { @@ -797,7 +797,8 @@ export class CustomMarkdownDocumenter { ]), ); - this._writeApiItemPage(apiMember); + // this._writeApiItemPage(apiMember); + postApiMembers.push(apiMember); break; } case ApiItemKind.Property: { @@ -821,7 +822,8 @@ export class CustomMarkdownDocumenter { ); } - this._writeApiItemPage(apiMember); + // this._writeApiItemPage(apiMember); + postApiMembers.push(apiMember); break; } } @@ -866,6 +868,12 @@ export class CustomMarkdownDocumenter { ); output.appendNode(methodsTable); } + + if (postApiMembers.length > 0) { + postApiMembers.forEach(postApiMember => + this._writeApiItemPage(postApiMember, output), + ); + } } /** @@ -940,7 +948,7 @@ export class CustomMarkdownDocumenter { headerTitles: ['Method', 'Description'], }); - const postMembers: ApiItem[] = []; + const postApiMembers: ApiItem[] = []; for (const apiMember of apiClass.members) { switch (apiMember.kind) { @@ -954,7 +962,8 @@ export class CustomMarkdownDocumenter { ); // se pá é aqui que ele diverge e cria um novo arquivo - this._writeApiItemPage(apiMember); + // this._writeApiItemPage(apiMember); + postApiMembers.push(apiMember); break; } case ApiItemKind.PropertySignature: { @@ -976,7 +985,8 @@ export class CustomMarkdownDocumenter { ); } - this._writeApiItemPage(apiMember); + // this._writeApiItemPage(apiMember); + postApiMembers.push(apiMember); break; } } @@ -1011,6 +1021,12 @@ export class CustomMarkdownDocumenter { ); output.appendNode(methodsTable); } + + if (postApiMembers.length > 0) { + postApiMembers.forEach(postApiItem => + this._writeApiItemPage(postApiItem, output), + ); + } } /** @@ -1110,9 +1126,7 @@ export class CustomMarkdownDocumenter { paragraph.appendNode( new DocPlainText({ configuration, text: '(not declared)' }), ); - } else { - this._appendExcerptWithHyperlinks(paragraph, excerpt); - } + } else this._appendExcerptWithHyperlinks(paragraph, excerpt); return paragraph; } @@ -1121,9 +1135,8 @@ export class CustomMarkdownDocumenter { docNodeContainer: DocNodeContainer, excerpt: Excerpt, ): void { - for (const token of excerpt.spannedTokens) { + for (const token of excerpt.spannedTokens) this._appendExcerptTokenWithHyperlinks(docNodeContainer, token); - } } private _appendExcerptTokenWithHyperlinks( @@ -1170,9 +1183,8 @@ export class CustomMarkdownDocumenter { const configuration: TSDocConfiguration = this._tsdocConfiguration; let linkText: string = Utilities.getConciseSignature(apiItem); - if (ApiOptionalMixin.isBaseClassOf(apiItem) && apiItem.isOptional) { + if (ApiOptionalMixin.isBaseClassOf(apiItem) && apiItem.isOptional) linkText += '?'; - } return new DocTableCell({ configuration }, [ new DocParagraph({ configuration }, [ @@ -1307,9 +1319,7 @@ export class CustomMarkdownDocumenter { } private _appendSection(output: DocSection, docSection: DocSection): void { - for (const node of docSection.nodes) { - output.appendNode(node); - } + for (const node of docSection.nodes) output.appendNode(node); } private _appendAndMergeSection( @@ -1366,9 +1376,7 @@ export class CustomMarkdownDocumenter { } // when we don't have name, usually is the package documentation - if (!baseName) { - return `index.md`; - } + if (!baseName) return 'index.md'; return baseName + '.md'; } diff --git a/scripts/libs/CustomUtilities.ts b/scripts/libs/CustomUtilities.ts index 2bd8c5d5..adb4f641 100644 --- a/scripts/libs/CustomUtilities.ts +++ b/scripts/libs/CustomUtilities.ts @@ -1,7 +1,7 @@ import { ApiItem, ApiParameterListMixin } from '@microsoft/api-extractor-model'; export class CustomUtilities { - private static readonly _badFilenameCharsRegExp: RegExp = /[^a-z0-9_\-\.]/gi; + private static readonly _badFilenameCharsRegExp: RegExp = /[^a-z0-9_\-.]/gi; /** * Generates a concise signature for a function. Example: "getArea(width, height)" diff --git a/scripts/apidoc.types.ts b/scripts/models/apidoc.types.ts similarity index 100% rename from scripts/apidoc.types.ts rename to scripts/models/apidoc.types.ts diff --git a/scripts/parse-docs.ts b/scripts/parse-docs.ts new file mode 100644 index 00000000..2eed3104 --- /dev/null +++ b/scripts/parse-docs.ts @@ -0,0 +1,24 @@ +import { resolve } from 'path'; +import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'; + +const apiExtractConfig = resolve('./api-extractor.json'); + +function build(): void { + const config = ExtractorConfig.loadFileAndPrepare(apiExtractConfig); + + const extractorResult = Extractor.invoke(config, { + localBuild: true, + }); + + if (!extractorResult.succeeded) { + console.error( + `API Extractor completed with ${extractorResult.errorCount} errors` + + ` and ${extractorResult.warningCount} warnings`, + ); + process.exitCode = 1; + } + + console.log('API Extractor completed successfully'); +} + +build(); diff --git a/src/adapters/aws/alb.adapter.ts b/src/adapters/aws/alb.adapter.ts index 0136a311..e46797e9 100644 --- a/src/adapters/aws/alb.adapter.ts +++ b/src/adapters/aws/alb.adapter.ts @@ -20,6 +20,7 @@ import { /** * The options to customize the {@link AlbAdapter} * + * @breadcumb Adapters / AWS / AlbAdapter * @public */ export interface AlbAdapterOptions { @@ -42,9 +43,8 @@ export interface AlbAdapterOptions { * * {@link https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html | Event Reference} * + * @breadcumb Adapters / AWS * @public - * {@menu Adapters} - * {@submenu AWS} */ export class AlbAdapter implements AdapterContract diff --git a/tsconfig.json b/tsconfig.json index 4a7cde0c..c9e46f77 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -70,6 +70,6 @@ "skipLibCheck": true, /* Skip type checking of declaration files. */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "include": ["src/**/*.ts", "test/**/*.ts"], + "include": ["src/**/*.ts", "test/**/*.ts", "scripts/**/*.ts"], "exclude": ["src/index.doc.ts"] } diff --git a/tsdoc.json b/tsdoc.json index 96139d8c..9c31d629 100644 --- a/tsdoc.json +++ b/tsdoc.json @@ -2,13 +2,8 @@ "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", "tagDefinitions": [ { - "tagName": "@menu", - "syntaxKind": "inline", - "allowMultiple": false - }, - { - "tagName": "@submenu", - "syntaxKind": "inline", + "tagName": "@breadcumb", + "syntaxKind": "block", "allowMultiple": false } ],