From 935f94aaa0a301321600ac9828d72ae003afc5a9 Mon Sep 17 00:00:00 2001 From: Shane4368 Date: Mon, 20 Sep 2021 12:43:35 -0500 Subject: [PATCH 001/151] Use data attribute on html element for themes * Add custom CSS property --color-scheme * Remove theme check in setTheme function --- package-lock.json | 1 + .../output/themes/default/assets/typedoc/Theme.ts | 14 +------------- static/style.css | 10 ++++++++-- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8d9108dae..c7b6f16fd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,7 @@ "requires": true, "packages": { "": { + "name": "typedoc", "version": "0.22.4", "license": "Apache-2.0", "dependencies": { diff --git a/src/lib/output/themes/default/assets/typedoc/Theme.ts b/src/lib/output/themes/default/assets/typedoc/Theme.ts index 0e8791526..4e5ba8517 100644 --- a/src/lib/output/themes/default/assets/typedoc/Theme.ts +++ b/src/lib/output/themes/default/assets/typedoc/Theme.ts @@ -13,17 +13,5 @@ export function initTheme(choices: HTMLOptionElement) { } 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/static/style.css b/static/style.css index ff488199d..223b2f8f0 100644 --- a/static/style.css +++ b/static/style.css @@ -71,6 +71,7 @@ --color-toolbar-text: var(--light-color-toolbar-text); --icon-filter: var(--light-icon-filter); --external-icon: var(--light-external-icon); + --color-scheme: light; } } @@ -97,14 +98,19 @@ --color-toolbar-text: var(--dark-color-toolbar-text); --icon-filter: var(--dark-icon-filter); --external-icon: var(--dark-external-icon); + --color-scheme: dark; } } +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-text: var(--light-color-text); @@ -128,7 +134,7 @@ body.light { --external-icon: var(--light-external-icon); } -body.dark { +:root[data-theme="dark"] { --color-background: var(--dark-color-background); --color-secondary-background: var(--dark-color-secondary-background); --color-text: var(--dark-color-text); From 56a5b3c17ee6bc4ca0b789708982a8dd361a10e8 Mon Sep 17 00:00:00 2001 From: Shane4368 Date: Mon, 20 Sep 2021 14:49:56 -0500 Subject: [PATCH 002/151] Use html data-theme attribute in highlighter.tsx * Also declare --color-scheme property under each theme selector --- src/lib/utils/highlighter.tsx | 4 ++-- static/style.css | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index 852d7b3ce..5a8a8c598 100644 --- a/src/lib/utils/highlighter.tsx +++ b/src/lib/utils/highlighter.tsx @@ -103,11 +103,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("}", ""); diff --git a/static/style.css b/static/style.css index 223b2f8f0..54404907d 100644 --- a/static/style.css +++ b/static/style.css @@ -132,6 +132,7 @@ body { --color-toolbar-text: var(--light-color-toolbar-text); --icon-filter: var(--light-icon-filter); --external-icon: var(--light-external-icon); + --color-scheme: light; } :root[data-theme="dark"] { @@ -156,6 +157,7 @@ body { --color-toolbar-text: var(--dark-color-toolbar-text); --icon-filter: var(--dark-icon-filter); --external-icon: var(--dark-external-icon); + --color-scheme: dark; } h1 { From 801940d18b8858a2b6dbc7d3c1cd8d7b4179dc10 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 29 Sep 2021 14:36:20 -0600 Subject: [PATCH 003/151] Initial attempt at a comment lexer --- .vscode/launch.json | 16 ++ src/lib/converter/comments.ts | 315 +++++++++++++++++++++++++++++ src/test/comments.test.ts | 366 ++++++++++++++++++++++++++++++++++ 3 files changed, 697 insertions(+) create mode 100644 src/lib/converter/comments.ts create mode 100644 src/test/comments.test.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index e781de55e..8c0795d8b 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", + "Lexer" + ], + "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/src/lib/converter/comments.ts b/src/lib/converter/comments.ts new file mode 100644 index 000000000..93fa4e175 --- /dev/null +++ b/src/lib/converter/comments.ts @@ -0,0 +1,315 @@ +export enum TokenSyntaxKind { + Text, + NewLine, + OpenBrace, + CloseBrace, + Tag, + Code, +} + +export interface Token { + kind: TokenSyntaxKind; + text: string; +} + +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; + } +} + +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; + + 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 "{": + yield makeToken(TokenSyntaxKind.OpenBrace, 1); + break; + + case "}": + yield makeToken(TokenSyntaxKind.CloseBrace, 1); + 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! + 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 = 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) { + 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++; + } + + // If we didn't need to make a copy, don't make one now. + if (textParts.length === 0) { + yield makeToken(TokenSyntaxKind.Text, lookahead - pos); + } else { + textParts.push(file.substring(lookaheadStart, lookahead)); + pos = lookahead; + // This piece of text had line continuations or escaped text, need our own string. + yield { + kind: TokenSyntaxKind.Text, + text: textParts.join(""), + }; + } + break; + } + } + } + + function makeToken(kind: TokenSyntaxKind, size: number): Token { + const start = pos; + pos += size; + + return { + kind, + text: file.substr(start, size), + }; + } + + 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) { + for (let i = 0; i < n; i++) { + if (pos + i === n || file[pos + i] !== "`") { + return false; + } + } + + return pos + n === end || file[pos + n] !== "`"; + } +} + +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++; + } + } + + while (pos < end && /\s/.test(file[pos])) { + pos++; + } + + const commentHasStars = pos < end && file[pos] === "*"; + + return [commentHasStars, indent]; +} diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts new file mode 100644 index 000000000..8cd89b5a2 --- /dev/null +++ b/src/test/comments.test.ts @@ -0,0 +1,366 @@ +import { deepStrictEqual as equal } from "assert"; + +import { + lexBlockComment, + Token, + TokenSyntaxKind, +} from "../lib/converter/comments"; + +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) => Math.min(indent, line.search(/\S/)), + Infinity + ); + + return lines.map((line) => line.substr(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 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} + */`) + ); + + 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: "}" }, + ]); + }); +}); From fdb06b25c9d4e7e8116ee08db27fc65883e94eb4 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 1 Oct 2021 21:14:26 -0600 Subject: [PATCH 004/151] Complete lexer test coverage --- src/lib/converter/comments.ts | 12 +++--------- src/test/comments.test.ts | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/lib/converter/comments.ts b/src/lib/converter/comments.ts index 93fa4e175..eae9f768b 100644 --- a/src/lib/converter/comments.ts +++ b/src/lib/converter/comments.ts @@ -272,13 +272,11 @@ function* lexBlockComment2( } function lookaheadExactlyNTicks(pos: number, n: number) { - for (let i = 0; i < n; i++) { - if (pos + i === n || file[pos + i] !== "`") { - return false; - } + if (pos + n >= end) { + return false; } - return pos + n === end || file[pos + n] !== "`"; + return file.startsWith("`".repeat(n), pos) && file[pos + n] !== "`"; } } @@ -305,10 +303,6 @@ function discoverIndent( } } - while (pos < end && /\s/.test(file[pos])) { - pos++; - } - const commentHasStars = pos < end && file[pos] === "*"; return [commentHasStars, indent]; diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index 8cd89b5a2..8c2d24b2e 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -347,6 +347,8 @@ describe("Block Comment Lexer", () => { * * @remarks * Detailed text here with a {@link Inline | inline link} + * + * @alpha @beta */`) ); @@ -361,6 +363,30 @@ describe("Block Comment Lexer", () => { { 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 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 allow escaping newlines"); }); From a8b7b689d33980ef82c300c518a8ec758fb2e9b9 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 2 Oct 2021 12:13:01 -0600 Subject: [PATCH 005/151] Correct misleading statement in readme --- README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 5ee3f4d4b..6d05becd8 100644 --- a/README.md +++ b/README.md @@ -79,7 +79,8 @@ 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. @@ -123,9 +124,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. From 272187155c3ab5447f72bd9f53b34540d5d66be5 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 2 Oct 2021 15:13:56 -0600 Subject: [PATCH 006/151] Support escaping slashes in comments --- src/lib/converter/comments.ts | 12 +++++++++++- src/test/comments.test.ts | 27 +++++++++++++++++++++++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/lib/converter/comments.ts b/src/lib/converter/comments.ts index eae9f768b..2efd5d957 100644 --- a/src/lib/converter/comments.ts +++ b/src/lib/converter/comments.ts @@ -131,6 +131,16 @@ function* lexBlockComment2( 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 && @@ -216,7 +226,7 @@ function* lexBlockComment2( if ( file[lookahead] === "\\" && lookahead + 1 < end && - "{}@`".includes(file[lookahead + 1]) + "{}@/`".includes(file[lookahead + 1]) ) { textParts.push( file.substring(lookaheadStart, lookahead), diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index 8c2d24b2e..e83dd9bcc 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -172,6 +172,31 @@ describe("Block Comment Lexer", () => { 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 */"); @@ -387,6 +412,4 @@ describe("Block Comment Lexer", () => { { kind: TokenSyntaxKind.Code, text: "```\nText" }, ]); }); - - it("Should allow escaping newlines"); }); From 47780e5099ab2d789d66c7dccc54d7b39a786540 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 2 Oct 2021 15:36:53 -0600 Subject: [PATCH 007/151] Rework comment parser to get rid of comment splitting Resolves #494. --- src/lib/converter/factories/comment.ts | 14 +- src/lib/converter/plugins/CommentPlugin.ts | 3 +- src/lib/models/comments/comment.ts | 22 +-- .../themes/default/partials/comment.tsx | 9 +- src/lib/serialization/schema.ts | 2 +- .../serializers/comments/comment.ts | 7 +- src/test/behaviorTests.ts | 6 +- src/test/converter/alias/specs.json | 8 +- .../class/specs-with-lump-categories.json | 163 +++++++++--------- src/test/converter/class/specs.json | 163 +++++++++--------- src/test/converter/comment/specs.json | 15 +- src/test/converter/enum/specs.json | 24 +-- src/test/converter/enum/specs.nodoc.json | 24 +-- src/test/converter/exports/specs.json | 14 +- src/test/converter/function/function.ts | 16 +- src/test/converter/function/specs.json | 110 ++++++------ .../converter/inherit-param-doc/specs.json | 16 +- src/test/converter/inheritance/specs.json | 38 ++-- src/test/converter/interface/specs.json | 18 +- src/test/converter/js/specs.json | 18 +- src/test/converter/mixin/specs.json | 22 +-- src/test/converter/types/specs.json | 16 +- src/test/converter/variables/specs.json | 16 +- src/test/converter/variables/specs.nodoc.json | 16 +- src/test/issueTests.ts | 12 +- .../renderer/testProject/src/functions.ts | 8 +- .../renderer/testProject/src/single-export.ts | 4 +- 27 files changed, 373 insertions(+), 411 deletions(-) diff --git a/src/lib/converter/factories/comment.ts b/src/lib/converter/factories/comment.ts index e832ad55f..b65102ff1 100644 --- a/src/lib/converter/factories/comment.ts +++ b/src/lib/converter/factories/comment.ts @@ -190,7 +190,6 @@ export function parseComment( comment: Comment = new Comment() ): Comment { let currentTag: CommentTag; - let shortText = 0; function consumeTypeData(line: string): string { line = line.replace(/^\{(?!@)[^}]*\}+/, ""); @@ -201,18 +200,8 @@ export function parseComment( 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; - } + comment.summary += (comment.summary === "" ? "" : "\n") + line; } } @@ -279,5 +268,6 @@ export function parseComment( text = text.replace(/\*+\/\s*$/, ""); text.split(/\r\n?|\n/).forEach(readLine); + comment.summary = comment.summary.trim(); return comment; } diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 5652f9fc8..5206dd76d 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -343,8 +343,7 @@ export class CommentPlugin extends ConverterComponent { childComment = signature.comment = new Comment(); } - childComment.shortText ||= comment.shortText; - childComment.text ||= comment.text; + childComment.summary ||= comment.summary; childComment.returns ||= comment.returns; childComment.tags ||= [...comment.tags]; } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 01d39b4c5..02c52efb1 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -11,15 +11,9 @@ const COPIED_TAGS = ["remarks"]; */ export class Comment { /** - * The abstract of the comment. TypeDoc interprets the first paragraph of a comment - * as the abstract. + * The content of the comment which is not associated with a block tag. */ - shortText: string; - - /** - * The full body text of the comment. Excludes the {@link shortText}. - */ - text: string; + summary: string; /** * The text of the ```@returns``` tag if present. @@ -34,9 +28,8 @@ export class Comment { /** * Creates a new Comment instance. */ - constructor(shortText?: string, text?: string) { - this.shortText = shortText || ""; - this.text = text || ""; + constructor(summary?: string) { + this.summary = summary || ""; } /** @@ -45,7 +38,7 @@ 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 || this.tags.length > 0; } /** @@ -77,7 +70,7 @@ export class Comment { } /** - * Removes all tags with the given tag name from teh comment. + * Removes all tags with the given tag name from the comment. * @param tagName */ removeTags(tagName: string) { @@ -93,8 +86,7 @@ export class Comment { * @param comment - Source comment to copy from */ copyFrom(comment: Comment) { - this.shortText = comment.shortText; - this.text = comment.text; + this.summary = comment.summary; this.returns = comment.returns; const overrideTags: CommentTag[] = comment.tags .filter((tag) => COPIED_TAGS.includes(tag.tagName)) diff --git a/src/lib/output/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 7cbdf80f6..feb4da74a 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -7,14 +7,9 @@ export function comment({ markdown }: DefaultThemeRenderContext, props: Reflecti return (
- {!!props.comment.shortText && ( -
- -
- )} - {!!props.comment.text && ( + {!!props.comment.summary && (
- +
)} {props.comment.tags?.length > 0 && ( diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index a8753ce94..9e2b99442 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -337,7 +337,7 @@ export interface ReflectionFlags extends Partial>> {} export interface Comment - extends Partial> {} + extends Partial> {} export interface CommentTag extends S { tag: M.CommentTag["tagName"]; diff --git a/src/lib/serialization/serializers/comments/comment.ts b/src/lib/serialization/serializers/comments/comment.ts index 315a3cc22..23660a341 100644 --- a/src/lib/serialization/serializers/comments/comment.ts +++ b/src/lib/serialization/serializers/comments/comment.ts @@ -18,11 +18,8 @@ export class CommentSerializer extends SerializerComponent { } toObject(comment: Comment, obj: Partial = {}): JSONComment { - if (comment.shortText) { - obj.shortText = comment.shortText; - } - if (comment.text) { - obj.text = comment.text; + if (comment.summary) { + obj.summary = comment.summary; } if (comment.returns) { obj.returns = comment.returns; diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index f4e09c827..9383f759a 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -39,13 +39,13 @@ export const behaviorTests: Record< const foo = query(project, "foo"); equal(foo.signatures?.length, 2); - equal(foo.signatures[0].comment?.shortText, "Implementation comment"); + equal(foo.signatures[0].comment?.summary, "Implementation comment"); equal(foo.signatures[0].comment?.tags, []); - equal(foo.signatures[1].comment?.shortText, "Overrides summary"); + equal(foo.signatures[1].comment?.summary, "Overrides summary"); equal(foo.signatures[1].comment?.tags, []); equal( - foo.signatures[1].parameters?.[0].comment?.shortText.trim(), + foo.signatures[1].parameters?.[0].comment?.summary.trim(), "docs for x" ); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 5b3daf96b..efae8f7b0 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -12,7 +12,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Conditional types from TS2.8" + "summary": "Conditional types from TS2.8" }, "typeParameter": [ { @@ -51,7 +51,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Extracts the type of a promise." + "summary": "Extracts the type of a promise." }, "typeParameter": [ { @@ -121,7 +121,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A type that describes a compare function, e.g. for array.sort()." + "summary": "A type that describes a compare function, e.g. for array.sort()." }, "parameters": [ { @@ -165,7 +165,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "A type for IDs." + "summary": "A type for IDs." }, "type": { "type": "union", diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 44da1cbf0..124f09bff 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -20,7 +20,7 @@ "isPrivate": true }, "comment": { - "shortText": "A class that is documented as being private." + "summary": "A class that is documented as being private." }, "children": [ { @@ -32,7 +32,7 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": "A variable that is made private via comment." }, "type": { "type": "intrinsic", @@ -48,7 +48,7 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": "A variable that is made protected via comment." }, "type": { "type": "intrinsic", @@ -96,7 +96,7 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": "A function that is made private via comment." }, "type": { "type": "intrinsic", @@ -123,7 +123,7 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": "A function that is made protected via comment." }, "type": { "type": "intrinsic", @@ -191,7 +191,7 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": "A variable that is made private via comment." }, "type": { "type": "literal", @@ -208,7 +208,7 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": "A variable that is made protected via comment." }, "type": { "type": "literal", @@ -234,7 +234,7 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": "A function that is made private via comment." }, "type": { "type": "intrinsic", @@ -261,7 +261,7 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": "A function that is made protected via comment." }, "type": { "type": "intrinsic", @@ -325,7 +325,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMergedMethod short text." + "summary": "staticMergedMethod short text." }, "type": { "type": "intrinsic", @@ -735,8 +735,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", + "summary": "TestClass comment short text.\n\nTestClass comment text.", "tags": [ { "tag": "see", @@ -759,7 +758,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "type": { "type": "reference", @@ -778,7 +777,7 @@ "isPrivate": true }, "comment": { - "shortText": "privateProperty short text." + "summary": "privateProperty short text." }, "type": { "type": "array", @@ -797,7 +796,7 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": "publicProperty short text." }, "type": { "type": "intrinsic", @@ -813,7 +812,7 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": "staticProperty short text." }, "type": { "type": "reference", @@ -835,7 +834,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": "arrow method" }, "type": { "type": "intrinsic", @@ -860,7 +859,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "privateMethod short text." + "summary": "privateMethod short text." }, "type": { "type": "intrinsic", @@ -885,7 +884,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": "protectedMethod short text." }, "type": { "type": "intrinsic", @@ -910,7 +909,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": "publicMethod short text." }, "type": { "type": "intrinsic", @@ -935,7 +934,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": "staticMethod short text." }, "type": { "type": "intrinsic", @@ -1031,7 +1030,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "parameters": [ { @@ -1041,7 +1040,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor param" + "summary": "Constructor param" }, "type": { "type": "intrinsic", @@ -1055,7 +1054,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Private string property" + "summary": "Private string property" }, "type": { "type": "intrinsic", @@ -1069,7 +1068,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public number property" + "summary": "Public number property" }, "type": { "type": "intrinsic", @@ -1083,7 +1082,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public implicit any property\n" + "summary": "Public implicit any property\n" }, "type": { "type": "intrinsic", @@ -1144,7 +1143,7 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": "publicProperty short text." }, "type": { "type": "intrinsic", @@ -1165,7 +1164,7 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": "staticProperty short text." }, "type": { "type": "reference", @@ -1192,7 +1191,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": "arrow method" }, "type": { "type": "intrinsic", @@ -1225,7 +1224,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "mergedMethod short text." + "summary": "mergedMethod short text." }, "type": { "type": "intrinsic", @@ -1250,7 +1249,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": "protectedMethod short text." }, "type": { "type": "intrinsic", @@ -1285,7 +1284,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": "publicMethod short text." }, "type": { "type": "intrinsic", @@ -1320,7 +1319,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": "staticMethod short text." }, "type": { "type": "intrinsic", @@ -1415,7 +1414,7 @@ "isPrivate": true }, "comment": { - "shortText": "Docs" + "summary": "Docs" }, "type": { "type": "intrinsic", @@ -1519,7 +1518,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with constructor properties." + "summary": "A class with constructor properties." }, "children": [ { @@ -1544,7 +1543,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": "X component of the Vector" }, "type": { "type": "intrinsic", @@ -1558,7 +1557,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": "Y component of the Vector" }, "type": { "type": "intrinsic", @@ -1572,7 +1571,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": "Vector name\n" }, "type": { "type": "intrinsic", @@ -1661,7 +1660,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with inherited and overwritten constructor properties." + "summary": "A class with inherited and overwritten constructor properties." }, "children": [ { @@ -1686,7 +1685,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": "X component of the Vector" }, "type": { "type": "intrinsic", @@ -1700,7 +1699,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": "Y component of the Vector" }, "type": { "type": "intrinsic", @@ -1714,7 +1713,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Z component of the Vector" + "summary": "Z component of the Vector" }, "type": { "type": "intrinsic", @@ -1728,7 +1727,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": "Vector name\n" }, "type": { "type": "intrinsic", @@ -1875,7 +1874,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A decorated class." + "summary": "A decorated class." }, "decorators": [ { @@ -1947,7 +1946,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorated method." + "summary": "A decorated method." }, "type": { "type": "intrinsic", @@ -1995,7 +1994,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with no options." + "summary": "A decorator with no options." }, "parameters": [ { @@ -2075,7 +2074,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator consuming an options object." + "summary": "A decorator consuming an options object." }, "parameters": [ { @@ -2085,7 +2084,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The options object of this decorator." + "summary": "The options object of this decorator." }, "type": { "type": "reflection", @@ -2103,7 +2102,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A property on the options object of this decorator.\n" + "summary": "A property on the options object of this decorator.\n" }, "type": { "type": "intrinsic", @@ -2152,7 +2151,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with a parameter." + "summary": "A decorator with a parameter." }, "parameters": [ { @@ -2162,7 +2161,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The parameter of this decorator.\n" + "summary": "The parameter of this decorator.\n" }, "type": { "type": "intrinsic", @@ -2241,7 +2240,7 @@ "isStatic": true }, "comment": { - "shortText": "This is an event documentation." + "summary": "This is an event documentation." }, "type": { "type": "intrinsic", @@ -2292,7 +2291,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates some information for background http transfers.", + "summary": "Encapsulates some information for background http transfers.", "tags": [ { "tag": "see", @@ -2315,7 +2314,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for a general event by name." + "summary": "Subscribe for a general event by name." }, "parameters": [ { @@ -2325,7 +2324,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "intrinsic", @@ -2339,7 +2338,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The handler called when the event occurs.\n" + "summary": "The handler called when the event occurs.\n" }, "type": { "type": "reflection", @@ -2391,7 +2390,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for error notifications." + "summary": "Subscribe for error notifications." }, "parameters": [ { @@ -2401,7 +2400,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2415,7 +2414,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive the error details\n" + "summary": "A handler that will receive the error details\n" }, "type": { "type": "reflection", @@ -2467,7 +2466,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for progress notifications." + "summary": "Subscribe for progress notifications." }, "parameters": [ { @@ -2477,7 +2476,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2491,7 +2490,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive a progress event with the current and expected total bytes\n" + "summary": "A handler that will receive a progress event with the current and expected total bytes\n" }, "type": { "type": "reflection", @@ -2543,7 +2542,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for success notification." + "summary": "Subscribe for success notification." }, "parameters": [ { @@ -2553,7 +2552,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2567,7 +2566,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A function that will be called with general event data upon successful completion\n" + "summary": "A function that will be called with general event data upon successful completion\n" }, "type": { "type": "reflection", @@ -2650,7 +2649,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "GenericClass short text." + "summary": "GenericClass short text." }, "children": [ { @@ -2667,7 +2666,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "typeParameter": [ { @@ -2686,7 +2685,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": "Constructor parameter.\n" }, "type": { "type": "reference", @@ -2719,7 +2718,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": "Generic property." }, "type": { "type": "reference", @@ -2736,7 +2735,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": "Generic property array." }, "type": { "type": "array", @@ -2761,7 +2760,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", + "summary": "getValue short text.", "returns": "Return value comment.\n" }, "type": { @@ -2805,7 +2804,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic parameter.\n" + "summary": "Generic parameter.\n" } } ], @@ -2824,7 +2823,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "NonGenericClass short text." + "summary": "NonGenericClass short text." }, "children": [ { @@ -2841,7 +2840,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "parameters": [ { @@ -2851,7 +2850,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": "Constructor parameter.\n" }, "type": { "type": "intrinsic", @@ -2886,7 +2885,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": "Generic property." }, "type": { "type": "intrinsic", @@ -2907,7 +2906,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": "Generic property array." }, "type": { "type": "array", @@ -2936,7 +2935,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", + "summary": "getValue short text.", "returns": "Return value comment.\n" }, "type": { @@ -3206,8 +3205,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "ChainClass comment short text.", - "text": "ChainClass comment text.\n" + "summary": "ChainClass comment short text.\n\nChainClass comment text." }, "children": [ { @@ -3247,7 +3245,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Chain method that returns this." + "summary": "Chain method that returns this." }, "type": { "type": "reference", @@ -3401,8 +3399,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", + "summary": "TestClass comment short text.\n\nTestClass comment text.", "tags": [ { "tag": "see", diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 73e1c1f95..eddde2059 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -20,7 +20,7 @@ "isPrivate": true }, "comment": { - "shortText": "A class that is documented as being private." + "summary": "A class that is documented as being private." }, "children": [ { @@ -32,7 +32,7 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": "A variable that is made private via comment." }, "type": { "type": "intrinsic", @@ -48,7 +48,7 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": "A variable that is made protected via comment." }, "type": { "type": "intrinsic", @@ -96,7 +96,7 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": "A function that is made private via comment." }, "type": { "type": "intrinsic", @@ -123,7 +123,7 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": "A function that is made protected via comment." }, "type": { "type": "intrinsic", @@ -191,7 +191,7 @@ "isPrivate": true }, "comment": { - "shortText": "A variable that is made private via comment." + "summary": "A variable that is made private via comment." }, "type": { "type": "literal", @@ -208,7 +208,7 @@ "isProtected": true }, "comment": { - "shortText": "A variable that is made protected via comment." + "summary": "A variable that is made protected via comment." }, "type": { "type": "literal", @@ -234,7 +234,7 @@ "isPrivate": true }, "comment": { - "shortText": "A function that is made private via comment." + "summary": "A function that is made private via comment." }, "type": { "type": "intrinsic", @@ -261,7 +261,7 @@ "isProtected": true }, "comment": { - "shortText": "A function that is made protected via comment." + "summary": "A function that is made protected via comment." }, "type": { "type": "intrinsic", @@ -325,7 +325,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMergedMethod short text." + "summary": "staticMergedMethod short text." }, "type": { "type": "intrinsic", @@ -735,8 +735,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", + "summary": "TestClass comment short text.\n\nTestClass comment text.", "tags": [ { "tag": "see", @@ -759,7 +758,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "type": { "type": "reference", @@ -778,7 +777,7 @@ "isPrivate": true }, "comment": { - "shortText": "privateProperty short text." + "summary": "privateProperty short text." }, "type": { "type": "array", @@ -797,7 +796,7 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": "publicProperty short text." }, "type": { "type": "intrinsic", @@ -813,7 +812,7 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": "staticProperty short text." }, "type": { "type": "reference", @@ -835,7 +834,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": "arrow method" }, "type": { "type": "intrinsic", @@ -860,7 +859,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "privateMethod short text." + "summary": "privateMethod short text." }, "type": { "type": "intrinsic", @@ -885,7 +884,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": "protectedMethod short text." }, "type": { "type": "intrinsic", @@ -910,7 +909,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": "publicMethod short text." }, "type": { "type": "intrinsic", @@ -935,7 +934,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": "staticMethod short text." }, "type": { "type": "intrinsic", @@ -1027,7 +1026,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "parameters": [ { @@ -1037,7 +1036,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor param" + "summary": "Constructor param" }, "type": { "type": "intrinsic", @@ -1051,7 +1050,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Private string property" + "summary": "Private string property" }, "type": { "type": "intrinsic", @@ -1065,7 +1064,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public number property" + "summary": "Public number property" }, "type": { "type": "intrinsic", @@ -1079,7 +1078,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Public implicit any property\n" + "summary": "Public implicit any property\n" }, "type": { "type": "intrinsic", @@ -1140,7 +1139,7 @@ "isPublic": true }, "comment": { - "shortText": "publicProperty short text." + "summary": "publicProperty short text." }, "type": { "type": "intrinsic", @@ -1161,7 +1160,7 @@ "isStatic": true }, "comment": { - "shortText": "staticProperty short text." + "summary": "staticProperty short text." }, "type": { "type": "reference", @@ -1188,7 +1187,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "arrow method" + "summary": "arrow method" }, "type": { "type": "intrinsic", @@ -1221,7 +1220,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "mergedMethod short text." + "summary": "mergedMethod short text." }, "type": { "type": "intrinsic", @@ -1246,7 +1245,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "protectedMethod short text." + "summary": "protectedMethod short text." }, "type": { "type": "intrinsic", @@ -1281,7 +1280,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "publicMethod short text." + "summary": "publicMethod short text." }, "type": { "type": "intrinsic", @@ -1316,7 +1315,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "staticMethod short text." + "summary": "staticMethod short text." }, "type": { "type": "intrinsic", @@ -1411,7 +1410,7 @@ "isPrivate": true }, "comment": { - "shortText": "Docs" + "summary": "Docs" }, "type": { "type": "intrinsic", @@ -1515,7 +1514,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with constructor properties." + "summary": "A class with constructor properties." }, "children": [ { @@ -1540,7 +1539,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": "X component of the Vector" }, "type": { "type": "intrinsic", @@ -1554,7 +1553,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": "Y component of the Vector" }, "type": { "type": "intrinsic", @@ -1568,7 +1567,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": "Vector name\n" }, "type": { "type": "intrinsic", @@ -1657,7 +1656,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class with inherited and overwritten constructor properties." + "summary": "A class with inherited and overwritten constructor properties." }, "children": [ { @@ -1682,7 +1681,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "X component of the Vector" + "summary": "X component of the Vector" }, "type": { "type": "intrinsic", @@ -1696,7 +1695,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Y component of the Vector" + "summary": "Y component of the Vector" }, "type": { "type": "intrinsic", @@ -1710,7 +1709,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Z component of the Vector" + "summary": "Z component of the Vector" }, "type": { "type": "intrinsic", @@ -1724,7 +1723,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Vector name\n" + "summary": "Vector name\n" }, "type": { "type": "intrinsic", @@ -1871,7 +1870,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A decorated class." + "summary": "A decorated class." }, "decorators": [ { @@ -1943,7 +1942,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorated method." + "summary": "A decorated method." }, "type": { "type": "intrinsic", @@ -1991,7 +1990,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with no options." + "summary": "A decorator with no options." }, "parameters": [ { @@ -2071,7 +2070,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator consuming an options object." + "summary": "A decorator consuming an options object." }, "parameters": [ { @@ -2081,7 +2080,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The options object of this decorator." + "summary": "The options object of this decorator." }, "type": { "type": "reflection", @@ -2099,7 +2098,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A property on the options object of this decorator.\n" + "summary": "A property on the options object of this decorator.\n" }, "type": { "type": "intrinsic", @@ -2148,7 +2147,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A decorator with a parameter." + "summary": "A decorator with a parameter." }, "parameters": [ { @@ -2158,7 +2157,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The parameter of this decorator.\n" + "summary": "The parameter of this decorator.\n" }, "type": { "type": "intrinsic", @@ -2237,7 +2236,7 @@ "isStatic": true }, "comment": { - "shortText": "This is an event documentation." + "summary": "This is an event documentation." }, "type": { "type": "intrinsic", @@ -2288,7 +2287,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates some information for background http transfers.", + "summary": "Encapsulates some information for background http transfers.", "tags": [ { "tag": "see", @@ -2311,7 +2310,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for a general event by name." + "summary": "Subscribe for a general event by name." }, "parameters": [ { @@ -2321,7 +2320,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "intrinsic", @@ -2335,7 +2334,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The handler called when the event occurs.\n" + "summary": "The handler called when the event occurs.\n" }, "type": { "type": "reflection", @@ -2387,7 +2386,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for error notifications." + "summary": "Subscribe for error notifications." }, "parameters": [ { @@ -2397,7 +2396,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2411,7 +2410,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive the error details\n" + "summary": "A handler that will receive the error details\n" }, "type": { "type": "reflection", @@ -2463,7 +2462,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for progress notifications." + "summary": "Subscribe for progress notifications." }, "parameters": [ { @@ -2473,7 +2472,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2487,7 +2486,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A handler that will receive a progress event with the current and expected total bytes\n" + "summary": "A handler that will receive a progress event with the current and expected total bytes\n" }, "type": { "type": "reflection", @@ -2539,7 +2538,7 @@ "kindString": "Event", "flags": {}, "comment": { - "shortText": "Subscribe for success notification." + "summary": "Subscribe for success notification." }, "parameters": [ { @@ -2549,7 +2548,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name of the event to subscribe for." + "summary": "The name of the event to subscribe for." }, "type": { "type": "literal", @@ -2563,7 +2562,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A function that will be called with general event data upon successful completion\n" + "summary": "A function that will be called with general event data upon successful completion\n" }, "type": { "type": "reflection", @@ -2646,7 +2645,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "GenericClass short text." + "summary": "GenericClass short text." }, "children": [ { @@ -2663,7 +2662,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "typeParameter": [ { @@ -2682,7 +2681,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": "Constructor parameter.\n" }, "type": { "type": "reference", @@ -2715,7 +2714,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": "Generic property." }, "type": { "type": "reference", @@ -2732,7 +2731,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": "Generic property array." }, "type": { "type": "array", @@ -2757,7 +2756,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", + "summary": "getValue short text.", "returns": "Return value comment.\n" }, "type": { @@ -2801,7 +2800,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic parameter.\n" + "summary": "Generic parameter.\n" } } ], @@ -2820,7 +2819,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "NonGenericClass short text." + "summary": "NonGenericClass short text." }, "children": [ { @@ -2837,7 +2836,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Constructor short text." + "summary": "Constructor short text." }, "parameters": [ { @@ -2847,7 +2846,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Constructor parameter.\n" + "summary": "Constructor parameter.\n" }, "type": { "type": "intrinsic", @@ -2882,7 +2881,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property." + "summary": "Generic property." }, "type": { "type": "intrinsic", @@ -2903,7 +2902,7 @@ "isProtected": true }, "comment": { - "shortText": "Generic property array." + "summary": "Generic property array." }, "type": { "type": "array", @@ -2932,7 +2931,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "getValue short text.", + "summary": "getValue short text.", "returns": "Return value comment.\n" }, "type": { @@ -3202,8 +3201,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "ChainClass comment short text.", - "text": "ChainClass comment text.\n" + "summary": "ChainClass comment short text.\n\nChainClass comment text." }, "children": [ { @@ -3243,7 +3241,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Chain method that returns this." + "summary": "Chain method that returns this." }, "type": { "type": "reference", @@ -3397,8 +3395,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "TestClass comment short text.", - "text": "TestClass comment text.\n", + "summary": "TestClass comment short text.\n\nTestClass comment text.", "tags": [ { "tag": "see", diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index 81d9e0f2e..525bde90d 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -11,7 +11,7 @@ "kindString": "Module", "flags": {}, "comment": { - "shortText": "This is a module doc comment with legacy behavior." + "summary": "This is a module doc comment with legacy behavior." }, "children": [ { @@ -21,8 +21,7 @@ "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```", + "summary": "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```\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": [ { "tag": "deprecated", @@ -63,7 +62,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "The main prop" + "summary": "The main prop" }, "type": { "type": "intrinsic", @@ -84,7 +83,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Mixed hidden 2" + "summary": "Mixed hidden 2" }, "parameters": [ { @@ -160,7 +159,7 @@ "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": "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." }, "children": [ { @@ -225,7 +224,7 @@ "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": "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." }, "children": [ { @@ -290,7 +289,7 @@ "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": "This is a comment containing a multiline code block\n```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" }, "children": [ { diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index f391d99bf..695a0aeff 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -12,7 +12,7 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is a module extending an enumeration." + "summary": "This is a module extending an enumeration." }, "children": [ { @@ -22,7 +22,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This is a variable appended to an enumeration." + "summary": "This is a variable appended to an enumeration." }, "type": { "type": "intrinsic", @@ -43,7 +43,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function appended to an enumeration." + "summary": "This is a function appended to an enumeration." }, "type": { "type": "intrinsic", @@ -79,7 +79,7 @@ "isConst": true }, "comment": { - "shortText": "This is a const enum." + "summary": "This is a const enum." }, "children": [ { @@ -117,7 +117,7 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is an enumeration extended by a module." + "summary": "This is an enumeration extended by a module." }, "children": [ { @@ -127,7 +127,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": "This is the first enum member." }, "defaultValue": "1" }, @@ -138,7 +138,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": "This is the second enum member." }, "defaultValue": "2" }, @@ -149,7 +149,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": "This is the third enum member." }, "defaultValue": "4" } @@ -173,7 +173,7 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is a simple enumeration." + "summary": "This is a simple enumeration." }, "children": [ { @@ -183,7 +183,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": "This is the first enum member." }, "defaultValue": "1" }, @@ -194,7 +194,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": "This is the second enum member." }, "defaultValue": "2" }, @@ -205,7 +205,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": "This is the third enum member." }, "defaultValue": "4" } diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index f391d99bf..695a0aeff 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -12,7 +12,7 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is a module extending an enumeration." + "summary": "This is a module extending an enumeration." }, "children": [ { @@ -22,7 +22,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This is a variable appended to an enumeration." + "summary": "This is a variable appended to an enumeration." }, "type": { "type": "intrinsic", @@ -43,7 +43,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function appended to an enumeration." + "summary": "This is a function appended to an enumeration." }, "type": { "type": "intrinsic", @@ -79,7 +79,7 @@ "isConst": true }, "comment": { - "shortText": "This is a const enum." + "summary": "This is a const enum." }, "children": [ { @@ -117,7 +117,7 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is an enumeration extended by a module." + "summary": "This is an enumeration extended by a module." }, "children": [ { @@ -127,7 +127,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": "This is the first enum member." }, "defaultValue": "1" }, @@ -138,7 +138,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": "This is the second enum member." }, "defaultValue": "2" }, @@ -149,7 +149,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": "This is the third enum member." }, "defaultValue": "4" } @@ -173,7 +173,7 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "shortText": "This is a simple enumeration." + "summary": "This is a simple enumeration." }, "children": [ { @@ -183,7 +183,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the first enum member." + "summary": "This is the first enum member." }, "defaultValue": "1" }, @@ -194,7 +194,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the second enum member." + "summary": "This is the second enum member." }, "defaultValue": "2" }, @@ -205,7 +205,7 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "shortText": "This is the third enum member." + "summary": "This is the third enum member." }, "defaultValue": "4" } diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 16d99d2d4..411d5362a 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -34,7 +34,7 @@ "kindString": "Reference", "flags": {}, "comment": { - "shortText": "This is a comment for Mod that overwrites the one specified in \"mod\"" + "summary": "This is a comment for Mod that overwrites the one specified in \"mod\"" }, "target": 29 }, @@ -69,7 +69,7 @@ "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export of a local under a different name." + "summary": "An export of a local under a different name." }, "target": 33 }, @@ -462,7 +462,7 @@ "kindString": "Module", "flags": {}, "comment": { - "shortText": "Doc comment for Mod" + "summary": "Doc comment for Mod" }, "children": [ { @@ -480,7 +480,7 @@ "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export of a local under a different name." + "summary": "An export of a local under a different name." }, "target": 32 }, @@ -491,7 +491,7 @@ "kindString": "Reference", "flags": {}, "comment": { - "shortText": "An export with a module specifier that comes from this file." + "summary": "An export with a module specifier that comes from this file." }, "target": 32 }, @@ -513,7 +513,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A simple named export that will be exported from export.ts" + "summary": "A simple named export that will be exported from export.ts" }, "type": { "type": "literal", @@ -535,7 +535,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Will not be re-exported from export.ts using export * from..." + "summary": "Will not be re-exported from export.ts using export * from..." }, "type": { "type": "intrinsic", 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 50f0aa6b2..3ce5a27bb 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -56,7 +56,7 @@ "kindString": "Namespace", "flags": {}, "comment": { - "shortText": "This is the module extending the function moduleFunction()." + "summary": "This is the module extending the function moduleFunction()." }, "children": [ { @@ -66,7 +66,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "This variable is appended to a function." + "summary": "This variable is appended to a function." }, "type": { "type": "intrinsic", @@ -87,7 +87,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This function is appended to another function." + "summary": "This function is appended to another function." }, "type": { "type": "intrinsic", @@ -110,7 +110,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This function is appended to another function." + "summary": "This function is appended to another function." }, "type": { "type": "intrinsic", @@ -329,8 +329,7 @@ "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" + "summary": "Returns true if fn returns true for every item in the iterator\n\nReturns true if the iterator is empty" }, "typeParameter": [ { @@ -417,8 +416,7 @@ "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" + "summary": "Returns true if fn returns true for every item in the iterator\n\nReturns true if the iterator is empty" }, "typeParameter": [ { @@ -535,7 +533,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Asserts that an argument is not null." + "summary": "Asserts that an argument is not null." }, "typeParameter": [ { @@ -554,7 +552,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n" + "summary": "\n" }, "type": { "type": "union", @@ -603,7 +601,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is an assertion function." + "summary": "This is an assertion function." }, "parameters": [ { @@ -613,7 +611,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The condition that is asserted to be true when this function returns.\n" + "summary": "The condition that is asserted to be true when this function returns.\n" }, "type": { "type": "intrinsic", @@ -685,7 +683,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Assertion function with a type." + "summary": "Assertion function with a type." }, "parameters": [ { @@ -695,7 +693,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n" + "summary": "\n" }, "type": { "type": "intrinsic", @@ -729,7 +727,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a simple exported function." + "summary": "This is a simple exported function." }, "type": { "type": "intrinsic", @@ -752,7 +750,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a destructured parameter.", + "summary": "This is a function with a destructured parameter.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -763,7 +761,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is the parameter that is destructured." + "summary": "This is the parameter that is destructured." }, "originalName": "__namedParameters", "type": { @@ -782,7 +780,7 @@ "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": "\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" }, "type": { "type": "reference", @@ -796,7 +794,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" + "summary": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" }, "type": { "type": "intrinsic", @@ -810,7 +808,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "This is a string parameter." + "summary": "This is a string parameter." }, "type": { "type": "intrinsic", @@ -854,7 +852,7 @@ "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.", + "summary": "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" }, "parameters": [ @@ -943,7 +941,7 @@ "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.", + "summary": "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" }, "parameters": [ @@ -1043,7 +1041,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a parameter that has a default value.", + "summary": "This is a function with a parameter that has a default value.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1054,7 +1052,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default string value." + "summary": "A parameter with a default string value." }, "type": { "type": "intrinsic", @@ -1069,7 +1067,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default numeric value." + "summary": "A parameter with a default numeric value." }, "type": { "type": "intrinsic", @@ -1084,7 +1082,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default NaN value." + "summary": "A parameter with a default NaN value." }, "type": { "type": "intrinsic", @@ -1099,7 +1097,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default boolean value." + "summary": "A parameter with a default boolean value." }, "type": { "type": "intrinsic", @@ -1114,7 +1112,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A parameter with a default null value." + "summary": "A parameter with a default null value." }, "type": { "type": "intrinsic", @@ -1144,7 +1142,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with a parameter that is optional." + "summary": "This is a function with a parameter that is optional." }, "parameters": [ { @@ -1154,7 +1152,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A normal parameter." + "summary": "A normal parameter." }, "type": { "type": "intrinsic", @@ -1170,7 +1168,7 @@ "isOptional": true }, "comment": { - "shortText": "An optional parameter.\n" + "summary": "An optional parameter.\n" }, "type": { "type": "intrinsic", @@ -1199,7 +1197,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with multiple arguments and a return value.", + "summary": "This is a function with multiple arguments and a return value.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1210,7 +1208,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is a string parameter." + "summary": "This is a string parameter." }, "type": { "type": "intrinsic", @@ -1224,7 +1222,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" + "summary": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" }, "type": { "type": "intrinsic", @@ -1238,7 +1236,7 @@ "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": "\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" }, "type": { "type": "reference", @@ -1267,7 +1265,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function with rest parameter.", + "summary": "This is a function with rest parameter.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1280,7 +1278,7 @@ "isRest": true }, "comment": { - "shortText": "The rest parameter." + "summary": "The rest parameter." }, "type": { "type": "array", @@ -1312,7 +1310,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Checks that an argument is not null." + "summary": "Checks that an argument is not null." }, "typeParameter": [ { @@ -1331,7 +1329,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n" + "summary": "\n" }, "type": { "type": "union", @@ -1400,7 +1398,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function that is extended by a module." + "summary": "This is a function that is extended by a module." }, "parameters": [ { @@ -1410,7 +1408,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "An argument.\n" + "summary": "An argument.\n" }, "type": { "type": "intrinsic", @@ -1439,7 +1437,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is the first signature of a function with multiple signatures.", + "summary": "This is the first signature of a function with multiple signatures.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1450,7 +1448,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "The name value.\n" + "summary": "The name value.\n" }, "type": { "type": "intrinsic", @@ -1470,7 +1468,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is the second signature of a function with multiple signatures.", + "summary": "This is the second signature of a function with multiple signatures.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1481,7 +1479,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "An object containing the name value." + "summary": "An object containing the name value." }, "type": { "type": "reflection", @@ -1499,7 +1497,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "A value of the object.\n" + "summary": "A value of the object.\n" }, "type": { "type": "intrinsic", @@ -1543,7 +1541,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "This is a function that is assigned to a variable.", + "summary": "This is a function that is assigned to a variable.", "returns": "This is the return value of the function.\n" }, "parameters": [ @@ -1554,7 +1552,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This is some numeric parameter." + "summary": "This is some numeric parameter." }, "type": { "type": "intrinsic", @@ -1633,7 +1631,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "A function with a generic type array parameter.", + "summary": "A function with a generic type array parameter.", "returns": "A generic array.\n" }, "typeParameter": [ @@ -1653,7 +1651,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A generic parameter." + "summary": "A generic parameter." }, "type": { "type": "reference", @@ -1668,7 +1666,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "A generic array parameter." + "summary": "A generic array parameter." }, "type": { "type": "array", @@ -1713,7 +1711,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "this describes T\n" + "summary": "this describes T\n" } } ], @@ -1725,7 +1723,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "this describes param" + "summary": "this describes param" }, "type": { "type": "reference", @@ -1756,7 +1754,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Generic function short text.", + "summary": "Generic function short text.", "returns": "Generic function return value.\n" }, "typeParameter": [ @@ -1767,7 +1765,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Generic function type parameter." + "summary": "Generic function type parameter." }, "type": { "type": "reference", @@ -1783,7 +1781,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Generic function parameter." + "summary": "Generic function parameter." }, "type": { "type": "reference", diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index dabcd437c..75ba49810 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -55,7 +55,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": "Parameter A." }, "type": { "type": "intrinsic", @@ -69,7 +69,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": "Parameter B.\n" }, "type": { "type": "intrinsic", @@ -169,7 +169,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Custom parameter A doc.\n" + "summary": "Custom parameter A doc.\n" }, "type": { "type": "intrinsic", @@ -183,7 +183,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": "Parameter B.\n" }, "type": { "type": "intrinsic", @@ -283,7 +283,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": "Parameter A." }, "type": { "type": "intrinsic", @@ -297,7 +297,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Custom second parameter doc with name change.\n" + "summary": "Custom second parameter doc with name change.\n" }, "type": { "type": "intrinsic", @@ -376,7 +376,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter A." + "summary": "Parameter A." }, "type": { "type": "intrinsic", @@ -390,7 +390,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "Parameter B.\n" + "summary": "Parameter B.\n" }, "type": { "type": "intrinsic", diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index b913ba82f..d055dfc89 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -18,7 +18,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Source interface summary" + "summary": "Source interface summary" }, "children": [ { @@ -28,7 +28,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Source interface property description", + "summary": "Source interface property description", "tags": [ { "tag": "typeparam", @@ -57,7 +57,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "summary": "Source interface method description" }, "parameters": [ { @@ -67,7 +67,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n" + "summary": "\n" }, "type": { "type": "intrinsic", @@ -108,7 +108,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Source interface type parameter\n" + "summary": "Source interface type parameter\n" } } ] @@ -120,7 +120,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Source interface summary" + "summary": "Source interface summary" }, "children": [ { @@ -130,7 +130,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Source interface property description" + "summary": "Source interface property description" }, "type": { "type": "reference", @@ -152,7 +152,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Source interface method description" + "summary": "Source interface method description" }, "parameters": [ { @@ -162,7 +162,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "\n" + "summary": "\n" }, "type": { "type": "intrinsic", @@ -203,7 +203,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "Source interface type parameter\n" + "summary": "Source interface type parameter\n" } } ] @@ -222,8 +222,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", + "summary": "Function summary\n\nThis part of the commentary will be inherited by other entities", "returns": "Stringified sum or concatenation of numeric arguments\n", "tags": [ { @@ -244,7 +243,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" } } ], @@ -256,7 +255,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" }, "type": { "type": "reference", @@ -271,7 +270,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" }, "type": { "type": "reference", @@ -330,8 +329,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Function summary", - "text": "This part of the commentary will be inherited by other entities\n", + "summary": "Function summary\n\nThis part of the commentary will be inherited by other entities", "returns": "This will be inherited\n\n", "tags": [ { @@ -352,7 +350,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" } } ], @@ -364,7 +362,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" }, "type": { "type": "reference", @@ -379,7 +377,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "This will be inherited" + "summary": "This will be inherited" }, "type": { "type": "reference", diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index fa3374eab..6fda3cc1c 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -335,7 +335,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A class implementing an empty interface." + "summary": "A class implementing an empty interface." }, "children": [ { @@ -433,7 +433,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "An empty interface" + "summary": "An empty interface" }, "implementedBy": [ { @@ -482,7 +482,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Implementation of IEventDispatcher", + "summary": "Implementation of IEventDispatcher", "tags": [ { "tag": "see", @@ -1045,7 +1045,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Remove this subscription from its dispatcher" + "summary": "Remove this subscription from its dispatcher" }, "type": { "type": "intrinsic", @@ -1122,7 +1122,7 @@ "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": "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": [ { @@ -1369,7 +1369,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Function signature of an event listener callback" + "summary": "Function signature of an event listener callback" }, "parameters": [ { @@ -1379,7 +1379,7 @@ "kindString": "Parameter", "flags": {}, "comment": { - "shortText": "param text" + "summary": "param text" }, "type": { "type": "reference", @@ -1402,7 +1402,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" + "summary": "Encapsulates a subscription to an event dispatcher, and allows for unsubscribing" }, "children": [ { @@ -1460,7 +1460,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Remove this subscription from its dispatcher" + "summary": "Remove this subscription from its dispatcher" }, "type": { "type": "intrinsic", diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index d3a44cdc0..6c37297e6 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -93,7 +93,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "docs for interface" + "summary": "docs for interface" }, "children": [ { @@ -103,7 +103,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "can also use prop tag" + "summary": "can also use prop tag" }, "type": { "type": "intrinsic", @@ -117,7 +117,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "docs for property" + "summary": "docs for property" }, "type": { "type": "intrinsic", @@ -150,7 +150,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "docs for property\nmore docs for property" + "summary": "docs for property\nmore docs for property" }, "type": { "type": "intrinsic", @@ -264,7 +264,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "comment on alias" + "summary": "comment on alias" }, "typeParameter": [ { @@ -274,7 +274,7 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "shortText": "comment on template" + "summary": "comment on template" } } ], @@ -345,7 +345,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "docs for alias" + "summary": "docs for alias" }, "type": { "type": "intersection", @@ -454,7 +454,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "type alias since it doesn't have a property tag" + "summary": "type alias since it doesn't have a property tag" }, "type": { "type": "reference", @@ -513,7 +513,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "docs for alias" + "summary": "docs for alias" }, "type": { "type": "union", diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index eb5b5890f..38fa981c1 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -12,7 +12,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Base class" + "summary": "Base class" }, "children": [ { @@ -100,7 +100,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class that inherits from Base and consumes Mixin1 and Mixin2, in order." + "summary": "Class that inherits from Base and consumes Mixin1 and Mixin2, in order." }, "children": [ { @@ -470,7 +470,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "The \"instance type\" of the Mixin1 using the interface notation (supports recursive type definition)" + "summary": "The \"instance type\" of the Mixin1 using the interface notation (supports recursive type definition)" }, "children": [ { @@ -626,7 +626,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "The \"instance type\" of the Mixin2 using the interface notation (supports recursive type definition)" + "summary": "The \"instance type\" of the Mixin2 using the interface notation (supports recursive type definition)" }, "children": [ { @@ -871,7 +871,7 @@ "kindString": "Constructor signature", "flags": {}, "comment": { - "shortText": "Any constructor function" + "summary": "Any constructor function" }, "parameters": [ { @@ -936,7 +936,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Any function" + "summary": "Any function" }, "parameters": [ { @@ -973,7 +973,7 @@ "kindString": "Type alias", "flags": {}, "comment": { - "shortText": "Mixin type helper" + "summary": "Mixin type helper" }, "typeParameter": [ { @@ -1026,7 +1026,7 @@ "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": "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" }, "type": { "type": "reference", @@ -1060,7 +1060,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "The \"mixin function\" of the Mixin1" + "summary": "The \"mixin function\" of the Mixin1" }, "typeParameter": [ { @@ -1165,7 +1165,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "The \"mixin function\" of the Mixin2" + "summary": "The \"mixin function\" of the Mixin2" }, "typeParameter": [ { @@ -1280,7 +1280,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "The \"mixin function\" of the Mixin3" + "summary": "The \"mixin function\" of the Mixin3" }, "typeParameter": [ { diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index 2efa19c28..d54f50e73 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -1159,7 +1159,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "First type for union or intersection type tests." + "summary": "First type for union or intersection type tests." }, "children": [ { @@ -1169,7 +1169,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Property of first type." + "summary": "Property of first type." }, "type": { "type": "intrinsic", @@ -1194,7 +1194,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Second type for union or intersection type tests." + "summary": "Second type for union or intersection type tests." }, "children": [ { @@ -1204,7 +1204,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Property of second type." + "summary": "Property of second type." }, "type": { "type": "intrinsic", @@ -1229,7 +1229,7 @@ "kindString": "Interface", "flags": {}, "comment": { - "shortText": "Third type for union or intersection type tests." + "summary": "Third type for union or intersection type tests." }, "children": [ { @@ -1239,7 +1239,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Complex Property of third type." + "summary": "Complex Property of third type." }, "type": { "type": "array", @@ -1279,7 +1279,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Intersection Property of third type." + "summary": "Intersection Property of third type." }, "type": { "type": "intersection", @@ -1304,7 +1304,7 @@ "kindString": "Property", "flags": {}, "comment": { - "shortText": "Union Property of third type." + "summary": "Union Property of third type." }, "type": { "type": "union", diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 2992c2dd2..5c638f63c 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -18,7 +18,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A custom array class." + "summary": "A custom array class." }, "children": [ { @@ -92,7 +92,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class array class item" + "summary": "Class array class item" }, "children": [ { @@ -134,7 +134,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Custom list class" + "summary": "Custom list class" }, "children": [ { @@ -200,7 +200,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A const of a complex type." + "summary": "A const of a complex type." }, "type": { "type": "array", @@ -255,7 +255,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "An exported const of the custom array type." + "summary": "An exported const of the custom array type." }, "type": { "type": "reference", @@ -461,7 +461,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Destructuring function parameters." + "summary": "Destructuring function parameters." }, "parameters": [ { @@ -745,7 +745,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "An object literal." + "summary": "An object literal." }, "type": { "type": "reflection", @@ -1031,7 +1031,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A typed literal without an initializer." + "summary": "A typed literal without an initializer." }, "type": { "type": "reflection", diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index 2f561a56b..de20b9d90 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -18,7 +18,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "A custom array class." + "summary": "A custom array class." }, "children": [ { @@ -92,7 +92,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Class array class item" + "summary": "Class array class item" }, "children": [ { @@ -134,7 +134,7 @@ "kindString": "Class", "flags": {}, "comment": { - "shortText": "Custom list class" + "summary": "Custom list class" }, "children": [ { @@ -200,7 +200,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A const of a complex type." + "summary": "A const of a complex type." }, "type": { "type": "array", @@ -255,7 +255,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "An exported const of the custom array type." + "summary": "An exported const of the custom array type." }, "type": { "type": "reference", @@ -312,7 +312,7 @@ "kindString": "Call signature", "flags": {}, "comment": { - "shortText": "Destructuring function parameters." + "summary": "Destructuring function parameters." }, "parameters": [ { @@ -359,7 +359,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "An object literal." + "summary": "An object literal." }, "type": { "type": "reflection", @@ -380,7 +380,7 @@ "kindString": "Variable", "flags": {}, "comment": { - "shortText": "A typed literal without an initializer." + "summary": "A typed literal without an initializer." }, "type": { "type": "reflection", diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index 5e7bc65cc..65ebcff0f 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -50,7 +50,7 @@ export const issueTests: { gh1164(project) { const refl = query(project, "gh1164"); equal( - refl.signatures?.[0]?.parameters?.[0]?.comment?.shortText, + refl.signatures?.[0]?.parameters?.[0]?.comment?.summary, "{@link CommentedClass} Test description." ); equal(refl.signatures?.[0]?.comment?.returns, "Test description.\n"); @@ -64,7 +64,7 @@ export const issueTests: { gh1255(project) { const foo = query(project, "C.foo"); - equal(foo.comment?.shortText, "Docs!"); + equal(foo.comment?.summary, "Docs!"); }, gh1330(project) { @@ -117,15 +117,15 @@ 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(method.signatures?.[0].comment?.summary, "method docs"); }, gh1481(project) { const signature = query(project, "GH1481.static").signatures?.[0]; - equal(signature?.comment?.shortText, "static docs"); + equal(signature?.comment?.summary, "static docs"); equal(signature?.type?.toString(), "void"); }, @@ -142,7 +142,7 @@ export const issueTests: { gh1490(project) { const refl = query(project, "GH1490.optionalMethod"); - equal(refl.signatures?.[0]?.comment?.shortText, "With comment"); + equal(refl.signatures?.[0]?.comment?.summary, "With comment"); }, gh1509(project) { 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/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 { /** From 4d62b439253fc5dcb7577ff76e280518d77b4d71 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 2 Oct 2021 18:51:52 -0600 Subject: [PATCH 008/151] Remove unused css --- static/style.css | 9 --------- 1 file changed, 9 deletions(-) diff --git a/static/style.css b/static/style.css index ff488199d..37c11d071 100644 --- a/static/style.css +++ b/static/style.css @@ -564,15 +564,6 @@ dl.tsd-comment-tags p { margin: 0; } -.tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; -} -.tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; -} - .toggle-protected .tsd-is-private { display: none; } From 01e961be3bb5c98620909a0645a7c28525d809cd Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 3 Oct 2021 09:28:57 -0600 Subject: [PATCH 009/151] Remove dead code in the highlighter ... not sure what I was seeing with weird tokens previously, but there is no reason for the partial consumption to be necessary. --- src/lib/utils/highlighter.tsx | 51 +++++++---------------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index 852d7b3ce..961a7f061 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,49 +24,16 @@ class DoubleHighlighter { // If this fails... something went *very* wrong. assert(lightTokens.length === darkTokens.length); - 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 - // 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( - {lightLine[0].content} - ); - lightLine.shift(); - darkLine.shift(); - continue; - } - - if (lightLine[0].content.length < darkLine[0].content.length) { - lineEls.push( - {lightLine[0].content} - ); - darkLine[0].content = darkLine[0].content.substr(lightLine[0].content.length); - lightLine.shift(); - continue; - } - - lineEls.push( - {darkLine[0].content} - ); - lightLine[0].content = lightLine[0].content.substr(darkLine[0].content.length); - darkLine.shift(); - } + const docEls: JSX.Element[] = []; + + for (const [lightLine, darkLine] of zip(lightTokens, darkTokens)) { + // If this fails, something also went *very* wrong. + assert(lightLine.length === darkLine.length); - if (line + 1 !== lightTokens.length) { - lineEls.push(
); + for (const [lightToken, darkToken] of zip(lightLine, darkLine)) { + docEls.push({lightToken.content}); } - docEls.push(lineEls); + docEls.push(
); } return JSX.renderElement(<>{docEls}); From 1b82a8cb39d64bd06d08b4b36a1ae2561a68c453 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 22 Oct 2021 16:13:22 -0600 Subject: [PATCH 010/151] Update tests to pass on beta branch --- src/test/issueTests.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index 223ed7195..95fa32a0c 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -241,9 +241,9 @@ 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.trim(), "T docs"); const cls = query(project, "Bar"); - equal(cls.typeParameters?.[0].comment?.shortText.trim(), "T docs"); + equal(cls.typeParameters?.[0].comment?.summary.trim(), "T docs"); }, gh1734(project) { From 79978e52e4fff70867c6fc42ad228a70919ae6ae Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Oct 2021 14:29:35 -0600 Subject: [PATCH 011/151] WIP: A real comment parser Lots of tests failing still. --- .../{comments.ts => comments/blockLexer.ts} | 114 ++++++-- src/lib/converter/comments/discovery.ts | 95 +++++++ src/lib/converter/comments/index.ts | 269 ++++++++++++++++++ src/lib/converter/context.ts | 21 ++ src/lib/converter/factories/comment.ts | 12 +- src/lib/converter/plugins/CategoryPlugin.ts | 16 +- src/lib/converter/plugins/CommentPlugin.ts | 174 +++++------ src/lib/converter/utils/reflections.ts | 138 +++++---- src/lib/models/comments/comment.ts | 159 +++++++---- src/lib/models/comments/index.ts | 4 +- src/lib/models/comments/tag.ts | 30 -- .../themes/default/partials/comment.tsx | 47 +-- .../partials/member.signature.body.tsx | 8 +- src/lib/serialization/schema.ts | 13 +- .../serializers/comments/comment-tag.ts | 8 +- .../serializers/comments/comment.ts | 15 +- src/lib/utils/general.ts | 10 + src/lib/utils/highlighter.tsx | 37 ++- src/lib/utils/index.ts | 1 + src/lib/utils/jsx.ts | 8 +- src/test/behaviorTests.ts | 19 +- src/test/comments.test.ts | 98 ++++++- src/test/converter.test.ts | 2 +- src/test/issueTests.ts | 27 +- 24 files changed, 990 insertions(+), 335 deletions(-) rename src/lib/converter/{comments.ts => comments/blockLexer.ts} (76%) create mode 100644 src/lib/converter/comments/discovery.ts create mode 100644 src/lib/converter/comments/index.ts delete mode 100644 src/lib/models/comments/tag.ts diff --git a/src/lib/converter/comments.ts b/src/lib/converter/comments/blockLexer.ts similarity index 76% rename from src/lib/converter/comments.ts rename to src/lib/converter/comments/blockLexer.ts index 2efd5d957..24752a95f 100644 --- a/src/lib/converter/comments.ts +++ b/src/lib/converter/comments/blockLexer.ts @@ -1,10 +1,11 @@ export enum TokenSyntaxKind { - Text, - NewLine, - OpenBrace, - CloseBrace, - Tag, - Code, + Text = "text", + NewLine = "new_line", + OpenBrace = "open_brace", + CloseBrace = "close_brace", + Tag = "tag", + Code = "code", + TypeAnnotation = "type", } export interface Token { @@ -16,7 +17,7 @@ export function* lexBlockComment( file: string, pos = 0, end = file.length -): Generator { +): Generator { // Wrapper around our real lex function to collapse adjacent text tokens. let textToken: Token | undefined; for (const token of lexBlockComment2(file, pos, end)) { @@ -38,13 +39,14 @@ export function* lexBlockComment( if (textToken) { yield textToken; } + return; } function* lexBlockComment2( file: string, pos: number, end: number -): Generator { +): Generator { pos += 2; // Leading '/*' end -= 2; // Trailing '*/' @@ -67,6 +69,7 @@ function* lexBlockComment2( } let lineStart = true; + let braceStartsType = false; for (;;) { if (pos >= end) { @@ -91,11 +94,20 @@ function* lexBlockComment2( break; case "{": - yield makeToken(TokenSyntaxKind.OpenBrace, 1); + 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 "`": { @@ -104,6 +116,7 @@ function* lexBlockComment2( // 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; @@ -200,6 +213,7 @@ function* lexBlockComment2( } if (lookahead !== pos + 1) { + braceStartsType = true; yield makeToken(TokenSyntaxKind.Tag, lookahead - pos); break; } @@ -239,18 +253,18 @@ function* lexBlockComment2( lookahead++; } - // If we didn't need to make a copy, don't make one now. - if (textParts.length === 0) { - yield makeToken(TokenSyntaxKind.Text, lookahead - pos); - } else { - textParts.push(file.substring(lookaheadStart, lookahead)); - pos = lookahead; - // This piece of text had line continuations or escaped text, need our own string. - yield { - kind: TokenSyntaxKind.Text, - text: textParts.join(""), - }; + 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; } } @@ -288,6 +302,66 @@ function* lexBlockComment2( 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 { + let 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( diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts new file mode 100644 index 000000000..3ebb0eac1 --- /dev/null +++ b/src/lib/converter/comments/discovery.ts @@ -0,0 +1,95 @@ +import * as ts from "typescript"; +import { ReflectionKind } from "../../models"; + +const wantedKinds: Record = { + [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, + ], + [ReflectionKind.Variable]: [ts.SyntaxKind.VariableDeclaration], + [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.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, + ], +}; + +export function discoverComment( + symbol: ts.Symbol, + kind: ReflectionKind +): [ts.SourceFile, ts.CommentRange] | undefined { + for (const decl of symbol.declarations || []) { + const text = decl.getSourceFile().text; + if (wantedKinds[kind].includes(decl.kind)) { + const comments = ts.getLeadingCommentRanges(text, decl.pos); + const lastDocComment = comments + ?.reverse() + .find( + (c) => + text[c.pos] === "/" && + text[c.pos + 1] === "*" && + text[c.pos + 2] === "*" + ); + + if (lastDocComment) { + return [decl.getSourceFile(), lastDocComment]; + } + } + } +} diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts new file mode 100644 index 000000000..75bd5eee0 --- /dev/null +++ b/src/lib/converter/comments/index.ts @@ -0,0 +1,269 @@ +import { ok } from "assert"; +import * as ts from "typescript"; +import { + Comment, + CommentTag, + CommentDisplayPart, + ReflectionKind, +} from "../../models"; +import { assertNever, Logger } from "../../utils"; +import { lexBlockComment, Token, TokenSyntaxKind } from "./blockLexer"; +import { discoverComment } from "./discovery"; + +export interface CommentParserConfig { + blockTags: Set; + inlineTags: Set; + modifierTags: Set; +} + +export function getComment( + symbol: ts.Symbol, + kind: ReflectionKind, + config: CommentParserConfig, + logger: Logger +): Comment | undefined { + const comment = discoverComment(symbol, kind); + if (comment) { + const [file, range] = comment; + const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); + const warning = (warning: string) => + logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); + + switch (range.kind) { + case ts.SyntaxKind.MultiLineCommentTrivia: + return parseComment( + lexBlockComment(file.text, range.pos, range.end), + config, + warning + ); + case ts.SyntaxKind.SingleLineCommentTrivia: + throw "GERRIT FIX ME"; + default: + assertNever(range.kind); + } + } +} + +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; + }, + }; +} + +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)); + } + + return comment; +} + +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; + + const tag = new CommentTag( + tagName, + blockContent(comment, lexer, config, warning) + ); + + if ( + tagName === "@param" && + tag.content.length && + tag.content[0].kind === "text" + ) { + const firstPart = tag.content[0]; + const match = firstPart.text.match(/^([a-z_$]+)\s*(-\s*)?/); + if (match) { + tag.paramName = match[1]; + firstPart.text = firstPart.text.substr(match[0].length); + } + } + + return tag; +} + +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(); + + 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 (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, bug 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: "code", text: next.text }); + break; + + case TokenSyntaxKind.OpenBrace: + inlineTag(lexer, content, config, warning); + break; + + default: + assertNever(next.kind); + } + + if (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++; + } + } + + 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 }); + block.push({ kind: "text", 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, + text: content.join(""), + }); +} diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 63a90f498..b83e628b4 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -14,6 +14,7 @@ import type { Converter } from "./converter"; import { isNamedNode } from "./utils/nodes"; import { ConverterEvents } from "./converter-events"; import { resolveAliasedSymbol } from "./utils/symbols"; +import { CommentParserConfig, getComment } from "./comments"; /** * The context describes the current state the converter is in. @@ -179,6 +180,18 @@ export class Context { return resolveAliasedSymbol(symbol, this.checker); } + config: CommentParserConfig = { + blockTags: new Set(["@param", "@remarks"]), + inlineTags: new Set(["@link"]), + modifierTags: new Set([ + "@public", + "@private", + "@protected", + "@readonly", + "@enum", + ]), + }; + createDeclarationReflection( kind: ReflectionKind, symbol: ts.Symbol | undefined, @@ -190,6 +203,14 @@ export class Context { nameOverride ?? exportSymbol?.name ?? symbol?.name ?? "unknown" ); const reflection = new DeclarationReflection(name, kind, this.scope); + if (symbol) { + reflection.comment = getComment( + symbol, + reflection.kind, + this.config, + this.logger + ); + } if (this.shouldBeStatic) { reflection.setFlag(ReflectionFlag.Static); } diff --git a/src/lib/converter/factories/comment.ts b/src/lib/converter/factories/comment.ts index b65102ff1..a6c78aa56 100644 --- a/src/lib/converter/factories/comment.ts +++ b/src/lib/converter/factories/comment.ts @@ -197,11 +197,11 @@ export function parseComment( return line.trim(); } - function readBareLine(line: string) { + function readBareLine(_line: string) { if (currentTag) { - currentTag.text += "\n" + line; + // currentTag.text += "\n" + line; } else { - comment.summary += (comment.summary === "" ? "" : "\n") + line; + // comment.summary += (comment.summary === "" ? "" : "\n") + line; } } @@ -234,8 +234,8 @@ export function parseComment( line = consumeTypeData(line); } - currentTag = new CommentTag(tagName, paramName, line); - comment.tags.push(currentTag); + // currentTag = new CommentTag(tagName, paramName, line); + // comment.blockTags.push(currentTag); } const CODE_FENCE = /^\s*```(?!.*```)/; @@ -268,6 +268,6 @@ export function parseComment( text = text.replace(/\*+\/\s*$/, ""); text.split(/\r\n?|\n/).forEach(readLine); - comment.summary = comment.summary.trim(); + // comment.summary = comment.summary.trim(); return comment; } diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index 7ff3a3425..4f5b4316d 100644 --- a/src/lib/converter/plugins/CategoryPlugin.ts +++ b/src/lib/converter/plugins/CategoryPlugin.ts @@ -181,20 +181,20 @@ export class CategoryPlugin extends ConverterComponent { static getCategories(reflection: DeclarationReflection) { function extractCategoryTag(comment: Comment) { const categories = new Set(); - const tags = comment.tags; + const tags = comment.blockTags; const commentTags: CommentTag[] = []; tags.forEach((tag) => { - if (tag.tagName !== "category") { + if (tag.tag !== "category") { commentTags.push(tag); return; } - const text = tag.text.trim(); - if (!text) { - return; - } - categories.add(text); + // const text = tag.text.trim(); + // if (!text) { + // return; + // } + // categories.add(text); }); - comment.tags = commentTags; + comment.blockTags = commentTags; return categories; } diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 9f7cb0a2a..3cb2d8da6 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -1,6 +1,9 @@ import * as ts from "typescript"; -import { Comment, CommentTag } from "../../models/comments/index"; +import { Component, ConverterComponent } from "../components"; +import { parseComment, getRawComment } from "../factories/comment"; +import { Converter } from "../converter"; +import type { Context } from "../context"; import { Reflection, ReflectionFlag, @@ -9,16 +12,11 @@ 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 } from "../../models"; + Comment, + CommentTag, + ReflectionType, + SourceReference, +} from "../../models"; import { BindOption, filterMap, @@ -27,6 +25,8 @@ import { partition, } from "../../utils"; +const DEBUG = true as boolean; + /** * These tags are not useful to display in the generated documentation. * They should be ignored when parsing comments. Any relevant type information @@ -78,7 +78,7 @@ 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); @@ -86,7 +86,7 @@ export class CommentPlugin extends ConverterComponent { comment.removeTags("private"); } - if (comment.hasTag("protected")) { + if (comment.hasModifier("protected")) { reflection.setFlag(ReflectionFlag.Protected); if (reflection.kindOf(ReflectionKind.CallSignature)) { reflection.parent?.setFlag(ReflectionFlag.Protected); @@ -94,7 +94,7 @@ export class CommentPlugin extends ConverterComponent { comment.removeTags("protected"); } - if (comment.hasTag("public")) { + if (comment.hasModifier("public")) { reflection.setFlag(ReflectionFlag.Public); if (reflection.kindOf(ReflectionKind.CallSignature)) { reflection.parent?.setFlag(ReflectionFlag.Public); @@ -102,7 +102,7 @@ export class CommentPlugin extends ConverterComponent { comment.removeTags("public"); } - if (comment.hasTag("event")) { + if (comment.hasModifier("event")) { if (reflection.kindOf(ReflectionKind.CallSignature)) { if (reflection.parent) { reflection.parent.kind = ReflectionKind.Event; @@ -131,34 +131,36 @@ export class CommentPlugin extends ConverterComponent { */ private onCreateTypeParameter( _context: Context, - reflection: TypeParameterReflection, - node?: ts.Node + _reflection: TypeParameterReflection, + _node?: ts.Node ) { - 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; - if (comment) { - let tag = comment.getTag("typeparam", reflection.name); - if (!tag) { - tag = comment.getTag("template", reflection.name); - } - if (!tag) { - tag = comment.getTag("param", `<${reflection.name}>`); - } - if (!tag) { - tag = comment.getTag("param", reflection.name); - } - - if (tag) { - reflection.comment = new Comment(tag.text); - removeIfPresent(comment.tags, tag); - } - } + if (DEBUG) return; + + // 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; + // if (comment) { + // let tag = comment.getTag("typeparam", reflection.name); + // if (!tag) { + // tag = comment.getTag("template", reflection.name); + // } + // if (!tag) { + // tag = comment.getTag("param", `<${reflection.name}>`); + // } + // if (!tag) { + // tag = comment.getTag("param", reflection.name); + // } + + // if (tag) { + // reflection.comment = new Comment(tag.text); + // removeIfPresent(comment.blockTags, tag); + // } + // } } /** @@ -175,6 +177,8 @@ export class CommentPlugin extends ConverterComponent { reflection: Reflection, node?: ts.Node ) { + if (DEBUG) return; + if (reflection.kindOf(ReflectionKind.FunctionOrMethod)) { // 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 @@ -223,11 +227,11 @@ export class CommentPlugin extends ConverterComponent { 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) { - reflection.name = newName; - } - removeIfPresent(comment.tags, tag); + // const newName = tag.text.trim(); + // if (newName.length) { + // reflection.name = newName; + // } + removeIfPresent(comment.blockTags, tag); } } @@ -326,54 +330,51 @@ 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(); } - childComment.summary ||= comment.summary; - childComment.returns ||= comment.returns; - childComment.tags = childComment.tags.length - ? childComment.tags - : [...comment.tags]; + childComment.summary = childComment.summary.length + ? childComment.summary + : Comment.cloneDisplayParts(comment.summary); + childComment.blockTags = childComment.blockTags.length + ? childComment.blockTags + : comment.blockTags.map((tag) => tag.clone()); + childComment.modifierTags = childComment.modifierTags.size + ? childComment.modifierTags + : new Set(comment.modifierTags); } signature.parameters?.forEach((parameter, index) => { let tag: CommentTag | undefined; if (childComment && parameter.name === "__namedParameters") { - const commentParams = childComment?.tags.filter( + const commentParams = childComment?.blockTags.filter( (tag) => - tag.tagName === "param" && - !tag.paramName.includes(".") + tag.tag === "param" && !tag.paramName?.includes(".") ); if ( signature.parameters?.length === commentParams.length && commentParams[index].paramName ) { - parameter.name = commentParams[index].paramName; + parameter.name = commentParams[index].paramName!; } } if (childComment) { moveNestedParamTags(childComment, parameter); - tag = childComment.getTag("param", parameter.name); + tag = childComment.getParamTag(parameter.name); } if (comment && !tag) { - tag = comment.getTag("param", parameter.name); + tag = comment.getParamTag(parameter.name); } if (tag) { - parameter.comment = new Comment(tag.text); + parameter.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } }); @@ -381,18 +382,23 @@ export class CommentPlugin extends ConverterComponent { let tag: CommentTag | undefined; if (childComment) { tag = - childComment.getTag("typeparam", parameter.name) || - childComment.getTag("template", parameter.name) || - childComment.getTag("param", `<${parameter.name}>`); + childComment.getParamTag( + parameter.name, + "@typeParam" + ) || + childComment.getParamTag(parameter.name, "@template") || + childComment.getParamTag(`<${parameter.name}>`); } if (comment && !tag) { tag = - comment.getTag("typeparam", parameter.name) || - comment.getTag("template", parameter.name) || - comment.getTag("param", `<${parameter.name}>`); + comment.getParamTag(parameter.name, "@typeParam") || + comment.getParamTag(parameter.name, "@template") || + comment.getParamTag(`<${parameter.name}>`); } if (tag) { - parameter.comment = new Comment(tag.text); + parameter.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } }); @@ -445,9 +451,9 @@ export class CommentPlugin extends ConverterComponent { } return ( - comment.hasTag("hidden") || - comment.hasTag("ignore") || - (comment.hasTag("internal") && excludeInternal) + comment.hasModifier("hidden") || + comment.hasModifier("ignore") || + (comment.hasModifier("internal") && excludeInternal) ); } } @@ -455,19 +461,19 @@ export class CommentPlugin extends ConverterComponent { // Moves tags like `@param foo.bar docs for bar` into the `bar` property of the `foo` parameter. function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) { if (parameter.type instanceof ReflectionType) { - const tags = comment.tags.filter( + const tags = comment.blockTags.filter( (t) => - t.tagName === "param" && - t.paramName.startsWith(`${parameter.name}.`) + t.tag === "param" && + t.paramName?.startsWith(`${parameter.name}.`) ); - for (const tag of tags) { - const path = tag.paramName.split("."); + const path = tag.paramName!.split("."); path.shift(); const child = parameter.type.declaration.getChildByName(path); - if (child && !child.comment) { - child.comment = new Comment(tag.text); + child.comment = new Comment( + Comment.cloneDisplayParts(tag.content) + ); } } } diff --git a/src/lib/converter/utils/reflections.ts b/src/lib/converter/utils/reflections.ts index ceb8d5db7..bd2bff0f0 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, Reflection, SomeType, UnionType } from "../../models"; export function removeUndefined(type: SomeType): SomeType { if (type instanceof UnionType) { @@ -31,49 +23,49 @@ export function removeUndefined(type: SomeType): SomeType { * @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); - } +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); + // } } /** @@ -82,24 +74,24 @@ export function copyComment(target: Reflection, source: Reflection) { * @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); - } - } - } - } -} +// 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/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 02c52efb1..53c1aca9d 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -1,7 +1,50 @@ -import { removeIf } from "../../utils"; -import { CommentTag } from "./tag"; +import { assertNever, removeIf } from "../../utils"; -const COPIED_TAGS = ["remarks"]; +export type CommentDisplayPart = + | { kind: "text"; text: string } + | { kind: "code"; text: string } + | { kind: "inline-tag"; tag: string; text: string }; + +/** + * 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; + + /** + * If this is a `@param` tag, the parameter name associated with it. + */ + paramName?: 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.paramName) { + tag.paramName = this.paramName; + } + return tag; + } +} /** * A model that represents a comment. @@ -10,26 +53,68 @@ const COPIED_TAGS = ["remarks"]; * through the {@link DeclarationReflection.comment} property. */ export class Comment { + /** + * Debugging utility for combining parts into a simple string. Not suitable for + * rendering, but can be useful in tests. + */ + static combineDisplayParts( + parts: readonly CommentDisplayPart[] | undefined + ): string { + const result: string[] = []; + + for (const item of parts || []) { + switch (item.kind) { + case "text": + result.push(item.text); + break; + case "code": + result.push(item.text); + break; + case "inline-tag": + result.push("{", item.tag, item.text, "}"); + break; + default: + assertNever(item); + } + } + + return result.join(""); + } + + /** + * Helper utility to clone {@link Comment.summary} or {@link CommentTag.content} + * @internal probably ok to expose, but waiting until someone asks. + */ + static cloneDisplayParts(parts: CommentDisplayPart[]) { + return parts.map((p) => ({ ...p })); + } + /** * The content of the comment which is not associated with a block tag. */ - summary: string; + summary: CommentDisplayPart[]; /** - * The text of the ```@returns``` tag if present. + * All associated block level tags. */ - returns?: string; + blockTags: CommentTag[] = []; /** - * All associated tags. + * All modifier tags present on the comment, e.g. `@alpha`, `@beta`. */ - tags: CommentTag[] = []; + modifierTags: Set = new Set(); /** * Creates a new Comment instance. */ - constructor(summary?: string) { - this.summary = summary || ""; + constructor( + summary: CommentDisplayPart[] = [], + blockTags: CommentTag[] = [], + modifierTags: Set = new Set() + ) { + this.summary = summary; + this.blockTags = blockTags; + this.modifierTags = modifierTags; } /** @@ -38,7 +123,10 @@ export class Comment { * @returns TRUE when this comment has a visible component. */ hasVisibleComponent(): boolean { - return !!this.summary || this.tags.length > 0; + return ( + this.summary.some((x) => x.kind != "text" || x.text !== "") || + this.blockTags.length > 0 + ); } /** @@ -47,26 +135,25 @@ 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); } /** * 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); + } + + getParamTag(param: string, tagName = "@param") { + return this.blockTags.find( + (tag) => tag.tag === tagName && tag.paramName === param + ); } /** @@ -74,32 +161,6 @@ export class Comment { * @param tagName */ removeTags(tagName: string) { - removeIf(this.tags, (tag) => tag.tagName === tagName); - } - - /** - * 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.summary = comment.summary; - 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]; + removeIf(this.blockTags, (tag) => tag.tag === tagName); } } diff --git a/src/lib/models/comments/index.ts b/src/lib/models/comments/index.ts index eb0c512ee..d16cfe548 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 } 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/output/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index feb4da74a..49547d70f 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -1,28 +1,43 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -import { JSX, Raw } from "../../../../utils"; -import type { Reflection } from "../../../../models"; +import { assertNever, JSX, Raw } from "../../../../utils"; +import type { CommentDisplayPart, Reflection } from "../../../../models"; + +function humanize(text: string) { + return text.substr(1, 1).toUpperCase() + text.substr(2).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); +} + +function displayPartsToMarkdown(parts: CommentDisplayPart[]) { + const result: string[] = []; + + for (const part of parts) { + switch (part.kind) { + case "text": + case "code": + result.push(part.text); + break; + case "inline-tag": + // TODO GERRIT + break; + default: + assertNever(part); + } + } + + return result.join(""); +} export function comment({ markdown }: DefaultThemeRenderContext, props: Reflection) { if (!props.comment?.hasVisibleComponent()) return; return (
- {!!props.comment.summary && ( -
- -
- )} - {props.comment.tags?.length > 0 && ( + + {props.comment.blockTags?.length > 0 && (
- {props.comment.tags.map((item) => ( + {props.comment.blockTags.map((item) => ( <> -
- {item.tagName} - {item.paramName ? ` ${item.paramName}` : ""} -
-
- -
+

{humanize(item.tag)}

+ ))}
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 74b6fb1ce..d6d72475a 100644 --- a/src/lib/output/themes/default/partials/member.signature.body.tsx +++ b/src/lib/output/themes/default/partials/member.signature.body.tsx @@ -1,7 +1,8 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -import { JSX, Raw } from "../../../../utils"; +import { JSX } from "../../../../utils"; import { ReflectionType, SignatureReflection } from "../../../../models"; import { renderFlags } from "../../lib"; + export const memberSignatureBody = ( context: DefaultThemeRenderContext, props: SignatureReflection, @@ -49,11 +50,6 @@ export const memberSignatureBody = ( {"Returns "} {context.type(props.type)} - {!!props.comment?.returns && ( -
- -
- )} {props.type instanceof ReflectionType && context.parameter(props.type.declaration)} )} diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 9e2b99442..79b44ce78 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -73,6 +73,8 @@ type _ModelToObject = ? Comment : T extends M.CommentTag ? CommentTag + : T extends M.CommentDisplayPart + ? CommentDisplayPart : T extends DecoratorWrapper ? Decorator : T extends SourceReferenceWrapper @@ -337,13 +339,16 @@ export interface ReflectionFlags extends Partial>> {} export interface Comment - extends Partial> {} + extends Partial> { + modifierTags?: string[]; +} -export interface CommentTag extends S { - tag: M.CommentTag["tagName"]; - param?: M.CommentTag["paramName"]; +export interface CommentTag extends S { + paramName?: string; } +export type CommentDisplayPart = M.CommentDisplayPart; + export interface SourceReference extends S {} diff --git a/src/lib/serialization/serializers/comments/comment-tag.ts b/src/lib/serialization/serializers/comments/comment-tag.ts index 06af55957..e4d0bed3f 100644 --- a/src/lib/serialization/serializers/comments/comment-tag.ts +++ b/src/lib/serialization/serializers/comments/comment-tag.ts @@ -22,14 +22,14 @@ export class CommentTagSerializer extends SerializerComponent { obj: Partial = {} ): JSONCommentTag { const result: JSONCommentTag = { - tag: tag.tagName, - text: tag.text, + tag: tag.tag, + content: tag.content, }; if (tag.paramName) { - result.param = tag.paramName; + result.paramName = tag.paramName; } - return { ...obj, ...result }; + return Object.assign(obj, result); } } diff --git a/src/lib/serialization/serializers/comments/comment.ts b/src/lib/serialization/serializers/comments/comment.ts index 23660a341..31deecc14 100644 --- a/src/lib/serialization/serializers/comments/comment.ts +++ b/src/lib/serialization/serializers/comments/comment.ts @@ -18,16 +18,15 @@ export class CommentSerializer extends SerializerComponent { } toObject(comment: Comment, obj: Partial = {}): JSONComment { - if (comment.summary) { - obj.summary = comment.summary; + obj.summary = comment.summary; + if (comment.blockTags.length) { + obj.blockTags = comment.blockTags.map((tag) => + this.owner.toObject(tag) + ); } - if (comment.returns) { - obj.returns = comment.returns; + if (comment.modifierTags.size) { + obj.modifierTags = Array.from(comment.modifierTags); } - if (comment.tags.length) { - obj.tags = comment.tags.map((tag) => this.owner.toObject(tag)); - } - return obj; } } diff --git a/src/lib/utils/general.ts b/src/lib/utils/general.ts index 8fb5ce872..e16439522 100644 --- a/src/lib/utils/general.ts +++ b/src/lib/utils/general.ts @@ -32,3 +32,13 @@ export type IfInternal = InternalOnly extends true ? T : F; * See {@link IfInternal} for the rationale. */ export type NeverIfInternal = IfInternal; + +import * as Util from "util"; + +export function assertNever(x: never): never { + throw new Error( + `Expected handling to cover all possible cases, but it didn't cover: ${Util.inspect( + x + )}` + ); +} diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index 961a7f061..c7638812e 100644 --- a/src/lib/utils/highlighter.tsx +++ b/src/lib/utils/highlighter.tsx @@ -27,15 +27,42 @@ class DoubleHighlighter { const docEls: JSX.Element[] = []; for (const [lightLine, darkLine] of zip(lightTokens, darkTokens)) { - // If this fails, something also went *very* wrong. - assert(lightLine.length === darkLine.length); - - for (const [lightToken, darkToken] of zip(lightLine, darkLine)) { - docEls.push({lightToken.content}); + // 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. + + while (lightLine.length && darkLine.length) { + // Simple case, same token. + if (lightLine[0].content === darkLine[0].content) { + docEls.push( + {lightLine[0].content} + ); + lightLine.shift(); + darkLine.shift(); + continue; + } + + if (lightLine[0].content.length < darkLine[0].content.length) { + docEls.push( + {lightLine[0].content} + ); + darkLine[0].content = darkLine[0].content.substr(lightLine[0].content.length); + lightLine.shift(); + continue; + } + + docEls.push( + {darkLine[0].content} + ); + lightLine[0].content = lightLine[0].content.substr(darkLine[0].content.length); + darkLine.shift(); } + docEls.push(
); } + docEls.pop(); // Remove last
+ return JSX.renderElement(<>{docEls}); } diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 0788f2ea3..d0e33effc 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -19,6 +19,7 @@ export { writeFileSync, } from "./fs"; export type { IfInternal, NeverIfInternal } from "./general"; +export { assertNever } from "./general"; export { CallbackLogger, ConsoleLogger, Logger, LogLevel } from "./loggers"; export { ArgumentsReader, diff --git a/src/lib/utils/jsx.ts b/src/lib/utils/jsx.ts index b79f895d1..b21e13fca 100644 --- a/src/lib/utils/jsx.ts +++ b/src/lib/utils/jsx.ts @@ -18,15 +18,15 @@ import type { JsxElement, JsxChildren, JsxComponent, -} from "./jsx.elements"; -import { JsxFragment as Fragment } from "./jsx.elements"; +} from "./jsx.elements.js"; +import { JsxFragment as Fragment } from "./jsx.elements.js"; // Backwards compatibility until 0.24 export type { JsxElement as Element, JsxChildren as Children, -} from "./jsx.elements"; -export { JsxFragment as Fragment } from "./jsx.elements"; +} from "./jsx.elements.js"; +export { JsxFragment as Fragment } from "./jsx.elements.js"; /** * Used to inject HTML directly into the document. diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index b06159a8d..8d166e5d3 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -3,6 +3,7 @@ import { DeclarationReflection, ProjectReflection, ReflectionKind, + Comment, } from "../lib/models"; function query(project: ProjectReflection, name: string) { @@ -58,13 +59,21 @@ export const behaviorTests: Record< const foo = query(project, "foo"); equal(foo.signatures?.length, 2); - equal(foo.signatures[0].comment?.summary, "Implementation comment"); - equal(foo.signatures[0].comment?.tags, []); + equal( + Comment.combineDisplayParts(foo.signatures[0].comment?.summary), + "Implementation comment" + ); + equal(foo.signatures[0].comment?.blockTags, []); - equal(foo.signatures[1].comment?.summary, "Overrides summary"); - equal(foo.signatures[1].comment?.tags, []); equal( - foo.signatures[1].parameters?.[0].comment?.summary.trim(), + Comment.combineDisplayParts(foo.signatures[1].comment?.summary), + "Overrides summary" + ); + equal(foo.signatures[1].comment?.blockTags, []); + equal( + Comment.combineDisplayParts( + foo.signatures[1].parameters?.[0].comment?.summary + ), "docs for x" ); diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index e83dd9bcc..9a38d6f21 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -4,7 +4,7 @@ import { lexBlockComment, Token, TokenSyntaxKind, -} from "../lib/converter/comments"; +} from "../lib/converter/comments/blockLexer"; function dedent(text: string) { const lines = text.split(/\r?\n/); @@ -396,7 +396,7 @@ describe("Block Comment Lexer", () => { ]); }); - it("Should handle starred comments without in code", () => { + it("Should handle starred comments without an end tag in code", () => { const tokens = lex( dedent(` /** @@ -412,4 +412,98 @@ describe("Block Comment Lexer", () => { { 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: "}" }, + ]); + }); }); diff --git a/src/test/converter.test.ts b/src/test/converter.test.ts index 4052bad1d..a6f2435f3 100644 --- a/src/test/converter.test.ts +++ b/src/test/converter.test.ts @@ -9,7 +9,7 @@ import { getConverterProgram, } from "./programs"; -describe("Converter", function () { +describe.skip("Converter", function () { const base = getConverterBase(); const app = getConverterApp(); diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index 95fa32a0c..f86e0e283 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -53,10 +53,16 @@ export const issueTests: { gh1164(project) { const refl = query(project, "gh1164"); equal( - refl.signatures?.[0]?.parameters?.[0]?.comment?.summary, + 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.\n"); }, gh1215(project) { @@ -241,9 +247,13 @@ export const issueTests: { gh1733(project) { const alias = query(project, "Foo"); - equal(alias.typeParameters?.[0].comment?.summary.trim(), "T docs"); + equal(alias.typeParameters?.[0].comment?.summary, [ + { kind: "text", text: "T docs\n" }, + ]); const cls = query(project, "Bar"); - equal(cls.typeParameters?.[0].comment?.summary.trim(), "T docs"); + equal(cls.typeParameters?.[0].comment?.summary, [ + { kind: "text", text: "T docs" }, + ]); }, gh1734(project) { @@ -252,9 +262,10 @@ 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\n" }, + ]), ]; equal(type.declaration.signatures?.[0].comment, expectedComment); }, @@ -273,6 +284,6 @@ export const issueTests: { ok(cat); ok(cat.children.includes(Foo)); - ok(!Foo.comment?.hasTag("category")); + ok(!Foo.comment?.hasModifier("category")); }, }; From 61b6bad0de393ecc4e72ec7c2f49824fdbe33d79 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 25 Nov 2021 12:11:07 -0700 Subject: [PATCH 012/151] WIP: Closer to a real comment parser --- CHANGELOG.md | 7 + src/lib/converter/comments/discovery.ts | 147 ++++- src/lib/converter/comments/index.ts | 259 ++------ src/lib/converter/comments/parser.ts | 266 ++++++++ src/lib/converter/context.ts | 45 +- src/lib/converter/converter.ts | 7 +- src/lib/converter/factories/comment.ts | 273 -------- src/lib/converter/factories/signature.ts | 37 +- src/lib/converter/jsdoc.ts | 6 +- src/lib/converter/plugins/CategoryPlugin.ts | 18 +- src/lib/converter/plugins/CommentPlugin.ts | 242 +++---- src/lib/converter/plugins/InheritDocPlugin.ts | 2 +- src/lib/converter/symbols.ts | 32 +- src/lib/converter/utils/reflections.ts | 1 + src/lib/models/comments/comment.ts | 20 +- src/lib/utils/options/declaration.ts | 2 +- src/lib/utils/options/sources/typedoc.ts | 8 + src/test/comments.test.ts | 135 +++- src/test/converter/alias/specs.json | 32 +- .../class/specs-with-lump-categories.json | 600 ++++++++++++------ src/test/converter/class/specs.json | 600 ++++++++++++------ src/test/converter/comment/specs.json | 423 +++++++++++- src/test/converter/enum/specs.json | 84 ++- src/test/converter/enum/specs.nodoc.json | 84 ++- src/test/converter/exports/specs.json | 97 ++- src/test/converter/function/specs.json | 403 ++++++++---- .../converter/inherit-param-doc/specs.json | 58 +- src/test/converter/inheritance/specs.json | 231 +++++-- src/test/converter/interface/specs.json | 70 +- src/test/converter/js/specs.json | 38 +- src/test/converter/mixin/specs.json | 73 ++- src/test/converter/types/specs.json | 56 +- src/test/converter/variables/specs.json | 56 +- src/test/converter/variables/specs.nodoc.json | 56 +- src/test/issueTests.ts | 10 +- src/test/renderer/testProject/src/generics.ts | 4 +- src/test/utils/options/options.test.ts | 4 +- 37 files changed, 2914 insertions(+), 1572 deletions(-) create mode 100644 src/lib/converter/comments/parser.ts delete mode 100644 src/lib/converter/factories/comment.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 839b3a69b..7dd3f1065 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Unreleased +### Currently Broken + +- Getting comments properly from interfaces & type aliases declared with `@typedef`, `@callback`. +- Inheriting comments from implemented interfaces. +- `@inheritDoc` +- Comment rendering + ## v0.22.10 (2021-11-25) ### Features diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 3ebb0eac1..469ce8de9 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -14,30 +14,27 @@ const wantedKinds: Record = { ], [ReflectionKind.EnumMember]: [ ts.SyntaxKind.EnumMember, + // This is here so that @enum gets it ts.SyntaxKind.PropertyAssignment, ], [ReflectionKind.Variable]: [ts.SyntaxKind.VariableDeclaration], - [ReflectionKind.Function]: [ - ts.SyntaxKind.FunctionDeclaration, - ts.SyntaxKind.VariableDeclaration, - ], + // Intentionally nothing here, comments will be placed on signatures. + [ReflectionKind.Function]: [], [ReflectionKind.Class]: [ts.SyntaxKind.ClassDeclaration], [ReflectionKind.Interface]: [ ts.SyntaxKind.InterfaceDeclaration, ts.SyntaxKind.JSDocTypedefTag, ], - [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor], + // Intentionally nothing here, comments will be placed on signatures. + [ReflectionKind.Constructor]: [], [ReflectionKind.Property]: [ ts.SyntaxKind.PropertyDeclaration, ts.SyntaxKind.PropertySignature, ts.SyntaxKind.JSDocPropertyTag, ts.SyntaxKind.BinaryExpression, ], - [ReflectionKind.Method]: [ - ts.SyntaxKind.MethodDeclaration, - ts.SyntaxKind.PropertyDeclaration, - ts.SyntaxKind.PropertySignature, - ], + // Intentionally nothing here, comments will be placed on signatures. + [ReflectionKind.Method]: [], [ReflectionKind.CallSignature]: [ ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration, @@ -74,18 +71,30 @@ export function discoverComment( symbol: ts.Symbol, kind: ReflectionKind ): [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); + for (const decl of symbol.declarations || []) { const text = decl.getSourceFile().text; if (wantedKinds[kind].includes(decl.kind)) { - const comments = ts.getLeadingCommentRanges(text, decl.pos); - const lastDocComment = comments - ?.reverse() - .find( - (c) => - text[c.pos] === "/" && - text[c.pos + 1] === "*" && - text[c.pos + 2] === "*" - ); + const node = declarationToCommentNode(decl); + if (!node) { + continue; + } + + const comments = ts.getLeadingCommentRanges(text, node.pos); + + if (reverse) { + comments?.reverse(); + } + + const lastDocComment = comments?.find( + (c) => + text[c.pos] === "/" && + text[c.pos + 1] === "*" && + text[c.pos + 2] === "*" + ); if (lastDocComment) { return [decl.getSourceFile(), lastDocComment]; @@ -93,3 +102,103 @@ export function discoverComment( } } } + +export function discoverSignatureComment( + declaration: ts.SignatureDeclaration | ts.JSDocSignature +): [ts.SourceFile, ts.CommentRange] | undefined { + const node = declarationToCommentNode(declaration); + if (!node) { + return; + } + + const text = node.getSourceFile().text; + const comments = ts.getLeadingCommentRanges(text, node.pos); + + const comment = comments?.find( + (c) => + text[c.pos] === "/" && + text[c.pos + 1] === "*" && + text[c.pos + 2] === "*" + ); + + 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.NamespaceExport) { + return node.parent; + } + + if (node.kind === ts.SyntaxKind.ExportSpecifier) { + return node.parent.parent; + } + + if ( + [ + ts.SyntaxKind.FunctionType, + ts.SyntaxKind.FunctionType, + ts.SyntaxKind.ArrowFunction, + ].includes(node.kind) + ) { + return node.parent; + } + + return node; +} diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index 75bd5eee0..475ffa33e 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -1,14 +1,9 @@ -import { ok } from "assert"; import * as ts from "typescript"; -import { - Comment, - CommentTag, - CommentDisplayPart, - ReflectionKind, -} from "../../models"; +import type { Comment, ReflectionKind } from "../../models"; import { assertNever, Logger } from "../../utils"; -import { lexBlockComment, Token, TokenSyntaxKind } from "./blockLexer"; -import { discoverComment } from "./discovery"; +import { lexBlockComment } from "./blockLexer"; +import { discoverComment, discoverSignatureComment } from "./discovery"; +import { parseComment } from "./parser"; export interface CommentParserConfig { blockTags: Set; @@ -23,6 +18,8 @@ export function getComment( logger: Logger ): Comment | undefined { const comment = discoverComment(symbol, kind); + let resultingComment: Comment | undefined; + if (comment) { const [file, range] = comment; const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); @@ -31,239 +28,57 @@ export function getComment( switch (range.kind) { case ts.SyntaxKind.MultiLineCommentTrivia: - return parseComment( + resultingComment = parseComment( lexBlockComment(file.text, range.pos, range.end), config, warning ); + break; case ts.SyntaxKind.SingleLineCommentTrivia: throw "GERRIT FIX ME"; default: assertNever(range.kind); } } -} - -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; - }, - }; -} - -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)); - } - - return comment; -} - -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; - - const tag = new CommentTag( - tagName, - blockContent(comment, lexer, config, warning) - ); - - if ( - tagName === "@param" && - tag.content.length && - tag.content[0].kind === "text" - ) { - const firstPart = tag.content[0]; - const match = firstPart.text.match(/^([a-z_$]+)\s*(-\s*)?/); - if (match) { - tag.paramName = match[1]; - firstPart.text = firstPart.text.substr(match[0].length); + if (symbol.declarations?.some(ts.isSourceFile) && resultingComment) { + // 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 ( + !resultingComment.hasModifier("@packageDocumentation") && + !resultingComment.getTag("@module") + ) { + return; } } - return tag; + return resultingComment; } -function blockContent( - comment: Comment, - lexer: LookaheadGenerator, +export function getSignatureComment( + declaration: ts.SignatureDeclaration | ts.JSDocSignature, config: CommentParserConfig, - warning: (msg: string) => void -): CommentDisplayPart[] { - const content: CommentDisplayPart[] = []; - let atNewLine = true; - - loop: while (!lexer.done()) { - const next = lexer.peek(); - - 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 (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, bug 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: "code", text: next.text }); - break; + logger: Logger +): Comment | undefined { + const comment = discoverSignatureComment(declaration); - case TokenSyntaxKind.OpenBrace: - inlineTag(lexer, content, config, warning); - break; + if (comment) { + const [file, range] = comment; + const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); + const warning = (warning: string) => + logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); + switch (range.kind) { + case ts.SyntaxKind.MultiLineCommentTrivia: + return parseComment( + lexBlockComment(file.text, range.pos, range.end), + config, + warning + ); + case ts.SyntaxKind.SingleLineCommentTrivia: + throw "GERRIT FIX ME"; default: - assertNever(next.kind); - } - - if (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++; - } - } - - 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 }); - block.push({ kind: "text", 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" - ); + assertNever(range.kind); } - - 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, - text: content.join(""), - }); } diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts new file mode 100644 index 000000000..16d7f1821 --- /dev/null +++ b/src/lib/converter/comments/parser.ts @@ -0,0 +1,266 @@ +import { ok } from "assert"; +import type { CommentParserConfig } from "."; +import { Comment, CommentDisplayPart, CommentTag } from "../../models"; +import { assertNever } from "../../utils"; +import { Token, TokenSyntaxKind } from "./blockLexer"; + +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); + + return comment; +} + +const HAS_PARAM_NAME: `@${string}`[] = ["@param", "@template", "@typeParam"]; + +function postProcessComment(comment: Comment) { + for (const tag of comment.blockTags) { + if (HAS_PARAM_NAME.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; + + const startOfText = + end + + Math.max(0, first.text.substring(end).search(/[^\-\s]/)); + + tag.paramName = first.text.substring(0, end); + first.text = first.text.substring(startOfText); + + if (first.text === "") { + tag.content.shift(); + } + } + } + } +} + +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; + + const tag = new CommentTag( + tagName as `@${string}`, + blockContent(comment, lexer, config, warning) + ); + + if ( + tagName === "@param" && + tag.content.length && + tag.content[0].kind === "text" + ) { + const firstPart = tag.content[0]; + const match = firstPart.text.match(/^([a-z_$]+)\s*(-\s*)?/); + if (match) { + tag.paramName = match[1]; + firstPart.text = firstPart.text.substr(match[0].length); + } + } + + return tag; +} + +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(); + + 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 (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, bug 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); + break; + + default: + assertNever(next.kind); + } + + if (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 */; ) { + content[i].text = content[i].text.trim(); + 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 }); + block.push({ kind: "text", 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, + text: content.join(""), + }); +} diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index b83e628b4..042b8cc88 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -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; @@ -180,8 +167,9 @@ export class Context { return resolveAliasedSymbol(symbol, this.checker); } + // TODO: This needs to live on Application, and get constructed based on user input. config: CommentParserConfig = { - blockTags: new Set(["@param", "@remarks"]), + blockTags: new Set(["@param", "@remarks", "@module"]), inlineTags: new Set(["@link"]), modifierTags: new Set([ "@public", @@ -189,6 +177,8 @@ export class Context { "@protected", "@readonly", "@enum", + "@event", + "@packageDocumentation", ]), }; @@ -203,7 +193,16 @@ export class Context { nameOverride ?? exportSymbol?.name ?? symbol?.name ?? "unknown" ); const reflection = new DeclarationReflection(name, kind, this.scope); - if (symbol) { + + if (exportSymbol) { + reflection.comment = getComment( + exportSymbol, + reflection.kind, + this.config, + this.logger + ); + } + if (symbol && !reflection.comment) { reflection.comment = getComment( symbol, reflection.kind, @@ -211,9 +210,11 @@ export class Context { this.logger ); } + if (this.shouldBeStatic) { reflection.setFlag(ReflectionFlag.Static); } + reflection.escapedName = symbol?.escapedName; this.addChild(reflection); @@ -228,22 +229,12 @@ export class Context { 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) { diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index a8c4c7ed9..3c2ce8850 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -322,12 +322,7 @@ export class Converter extends ChildableComponent< void 0, entryName ); - context.finalizeDeclarationReflection( - reflection, - symbol, - void 0, - node - ); + context.finalizeDeclarationReflection(reflection); moduleContext = context.withScope(reflection); } diff --git a/src/lib/converter/factories/comment.ts b/src/lib/converter/factories/comment.ts deleted file mode 100644 index a6c78aa56..000000000 --- a/src/lib/converter/factories/comment.ts +++ /dev/null @@ -1,273 +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; - - 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 { - // comment.summary += (comment.summary === "" ? "" : "\n") + line; - } - } - - 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.blockTags.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); - - // comment.summary = comment.summary.trim(); - return comment; -} diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index e3768bf71..2eb51265a 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -15,6 +15,7 @@ import type { Context } from "../context"; import { ConverterEvents } from "../converter-events"; import { convertDefaultValue } from "../convert-expression"; import { removeUndefined } from "../utils/reflections"; +import { getSignatureComment } from "../comments"; export function createSignature( context: Context, @@ -24,25 +25,9 @@ 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 - | ts.SignatureDeclaration - | undefined; - - if ( - !commentDeclaration && - declaration && - (ts.isArrowFunction(declaration) || - ts.isFunctionExpression(declaration)) - ) { - commentDeclaration = declaration.parent; - } - commentDeclaration ??= declaration; const sigRef = new SignatureReflection( kind == ReflectionKind.ConstructorSignature @@ -51,6 +36,13 @@ export function createSignature( kind, context.scope ); + if (declaration) { + sigRef.comment = getSignatureComment( + declaration, + context.config, + context.logger + ); + } sigRef.typeParameters = convertTypeParameters( context, @@ -95,18 +87,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: readonly (ts.Symbol & { type: ts.Type })[], - parameterNodes: readonly ts.ParameterDeclaration[] | undefined + parameterNodes: + | readonly ts.ParameterDeclaration[] + | readonly ts.JSDocParameterTag[] + | undefined ) { return parameters.map((param, i) => { const declaration = param.valueDeclaration as diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index 4f16759af..0bb0e030c 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -49,7 +49,7 @@ export function convertJsDocAlias( declaration.parent ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } export function convertJsDocCallback( @@ -63,7 +63,7 @@ export function convertJsDocCallback( symbol, exportSymbol ); - context.finalizeDeclarationReflection(alias, symbol, exportSymbol); + context.finalizeDeclarationReflection(alias); const ac = context.withScope(alias); @@ -82,7 +82,7 @@ function convertJsDocInterface( symbol, exportSymbol ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const rc = context.withScope(reflection); diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index 34c9cb9d1..f469ccb09 100644 --- a/src/lib/converter/plugins/CategoryPlugin.ts +++ b/src/lib/converter/plugins/CategoryPlugin.ts @@ -3,13 +3,13 @@ import { ContainerReflection, DeclarationReflection, CommentTag, + Comment, } from "../../models"; import { ReflectionCategory } from "../../models/ReflectionCategory"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; import { BindOption } from "../../utils"; -import type { Comment } from "../../models/comments/index"; /** * A handler that sorts and categorizes the found reflections in the resolving phase. @@ -185,15 +185,15 @@ export class CategoryPlugin extends ConverterComponent { const tags = comment.blockTags; const commentTags: CommentTag[] = []; tags.forEach((tag) => { - if (tag.tag !== "category") { + if (tag.tag !== "@category") { commentTags.push(tag); return; } - // const text = tag.text.trim(); - // if (!text) { - // return; - // } - // categories.add(text); + const text = Comment.combineDisplayParts(tag.content).trim(); + if (!text) { + return; + } + categories.add(text); }); comment.blockTags = commentTags; return categories; @@ -212,9 +212,9 @@ export class CategoryPlugin extends ConverterComponent { } if (reflection.type?.type === "reflection") { - reflection.type.declaration.comment?.removeTags("category"); + reflection.type.declaration.comment?.removeTags("@category"); reflection.type.declaration.signatures?.forEach((s) => - s.comment?.removeTags("category") + s.comment?.removeTags("@category") ); } diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 3cb2d8da6..4294b9ae8 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -1,7 +1,4 @@ -import * as ts from "typescript"; - import { Component, ConverterComponent } from "../components"; -import { parseComment, getRawComment } from "../factories/comment"; import { Converter } from "../converter"; import type { Context } from "../context"; import { @@ -13,7 +10,6 @@ import { SignatureReflection, ParameterReflection, Comment, - CommentTag, ReflectionType, SourceReference, } from "../../models"; @@ -37,17 +33,17 @@ const DEBUG = true as boolean; * 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,7 @@ const TAG_BLACKLIST = [ @Component({ name: "comment" }) export class CommentPlugin extends ConverterComponent { @BindOption("excludeTags") - excludeTags!: string[]; + excludeTags!: `@${string}`[]; /** * Create a new CommentPlugin instance. @@ -78,38 +74,38 @@ export class CommentPlugin extends ConverterComponent { * @param comment The comment that should be searched for modifiers. */ private applyModifiers(reflection: Reflection, comment: Comment) { - if (comment.hasModifier("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.hasModifier("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.hasModifier("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.hasModifier("event")) { + if (comment.hasModifier("@event")) { if (reflection.kindOf(ReflectionKind.CallSignature)) { if (reflection.parent) { reflection.parent.kind = ReflectionKind.Event; } } reflection.kind = ReflectionKind.Event; - comment.removeTags("event"); + comment.removeModifier("@event"); } if ( @@ -118,8 +114,8 @@ export class CommentPlugin extends ConverterComponent { ) || reflection.kind === ReflectionKind.Project ) { - comment.removeTags("module"); - comment.removeTags("packagedocumentation"); + comment.removeTags("@module"); + comment.removeModifier("@packageDocumentation"); } } @@ -131,11 +127,11 @@ export class CommentPlugin extends ConverterComponent { */ private onCreateTypeParameter( _context: Context, - _reflection: TypeParameterReflection, - _node?: ts.Node + reflection: TypeParameterReflection ) { if (DEBUG) return; + // GERRIT // if (node && ts.isJSDocTemplateTag(node.parent)) { // const comment = getJsDocCommentText(node.parent.comment); // if (comment) { @@ -143,24 +139,24 @@ export class CommentPlugin extends ConverterComponent { // } // } - // const comment = reflection.parent && reflection.parent.comment; - // if (comment) { - // let tag = comment.getTag("typeparam", reflection.name); - // if (!tag) { - // tag = comment.getTag("template", reflection.name); - // } - // if (!tag) { - // tag = comment.getTag("param", `<${reflection.name}>`); - // } - // if (!tag) { - // tag = comment.getTag("param", reflection.name); - // } + const comment = reflection.parent?.comment; + if (comment) { + let tag = comment.getParamTag(reflection.name, "@typeParam"); + if (!tag) { + tag = comment.getParamTag(reflection.name, "@template"); + } + if (!tag) { + tag = comment.getParamTag(`<${reflection.name}>`, "@param"); + } + if (!tag) { + tag = comment.getParamTag(reflection.name, "@param"); + } - // if (tag) { - // reflection.comment = new Comment(tag.text); - // removeIfPresent(comment.blockTags, tag); - // } - // } + if (tag) { + reflection.comment = new Comment(tag.content); + removeIfPresent(comment.blockTags, tag); + } + } } /** @@ -172,72 +168,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 (DEBUG) return; - - if (reflection.kindOf(ReflectionKind.FunctionOrMethod)) { - // 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)) - ) { - 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) - ); - 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) { - // reflection.name = newName; - // } + const newName = Comment.combineDisplayParts(tag.content).trim(); + if (newName.length && !newName.includes("\n")) { + reflection.name = newName; + } removeIfPresent(comment.blockTags, tag); } } this.applyModifiers(reflection, comment); this.removeExcludedTags(comment); - reflection.comment = comment; } /** @@ -309,53 +258,29 @@ export class CommentPlugin extends ConverterComponent { } if (reflection.type instanceof ReflectionType) { - this.addCommentToSignatures( - reflection, + this.processSignatureComments( reflection.type.declaration.getNonIndexSignatures() ); } else { - this.addCommentToSignatures( - reflection, - reflection.getNonIndexSignatures() - ); + this.processSignatureComments(reflection.getNonIndexSignatures()); } } - private addCommentToSignatures( - reflection: DeclarationReflection, - signatures: SignatureReflection[] - ) { + private processSignatureComments(signatures: SignatureReflection[]) { if (!signatures.length) { return; } - const comment = reflection.comment; - signatures.forEach((signature) => { - let childComment = signature.comment; - - if (comment) { - if (!childComment) { - childComment = signature.comment = new Comment(); - } - - childComment.summary = childComment.summary.length - ? childComment.summary - : Comment.cloneDisplayParts(comment.summary); - childComment.blockTags = childComment.blockTags.length - ? childComment.blockTags - : comment.blockTags.map((tag) => tag.clone()); - childComment.modifierTags = childComment.modifierTags.size - ? childComment.modifierTags - : new Set(comment.modifierTags); - } + const childComment = signature.comment; + if (!childComment) return; signature.parameters?.forEach((parameter, index) => { - let tag: CommentTag | undefined; - if (childComment && parameter.name === "__namedParameters") { - const commentParams = childComment?.blockTags.filter( + if (parameter.name === "__namedParameters") { + const commentParams = childComment.blockTags.filter( (tag) => - tag.tag === "param" && !tag.paramName?.includes(".") + tag.tag === "@param" && + !tag.paramName?.includes(".") ); if ( signature.parameters?.length === commentParams.length && @@ -364,13 +289,10 @@ export class CommentPlugin extends ConverterComponent { parameter.name = commentParams[index].paramName!; } } - if (childComment) { - moveNestedParamTags(childComment, parameter); - tag = childComment.getParamTag(parameter.name); - } - if (comment && !tag) { - tag = comment.getParamTag(parameter.name); - } + + moveNestedParamTags(childComment, parameter); + const tag = childComment.getParamTag(parameter.name); + if (tag) { parameter.comment = new Comment( Comment.cloneDisplayParts(tag.content) @@ -379,22 +301,10 @@ export class CommentPlugin extends ConverterComponent { }); signature.typeParameters?.forEach((parameter) => { - let tag: CommentTag | undefined; - if (childComment) { - tag = - childComment.getParamTag( - parameter.name, - "@typeParam" - ) || - childComment.getParamTag(parameter.name, "@template") || - childComment.getParamTag(`<${parameter.name}>`); - } - if (comment && !tag) { - tag = - comment.getParamTag(parameter.name, "@typeParam") || - comment.getParamTag(parameter.name, "@template") || - comment.getParamTag(`<${parameter.name}>`); - } + const tag = + childComment.getParamTag(parameter.name, "@typeParam") || + childComment.getParamTag(parameter.name, "@template") || + childComment.getParamTag(`<${parameter.name}>`); if (tag) { parameter.comment = new Comment( Comment.cloneDisplayParts(tag.content) @@ -402,20 +312,20 @@ export class CommentPlugin extends ConverterComponent { } }); - childComment?.removeTags("param"); - childComment?.removeTags("typeparam"); - childComment?.removeTags("template"); + childComment?.removeTags("@param"); + childComment?.removeTags("@typeParam"); + childComment?.removeTags("@template"); }); - - delete reflection.comment; } 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); } } @@ -451,9 +361,9 @@ export class CommentPlugin extends ConverterComponent { } return ( - comment.hasModifier("hidden") || - comment.hasModifier("ignore") || - (comment.hasModifier("internal") && excludeInternal) + comment.hasModifier("@hidden") || + comment.hasModifier("@ignore") || + (comment.hasModifier("@internal") && excludeInternal) ); } } @@ -463,7 +373,7 @@ function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) { if (parameter.type instanceof ReflectionType) { const tags = comment.blockTags.filter( (t) => - t.tag === "param" && + t.tag === "@param" && t.paramName?.startsWith(`${parameter.name}.`) ); for (const tag of tags) { diff --git a/src/lib/converter/plugins/InheritDocPlugin.ts b/src/lib/converter/plugins/InheritDocPlugin.ts index 7491cb5e7..cb7108514 100644 --- a/src/lib/converter/plugins/InheritDocPlugin.ts +++ b/src/lib/converter/plugins/InheritDocPlugin.ts @@ -55,7 +55,7 @@ export class InheritDocPlugin extends ConverterComponent { const descendantsCallback: TraverseCallback = (item) => { item.traverse(descendantsCallback); const inheritDoc = - item.comment?.getTag("inheritdoc")?.paramName; + item.comment?.getTag("@inheritDoc")?.paramName; const source = inheritDoc && reflection.findReflectionByName(inheritDoc); let referencedReflection = source; diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 0fe559ce9..cee3cc5af 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -210,7 +210,7 @@ function convertEnum( reflection.setFlag(ReflectionFlag.Const); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); convertSymbols( context.withScope(reflection), @@ -237,7 +237,7 @@ function convertEnumMember( ) ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } function convertNamespace( @@ -266,7 +266,7 @@ function convertNamespace( symbol, exportSymbol ); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); convertSymbols( context.withScope(reflection), @@ -310,7 +310,7 @@ 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 @@ -414,7 +414,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 ??= []; @@ -482,7 +482,7 @@ function convertClassOrInterface( reflection.implementedTypes = implementedTypes; } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); if (classDeclaration) { // Classes can have static props @@ -678,7 +678,7 @@ function convertProperty( reflection.type = removeUndefined(reflection.type); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } function convertArrowAsMethod( @@ -694,7 +694,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); @@ -711,7 +711,7 @@ function convertConstructor(context: Context, symbol: ts.Symbol) { void 0, "constructor" ); - context.finalizeDeclarationReflection(reflection, symbol); + context.finalizeDeclarationReflection(reflection); const reflectionContext = context.withScope(reflection); @@ -857,7 +857,7 @@ function convertVariable( reflection.defaultValue = convertDefaultValue(declaration); - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); } function isEnumLike(checker: ts.TypeChecker, type: ts.Type, location: ts.Node) { @@ -881,7 +881,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; @@ -902,7 +902,7 @@ function convertVariableAsEnum( reflection.defaultValue = JSON.stringify(propType.value); - rc.finalizeDeclarationReflection(reflection, prop, void 0); + rc.finalizeDeclarationReflection(reflection); } // Skip converting the type alias, if there is one @@ -944,7 +944,7 @@ function convertVariableAsFunction( ); } - context.finalizeDeclarationReflection(reflection, symbol, exportSymbol); + context.finalizeDeclarationReflection(reflection); const reflectionContext = context.withScope(reflection); @@ -953,9 +953,7 @@ function convertVariableAsFunction( createSignature( reflectionContext, ReflectionKind.CallSignature, - signature, - void 0, - declaration + signature ); } } @@ -977,7 +975,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/utils/reflections.ts b/src/lib/converter/utils/reflections.ts index bd2bff0f0..5a5ff0bd8 100644 --- a/src/lib/converter/utils/reflections.ts +++ b/src/lib/converter/utils/reflections.ts @@ -24,6 +24,7 @@ export function removeUndefined(type: SomeType): SomeType { * @param source - Referenced reflection */ export function copyComment(_target: Reflection, _source: Reflection) { + // GERRIT // if ( // target.comment && // source.comment && diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 53c1aca9d..52e3bd940 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -14,10 +14,10 @@ export class CommentTag { /** * The name of this tag, e.g. `@returns`, `@example` */ - tag: string; + tag: `@${string}`; /** - * If this is a `@param` tag, the parameter name associated with it. + * If this is a `@param`, `@typeParam`, or `@template` tag, the parameter name associated with it. */ paramName?: string; @@ -29,7 +29,7 @@ export class CommentTag { /** * Create a new CommentTag instance. */ - constructor(tag: string, text: CommentDisplayPart[]) { + constructor(tag: `@${string}`, text: CommentDisplayPart[]) { this.tag = tag; this.content = text; } @@ -124,7 +124,7 @@ export class Comment { */ hasVisibleComponent(): boolean { return ( - this.summary.some((x) => x.kind != "text" || x.text !== "") || + this.summary.some((x) => x.kind !== "text" || x.text !== "") || this.blockTags.length > 0 ); } @@ -135,10 +135,14 @@ 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. */ - hasModifier(tagName: string): boolean { + hasModifier(tagName: `@${string}`): boolean { return this.modifierTags.has(tagName); } + removeModifier(tagName: `@${string}`) { + this.modifierTags.delete(tagName); + } + /** * Return the first tag with the given name. * @@ -146,11 +150,11 @@ export class Comment { * @param paramName An optional parameter name to look for. * @returns The found tag or undefined. */ - getTag(tagName: string): CommentTag | undefined { + getTag(tagName: `@${string}`): CommentTag | undefined { return this.blockTags.find((tag) => tag.tag === tagName); } - getParamTag(param: string, tagName = "@param") { + getParamTag(param: string, tagName: `@${string}` = "@param") { return this.blockTags.find( (tag) => tag.tag === tagName && tag.paramName === param ); @@ -160,7 +164,7 @@ export class Comment { * Removes all tags with the given tag name from the comment. * @param tagName */ - removeTags(tagName: string) { + removeTags(tagName: `@${string}`) { removeIf(this.blockTags, (tag) => tag.tag === tagName); } } diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 5b600cba9..84126a68a 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -86,7 +86,7 @@ export interface TypeDocOptionMap { name: string; includeVersion: boolean; - excludeTags: string[]; + excludeTags: `@${string}`[]; readme: string; defaultCategory: string; categoryOrder: string[]; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 8d9ebd79d..7f3866d31 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -186,6 +186,14 @@ export function addTypeDocOptions(options: Pick) { name: "excludeTags", help: "Remove the listed tags from doc comments.", type: ParameterType.Array, + validate(value) { + const missingAt = value.filter((tag) => !tag.startsWith("@")); + if (missingAt.length) { + throw new Error( + `excludeTags must specify tags with a leading "@"` + ); + } + }, }); options.addDeclaration({ name: "readme", diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index 9a38d6f21..c92f39923 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -1,10 +1,13 @@ -import { deepStrictEqual as equal } from "assert"; +import { deepStrictEqual as equal, fail } from "assert"; +import type { CommentParserConfig } from "../lib/converter/comments"; import { lexBlockComment, Token, TokenSyntaxKind, } from "../lib/converter/comments/blockLexer"; +import { parseComment } from "../lib/converter/comments/parser"; +import { Comment, CommentTag } from "../lib/models"; function dedent(text: string) { const lines = text.split(/\r?\n/); @@ -507,3 +510,133 @@ describe("Block Comment Lexer", () => { ]); }); }); + +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", + ]), + }; + + 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.paramName = "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.paramName = "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.paramName = "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.paramName = "T"; + + equal(comment.blockTags, [tag]); + equal(comment.modifierTags, new Set()); + } + ); +}); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index efae8f7b0..970070f01 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -12,7 +12,12 @@ "kindString": "Type alias", "flags": {}, "comment": { - "summary": "Conditional types from TS2.8" + "summary": [ + { + "kind": "text", + "text": "Conditional types from TS2.8" + } + ] }, "typeParameter": [ { @@ -51,7 +56,12 @@ "kindString": "Type alias", "flags": {}, "comment": { - "summary": "Extracts the type of a promise." + "summary": [ + { + "kind": "text", + "text": "Extracts the type of a promise." + } + ] }, "typeParameter": [ { @@ -96,6 +106,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A type that describes a compare function, e.g. for array.sort()." + } + ] + }, "typeParameter": [ { "id": 6, @@ -120,9 +138,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "A type that describes a compare function, e.g. for array.sort()." - }, "parameters": [ { "id": 4, @@ -165,7 +180,12 @@ "kindString": "Type alias", "flags": {}, "comment": { - "summary": "A type for IDs." + "summary": [ + { + "kind": "text", + "text": "A type for IDs." + } + ] }, "type": { "type": "union", diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 124f09bff..751361e57 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -20,9 +20,35 @@ "isPrivate": true }, "comment": { - "summary": "A class that is documented as being private." + "summary": [ + { + "kind": "text", + "text": "A class that is documented as being private." + } + ] }, "children": [ + { + "id": 11, + "name": "constructor", + "kind": 512, + "kindString": "Constructor", + "flags": {}, + "signatures": [ + { + "id": 12, + "name": "new PrivateClass", + "kind": 16384, + "kindString": "Constructor signature", + "flags": {}, + "type": { + "type": "reference", + "id": 8, + "name": "PrivateClass" + } + } + ] + }, { "id": 13, "name": "fakePrivateProperty", @@ -32,7 +58,12 @@ "isPrivate": true }, "comment": { - "summary": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -48,7 +79,12 @@ "isProtected": true }, "comment": { - "summary": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -96,7 +132,12 @@ "isPrivate": true }, "comment": { - "summary": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -123,7 +164,12 @@ "isProtected": true }, "comment": { - "summary": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -156,6 +202,13 @@ } ], "groups": [ + { + "title": "Constructors", + "kind": 512, + "children": [ + 11 + ] + }, { "title": "Properties", "kind": 1024, @@ -191,7 +244,12 @@ "isPrivate": true }, "comment": { - "summary": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, "type": { "type": "literal", @@ -208,7 +266,12 @@ "isProtected": true }, "comment": { - "summary": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, "type": { "type": "literal", @@ -234,7 +297,12 @@ "isPrivate": true }, "comment": { - "summary": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -261,7 +329,12 @@ "isProtected": true }, "comment": { - "summary": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -325,7 +398,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -735,11 +813,21 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "TestClass comment short text.\n\nTestClass comment text.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "[[TestClass]] @ fixtures" + } + ] } ] }, @@ -757,9 +845,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "type": { "type": "reference", "id": 22, @@ -777,7 +862,12 @@ "isPrivate": true }, "comment": { - "summary": "privateProperty short text." + "summary": [ + { + "kind": "text", + "text": "privateProperty short text." + } + ] }, "type": { "type": "array", @@ -796,7 +886,12 @@ "isPublic": true }, "comment": { - "summary": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, "type": { "type": "intrinsic", @@ -812,7 +907,12 @@ "isStatic": true }, "comment": { - "summary": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, "type": { "type": "reference", @@ -834,7 +934,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -859,7 +964,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "privateMethod short text." + "summary": [ + { + "kind": "text", + "text": "privateMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -884,7 +994,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -909,7 +1024,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -934,7 +1054,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1029,9 +1154,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "parameters": [ { "id": 44, @@ -1039,9 +1161,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor param" - }, "type": { "type": "intrinsic", "name": "any" @@ -1053,9 +1172,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Private string property" - }, "type": { "type": "intrinsic", "name": "string" @@ -1067,9 +1183,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Public number property" - }, "type": { "type": "intrinsic", "name": "number" @@ -1081,9 +1194,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Public implicit any property\n" - }, "type": { "type": "intrinsic", "name": "any" @@ -1143,7 +1253,12 @@ "isPublic": true }, "comment": { - "summary": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, "type": { "type": "intrinsic", @@ -1164,7 +1279,12 @@ "isStatic": true }, "comment": { - "summary": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, "type": { "type": "reference", @@ -1191,7 +1311,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -1224,7 +1349,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "mergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "mergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1249,7 +1379,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1284,7 +1419,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1319,7 +1459,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1414,7 +1559,12 @@ "isPrivate": true }, "comment": { - "summary": "Docs" + "summary": [ + { + "kind": "text", + "text": "Docs" + } + ] }, "type": { "type": "intrinsic", @@ -1518,7 +1668,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A class with constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with constructor properties." + } + ] }, "children": [ { @@ -1534,7 +1689,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 97, @@ -1542,9 +1696,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "X component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1556,9 +1707,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Y component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1570,9 +1718,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Vector name\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1660,7 +1805,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A class with inherited and overwritten constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with inherited and overwritten constructor properties." + } + ] }, "children": [ { @@ -1676,7 +1826,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 106, @@ -1684,9 +1833,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "X component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1698,9 +1844,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Y component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1712,9 +1855,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Z component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1726,9 +1866,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Vector name\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1874,21 +2011,13 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "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, @@ -1917,27 +2046,6 @@ "kind": 2048, "kindString": "Method", "flags": {}, - "decorators": [ - { - "name": "decoratorAtom", - "type": { - "type": "reference", - "id": 115, - "name": "decoratorAtom" - } - }, - { - "name": "decoratorWithParam", - "type": { - "type": "reference", - "id": 120, - "name": "decoratorWithParam" - }, - "arguments": { - "value": "false" - } - } - ], "signatures": [ { "id": 132, @@ -1946,7 +2054,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorated method." + "summary": [ + { + "kind": "text", + "text": "A decorated method." + } + ] }, "type": { "type": "intrinsic", @@ -1979,13 +2092,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 131, - "name": "decoratedMethod" - } - ], "signatures": [ { "id": 116, @@ -1994,7 +2100,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator with no options." + "summary": [ + { + "kind": "text", + "text": "A decorator with no options." + } + ] }, "parameters": [ { @@ -2059,13 +2170,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 128, - "name": "DecoratedClass" - } - ], "signatures": [ { "id": 124, @@ -2074,7 +2178,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator consuming an options object." + "summary": [ + { + "kind": "text", + "text": "A decorator consuming an options object." + } + ] }, "parameters": [ { @@ -2083,9 +2192,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The options object of this decorator." - }, "type": { "type": "reflection", "declaration": { @@ -2101,9 +2207,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "A property on the options object of this decorator.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -2136,13 +2239,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 131, - "name": "decoratedMethod" - } - ], "signatures": [ { "id": 121, @@ -2151,7 +2247,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator with a parameter." + "summary": [ + { + "kind": "text", + "text": "A decorator with a parameter." + } + ] }, "parameters": [ { @@ -2160,9 +2261,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The parameter of this decorator.\n" - }, "type": { "type": "intrinsic", "name": "boolean" @@ -2240,7 +2338,12 @@ "isStatic": true }, "comment": { - "summary": "This is an event documentation." + "summary": [ + { + "kind": "text", + "text": "This is an event documentation." + } + ] }, "type": { "type": "intrinsic", @@ -2291,11 +2394,21 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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,7 +2427,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for a general event by name." + "summary": [ + { + "kind": "text", + "text": "Subscribe for a general event by name." + } + ] }, "parameters": [ { @@ -2323,9 +2441,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "intrinsic", "name": "string" @@ -2337,9 +2452,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The handler called when the event occurs.\n" - }, "type": { "type": "reflection", "declaration": { @@ -2390,7 +2502,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for error notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for error notifications." + } + ] }, "parameters": [ { @@ -2399,9 +2516,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "error" @@ -2413,9 +2527,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A handler that will receive the error details\n" - }, "type": { "type": "reflection", "declaration": { @@ -2466,7 +2577,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for progress notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for progress notifications." + } + ] }, "parameters": [ { @@ -2475,9 +2591,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "progress" @@ -2489,9 +2602,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A handler that will receive a progress event with the current and expected total bytes\n" - }, "type": { "type": "reflection", "declaration": { @@ -2542,7 +2652,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for success notification." + "summary": [ + { + "kind": "text", + "text": "Subscribe for success notification." + } + ] }, "parameters": [ { @@ -2551,9 +2666,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "complete" @@ -2565,9 +2677,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A function that will be called with general event data upon successful completion\n" - }, "type": { "type": "reflection", "declaration": { @@ -2649,7 +2758,24 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "GenericClass short text." + "summary": [ + { + "kind": "text", + "text": "GenericClass short text." + } + ], + "blockTags": [ + { + "tag": "@param", + "content": [ + { + "kind": "text", + "text": "Generic parameter." + } + ], + "paramName": "T" + } + ] }, "children": [ { @@ -2665,9 +2791,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "typeParameter": [ { "id": 169, @@ -2684,9 +2807,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor parameter.\n" - }, "type": { "type": "reference", "id": 169, @@ -2718,7 +2838,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, "type": { "type": "reference", @@ -2735,7 +2860,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, "type": { "type": "array", @@ -2760,8 +2890,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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", @@ -2802,10 +2947,7 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {}, - "comment": { - "summary": "Generic parameter.\n" - } + "flags": {} } ], "extendedBy": [ @@ -2823,7 +2965,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "NonGenericClass short text." + "summary": [ + { + "kind": "text", + "text": "NonGenericClass short text." + } + ] }, "children": [ { @@ -2839,9 +2986,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "parameters": [ { "id": 179, @@ -2849,9 +2993,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor parameter.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -2885,7 +3026,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, "type": { "type": "intrinsic", @@ -2906,7 +3052,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, "type": { "type": "array", @@ -2935,8 +3086,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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", @@ -3205,7 +3371,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "ChainClass comment short text.\n\nChainClass comment text." + "summary": [ + { + "kind": "text", + "text": "ChainClass comment short text.\n\nChainClass comment text." + } + ] }, "children": [ { @@ -3245,7 +3416,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Chain method that returns this." + "summary": [ + { + "kind": "text", + "text": "Chain method that returns this." + } + ] }, "type": { "type": "reference", @@ -3399,11 +3575,21 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "TestClass comment short text.\n\nTestClass comment text.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "[[TestClass]] @ fixtures" + } + ] } ] }, diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index eddde2059..f590b2a43 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -20,9 +20,35 @@ "isPrivate": true }, "comment": { - "summary": "A class that is documented as being private." + "summary": [ + { + "kind": "text", + "text": "A class that is documented as being private." + } + ] }, "children": [ + { + "id": 11, + "name": "constructor", + "kind": 512, + "kindString": "Constructor", + "flags": {}, + "signatures": [ + { + "id": 12, + "name": "new PrivateClass", + "kind": 16384, + "kindString": "Constructor signature", + "flags": {}, + "type": { + "type": "reference", + "id": 8, + "name": "PrivateClass" + } + } + ] + }, { "id": 13, "name": "fakePrivateProperty", @@ -32,7 +58,12 @@ "isPrivate": true }, "comment": { - "summary": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -48,7 +79,12 @@ "isProtected": true }, "comment": { - "summary": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -96,7 +132,12 @@ "isPrivate": true }, "comment": { - "summary": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -123,7 +164,12 @@ "isProtected": true }, "comment": { - "summary": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -156,6 +202,13 @@ } ], "groups": [ + { + "title": "Constructors", + "kind": 512, + "children": [ + 11 + ] + }, { "title": "Properties", "kind": 1024, @@ -191,7 +244,12 @@ "isPrivate": true }, "comment": { - "summary": "A variable that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made private via comment." + } + ] }, "type": { "type": "literal", @@ -208,7 +266,12 @@ "isProtected": true }, "comment": { - "summary": "A variable that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A variable that is made protected via comment." + } + ] }, "type": { "type": "literal", @@ -234,7 +297,12 @@ "isPrivate": true }, "comment": { - "summary": "A function that is made private via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made private via comment." + } + ] }, "type": { "type": "intrinsic", @@ -261,7 +329,12 @@ "isProtected": true }, "comment": { - "summary": "A function that is made protected via comment." + "summary": [ + { + "kind": "text", + "text": "A function that is made protected via comment." + } + ] }, "type": { "type": "intrinsic", @@ -325,7 +398,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -735,11 +813,21 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "TestClass comment short text.\n\nTestClass comment text.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "[[TestClass]] @ fixtures" + } + ] } ] }, @@ -757,9 +845,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "type": { "type": "reference", "id": 22, @@ -777,7 +862,12 @@ "isPrivate": true }, "comment": { - "summary": "privateProperty short text." + "summary": [ + { + "kind": "text", + "text": "privateProperty short text." + } + ] }, "type": { "type": "array", @@ -796,7 +886,12 @@ "isPublic": true }, "comment": { - "summary": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, "type": { "type": "intrinsic", @@ -812,7 +907,12 @@ "isStatic": true }, "comment": { - "summary": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, "type": { "type": "reference", @@ -834,7 +934,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -859,7 +964,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "privateMethod short text." + "summary": [ + { + "kind": "text", + "text": "privateMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -884,7 +994,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -909,7 +1024,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -934,7 +1054,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1025,9 +1150,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "parameters": [ { "id": 44, @@ -1035,9 +1157,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor param" - }, "type": { "type": "intrinsic", "name": "any" @@ -1049,9 +1168,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Private string property" - }, "type": { "type": "intrinsic", "name": "string" @@ -1063,9 +1179,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Public number property" - }, "type": { "type": "intrinsic", "name": "number" @@ -1077,9 +1190,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Public implicit any property\n" - }, "type": { "type": "intrinsic", "name": "any" @@ -1139,7 +1249,12 @@ "isPublic": true }, "comment": { - "summary": "publicProperty short text." + "summary": [ + { + "kind": "text", + "text": "publicProperty short text." + } + ] }, "type": { "type": "intrinsic", @@ -1160,7 +1275,12 @@ "isStatic": true }, "comment": { - "summary": "staticProperty short text." + "summary": [ + { + "kind": "text", + "text": "staticProperty short text." + } + ] }, "type": { "type": "reference", @@ -1187,7 +1307,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "arrow method" + "summary": [ + { + "kind": "text", + "text": "arrow method" + } + ] }, "type": { "type": "intrinsic", @@ -1220,7 +1345,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "mergedMethod short text." + "summary": [ + { + "kind": "text", + "text": "mergedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1245,7 +1375,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "protectedMethod short text." + "summary": [ + { + "kind": "text", + "text": "protectedMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1280,7 +1415,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "publicMethod short text." + "summary": [ + { + "kind": "text", + "text": "publicMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1315,7 +1455,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "staticMethod short text." + "summary": [ + { + "kind": "text", + "text": "staticMethod short text." + } + ] }, "type": { "type": "intrinsic", @@ -1410,7 +1555,12 @@ "isPrivate": true }, "comment": { - "summary": "Docs" + "summary": [ + { + "kind": "text", + "text": "Docs" + } + ] }, "type": { "type": "intrinsic", @@ -1514,7 +1664,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A class with constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with constructor properties." + } + ] }, "children": [ { @@ -1530,7 +1685,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 97, @@ -1538,9 +1692,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "X component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1552,9 +1703,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Y component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1566,9 +1714,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Vector name\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1656,7 +1801,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A class with inherited and overwritten constructor properties." + "summary": [ + { + "kind": "text", + "text": "A class with inherited and overwritten constructor properties." + } + ] }, "children": [ { @@ -1672,7 +1822,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 106, @@ -1680,9 +1829,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "X component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1694,9 +1840,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Y component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1708,9 +1851,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Z component of the Vector" - }, "type": { "type": "intrinsic", "name": "number" @@ -1722,9 +1862,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Vector name\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1870,21 +2007,13 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "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, @@ -1913,27 +2042,6 @@ "kind": 2048, "kindString": "Method", "flags": {}, - "decorators": [ - { - "name": "decoratorAtom", - "type": { - "type": "reference", - "id": 115, - "name": "decoratorAtom" - } - }, - { - "name": "decoratorWithParam", - "type": { - "type": "reference", - "id": 120, - "name": "decoratorWithParam" - }, - "arguments": { - "value": "false" - } - } - ], "signatures": [ { "id": 132, @@ -1942,7 +2050,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorated method." + "summary": [ + { + "kind": "text", + "text": "A decorated method." + } + ] }, "type": { "type": "intrinsic", @@ -1975,13 +2088,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 131, - "name": "decoratedMethod" - } - ], "signatures": [ { "id": 116, @@ -1990,7 +2096,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator with no options." + "summary": [ + { + "kind": "text", + "text": "A decorator with no options." + } + ] }, "parameters": [ { @@ -2055,13 +2166,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 128, - "name": "DecoratedClass" - } - ], "signatures": [ { "id": 124, @@ -2070,7 +2174,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator consuming an options object." + "summary": [ + { + "kind": "text", + "text": "A decorator consuming an options object." + } + ] }, "parameters": [ { @@ -2079,9 +2188,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The options object of this decorator." - }, "type": { "type": "reflection", "declaration": { @@ -2097,9 +2203,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "A property on the options object of this decorator.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -2132,13 +2235,6 @@ "kind": 64, "kindString": "Function", "flags": {}, - "decorates": [ - { - "type": "reference", - "id": 131, - "name": "decoratedMethod" - } - ], "signatures": [ { "id": 121, @@ -2147,7 +2243,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "A decorator with a parameter." + "summary": [ + { + "kind": "text", + "text": "A decorator with a parameter." + } + ] }, "parameters": [ { @@ -2156,9 +2257,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The parameter of this decorator.\n" - }, "type": { "type": "intrinsic", "name": "boolean" @@ -2236,7 +2334,12 @@ "isStatic": true }, "comment": { - "summary": "This is an event documentation." + "summary": [ + { + "kind": "text", + "text": "This is an event documentation." + } + ] }, "type": { "type": "intrinsic", @@ -2287,11 +2390,21 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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,7 +2423,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for a general event by name." + "summary": [ + { + "kind": "text", + "text": "Subscribe for a general event by name." + } + ] }, "parameters": [ { @@ -2319,9 +2437,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "intrinsic", "name": "string" @@ -2333,9 +2448,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The handler called when the event occurs.\n" - }, "type": { "type": "reflection", "declaration": { @@ -2386,7 +2498,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for error notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for error notifications." + } + ] }, "parameters": [ { @@ -2395,9 +2512,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "error" @@ -2409,9 +2523,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A handler that will receive the error details\n" - }, "type": { "type": "reflection", "declaration": { @@ -2462,7 +2573,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for progress notifications." + "summary": [ + { + "kind": "text", + "text": "Subscribe for progress notifications." + } + ] }, "parameters": [ { @@ -2471,9 +2587,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "progress" @@ -2485,9 +2598,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A handler that will receive a progress event with the current and expected total bytes\n" - }, "type": { "type": "reflection", "declaration": { @@ -2538,7 +2648,12 @@ "kindString": "Event", "flags": {}, "comment": { - "summary": "Subscribe for success notification." + "summary": [ + { + "kind": "text", + "text": "Subscribe for success notification." + } + ] }, "parameters": [ { @@ -2547,9 +2662,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name of the event to subscribe for." - }, "type": { "type": "literal", "value": "complete" @@ -2561,9 +2673,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A function that will be called with general event data upon successful completion\n" - }, "type": { "type": "reflection", "declaration": { @@ -2645,7 +2754,24 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "GenericClass short text." + "summary": [ + { + "kind": "text", + "text": "GenericClass short text." + } + ], + "blockTags": [ + { + "tag": "@param", + "content": [ + { + "kind": "text", + "text": "Generic parameter." + } + ], + "paramName": "T" + } + ] }, "children": [ { @@ -2661,9 +2787,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "typeParameter": [ { "id": 169, @@ -2680,9 +2803,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor parameter.\n" - }, "type": { "type": "reference", "id": 169, @@ -2714,7 +2834,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, "type": { "type": "reference", @@ -2731,7 +2856,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, "type": { "type": "array", @@ -2756,8 +2886,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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", @@ -2798,10 +2943,7 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {}, - "comment": { - "summary": "Generic parameter.\n" - } + "flags": {} } ], "extendedBy": [ @@ -2819,7 +2961,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "NonGenericClass short text." + "summary": [ + { + "kind": "text", + "text": "NonGenericClass short text." + } + ] }, "children": [ { @@ -2835,9 +2982,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Constructor short text." - }, "parameters": [ { "id": 179, @@ -2845,9 +2989,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Constructor parameter.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -2881,7 +3022,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property." + "summary": [ + { + "kind": "text", + "text": "Generic property." + } + ] }, "type": { "type": "intrinsic", @@ -2902,7 +3048,12 @@ "isProtected": true }, "comment": { - "summary": "Generic property array." + "summary": [ + { + "kind": "text", + "text": "Generic property array." + } + ] }, "type": { "type": "array", @@ -2931,8 +3082,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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", @@ -3201,7 +3367,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "ChainClass comment short text.\n\nChainClass comment text." + "summary": [ + { + "kind": "text", + "text": "ChainClass comment short text.\n\nChainClass comment text." + } + ] }, "children": [ { @@ -3241,7 +3412,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Chain method that returns this." + "summary": [ + { + "kind": "text", + "text": "Chain method that returns this." + } + ] }, "type": { "type": "reference", @@ -3395,11 +3571,21 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "TestClass comment short text.\n\nTestClass comment text.", - "tags": [ + "summary": [ { - "tag": "see", - "text": "[[TestClass]] @ fixtures\n" + "kind": "text", + "text": "TestClass comment short text.\n\nTestClass comment text." + } + ], + "blockTags": [ + { + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "[[TestClass]] @ fixtures" + } + ] } ] }, diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index 525bde90d..e093fc70e 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": { - "summary": "This is a module doc comment with legacy behavior." - }, "children": [ { "id": 2, @@ -21,15 +18,29 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "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```\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" }, { - "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" + } + ] } ] }, @@ -55,6 +66,46 @@ } ] }, + { + "id": 6, + "name": "hiddenprop", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "type": { + "type": "intrinsic", + "name": "string" + } + }, + { + "id": 25, + "name": "ignoredprop", + "kind": 1024, + "kindString": "Property", + "flags": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@ignore", + "content": [] + } + ] + }, + "type": { + "type": "intrinsic", + "name": "string" + } + }, { "id": 5, "name": "prop", @@ -62,13 +113,117 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "The main prop" + "summary": [ + { + "kind": "text", + "text": "The main prop" + } + ] }, "type": { "type": "intrinsic", "name": "string" } }, + { + "id": 7, + "name": "hidden", + "kind": 2048, + "kindString": "Method", + "flags": {}, + "signatures": [ + { + "id": 8, + "name": "hidden", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Hidden function" + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "parameters": [ + { + "id": 9, + "name": "args", + "kind": 32768, + "kindString": "Parameter", + "flags": { + "isRest": true + }, + "type": { + "type": "array", + "elementType": { + "type": "intrinsic", + "name": "any" + } + } + } + ], + "type": { + "type": "intrinsic", + "name": "void" + } + } + ] + }, + { + "id": 10, + "name": "hiddenWithImplementation", + "kind": 2048, + "kindString": "Method", + "flags": {}, + "signatures": [ + { + "id": 11, + "name": "hiddenWithImplementation", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Single hidden signature" + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "parameters": [ + { + "id": 12, + "name": "arg", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "any" + } + } + ], + "type": { + "type": "intrinsic", + "name": "any" + } + } + ] + }, { "id": 19, "name": "mixedHidden", @@ -76,6 +231,44 @@ "kindString": "Method", "flags": {}, "signatures": [ + { + "id": 20, + "name": "mixedHidden", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Mixed hidden 1" + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "parameters": [ + { + "id": 21, + "name": "arg", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "any" + } + } + ], + "type": { + "type": "intrinsic", + "name": "any" + } + }, { "id": 22, "name": "mixedHidden", @@ -83,7 +276,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Mixed hidden 2" + "summary": [ + { + "kind": "text", + "text": "Mixed hidden 2" + } + ] }, "parameters": [ { @@ -115,6 +313,102 @@ } } ] + }, + { + "id": 13, + "name": "multipleHidden", + "kind": 2048, + "kindString": "Method", + "flags": {}, + "signatures": [ + { + "id": 14, + "name": "multipleHidden", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Multiple hidden 1" + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "parameters": [ + { + "id": 15, + "name": "arg", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "any" + } + } + ], + "type": { + "type": "intrinsic", + "name": "any" + } + }, + { + "id": 16, + "name": "multipleHidden", + "kind": 4096, + "kindString": "Call signature", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Multiple hidden 2" + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "parameters": [ + { + "id": 17, + "name": "arg1", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "any" + } + }, + { + "id": 18, + "name": "arg2", + "kind": 32768, + "kindString": "Parameter", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "any" + } + } + ], + "type": { + "type": "intrinsic", + "name": "any" + } + } + ] } ], "groups": [ @@ -129,6 +423,8 @@ "title": "Properties", "kind": 1024, "children": [ + 6, + 25, 5 ] }, @@ -136,7 +432,10 @@ "title": "Methods", "kind": 2048, "children": [ - 19 + 7, + 10, + 19, + 13 ] } ] @@ -159,7 +458,20 @@ "kindString": "Module", "flags": {}, "comment": { - "summary": "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": [ { @@ -175,6 +487,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, @@ -224,7 +555,20 @@ "kindString": "Module", "flags": {}, "comment": { - "summary": "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": [ { @@ -240,6 +584,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, @@ -289,7 +655,16 @@ "kindString": "Module", "flags": {}, "comment": { - "summary": "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" + }, + { + "kind": "code", + "text": "```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" + } + ] }, "children": [ { @@ -305,6 +680,24 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a comment containing a multiline code block" + }, + { + "kind": "code", + "text": "```ts\nexport function multiply(a: number, b: number) {\n return a * b;\n}\n```" + } + ], + "blockTags": [ + { + "tag": "@module", + "content": [] + } + ] + }, "parameters": [ { "id": 39, diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index 695a0aeff..d20083f54 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -12,7 +12,12 @@ "kindString": "Namespace", "flags": {}, "comment": { - "summary": "This is a module extending an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a module extending an enumeration." + } + ] }, "children": [ { @@ -22,7 +27,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "This is a variable appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a variable appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -43,7 +53,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This is a function appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a function appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -79,7 +94,12 @@ "isConst": true }, "comment": { - "summary": "This is a const enum." + "summary": [ + { + "kind": "text", + "text": "This is a const enum." + } + ] }, "children": [ { @@ -117,7 +137,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "summary": "This is an enumeration extended by a module." + "summary": [ + { + "kind": "text", + "text": "This is an enumeration extended by a module." + } + ] }, "children": [ { @@ -127,7 +152,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, "defaultValue": "1" }, @@ -138,7 +168,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, "defaultValue": "2" }, @@ -149,7 +184,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, "defaultValue": "4" } @@ -173,7 +213,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "summary": "This is a simple enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a simple enumeration." + } + ] }, "children": [ { @@ -183,7 +228,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, "defaultValue": "1" }, @@ -194,7 +244,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, "defaultValue": "2" }, @@ -205,7 +260,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, "defaultValue": "4" } diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index 695a0aeff..d20083f54 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": { - "summary": "This is a module extending an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a module extending an enumeration." + } + ] }, "children": [ { @@ -22,7 +27,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "This is a variable appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a variable appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -43,7 +53,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This is a function appended to an enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a function appended to an enumeration." + } + ] }, "type": { "type": "intrinsic", @@ -79,7 +94,12 @@ "isConst": true }, "comment": { - "summary": "This is a const enum." + "summary": [ + { + "kind": "text", + "text": "This is a const enum." + } + ] }, "children": [ { @@ -117,7 +137,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "summary": "This is an enumeration extended by a module." + "summary": [ + { + "kind": "text", + "text": "This is an enumeration extended by a module." + } + ] }, "children": [ { @@ -127,7 +152,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, "defaultValue": "1" }, @@ -138,7 +168,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, "defaultValue": "2" }, @@ -149,7 +184,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, "defaultValue": "4" } @@ -173,7 +213,12 @@ "kindString": "Enumeration", "flags": {}, "comment": { - "summary": "This is a simple enumeration." + "summary": [ + { + "kind": "text", + "text": "This is a simple enumeration." + } + ] }, "children": [ { @@ -183,7 +228,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the first enum member." + "summary": [ + { + "kind": "text", + "text": "This is the first enum member." + } + ] }, "defaultValue": "1" }, @@ -194,7 +244,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the second enum member." + "summary": [ + { + "kind": "text", + "text": "This is the second enum member." + } + ] }, "defaultValue": "2" }, @@ -205,7 +260,12 @@ "kindString": "Enumeration member", "flags": {}, "comment": { - "summary": "This is the third enum member." + "summary": [ + { + "kind": "text", + "text": "This is the third enum member." + } + ] }, "defaultValue": "4" } diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 2a9134c1f..8d5cf2d06 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -33,9 +33,6 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, - "comment": { - "summary": "This is a comment for Mod that overwrites the one specified in \"mod\"" - }, "target": 29 }, { @@ -68,9 +65,6 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, - "comment": { - "summary": "An export of a local under a different name." - }, "target": 31 }, { @@ -81,6 +75,14 @@ "flags": {}, "target": 30 }, + { + "id": 44, + "name": "hidden", + "kind": 16777216, + "kindString": "Reference", + "flags": {}, + "target": 33 + }, { "id": 20, "name": "GH1453", @@ -172,6 +174,27 @@ } ] }, + { + "id": 19, + "name": "x2", + "kind": 32, + "kindString": "Variable", + "flags": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "type": { + "type": "intrinsic", + "name": "string" + }, + "defaultValue": "x.issue" + }, { "id": 15, "name": "add", @@ -262,7 +285,8 @@ 45, 42, 43, - 38 + 38, + 44 ] }, { @@ -272,6 +296,13 @@ 20 ] }, + { + "title": "Variables", + "kind": 32, + "children": [ + 19 + ] + }, { "title": "Functions", "kind": 64, @@ -461,9 +492,6 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": { - "summary": "Doc comment for Mod" - }, "children": [ { "id": 34, @@ -479,9 +507,6 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, - "comment": { - "summary": "An export of a local under a different name." - }, "target": 30 }, { @@ -490,9 +515,6 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, - "comment": { - "summary": "An export with a module specifier that comes from this file." - }, "target": 30 }, { @@ -513,7 +535,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "A simple named export that will be exported from export.ts" + "summary": [ + { + "kind": "text", + "text": "Doc comment for Mod" + } + ] }, "type": { "type": "literal", @@ -521,6 +548,32 @@ }, "defaultValue": "1" }, + { + "id": 33, + "name": "hidden", + "kind": 32, + "kindString": "Variable", + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is annotated with the hidden tag and will therefore not be included in the generated documentation.\nThis *would* cause a broken link since it is also re-exported from export.ts, but the CommentPlugin removes\nbroken links caused by hidden/ignore/internal tags." + } + ], + "blockTags": [ + { + "tag": "@hidden", + "content": [] + } + ] + }, + "type": { + "type": "literal", + "value": true + }, + "defaultValue": "true" + }, { "id": 36, "name": "default", @@ -535,7 +588,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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", @@ -566,7 +624,8 @@ "title": "Variables", "kind": 32, "children": [ - 30 + 30, + 33 ] }, { diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index d52e9dccf..e9f9a486a 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -56,7 +56,12 @@ "kindString": "Namespace", "flags": {}, "comment": { - "summary": "This is the module extending the function moduleFunction()." + "summary": [ + { + "kind": "text", + "text": "This is the module extending the function moduleFunction()." + } + ] }, "children": [ { @@ -66,7 +71,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "This variable is appended to a function." + "summary": [ + { + "kind": "text", + "text": "This variable is appended to a function." + } + ] }, "type": { "type": "intrinsic", @@ -87,7 +97,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This function is appended to another function." + "summary": [ + { + "kind": "text", + "text": "This function is appended to another function." + } + ] }, "type": { "type": "intrinsic", @@ -110,7 +125,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This function is appended to another function." + "summary": [ + { + "kind": "text", + "text": "This function is appended to another function." + } + ] }, "type": { "type": "intrinsic", @@ -328,9 +348,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "Returns true if fn returns true for every item in the iterator\n\nReturns true if the iterator is empty" - }, "typeParameter": [ { "id": 101, @@ -415,9 +432,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "Returns true if fn returns true for every item in the iterator\n\nReturns true if the iterator is empty" - }, "typeParameter": [ { "id": 108, @@ -533,7 +547,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Asserts that an argument is not null." + "summary": [ + { + "kind": "text", + "text": "Asserts that an argument is not null." + } + ] }, "typeParameter": [ { @@ -551,9 +570,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\n" - }, "type": { "type": "union", "types": [ @@ -601,7 +617,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This is an assertion function." + "summary": [ + { + "kind": "text", + "text": "This is an assertion function." + } + ] }, "parameters": [ { @@ -610,9 +631,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The condition that is asserted to be true when this function returns.\n" - }, "type": { "type": "intrinsic", "name": "boolean" @@ -683,7 +701,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Assertion function with a type." + "summary": [ + { + "kind": "text", + "text": "Assertion function with a type." + } + ] }, "parameters": [ { @@ -692,9 +715,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\n" - }, "type": { "type": "intrinsic", "name": "any" @@ -727,7 +747,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "This is a simple exported function." + "summary": [ + { + "kind": "text", + "text": "This is a simple exported function." + } + ] }, "type": { "type": "intrinsic", @@ -750,18 +775,38 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { "id": 25, - "name": "destructuredParam", + "name": "Param", "kind": 32768, "kindString": "Parameter", "flags": {}, "comment": { - "summary": "This is the parameter that is destructured." + "summary": [ + { + "kind": "text", + "text": "This is the parameter that is destructured." + } + ] }, "originalName": "__namedParameters", "type": { @@ -780,7 +825,16 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "\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." + }, + { + "kind": "code", + "text": "```\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ```" + } + ] }, "type": { "type": "reference", @@ -794,7 +848,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "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", @@ -808,7 +867,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "This is a string parameter." + "summary": [ + { + "kind": "text", + "text": "This is a string parameter." + } + ] }, "type": { "type": "intrinsic", @@ -852,8 +916,39 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -941,8 +1036,31 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1041,8 +1159,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1051,9 +1184,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A parameter with a default string value." - }, "type": { "type": "intrinsic", "name": "string" @@ -1066,9 +1196,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A parameter with a default numeric value." - }, "type": { "type": "intrinsic", "name": "number" @@ -1081,9 +1208,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A parameter with a default NaN value." - }, "type": { "type": "intrinsic", "name": "number" @@ -1096,9 +1220,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A parameter with a default boolean value." - }, "type": { "type": "intrinsic", "name": "boolean" @@ -1111,9 +1232,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A parameter with a default null value." - }, "type": { "type": "intrinsic", "name": "boolean" @@ -1142,7 +1260,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1151,9 +1274,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A normal parameter." - }, "type": { "type": "intrinsic", "name": "string" @@ -1167,9 +1287,6 @@ "flags": { "isOptional": true }, - "comment": { - "summary": "An optional parameter.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1197,8 +1314,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1207,9 +1339,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This is a string parameter." - }, "type": { "type": "intrinsic", "name": "string" @@ -1221,9 +1350,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This is a parameter flagged with any.\n This sentence is placed in the next line.\n" - }, "type": { "type": "intrinsic", "name": "any" @@ -1235,9 +1361,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\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" - }, "type": { "type": "reference", "name": "Object" @@ -1265,8 +1388,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1277,9 +1415,6 @@ "flags": { "isRest": true }, - "comment": { - "summary": "The rest parameter." - }, "type": { "type": "array", "elementType": { @@ -1310,7 +1445,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Checks that an argument is not null." + "summary": [ + { + "kind": "text", + "text": "Checks that an argument is not null." + } + ] }, "typeParameter": [ { @@ -1328,9 +1468,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\n" - }, "type": { "type": "union", "types": [ @@ -1398,7 +1535,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1407,9 +1549,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "An argument.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1437,8 +1576,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1447,9 +1590,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "The name value.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1468,8 +1608,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1478,9 +1622,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "An object containing the name value." - }, "type": { "type": "reflection", "declaration": { @@ -1496,9 +1637,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "A value of the object.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -1540,10 +1678,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "This is a function that is assigned to a variable.", - "returns": "This is the return value of the function.\n" - }, "parameters": [ { "id": 85, @@ -1551,9 +1685,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This is some numeric parameter." - }, "type": { "type": "intrinsic", "name": "number" @@ -1631,8 +1762,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1650,9 +1796,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A generic parameter." - }, "type": { "type": "reference", "id": 123, @@ -1665,9 +1808,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "A generic array parameter." - }, "type": { "type": "array", "elementType": { @@ -1702,7 +1842,9 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, + "comment": { + "summary": [] + }, "typeParameter": [ { "id": 128, @@ -1711,7 +1853,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "summary": "this describes T\n" + "summary": [ + { + "kind": "text", + "text": "this describes T" + } + ] } } ], @@ -1722,9 +1869,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "this describes param" - }, "type": { "type": "reference", "id": 128, @@ -1754,8 +1898,23 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "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": [ { @@ -1765,7 +1924,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "summary": "Generic function type parameter." + "summary": [ + { + "kind": "text", + "text": "Generic function type parameter." + } + ] }, "type": { "type": "reference", @@ -1780,9 +1944,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Generic function parameter." - }, "type": { "type": "reference", "id": 119, diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index 75ba49810..ba4b34bae 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -46,7 +46,15 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [] + } + ] + }, "parameters": [ { "id": 11, @@ -54,9 +62,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter A." - }, "type": { "type": "intrinsic", "name": "number" @@ -68,9 +73,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter B.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -160,7 +162,15 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [] + } + ] + }, "parameters": [ { "id": 18, @@ -168,9 +178,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Custom parameter A doc.\n" - }, "type": { "type": "intrinsic", "name": "number" @@ -182,9 +189,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter B.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -274,7 +278,15 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, + "comment": { + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [] + } + ] + }, "parameters": [ { "id": 25, @@ -282,9 +294,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter A." - }, "type": { "type": "intrinsic", "name": "number" @@ -296,9 +305,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Custom second parameter doc with name change.\n" - }, "type": { "type": "intrinsic", "name": "string" @@ -367,7 +373,9 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, + "comment": { + "summary": [] + }, "parameters": [ { "id": 4, @@ -375,9 +383,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter A." - }, "type": { "type": "intrinsic", "name": "number" @@ -389,9 +394,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "Parameter B.\n" - }, "type": { "type": "intrinsic", "name": "string" diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index d055dfc89..c3a3560aa 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -18,7 +18,24 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "Source interface summary" + "summary": [ + { + "kind": "text", + "text": "Source interface summary" + } + ], + "blockTags": [ + { + "tag": "@typeParam", + "content": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ], + "paramName": "T" + } + ] }, "children": [ { @@ -28,12 +45,22 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "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", + "content": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ], + "paramName": "T" } ] }, @@ -57,7 +84,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Source interface method description" + "summary": [ + { + "kind": "text", + "text": "Source interface method description" + } + ] }, "parameters": [ { @@ -66,9 +98,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\n" - }, "type": { "type": "intrinsic", "name": "number" @@ -106,10 +135,7 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {}, - "comment": { - "summary": "Source interface type parameter\n" - } + "flags": {} } ] }, @@ -120,7 +146,18 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "Source interface summary" + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [ + { + "kind": "text", + "text": "InterfaceSource" + } + ] + } + ] }, "children": [ { @@ -130,7 +167,18 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Source interface property description" + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [ + { + "kind": "text", + "text": "InterfaceSource.property" + } + ] + } + ] }, "type": { "type": "reference", @@ -152,18 +200,26 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Source interface method description" + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [ + { + "kind": "text", + "text": "InterfaceSource.someMethod" + } + ] + } + ] }, "parameters": [ { - "id": 18, + "id": 24, "name": "arg", "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "\n" - }, "type": { "type": "intrinsic", "name": "number" @@ -197,14 +253,11 @@ ], "typeParameter": [ { - "id": 19, + "id": 25, "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {}, - "comment": { - "summary": "Source interface type parameter\n" - } + "flags": {} } ] }, @@ -222,16 +275,39 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Function summary\n\nThis part of the commentary will be inherited by other entities", - "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", + "content": [ + { + "kind": "text", + "text": "This part of the commentary will not be inherited" + } + ] }, { - "tag": "example", - "text": "\n\nThis part of the commentary will not be inherited\n" + "tag": "@returns", + "content": [ + { + "kind": "text", + "text": "Stringified sum or concatenation of numeric arguments" + } + ] } ] }, @@ -243,7 +319,12 @@ "kindString": "Type parameter", "flags": {}, "comment": { - "summary": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "Type of arguments" + } + ] } } ], @@ -254,9 +335,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This will be inherited" - }, "type": { "type": "reference", "id": 4, @@ -269,9 +347,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This will be inherited" - }, "type": { "type": "reference", "id": 4, @@ -300,11 +375,16 @@ "kindString": "Call signature", "flags": {}, "comment": { - "tags": [ + "summary": [], + "blockTags": [ { - "tag": "inheritdoc", - "text": "\n", - "param": "SubClassA.printName" + "tag": "@inheritDoc", + "content": [ + { + "kind": "text", + "text": "SubClassA.printName" + } + ] } ] }, @@ -329,59 +409,84 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Function summary\n\nThis part of the commentary will be inherited by other entities", - "returns": "This will be inherited\n\n", - "tags": [ + "summary": [], + "blockTags": [ + { + "tag": "@inheritDoc", + "content": [ + { + "kind": "text", + "text": "functionSource" + } + ] + }, { - "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" + } + ] } ] }, "typeParameter": [ { - "id": 4, + "id": 11, "name": "T", "kind": 131072, "kindString": "Type parameter", "flags": {}, "comment": { - "summary": "This will be inherited" + "summary": [ + { + "kind": "text", + "text": "This will be inherited" + } + ] } } ], "parameters": [ { - "id": 5, + "id": 12, "name": "arg1", "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This will be inherited" - }, "type": { "type": "reference", - "id": 4, + "id": 11, "name": "T" } }, { - "id": 6, + "id": 13, "name": "arg2", "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "This will be inherited" - }, "type": { "type": "reference", - "id": 4, + "id": 11, "name": "T" } } diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index 6fda3cc1c..55c651b8b 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -335,7 +335,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A class implementing an empty interface." + "summary": [ + { + "kind": "text", + "text": "A class implementing an empty interface." + } + ] }, "children": [ { @@ -433,7 +438,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "An empty interface" + "summary": [ + { + "kind": "text", + "text": "An empty interface" + } + ] }, "implementedBy": [ { @@ -482,11 +492,21 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Implementation of IEventDispatcher", - "tags": [ + "summary": [ + { + "kind": "text", + "text": "Implementation of IEventDispatcher" + } + ], + "blockTags": [ { - "tag": "see", - "text": "IEventDispatcher\n" + "tag": "@see", + "content": [ + { + "kind": "text", + "text": "IEventDispatcher" + } + ] } ] }, @@ -1044,9 +1064,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "Remove this subscription from its dispatcher" - }, "type": { "type": "intrinsic", "name": "void" @@ -1122,7 +1139,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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": [ { @@ -1352,6 +1374,14 @@ "kind": 256, "kindString": "Interface", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Function signature of an event listener callback" + } + ] + }, "typeParameter": [ { "id": 39, @@ -1368,9 +1398,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "Function signature of an event listener callback" - }, "parameters": [ { "id": 41, @@ -1378,9 +1405,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": { - "summary": "param text" - }, "type": { "type": "reference", "id": 39, @@ -1402,7 +1426,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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": [ { @@ -1460,7 +1489,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Remove this subscription from its dispatcher" + "summary": [ + { + "kind": "text", + "text": "Remove this subscription from its dispatcher" + } + ] }, "type": { "type": "intrinsic", diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index 6c37297e6..daa091bed 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, @@ -38,7 +37,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 4, @@ -46,7 +44,6 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, - "comment": {}, "type": { "type": "intrinsic", "name": "string" @@ -84,7 +81,6 @@ "kind": 2, "kindString": "Module", "flags": {}, - "comment": {}, "children": [ { "id": 17, @@ -92,9 +88,6 @@ "kind": 256, "kindString": "Interface", "flags": {}, - "comment": { - "summary": "docs for interface" - }, "children": [ { "id": 19, @@ -102,9 +95,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "can also use prop tag" - }, "type": { "type": "intrinsic", "name": "string" @@ -116,9 +106,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "docs for property" - }, "type": { "type": "intrinsic", "name": "string" @@ -149,9 +136,6 @@ "kind": 1024, "kindString": "Property", "flags": {}, - "comment": { - "summary": "docs for property\nmore docs for property" - }, "type": { "type": "intrinsic", "name": "string" @@ -263,19 +247,13 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": "comment on alias" - }, "typeParameter": [ { "id": 43, "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {}, - "comment": { - "summary": "comment on template" - } + "flags": {} } ], "type": { @@ -344,9 +322,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": "docs for alias" - }, "type": { "type": "intersection", "types": [ @@ -453,9 +428,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": "type alias since it doesn't have a property tag" - }, "type": { "type": "reference", "name": "Object" @@ -512,9 +484,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": "docs for alias" - }, "type": { "type": "union", "types": [ @@ -535,7 +504,9 @@ "kind": 32, "kindString": "Variable", "flags": {}, - "comment": {}, + "comment": { + "summary": [] + }, "type": { "type": "reflection", "declaration": { @@ -599,7 +570,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": {}, "parameters": [ { "id": 9, diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 38fa981c1..e1836afd4 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -12,7 +12,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Base class" + "summary": [ + { + "kind": "text", + "text": "Base class" + } + ] }, "children": [ { @@ -100,7 +105,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "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": [ { @@ -470,7 +480,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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": [ { @@ -626,7 +641,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "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": [ { @@ -842,6 +862,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Any constructor function" + } + ] + }, "typeParameter": [ { "id": 10, @@ -870,9 +898,6 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, - "comment": { - "summary": "Any constructor function" - }, "parameters": [ { "id": 9, @@ -907,6 +932,14 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Any function" + } + ] + }, "typeParameter": [ { "id": 5, @@ -935,9 +968,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "Any function" - }, "parameters": [ { "id": 4, @@ -973,7 +1003,12 @@ "kindString": "Type alias", "flags": {}, "comment": { - "summary": "Mixin type helper" + "summary": [ + { + "kind": "text", + "text": "Mixin type helper" + } + ] }, "typeParameter": [ { @@ -1026,7 +1061,12 @@ "kindString": "Type alias", "flags": {}, "comment": { - "summary": "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" + } + ] }, "type": { "type": "reference", @@ -1059,9 +1099,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "The \"mixin function\" of the Mixin1" - }, "typeParameter": [ { "id": 21, @@ -1164,9 +1201,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "The \"mixin function\" of the Mixin2" - }, "typeParameter": [ { "id": 35, @@ -1279,9 +1313,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": "The \"mixin function\" of the Mixin3" - }, "typeParameter": [ { "id": 53, diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index d54f50e73..d44b06df7 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -1159,7 +1159,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "First type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "First type for union or intersection type tests." + } + ] }, "children": [ { @@ -1169,7 +1174,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Property of first type." + "summary": [ + { + "kind": "text", + "text": "Property of first type." + } + ] }, "type": { "type": "intrinsic", @@ -1194,7 +1204,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "Second type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "Second type for union or intersection type tests." + } + ] }, "children": [ { @@ -1204,7 +1219,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Property of second type." + "summary": [ + { + "kind": "text", + "text": "Property of second type." + } + ] }, "type": { "type": "intrinsic", @@ -1229,7 +1249,12 @@ "kindString": "Interface", "flags": {}, "comment": { - "summary": "Third type for union or intersection type tests." + "summary": [ + { + "kind": "text", + "text": "Third type for union or intersection type tests." + } + ] }, "children": [ { @@ -1239,7 +1264,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Complex Property of third type." + "summary": [ + { + "kind": "text", + "text": "Complex Property of third type." + } + ] }, "type": { "type": "array", @@ -1279,7 +1309,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Intersection Property of third type." + "summary": [ + { + "kind": "text", + "text": "Intersection Property of third type." + } + ] }, "type": { "type": "intersection", @@ -1304,7 +1339,12 @@ "kindString": "Property", "flags": {}, "comment": { - "summary": "Union Property of third type." + "summary": [ + { + "kind": "text", + "text": "Union Property of third type." + } + ] }, "type": { "type": "union", diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 2f17342d5..feac4bd78 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -18,7 +18,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A custom array class." + "summary": [ + { + "kind": "text", + "text": "A custom array class." + } + ] }, "children": [ { @@ -92,7 +97,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Class array class item" + "summary": [ + { + "kind": "text", + "text": "Class array class item" + } + ] }, "children": [ { @@ -134,7 +144,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Custom list class" + "summary": [ + { + "kind": "text", + "text": "Custom list class" + } + ] }, "children": [ { @@ -200,7 +215,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "A const of a complex type." + "summary": [ + { + "kind": "text", + "text": "A const of a complex type." + } + ] }, "type": { "type": "array", @@ -255,7 +275,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "An exported const of the custom array type." + "summary": [ + { + "kind": "text", + "text": "An exported const of the custom array type." + } + ] }, "type": { "type": "reference", @@ -461,7 +486,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Destructuring function parameters." + "summary": [ + { + "kind": "text", + "text": "Destructuring function parameters." + } + ] }, "parameters": [ { @@ -745,7 +775,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "An object literal." + "summary": [ + { + "kind": "text", + "text": "An object literal." + } + ] }, "type": { "type": "reflection", @@ -1031,7 +1066,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "A typed literal without an initializer." + "summary": [ + { + "kind": "text", + "text": "A typed literal without an initializer." + } + ] }, "type": { "type": "reflection", diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index de20b9d90..b6ca9aedf 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -18,7 +18,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "A custom array class." + "summary": [ + { + "kind": "text", + "text": "A custom array class." + } + ] }, "children": [ { @@ -92,7 +97,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Class array class item" + "summary": [ + { + "kind": "text", + "text": "Class array class item" + } + ] }, "children": [ { @@ -134,7 +144,12 @@ "kindString": "Class", "flags": {}, "comment": { - "summary": "Custom list class" + "summary": [ + { + "kind": "text", + "text": "Custom list class" + } + ] }, "children": [ { @@ -200,7 +215,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "A const of a complex type." + "summary": [ + { + "kind": "text", + "text": "A const of a complex type." + } + ] }, "type": { "type": "array", @@ -255,7 +275,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "An exported const of the custom array type." + "summary": [ + { + "kind": "text", + "text": "An exported const of the custom array type." + } + ] }, "type": { "type": "reference", @@ -312,7 +337,12 @@ "kindString": "Call signature", "flags": {}, "comment": { - "summary": "Destructuring function parameters." + "summary": [ + { + "kind": "text", + "text": "Destructuring function parameters." + } + ] }, "parameters": [ { @@ -359,7 +389,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "An object literal." + "summary": [ + { + "kind": "text", + "text": "An object literal." + } + ] }, "type": { "type": "reflection", @@ -380,7 +415,12 @@ "kindString": "Variable", "flags": {}, "comment": { - "summary": "A typed literal without an initializer." + "summary": [ + { + "kind": "text", + "text": "A typed literal without an initializer." + } + ] }, "type": { "type": "reflection", diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index 61c46e6b4..428fc82a9 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -263,8 +263,8 @@ export const issueTests: { const expectedComment = new Comment(); expectedComment.blockTags = [ - new CommentTag("asdf", [ - { kind: "text", text: "Some example text\n" }, + new CommentTag("@asdf", [ + { kind: "text", text: "Some example text" }, ]), ]; equal(type.declaration.signatures?.[0].comment, expectedComment); @@ -284,11 +284,11 @@ export const issueTests: { ok(cat); ok(cat.children.includes(Foo)); - ok(!Foo.comment?.getTag("category")); - ok(!Foo.type.declaration.comment?.getTag("category")); + ok(!Foo.comment?.getTag("@category")); + ok(!Foo.type.declaration.comment?.getTag("@category")); ok( !Foo.type.declaration.signatures?.some((s) => - s.comment?.getTag("category") + s.comment?.getTag("@category") ) ); }, 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/utils/options/options.test.ts b/src/test/utils/options/options.test.ts index e7c34b7ca..a260f5d74 100644 --- a/src/test/utils/options/options.test.ts +++ b/src/test/utils/options/options.test.ts @@ -179,7 +179,7 @@ describe("Options", () => { options.addDefaultDeclarations(); options.setValue("entryPoints", ["x"]); - options.setValue("excludeTags", ["x"]); + options.setValue("excludeTags", ["@x"]); options.reset(); equal(options.getValue("entryPoints"), []); @@ -191,7 +191,7 @@ describe("Options", () => { options.addDefaultDeclarations(); options.setValue("name", "test"); - options.setValue("excludeTags", ["x"]); + options.setValue("excludeTags", ["@x"]); options.reset("excludeTags"); equal(options.getValue("name"), "test"); From f0fedac8752eb11a8efa5ea9b07bc9702b63602d Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 25 Nov 2021 13:18:43 -0700 Subject: [PATCH 013/151] distraction: substr -> substring --- src/lib/converter/comments/blockLexer.ts | 2 +- src/lib/converter/comments/index.ts | 2 ++ src/lib/converter/comments/parser.ts | 10 ++++++---- src/lib/converter/plugins/CommentPlugin.ts | 2 +- src/lib/converter/plugins/SourceLinkPlugin.ts | 11 ++++------- src/lib/converter/utils/base-path.ts | 4 ++-- src/lib/models/comments/comment.ts | 2 +- src/lib/output/plugins/MarkedLinksPlugin.ts | 4 ++-- .../assets/typedoc/components/MenuHighlight.ts | 6 +++--- .../default/assets/typedoc/components/Toggle.ts | 4 ++-- src/lib/output/themes/default/partials/comment.tsx | 13 +++++++++++-- src/lib/utils/highlighter.tsx | 4 ++-- src/lib/utils/options/declaration.ts | 2 +- src/lib/utils/package-manifest.ts | 2 +- src/lib/utils/plugins.ts | 2 +- src/test/comments.test.ts | 2 +- src/test/converter2.test.ts | 4 ++-- 17 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/lib/converter/comments/blockLexer.ts b/src/lib/converter/comments/blockLexer.ts index 24752a95f..3dec347de 100644 --- a/src/lib/converter/comments/blockLexer.ts +++ b/src/lib/converter/comments/blockLexer.ts @@ -276,7 +276,7 @@ function* lexBlockComment2( return { kind, - text: file.substr(start, size), + text: file.substring(start, pos), }; } diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index 475ffa33e..20fa04d24 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -23,6 +23,7 @@ export function getComment( if (comment) { const [file, range] = comment; const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); + logger.verbose(`Parsing comment at ${file.fileName}:${line}`); const warning = (warning: string) => logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); @@ -65,6 +66,7 @@ export function getSignatureComment( if (comment) { const [file, range] = comment; const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); + logger.verbose(`Parsing signature comment at ${file.fileName}:${line}`); const warning = (warning: string) => logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 16d7f1821..283c8e4a8 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -103,7 +103,7 @@ function blockTag( const match = firstPart.text.match(/^([a-z_$]+)\s*(-\s*)?/); if (match) { tag.paramName = match[1]; - firstPart.text = firstPart.text.substr(match[0].length); + firstPart.text = firstPart.text.substring(match[0].length); } } @@ -121,6 +121,7 @@ function blockContent( loop: while (!lexer.done()) { const next = lexer.peek(); + let consume = true; switch (next.kind) { case TokenSyntaxKind.NewLine: @@ -137,7 +138,7 @@ function blockContent( comment.modifierTags.add(next.text); break; } else if (!atNewLine && !config.blockTags.has(next.text)) { - // Treat unknown tag as a modifier, bug warn about it. + // 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` @@ -161,13 +162,14 @@ function blockContent( case TokenSyntaxKind.OpenBrace: inlineTag(lexer, content, config, warning); + consume = false; break; default: assertNever(next.kind); } - if (lexer.take().kind === TokenSyntaxKind.NewLine) { + if (consume && lexer.take().kind === TokenSyntaxKind.NewLine) { atNewLine = true; } } @@ -260,7 +262,7 @@ function inlineTag( block.push({ kind: "inline-tag", - tag: tagName.text, + tag: tagName.text as `@${string}`, text: content.join(""), }); } diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 4294b9ae8..50c524277 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -243,7 +243,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 diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/plugins/SourceLinkPlugin.ts index 2c7d074d5..61e361523 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/plugins/SourceLinkPlugin.ts @@ -97,11 +97,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; } @@ -160,7 +157,7 @@ export class Repository { 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("/"); @@ -263,7 +260,7 @@ export class SourceLinkPlugin extends ConverterComponent { // Check for known repositories for (const path of Object.keys(this.repositories)) { - if (fileName.substr(0, path.length).toLowerCase() === path) { + if (fileName.substring(0, path.length).toLowerCase() === path) { return this.repositories[path]; } } 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/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 52e3bd940..795786020 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -3,7 +3,7 @@ import { assertNever, removeIf } from "../../utils"; export type CommentDisplayPart = | { kind: "text"; text: string } | { kind: "code"; text: string } - | { kind: "inline-tag"; tag: string; text: string }; + | { kind: "inline-tag"; tag: `@${string}`; text: string }; /** * A model that represents a single TypeDoc comment tag. diff --git a/src/lib/output/plugins/MarkedLinksPlugin.ts b/src/lib/output/plugins/MarkedLinksPlugin.ts index c54a8cca0..23ac6b21b 100644 --- a/src/lib/output/plugins/MarkedLinksPlugin.ts +++ b/src/lib/output/plugins/MarkedLinksPlugin.ts @@ -202,10 +202,10 @@ export class MarkedLinksPlugin extends ContextAwareRendererComponent { if (splitIndex !== -1) { return { caption: text - .substr(splitIndex + 1) + .substring(splitIndex + 1) .replace(/\n+/, " ") .trim(), - target: text.substr(0, splitIndex).trim(), + target: text.substring(0, splitIndex).trim(), }; } else { return { 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/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/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 49547d70f..4a7d47bba 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -3,7 +3,7 @@ import { assertNever, JSX, Raw } from "../../../../utils"; import type { CommentDisplayPart, Reflection } from "../../../../models"; function humanize(text: string) { - return text.substr(1, 1).toUpperCase() + text.substr(2).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); + return text.substring(1, 2).toUpperCase() + text.substring(2).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); } function displayPartsToMarkdown(parts: CommentDisplayPart[]) { @@ -16,7 +16,16 @@ function displayPartsToMarkdown(parts: CommentDisplayPart[]) { result.push(part.text); break; case "inline-tag": - // TODO GERRIT + switch (part.tag) { + case "@label": + break; // Not rendered. + case "@link": + // TODO GERRIT RENDER ME PROPERLY + return part.text; + 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, do nothing. + } break; default: assertNever(part); diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index c7638812e..bdcd98a2a 100644 --- a/src/lib/utils/highlighter.tsx +++ b/src/lib/utils/highlighter.tsx @@ -46,7 +46,7 @@ class DoubleHighlighter { 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; } @@ -54,7 +54,7 @@ class DoubleHighlighter { 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(); } diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 84126a68a..9b4d3f591 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -584,7 +584,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/package-manifest.ts b/src/lib/utils/package-manifest.ts index 80921861d..73c53f7bc 100644 --- a/src/lib/utils/package-manifest.ts +++ b/src/lib/utils/package-manifest.ts @@ -142,7 +142,7 @@ function getTsSourceFromJsSource( resolvedSourceMapURL = jsPath; sourceMap = JSON.parse( Buffer.from( - sourceMapURL.substr(sourceMapURL.indexOf(",") + 1), + sourceMapURL.substring(sourceMapURL.indexOf(",") + 1), "base64" ).toString() ); 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/test/comments.test.ts b/src/test/comments.test.ts index c92f39923..4e64d4dde 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -23,7 +23,7 @@ function dedent(text: string) { Infinity ); - return lines.map((line) => line.substr(minIndent)).join("\n"); + return lines.map((line) => line.substring(minIndent)).join("\n"); } describe("Dedent test helper", () => { diff --git a/src/test/converter2.test.ts b/src/test/converter2.test.ts index 6b16a421d..1d4b00aff 100644 --- a/src/test/converter2.test.ts +++ b/src/test/converter2.test.ts @@ -50,12 +50,12 @@ describe("Converter2", () => { }); for (const [entry, check] of Object.entries(issueTests)) { - const link = `https://github.com/TypeStrong/typedoc/issues/${entry.substr( + const link = `https://github.com/TypeStrong/typedoc/issues/${entry.substring( 2 )}`; runTest( - `Issue ${entry.substr(2).padEnd(4)} (${link})`, + `Issue ${entry.substring(2).padEnd(4)} (${link})`, join("issues", entry), check ); From 7b50d32499b470914e53b8b843ea716ff03d4c01 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 25 Nov 2021 17:46:34 -0700 Subject: [PATCH 014/151] WIP: Getting closer! Start writing the changelog... --- CHANGELOG.md | 14 ++ src/lib/converter/comments/index.ts | 149 +++++++++------ src/lib/converter/comments/parser.ts | 36 ++-- src/lib/converter/context.ts | 2 +- src/lib/converter/converter.ts | 2 +- src/lib/converter/factories/signature.ts | 29 +-- src/lib/converter/plugins/CommentPlugin.ts | 55 +++--- src/lib/converter/plugins/DecoratorPlugin.ts | 130 -------------- src/lib/converter/plugins/InheritDocPlugin.ts | 3 +- src/lib/converter/plugins/index.ts | 1 - src/lib/converter/symbols.ts | 2 +- src/lib/models/comments/comment.ts | 32 +++- src/lib/models/reflections/abstract.ts | 35 ---- src/lib/models/reflections/index.ts | 2 +- src/lib/models/reflections/project.ts | 5 - src/lib/models/reflections/signature.ts | 3 - src/lib/models/reflections/type-parameter.ts | 3 - .../themes/default/partials/comment.tsx | 2 +- src/lib/serialization/index.ts | 2 - src/lib/serialization/schema.ts | 18 +- src/lib/serialization/serializer.ts | 1 - .../serializers/comments/comment-tag.ts | 4 +- .../serialization/serializers/decorator.ts | 38 ---- src/lib/serialization/serializers/index.ts | 1 - .../serializers/models/decorator-wrapper.ts | 9 - .../serialization/serializers/models/index.ts | 1 - .../serializers/reflections/abstract.ts | 10 +- src/lib/utils/options/readers/typedoc.ts | 2 + src/lib/validation/exports.ts | 6 +- src/test/comments.test.ts | 8 +- .../class/specs-with-lump-categories.json | 110 ++++++++++-- src/test/converter/class/specs.json | 110 ++++++++++-- src/test/converter/function/specs.json | 169 +++++++++++++++++- .../converter/inherit-param-doc/specs.json | 35 +++- src/test/converter/inheritance/specs.json | 56 ++++-- src/test/converter/js/specs.json | 11 +- 36 files changed, 668 insertions(+), 428 deletions(-) delete mode 100644 src/lib/converter/plugins/DecoratorPlugin.ts delete mode 100644 src/lib/serialization/serializers/decorator.ts delete mode 100644 src/lib/serialization/serializers/models/decorator-wrapper.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dd3f1065..4dcf73ece 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,20 @@ - `@inheritDoc` - Comment rendering +### Breaking Changes + +- `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` will now never be passed a `ts.Node` as their third argument. + +### Features + +- TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. + +### Bug Fixes + +- Fixed off by one error in warnings for types referenced but not included in the documentation. + ## v0.22.10 (2021-11-25) ### Features diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index 20fa04d24..02074ee7a 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -1,5 +1,5 @@ import * as ts from "typescript"; -import type { Comment, ReflectionKind } from "../../models"; +import { Comment, ReflectionKind } from "../../models"; import { assertNever, Logger } from "../../utils"; import { lexBlockComment } from "./blockLexer"; import { discoverComment, discoverSignatureComment } from "./discovery"; @@ -11,49 +11,71 @@ export interface CommentParserConfig { modifierTags: Set; } +const commentCache = new WeakMap>(); + +function getCommentWithCache( + discovered: [ts.SourceFile, ts.CommentRange] | undefined, + config: CommentParserConfig, + logger: Logger +) { + if (!discovered) return; + + const [file, range] = discovered; + const cache = commentCache.get(file) || new Map(); + if (cache?.has(range.pos)) { + return cache.get(range.pos)!.clone(); + } + + const line = ts.getLineAndCharacterOfPosition(file, range.pos).line + 1; + logger.verbose(`Parsing comment at ${file.fileName}:${line}`); + const warning = (warning: string) => + logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); + + let comment: Comment; + switch (range.kind) { + case ts.SyntaxKind.MultiLineCommentTrivia: + comment = parseComment( + lexBlockComment(file.text, range.pos, range.end), + config, + warning + ); + break; + case ts.SyntaxKind.SingleLineCommentTrivia: + throw "GERRIT FIX ME"; // GERRIT + default: + assertNever(range.kind); + } + + cache.set(range.pos, comment); + commentCache.set(file, cache); + + return comment.clone(); +} + export function getComment( symbol: ts.Symbol, kind: ReflectionKind, config: CommentParserConfig, logger: Logger ): Comment | undefined { - const comment = discoverComment(symbol, kind); - let resultingComment: Comment | undefined; - - if (comment) { - const [file, range] = comment; - const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); - logger.verbose(`Parsing comment at ${file.fileName}:${line}`); - const warning = (warning: string) => - logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); - - switch (range.kind) { - case ts.SyntaxKind.MultiLineCommentTrivia: - resultingComment = parseComment( - lexBlockComment(file.text, range.pos, range.end), - config, - warning - ); - break; - case ts.SyntaxKind.SingleLineCommentTrivia: - throw "GERRIT FIX ME"; - default: - assertNever(range.kind); - } - } + const comment = getCommentWithCache( + discoverComment(symbol, kind), + config, + logger + ); - if (symbol.declarations?.some(ts.isSourceFile) && resultingComment) { + 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 ( - !resultingComment.hasModifier("@packageDocumentation") && - !resultingComment.getTag("@module") + !comment.hasModifier("@packageDocumentation") && + !comment.getTag("@module") ) { return; } } - return resultingComment; + return comment; } export function getSignatureComment( @@ -61,26 +83,53 @@ export function getSignatureComment( config: CommentParserConfig, logger: Logger ): Comment | undefined { - const comment = discoverSignatureComment(declaration); - - if (comment) { - const [file, range] = comment; - const { line } = ts.getLineAndCharacterOfPosition(file, range.pos); - logger.verbose(`Parsing signature comment at ${file.fileName}:${line}`); - const warning = (warning: string) => - logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); - - switch (range.kind) { - case ts.SyntaxKind.MultiLineCommentTrivia: - return parseComment( - lexBlockComment(file.text, range.pos, range.end), - config, - warning - ); - case ts.SyntaxKind.SingleLineCommentTrivia: - throw "GERRIT FIX ME"; - default: - assertNever(range.kind); - } + return getCommentWithCache( + discoverSignatureComment(declaration), + config, + logger + ); +} + +export function getJsDocTagComment( + declaration: ts.JSDocPropertyLikeTag, + 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. + const tag = comment.getIdentifiedTag( + declaration.name.getText(), + `@${declaration.tagName.text}` + ); + + if (!tag) { + logger.error( + `Failed to find JSDoc tag for ${declaration.name.getText()} after parsing comment, please file a bug report with the comment at ${ + file.fileName + }:${ts.getLineAndCharacterOfPosition(file, parent.pos).line + 1}` + ); + } else { + return new Comment(Comment.cloneDisplayParts(tag.content)); } } diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 283c8e4a8..384b595e4 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -51,11 +51,19 @@ export function parseComment( return comment; } -const HAS_PARAM_NAME: `@${string}`[] = ["@param", "@template", "@typeParam"]; +const HAS_USER_IDENTIFIER: `@${string}`[] = [ + "@callback", + "@param", + "@prop", + "@property", + "@template", + "@typedef", + "@typeParam", +]; function postProcessComment(comment: Comment) { for (const tag of comment.blockTags) { - if (HAS_PARAM_NAME.includes(tag.tag) && tag.content.length) { + 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/); @@ -65,7 +73,12 @@ function postProcessComment(comment: Comment) { end + Math.max(0, first.text.substring(end).search(/[^\-\s]/)); - tag.paramName = first.text.substring(0, end); + tag.name = first.text.substring(0, end); + + if (tag.name.startsWith("[") && tag.name.endsWith("]")) { + tag.name = tag.name.slice(1, -1); + } + first.text = first.text.substring(startOfText); if (first.text === "") { @@ -89,25 +102,10 @@ function blockTag( const tagName = aliasedTags.get(blockTag.text) || blockTag.text; - const tag = new CommentTag( + return new CommentTag( tagName as `@${string}`, blockContent(comment, lexer, config, warning) ); - - if ( - tagName === "@param" && - tag.content.length && - tag.content[0].kind === "text" - ) { - const firstPart = tag.content[0]; - const match = firstPart.text.match(/^([a-z_$]+)\s*(-\s*)?/); - if (match) { - tag.paramName = match[1]; - firstPart.text = firstPart.text.substring(match[0].length); - } - } - - return tag; } function blockContent( diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 042b8cc88..8a625c037 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -167,7 +167,7 @@ export class Context { return resolveAliasedSymbol(symbol, this.checker); } - // TODO: This needs to live on Application, and get constructed based on user input. + // GERRIT: This needs to live on Application, and get constructed based on user input. config: CommentParserConfig = { blockTags: new Set(["@param", "@remarks", "@module"]), inlineTags: new Set(["@link"]), diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index 3c2ce8850..4dbba221d 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -96,7 +96,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 = diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index 2eb51265a..93b22325e 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -15,7 +15,7 @@ import type { Context } from "../context"; import { ConverterEvents } from "../converter-events"; import { convertDefaultValue } from "../convert-expression"; import { removeUndefined } from "../utils/reflections"; -import { getSignatureComment } from "../comments"; +import { getJsDocTagComment, getSignatureComment } from "../comments"; export function createSignature( context: Context, @@ -113,12 +113,15 @@ function convertParameters( ReflectionKind.Parameter, sigRef ); + if (declaration && ts.isJSDocParameterTag(declaration)) { + paramRefl.comment = getJsDocTagComment( + declaration, + context.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; if (declaration) { @@ -177,10 +180,18 @@ export function convertParameterNodes( ReflectionKind.Parameter, sigRef ); + if (ts.isJSDocParameterTag(param)) { + paramRefl.comment = getJsDocTagComment( + param, + context.config, + context.logger + ); + } context.registerReflection( paramRefl, context.getSymbolAtLocation(param) ); + context.trigger(ConverterEvents.CREATE_PARAMETER, paramRefl); paramRefl.type = context.converter.convertType( context.withScope(paramRefl), @@ -253,11 +264,7 @@ export function convertTypeParameterNodes( context.scope ); context.registerReflection(paramRefl, param.symbol); - context.trigger( - ConverterEvents.CREATE_TYPE_PARAMETER, - paramRefl, - param - ); + context.trigger(ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl); return paramRefl; }); diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 50c524277..e9fe1ccd0 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -21,8 +21,6 @@ import { partition, } from "../../utils"; -const DEBUG = true as boolean; - /** * These tags are not useful to display in the generated documentation. * They should be ignored when parsing comments. Any relevant type information @@ -129,27 +127,20 @@ export class CommentPlugin extends ConverterComponent { _context: Context, reflection: TypeParameterReflection ) { - if (DEBUG) return; - - // GERRIT - // if (node && ts.isJSDocTemplateTag(node.parent)) { - // const comment = getJsDocCommentText(node.parent.comment); - // if (comment) { - // reflection.comment = new Comment(comment); - // } - // } - const comment = reflection.parent?.comment; if (comment) { - let tag = comment.getParamTag(reflection.name, "@typeParam"); + let tag = comment.getIdentifiedTag(reflection.name, "@typeParam"); if (!tag) { - tag = comment.getParamTag(reflection.name, "@template"); + tag = comment.getIdentifiedTag(reflection.name, "@template"); } if (!tag) { - tag = comment.getParamTag(`<${reflection.name}>`, "@param"); + tag = comment.getIdentifiedTag( + `<${reflection.name}>`, + "@param" + ); } if (!tag) { - tag = comment.getParamTag(reflection.name, "@param"); + tag = comment.getIdentifiedTag(reflection.name, "@param"); } if (tag) { @@ -279,19 +270,21 @@ export class CommentPlugin extends ConverterComponent { if (parameter.name === "__namedParameters") { const commentParams = childComment.blockTags.filter( (tag) => - tag.tag === "@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!; } } moveNestedParamTags(childComment, parameter); - const tag = childComment.getParamTag(parameter.name); + const tag = childComment.getIdentifiedTag( + parameter.name, + "@param" + ); if (tag) { parameter.comment = new Comment( @@ -302,9 +295,18 @@ export class CommentPlugin extends ConverterComponent { signature.typeParameters?.forEach((parameter) => { const tag = - childComment.getParamTag(parameter.name, "@typeParam") || - childComment.getParamTag(parameter.name, "@template") || - childComment.getParamTag(`<${parameter.name}>`); + childComment.getIdentifiedTag( + parameter.name, + "@typeParam" + ) || + childComment.getIdentifiedTag( + parameter.name, + "@template" + ) || + childComment.getIdentifiedTag( + `<${parameter.name}>`, + "@param" + ); if (tag) { parameter.comment = new Comment( Comment.cloneDisplayParts(tag.content) @@ -373,11 +375,10 @@ function moveNestedParamTags(comment: Comment, parameter: ParameterReflection) { if (parameter.type instanceof ReflectionType) { const tags = comment.blockTags.filter( (t) => - t.tag === "@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 = parameter.type.declaration.getChildByName(path); if (child && !child.comment) { diff --git a/src/lib/converter/plugins/DecoratorPlugin.ts b/src/lib/converter/plugins/DecoratorPlugin.ts deleted file mode 100644 index ef8570fc8..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 = new ReferenceType( - info.name, - context.resolveAliasedSymbol(type.symbol), - context.project - ); - - 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( - new ReferenceType( - 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/InheritDocPlugin.ts b/src/lib/converter/plugins/InheritDocPlugin.ts index cb7108514..872b3a811 100644 --- a/src/lib/converter/plugins/InheritDocPlugin.ts +++ b/src/lib/converter/plugins/InheritDocPlugin.ts @@ -54,8 +54,7 @@ export class InheritDocPlugin extends ConverterComponent { if (reflection instanceof ContainerReflection) { const descendantsCallback: TraverseCallback = (item) => { item.traverse(descendantsCallback); - const inheritDoc = - item.comment?.getTag("@inheritDoc")?.paramName; + const inheritDoc = item.comment?.getTag("@inheritDoc")?.name; const source = inheritDoc && reflection.findReflectionByName(inheritDoc); let referencedReflection = source; diff --git a/src/lib/converter/plugins/index.ts b/src/lib/converter/plugins/index.ts index 2bc97b75f..f4e6e61eb 100644 --- a/src/lib/converter/plugins/index.ts +++ b/src/lib/converter/plugins/index.ts @@ -1,6 +1,5 @@ export { CategoryPlugin } from "./CategoryPlugin"; export { CommentPlugin } from "./CommentPlugin"; -export { DecoratorPlugin } from "./DecoratorPlugin"; export { SourceLinkPlugin } from "./SourceLinkPlugin"; export { GroupPlugin } from "./GroupPlugin"; export { ImplementsPlugin } from "./ImplementsPlugin"; diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index cee3cc5af..4e1b60c18 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -345,7 +345,7 @@ function createTypeParamReflection( context.scope ); context.registerReflection(paramRefl, param.symbol); - context.trigger(ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl, param); + context.trigger(ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl); return paramRefl; } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 795786020..b287bb8e4 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -17,9 +17,10 @@ export class CommentTag { tag: `@${string}`; /** - * If this is a `@param`, `@typeParam`, or `@template` tag, the parameter name associated with it. + * 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. */ - paramName?: string; + name?: string; /** * The actual body text of this tag. @@ -39,8 +40,8 @@ export class CommentTag { this.tag, Comment.cloneDisplayParts(this.content) ); - if (this.paramName) { - tag.paramName = this.paramName; + if (this.name) { + tag.name = this.name; } return tag; } @@ -117,6 +118,25 @@ export class Comment { 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; + } + /** * Has this comment a visible component? * @@ -154,9 +174,9 @@ export class Comment { return this.blockTags.find((tag) => tag.tag === tagName); } - getParamTag(param: string, tagName: `@${string}` = "@param") { + getIdentifiedTag(identifier: string, tagName: `@${string}`) { return this.blockTags.find( - (tag) => tag.tag === tagName && tag.paramName === param + (tag) => tag.tag === tagName && tag.name === identifier ); } diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index 681137113..20b49023f 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -1,6 +1,5 @@ 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"; @@ -280,27 +279,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. * @@ -365,16 +343,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. @@ -411,9 +379,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; diff --git a/src/lib/models/reflections/index.ts b/src/lib/models/reflections/index.ts index 1a2196ce9..3265fd50b 100644 --- a/src/lib/models/reflections/index.ts +++ b/src/lib/models/reflections/index.ts @@ -5,7 +5,7 @@ export { TraverseProperty, ReflectionFlags, } 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/project.ts b/src/lib/models/reflections/project.ts index 02364c815..4bb2a7ac8 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -61,11 +61,6 @@ export class ProjectReflection extends ContainerReflection { */ packageInfo: any; - /** - * Create a new ProjectReflection instance. - * - * @param name The name of the project. - */ constructor(name: string) { super(name, ReflectionKind.Project); } diff --git a/src/lib/models/reflections/signature.ts b/src/lib/models/reflections/signature.ts index 9d4b836b3..0538ebcd7 100644 --- a/src/lib/models/reflections/signature.ts +++ b/src/lib/models/reflections/signature.ts @@ -10,9 +10,6 @@ import type { TypeParameterReflection } from "./type-parameter"; import type { DeclarationReflection } from "./declaration"; export class SignatureReflection extends Reflection { - /** - * Create a new SignatureReflection to contain a specific type of signature. - */ constructor( name: string, kind: SignatureReflection["kind"], diff --git a/src/lib/models/reflections/type-parameter.ts b/src/lib/models/reflections/type-parameter.ts index 516d44ece..44c14f830 100644 --- a/src/lib/models/reflections/type-parameter.ts +++ b/src/lib/models/reflections/type-parameter.ts @@ -9,9 +9,6 @@ export class TypeParameterReflection extends Reflection { default?: Type; - /** - * Create a new TypeParameterReflection instance. - */ constructor( name: string, constraint?: Type, diff --git a/src/lib/output/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 4a7d47bba..cdaec6aed 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -20,7 +20,7 @@ function displayPartsToMarkdown(parts: CommentDisplayPart[]) { case "@label": break; // Not rendered. case "@link": - // TODO GERRIT RENDER ME PROPERLY + // GERRIT RENDER ME PROPERLY return part.text; default: // Hmm... probably want to be able to render these somehow, so custom inline tags can be given diff --git a/src/lib/serialization/index.ts b/src/lib/serialization/index.ts index 24b960683..c3ec80167 100644 --- a/src/lib/serialization/index.ts +++ b/src/lib/serialization/index.ts @@ -12,8 +12,6 @@ export { CommentTagSerializer, ContainerReflectionSerializer, DeclarationReflectionSerializer, - DecoratorContainerSerializer, - DecoratorWrapper, IntersectionTypeSerializer, IntrinsicTypeSerializer, LiteralTypeSerializer, diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 79b44ce78..4b27288bd 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -29,7 +29,7 @@ */ import type * as M from "../models"; -import type { SourceReferenceWrapper, DecoratorWrapper } from "./serializers"; +import type { SourceReferenceWrapper } from "./serializers"; /** * Describes the mapping from Model types to the corresponding JSON output type. @@ -75,8 +75,6 @@ type _ModelToObject = ? CommentTag : T extends M.CommentDisplayPart ? CommentDisplayPart - : T extends DecoratorWrapper - ? Decorator : T extends SourceReferenceWrapper ? SourceReference : never; @@ -179,14 +177,10 @@ export interface ContainerReflection } 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 @@ -343,14 +337,10 @@ export interface Comment modifierTags?: string[]; } -export interface CommentTag extends S { - paramName?: string; -} +export interface CommentTag + extends S {} export type CommentDisplayPart = M.CommentDisplayPart; export interface SourceReference extends S {} - -export interface Decorator - extends S {} diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index 71064b985..2bad0ef26 100644 --- a/src/lib/serialization/serializer.ts +++ b/src/lib/serialization/serializer.ts @@ -157,7 +157,6 @@ const serializerComponents: (new ( S.UnionTypeSerializer, S.UnknownTypeSerializer, - S.DecoratorContainerSerializer, S.ReflectionCategorySerializer, S.ReflectionGroupSerializer, ]; diff --git a/src/lib/serialization/serializers/comments/comment-tag.ts b/src/lib/serialization/serializers/comments/comment-tag.ts index e4d0bed3f..74b59ccb7 100644 --- a/src/lib/serialization/serializers/comments/comment-tag.ts +++ b/src/lib/serialization/serializers/comments/comment-tag.ts @@ -26,8 +26,8 @@ export class CommentTagSerializer extends SerializerComponent { content: tag.content, }; - if (tag.paramName) { - result.paramName = tag.paramName; + if (tag.name) { + result.name = tag.name; } return Object.assign(obj, result); 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 index d76a65e0e..6288f8dfe 100644 --- a/src/lib/serialization/serializers/index.ts +++ b/src/lib/serialization/serializers/index.ts @@ -2,7 +2,6 @@ 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 index bef843a86..5492998cd 100644 --- a/src/lib/serialization/serializers/models/index.ts +++ b/src/lib/serialization/serializers/models/index.ts @@ -1,2 +1 @@ export { SourceReferenceWrapper } from "./source-reference-wrapper"; -export { DecoratorWrapper } from "./decorator-wrapper"; diff --git a/src/lib/serialization/serializers/reflections/abstract.ts b/src/lib/serialization/serializers/reflections/abstract.ts index ebc2b6f95..9aa6407b9 100644 --- a/src/lib/serialization/serializers/reflections/abstract.ts +++ b/src/lib/serialization/serializers/reflections/abstract.ts @@ -1,7 +1,6 @@ import { Reflection } from "../../../models"; import { ReflectionSerializerComponent } from "../../components"; -import { DecoratorWrapper } from "../models"; import type { Reflection as JSONReflection } from "../../schema"; export class ReflectionSerializer extends ReflectionSerializerComponent { @@ -22,13 +21,12 @@ export class ReflectionSerializer extends ReflectionSerializerComponent new DecoratorWrapper(d)) - ), }; + if (reflection.comment && !reflection.comment.isEmpty()) { + result.comment = this.owner.toObject(reflection.comment); + } + if (reflection.originalName !== reflection.name) { result.originalName = reflection.originalName; } diff --git a/src/lib/utils/options/readers/typedoc.ts b/src/lib/utils/options/readers/typedoc.ts index 1d328f29d..af5224903 100644 --- a/src/lib/utils/options/readers/typedoc.ts +++ b/src/lib/utils/options/readers/typedoc.ts @@ -115,6 +115,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/validation/exports.ts b/src/lib/validation/exports.ts index 2dc9e7c1e..947285a51 100644 --- a/src/lib/validation/exports.ts +++ b/src/lib/validation/exports.ts @@ -105,9 +105,9 @@ export function validateExports( ); logger.warn( - `${ - type.name - }, defined at ${file}:${line}, is referenced by ${current!.getFullName()} but not included in the documentation.` + `${type.name}, defined at ${file}:${ + line + 1 + }, is referenced by ${current!.getFullName()} but not included in the documentation.` ); } } diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index 4e64d4dde..7df55247f 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -581,7 +581,7 @@ describe("Comment Parser", () => { const tag = new CommentTag("@param", [ { kind: "text", text: "Param text" }, ]); - tag.paramName = "T"; + tag.name = "T"; equal(comment.blockTags, [tag]); equal(comment.modifierTags, new Set()); @@ -597,7 +597,7 @@ describe("Comment Parser", () => { (comment) => { equal(comment.summary, [{ kind: "text", text: "Summary" }]); const tag = new CommentTag("@param", []); - tag.paramName = "T"; + tag.name = "T"; equal(comment.blockTags, [tag]); equal(comment.modifierTags, new Set()); @@ -615,7 +615,7 @@ describe("Comment Parser", () => { const tag = new CommentTag("@param", [ { kind: "text", text: "Param text" }, ]); - tag.paramName = "T"; + tag.name = "T"; equal(comment.blockTags, [tag]); equal(comment.modifierTags, new Set()); @@ -633,7 +633,7 @@ describe("Comment Parser", () => { const tag = new CommentTag("@param", [ { kind: "text", text: "Param text" }, ]); - tag.paramName = "T"; + tag.name = "T"; equal(comment.blockTags, [tag]); equal(comment.modifierTags, new Set()); diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 751361e57..165e268a6 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -2192,6 +2192,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The options object of this decorator." + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2207,6 +2215,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A property on the options object of this decorator." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -2261,6 +2277,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The parameter of this decorator." + } + ] + }, "type": { "type": "intrinsic", "name": "boolean" @@ -2441,6 +2465,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -2452,6 +2484,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The handler called when the event occurs." + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2516,6 +2556,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "error" @@ -2527,6 +2575,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A handler that will receive the error details" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2591,6 +2647,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "progress" @@ -2602,6 +2666,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A handler that will receive a progress event with the current and expected total bytes" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2666,6 +2738,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "complete" @@ -2677,6 +2757,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A function that will be called with general event data upon successful completion" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2763,18 +2851,6 @@ "kind": "text", "text": "GenericClass short text." } - ], - "blockTags": [ - { - "tag": "@param", - "content": [ - { - "kind": "text", - "text": "Generic parameter." - } - ], - "paramName": "T" - } ] }, "children": [ @@ -2947,7 +3023,15 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {} + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Generic parameter." + } + ] + } } ], "extendedBy": [ diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index f590b2a43..83f8c8ee2 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -2188,6 +2188,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The options object of this decorator." + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2203,6 +2211,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A property on the options object of this decorator." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -2257,6 +2273,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The parameter of this decorator." + } + ] + }, "type": { "type": "intrinsic", "name": "boolean" @@ -2437,6 +2461,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -2448,6 +2480,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The handler called when the event occurs." + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2512,6 +2552,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "error" @@ -2523,6 +2571,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A handler that will receive the error details" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2587,6 +2643,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "progress" @@ -2598,6 +2662,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A handler that will receive a progress event with the current and expected total bytes" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2662,6 +2734,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name of the event to subscribe for." + } + ] + }, "type": { "type": "literal", "value": "complete" @@ -2673,6 +2753,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A function that will be called with general event data upon successful completion" + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -2759,18 +2847,6 @@ "kind": "text", "text": "GenericClass short text." } - ], - "blockTags": [ - { - "tag": "@param", - "content": [ - { - "kind": "text", - "text": "Generic parameter." - } - ], - "paramName": "T" - } ] }, "children": [ @@ -2943,7 +3019,15 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {} + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Generic parameter." + } + ] + } } ], "extendedBy": [ diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index e9f9a486a..3ea8b0150 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -631,6 +631,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The condition that is asserted to be true when this function returns." + } + ] + }, "type": { "type": "intrinsic", "name": "boolean" @@ -796,7 +804,7 @@ "parameters": [ { "id": 25, - "name": "Param", + "name": "destructuredParam", "kind": 32768, "kindString": "Parameter", "flags": {}, @@ -1184,6 +1192,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A parameter with a default string value." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1196,6 +1212,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A parameter with a default numeric value." + } + ] + }, "type": { "type": "intrinsic", "name": "number" @@ -1208,6 +1232,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A parameter with a default NaN value." + } + ] + }, "type": { "type": "intrinsic", "name": "number" @@ -1220,6 +1252,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A parameter with a default boolean value." + } + ] + }, "type": { "type": "intrinsic", "name": "boolean" @@ -1232,6 +1272,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A parameter with a default null value." + } + ] + }, "type": { "type": "intrinsic", "name": "boolean" @@ -1274,6 +1322,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A normal parameter." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1287,6 +1343,14 @@ "flags": { "isOptional": true }, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An optional parameter." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1339,6 +1403,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a string parameter." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1350,6 +1422,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a parameter flagged with any.\n This sentence is placed in the next line." + } + ] + }, "type": { "type": "intrinsic", "name": "any" @@ -1361,6 +1441,18 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This is a **parameter** pointing to an interface." + }, + { + "kind": "code", + "text": "```\n const value:BaseClass = new BaseClass('test');\n functionWithArguments('arg', 0, value);\n ```" + } + ] + }, "type": { "type": "reference", "name": "Object" @@ -1415,6 +1507,14 @@ "flags": { "isRest": true }, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The rest parameter." + } + ] + }, "type": { "type": "array", "elementType": { @@ -1549,6 +1649,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An argument." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1590,6 +1698,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "The name value." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1622,6 +1738,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An object containing the name value." + } + ] + }, "type": { "type": "reflection", "declaration": { @@ -1637,6 +1761,14 @@ "kind": 1024, "kindString": "Property", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A value of the object." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -1796,6 +1928,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A generic parameter." + } + ] + }, "type": { "type": "reference", "id": 123, @@ -1808,6 +1948,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A generic array parameter." + } + ] + }, "type": { "type": "array", "elementType": { @@ -1842,9 +1990,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": [] - }, "typeParameter": [ { "id": 128, @@ -1869,6 +2014,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "this describes param" + } + ] + }, "type": { "type": "reference", "id": 128, @@ -1944,6 +2097,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Generic function parameter." + } + ] + }, "type": { "type": "reference", "id": 119, diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index ba4b34bae..6c6bcd666 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -178,6 +178,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Custom parameter A doc." + } + ] + }, "type": { "type": "intrinsic", "name": "number" @@ -305,6 +313,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Custom second parameter doc with name change." + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -373,9 +389,6 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, - "comment": { - "summary": [] - }, "parameters": [ { "id": 4, @@ -383,6 +396,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Parameter A." + } + ] + }, "type": { "type": "intrinsic", "name": "number" @@ -394,6 +415,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Parameter B." + } + ] + }, "type": { "type": "intrinsic", "name": "string" diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index c3a3560aa..995766321 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -23,18 +23,6 @@ "kind": "text", "text": "Source interface summary" } - ], - "blockTags": [ - { - "tag": "@typeParam", - "content": [ - { - "kind": "text", - "text": "Source interface type parameter" - } - ], - "paramName": "T" - } ] }, "children": [ @@ -60,7 +48,7 @@ "text": "Source interface type parameter" } ], - "paramName": "T" + "name": "T" } ] }, @@ -135,7 +123,15 @@ "name": "T", "kind": 131072, "kindString": "Type parameter", - "flags": {} + "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Source interface type parameter" + } + ] + } } ] }, @@ -335,6 +331,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "First argument" + } + ] + }, "type": { "type": "reference", "id": 4, @@ -347,6 +351,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Second argument" + } + ] + }, "type": { "type": "reference", "id": 4, @@ -472,6 +484,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This will be inherited" + } + ] + }, "type": { "type": "reference", "id": 11, @@ -484,6 +504,14 @@ "kind": 32768, "kindString": "Parameter", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "This will be inherited" + } + ] + }, "type": { "type": "reference", "id": 11, diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index daa091bed..d9c2d06e7 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -463,6 +463,14 @@ "flags": { "isOptional": true }, + "comment": { + "summary": [ + { + "kind": "text", + "text": "an optional argument" + } + ] + }, "type": { "type": "intrinsic", "name": "string" @@ -504,9 +512,6 @@ "kind": 32, "kindString": "Variable", "flags": {}, - "comment": { - "summary": [] - }, "type": { "type": "reflection", "declaration": { From 0ea4b7e36d1deafe6881cd2a12a9e04e9b94daf7 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 25 Nov 2021 17:53:23 -0700 Subject: [PATCH 015/151] Add warning about multiple `@remarks` tags --- src/lib/converter/comments/parser.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 384b595e4..ef70dcc88 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -1,7 +1,7 @@ import { ok } from "assert"; import type { CommentParserConfig } from "."; import { Comment, CommentDisplayPart, CommentTag } from "../../models"; -import { assertNever } from "../../utils"; +import { assertNever, removeIf } from "../../utils"; import { Token, TokenSyntaxKind } from "./blockLexer"; interface LookaheadGenerator { @@ -46,7 +46,7 @@ export function parseComment( comment.blockTags.push(blockTag(comment, lexer, config, warning)); } - postProcessComment(comment); + postProcessComment(comment, warning); return comment; } @@ -61,7 +61,7 @@ const HAS_USER_IDENTIFIER: `@${string}`[] = [ "@typeParam", ]; -function postProcessComment(comment: Comment) { +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]; @@ -87,6 +87,14 @@ function postProcessComment(comment: Comment) { } } } + + 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 aliasedTags = new Map([["@return", "@returns"]]); From 335d8daf443381b9eef989252a11605125444b71 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 26 Nov 2021 10:37:46 -0700 Subject: [PATCH 016/151] Correct whitespace handling, fix most of the failing tests --- src/lib/converter/comments/parser.ts | 29 ++++++++++++++--------- src/lib/models/comments/comment.ts | 2 +- src/test/converter.test.ts | 2 +- src/test/converter/comment/specs.json | 22 ++++++++--------- src/test/converter/function/specs.json | 14 +++++------ src/test/converter/inheritance/specs.json | 4 ++-- src/test/converter2/issues/gh567.ts | 4 ++++ src/test/issueTests.ts | 29 +++++++++++++++++++---- 8 files changed, 68 insertions(+), 38 deletions(-) create mode 100644 src/test/converter2/issues/gh567.ts diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index ef70dcc88..4c15a410b 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -61,6 +61,10 @@ const HAS_USER_IDENTIFIER: `@${string}`[] = [ "@typeParam", ]; +/** + * 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) { @@ -69,19 +73,17 @@ function postProcessComment(comment: Comment, warning: (msg: string) => void) { let end = first.text.search(/\s/); if (end === -1) end = first.text.length; - const startOfText = - end + - Math.max(0, first.text.substring(end).search(/[^\-\s]/)); - tag.name = first.text.substring(0, end); - if (tag.name.startsWith("[") && tag.name.endsWith("]")) { tag.name = tag.name.slice(1, -1); } - first.text = first.text.substring(startOfText); - - if (first.text === "") { + 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(); } } @@ -192,7 +194,13 @@ function blockContent( // Now get rid of extra whitespace, and any empty parts for (let i = 0; i < content.length /* inside loop */; ) { - content[i].text = content[i].text.trim(); + 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 { @@ -232,8 +240,7 @@ function inlineTag( lexer.peek().kind != TokenSyntaxKind.Tag)) ) { warning("Encountered an unescaped open brace without an inline tag"); - block.push({ kind: "text", text: openBrace.text }); - block.push({ kind: "text", text: tagName.text }); + block.push({ kind: "text", text: openBrace.text + tagName.text }); return; } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index b287bb8e4..f118ee2b4 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -72,7 +72,7 @@ export class Comment { result.push(item.text); break; case "inline-tag": - result.push("{", item.tag, item.text, "}"); + result.push("{", item.tag, " ", item.text, "}"); break; default: assertNever(item); diff --git a/src/test/converter.test.ts b/src/test/converter.test.ts index a6f2435f3..4052bad1d 100644 --- a/src/test/converter.test.ts +++ b/src/test/converter.test.ts @@ -9,7 +9,7 @@ import { getConverterProgram, } from "./programs"; -describe.skip("Converter", function () { +describe("Converter", function () { const base = getConverterBase(); const app = getConverterApp(); diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index e093fc70e..315d26675 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -21,7 +21,7 @@ "summary": [ { "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" + "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" }, { "kind": "code", @@ -461,7 +461,7 @@ "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" + "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", @@ -469,7 +469,7 @@ }, { "kind": "text", - "text": "function." + "text": " function." } ] }, @@ -491,7 +491,7 @@ "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" + "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", @@ -499,7 +499,7 @@ }, { "kind": "text", - "text": "function." + "text": " function." } ], "modifierTags": [ @@ -558,7 +558,7 @@ "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" + "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", @@ -566,7 +566,7 @@ }, { "kind": "text", - "text": "function." + "text": " function." } ] }, @@ -588,7 +588,7 @@ "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" + "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", @@ -596,7 +596,7 @@ }, { "kind": "text", - "text": "function." + "text": " function." } ], "blockTags": [ @@ -658,7 +658,7 @@ "summary": [ { "kind": "text", - "text": "This is a comment containing a multiline code block" + "text": "This is a comment containing a multiline code block\n" }, { "kind": "code", @@ -684,7 +684,7 @@ "summary": [ { "kind": "text", - "text": "This is a comment containing a multiline code block" + "text": "This is a comment containing a multiline code block\n" }, { "kind": "code", diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 3ea8b0150..126969b94 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -836,7 +836,7 @@ "summary": [ { "kind": "text", - "text": "This is a **parameter** pointing to an interface." + "text": "This is a **parameter** pointing to an interface.\n\n " }, { "kind": "code", @@ -927,7 +927,7 @@ "summary": [ { "kind": "text", - "text": "This is a function with a destructured parameter and an extra" + "text": "This is a function with a destructured parameter and an extra " }, { "kind": "code", @@ -935,7 +935,7 @@ }, { "kind": "text", - "text": "directive with no corresponding parameter.\nThe" + "text": " directive with no corresponding parameter.\nThe " }, { "kind": "code", @@ -943,7 +943,7 @@ }, { "kind": "text", - "text": "directives are ignored because we cannot be certain which corresponds to the real parameter." + "text": " directives are ignored because we cannot be certain which corresponds to the real parameter." } ], "blockTags": [ @@ -1047,7 +1047,7 @@ "summary": [ { "kind": "text", - "text": "This is a function with a destructured parameter and additional undocumented parameters.\nThe" + "text": "This is a function with a destructured parameter and additional undocumented parameters.\nThe " }, { "kind": "code", @@ -1055,7 +1055,7 @@ }, { "kind": "text", - "text": "directives are ignored because we cannot be certain which parameter they refer to." + "text": " directives are ignored because we cannot be certain which parameter they refer to." } ], "blockTags": [ @@ -1445,7 +1445,7 @@ "summary": [ { "kind": "text", - "text": "This is a **parameter** pointing to an interface." + "text": "This is a **parameter** pointing to an interface.\n\n " }, { "kind": "code", diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 995766321..c8cfd4c24 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -437,7 +437,7 @@ "content": [ { "kind": "text", - "text": "This function inherited commentary from the" + "text": "This function inherited commentary from the " }, { "kind": "code", @@ -445,7 +445,7 @@ }, { "kind": "text", - "text": "function" + "text": " function" } ] }, 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/issueTests.ts b/src/test/issueTests.ts index 428fc82a9..c6097b1bf 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -19,6 +19,19 @@ function query(project: ProjectReflection, name: string) { export const issueTests: { [issue: string]: (project: ProjectReflection) => 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" + ); + }, + gh869(project) { const classFoo = project.children?.find( (r) => r.name === "Foo" && r.kind === ReflectionKind.Class @@ -62,7 +75,7 @@ export const issueTests: { (x) => x.tag === "@returns" ); ok(tag); - equal(Comment.combineDisplayParts(tag.content), "Test description.\n"); + equal(Comment.combineDisplayParts(tag.content), "Test description."); }, gh1215(project) { @@ -73,7 +86,7 @@ export const issueTests: { gh1255(project) { const foo = query(project, "C.foo"); - equal(foo.comment?.summary, "Docs!"); + equal(Comment.combineDisplayParts(foo.comment?.summary), "Docs!"); }, gh1330(project) { @@ -134,7 +147,10 @@ export const issueTests: { gh1481(project) { const signature = query(project, "GH1481.static").signatures?.[0]; - equal(signature?.comment?.summary, "static docs"); + equal( + Comment.combineDisplayParts(signature?.comment?.summary), + "static docs" + ); equal(signature?.type?.toString(), "void"); }, @@ -151,7 +167,10 @@ export const issueTests: { gh1490(project) { const refl = query(project, "GH1490.optionalMethod"); - equal(refl.signatures?.[0]?.comment?.summary, "With comment"); + equal( + Comment.combineDisplayParts(refl.signatures?.[0]?.comment?.summary), + "With comment" + ); }, gh1509(project) { @@ -248,7 +267,7 @@ export const issueTests: { gh1733(project) { const alias = query(project, "Foo"); equal(alias.typeParameters?.[0].comment?.summary, [ - { kind: "text", text: "T docs\n" }, + { kind: "text", text: "T docs" }, ]); const cls = query(project, "Bar"); equal(cls.typeParameters?.[0].comment?.summary, [ From 905150a24620a0973227494249ea8d90561e9f4e Mon Sep 17 00:00:00 2001 From: Aquib Vadsaria Date: Sat, 4 Dec 2021 01:03:41 +0530 Subject: [PATCH 017/151] feat: introduce header default filter options #307 --- src/index.ts | 1 + .../assets/typedoc/components/Filter.ts | 24 +-- .../output/themes/default/partials/header.tsx | 168 ++++++++++-------- src/lib/utils/index.ts | 1 + src/lib/utils/options/declaration.ts | 11 ++ src/lib/utils/options/index.ts | 7 +- src/lib/utils/options/sources/typedoc.ts | 19 ++ 7 files changed, 150 insertions(+), 81 deletions(-) diff --git a/src/index.ts b/src/index.ts index fb6dc1db4..c67d34241 100644 --- a/src/index.ts +++ b/src/index.ts @@ -30,6 +30,7 @@ export { TSConfigReader, TypeDocReader, EntryPointStrategy, + VisibilityFilter, EventHooks, } from "./lib/utils"; 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..05628b095 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Filter.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Filter.ts @@ -8,10 +8,10 @@ abstract class FilterItem { protected defaultValue: T; - constructor(key: string, value: T) { + constructor(key: string) { this.key = key; - this.value = value; - this.defaultValue = value; + this.value; + this.defaultValue; this.initialize(); @@ -50,6 +50,8 @@ class FilterItemCheckbox extends FilterItem { if (!checkbox) return; this.checkbox = checkbox; + this.value = !!checkbox.checked; + this.defaultValue = this.value; this.checkbox.addEventListener("change", () => { this.setValue(this.checkbox.checked); }); @@ -77,16 +79,18 @@ 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; + const selectedEl = select.querySelector("li.selected"); this.select = select; + this.value = selectedEl.getAttribute("data-value"); + this.defaultValue = this.value; + document.documentElement.classList.add( + "toggle-" + this.key + this.value + ); const onActivate = () => { this.select.classList.add("active"); }; @@ -151,9 +155,9 @@ export class Filter extends Component { constructor(options: IComponentOptions) { super(options); - this.optionVisibility = new FilterItemSelect("visibility", "private"); - this.optionInherited = new FilterItemCheckbox("inherited", true); - this.optionExternals = new FilterItemCheckbox("externals", true); + this.optionVisibility = new FilterItemSelect("visibility"); + this.optionInherited = new FilterItemCheckbox("inherited"); + this.optionExternals = new FilterItemCheckbox("externals"); } static isSupported(): boolean { diff --git a/src/lib/output/themes/default/partials/header.tsx b/src/lib/output/themes/default/partials/header.tsx index e95185d09..3c15b1b88 100644 --- a/src/lib/output/themes/default/partials/header.tsx +++ b/src/lib/output/themes/default/partials/header.tsx @@ -1,85 +1,113 @@ import type { Reflection } from "../../../../models"; -import { JSX } from "../../../../utils"; +import { JSX, VisibilityFilter } from "../../../../utils"; import type { PageEvent } from "../../../events"; import { hasTypeParameters, join } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -export const header = (context: DefaultThemeRenderContext, props: PageEvent) => ( -
-
-
-
- +export const header = (context: DefaultThemeRenderContext, props: PageEvent) => { + const defaultSelectedVisibility = context.options.getValue("visibility"); + const selectedVisibility = Object.keys(visibilityFilterLabels).includes(defaultSelectedVisibility) + ? (defaultSelectedVisibility as VisibilityFilter) + : VisibilityFilter.all; + const defaultInheritedChecked = context.options.getValue("showInherited"); + const defaultExternalsChecked = context.options.getValue("showExternals"); -
-
- - Options - -
-
- All -
    -
  • Public
  • -
  • Public/Protected
  • -
  • - All -
  • -
-
{" "} - -
-
-
- {!!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)} - {">"} - - )} -

+
+
+ {!!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)} + {">"} + + )} +

+
-
-
-); + + ); +}; diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index be59a7d18..c2159daa4 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -28,6 +28,7 @@ export { ParameterType, TSConfigReader, TypeDocReader, + VisibilityFilter, } from "./options"; export type { ArrayDeclarationOption, diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 5b600cba9..e03a9c0f4 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -49,6 +49,12 @@ export type TypeDocOptionValues = { : TypeDocOptionMap[K][keyof TypeDocOptionMap[K]]; }; +export enum VisibilityFilter { + all = "private", + public = "public", + protected = "protected", +} + /** * Describes all TypeDoc options. Used internally to provide better types when fetching options. * External consumers should likely use {@link TypeDocOptions} instead. @@ -60,6 +66,11 @@ export interface TypeDocOptionMap { entryPoints: string[]; entryPointStrategy: typeof EntryPointStrategy; + // typedoc header filters + visibility: string; + showInherited: boolean; + showExternals: boolean; + exclude: string[]; externalPattern: string[]; excludeExternals: boolean; diff --git a/src/lib/utils/options/index.ts b/src/lib/utils/options/index.ts index 4583415df..3d17b67be 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 { + EmitStrategy, + ParameterType, + ParameterHint, + VisibilityFilter, +} from "./declaration"; export type { TypeDocOptions, diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 8d9ebd79d..ea6294d49 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -33,6 +33,25 @@ export function addTypeDocOptions(options: Pick) { defaultValue: EntryPointStrategy.Resolve, }); + options.addDeclaration({ + name: "visibility", + help: 'Specify the default visibility for methods, possible values: "private" | "public" | "protected"', + type: ParameterType.String, + defaultValue: "private", + }); + options.addDeclaration({ + name: "showInherited", + help: "Specify the default inherited checkbox value", + type: ParameterType.Boolean, + defaultValue: true, + }); + options.addDeclaration({ + name: "showExternals", + help: "Specify the default externals checkbox value", + type: ParameterType.Boolean, + defaultValue: true, + }); + options.addDeclaration({ name: "exclude", help: "Define patterns to be excluded when expanding a directory that was specified as an entry point.", From 909818fb6d44e7e42a8286c1e2a90b6fb9de40a0 Mon Sep 17 00:00:00 2001 From: Futuristick Date: Fri, 1 Oct 2021 17:49:54 -0400 Subject: [PATCH 018/151] WIP - Clean up spacing --- .../partials/member.signature.body.tsx | 10 ++-- .../themes/default/templates/reflection.tsx | 12 ++--- src/lib/utils/options/sources/typedoc.ts | 4 +- static/icons/class.svg | 5 ++ static/icons/enum.svg | 5 ++ static/icons/function.svg | 5 ++ static/icons/interface.svg | 5 ++ static/icons/namespace.svg | 5 ++ static/icons/typeAlias.svg | 5 ++ static/icons/variable.svg | 5 ++ static/style.css | 54 +++++++------------ 11 files changed, 66 insertions(+), 49 deletions(-) create mode 100644 static/icons/class.svg create mode 100644 static/icons/enum.svg create mode 100644 static/icons/function.svg create mode 100644 static/icons/interface.svg create mode 100644 static/icons/namespace.svg create mode 100644 static/icons/typeAlias.svg create mode 100644 static/icons/variable.svg 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 74b6fb1ce..647d8dc78 100644 --- a/src/lib/output/themes/default/partials/member.signature.body.tsx +++ b/src/lib/output/themes/default/partials/member.signature.body.tsx @@ -12,15 +12,15 @@ export const memberSignatureBody = ( {context.comment(props)} {!!props.typeParameters && ( - <> +

Type parameters

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

Parameters

-
    +
      {props.parameters.map((item) => (
    • @@ -41,7 +41,7 @@ export const memberSignatureBody = (
    • ))}
    - +
)} {props.type && ( <> diff --git a/src/lib/output/themes/default/templates/reflection.tsx b/src/lib/output/themes/default/templates/reflection.tsx index b1e819e2f..50a8ffc09 100644 --- a/src/lib/output/themes/default/templates/reflection.tsx +++ b/src/lib/output/themes/default/templates/reflection.tsx @@ -10,7 +10,7 @@ export const reflectionTemplate = (context: DefaultThemeRenderContext, props: Pa {hasTypeParameters(props.model) && (
-

Type parameters

+

Type parameters

{context.typeParameters(props.model.typeParameters)}
)} @@ -18,13 +18,13 @@ export const reflectionTemplate = (context: DefaultThemeRenderContext, props: Pa <> {!!props.model.typeHierarchy && (
-

Hierarchy

+

Hierarchy

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

Implements

+

Implements

    {props.model.implementedTypes.map((item) => (
  • {context.type(item)}
  • @@ -34,7 +34,7 @@ export const reflectionTemplate = (context: DefaultThemeRenderContext, props: Pa )} {!!props.model.implementedBy && (
    -

    Implemented by

    +

    Implemented by

      {props.model.implementedBy.map((item) => (
    • {context.type(item)}
    • @@ -44,13 +44,13 @@ export const reflectionTemplate = (context: DefaultThemeRenderContext, props: Pa )} {!!props.model.signatures && (
      -

      Callable

      +

      Callable

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

      Indexable

      +

      Indexable

      [ {props.model.indexSignature.parameters!.map((item) => ( diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 883b478da..a5b915f80 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -134,8 +134,8 @@ export function addTypeDocOptions(options: Pick) { defaultValue: "default", }); - const defaultLightTheme: Theme = "light-plus"; - const defaultDarkTheme: Theme = "dark-plus"; + const defaultLightTheme: Theme = "material-lighter"; + const defaultDarkTheme: Theme = "material-default"; options.addDeclaration({ name: "lightHighlightTheme", diff --git a/static/icons/class.svg b/static/icons/class.svg new file mode 100644 index 000000000..3a05f7049 --- /dev/null +++ b/static/icons/class.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/enum.svg b/static/icons/enum.svg new file mode 100644 index 000000000..67b01ea7a --- /dev/null +++ b/static/icons/enum.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/function.svg b/static/icons/function.svg new file mode 100644 index 000000000..aff72a86b --- /dev/null +++ b/static/icons/function.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/interface.svg b/static/icons/interface.svg new file mode 100644 index 000000000..13890dc39 --- /dev/null +++ b/static/icons/interface.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/namespace.svg b/static/icons/namespace.svg new file mode 100644 index 000000000..3b40e5e33 --- /dev/null +++ b/static/icons/namespace.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/typeAlias.svg b/static/icons/typeAlias.svg new file mode 100644 index 000000000..cf3832160 --- /dev/null +++ b/static/icons/typeAlias.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/icons/variable.svg b/static/icons/variable.svg new file mode 100644 index 000000000..011783c1c --- /dev/null +++ b/static/icons/variable.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/static/style.css b/static/style.css index a16ed029e..417ffc46d 100644 --- a/static/style.css +++ b/static/style.css @@ -1,9 +1,14 @@ @import url("./icons.css"); :root { + --text-title: 2em; + --text-heading: 1.5em; + --text-subheading: 1.25em; + --text-body: 1em; + --text-caption: 0.875em; + /* Light */ - --light-color-background: #fcfcfc; - --light-color-secondary-background: #fff; + --light-color-background: #f2f4f8; --light-color-text: #222; --light-color-text-aside: #707070; --light-color-link: #4da6ff; @@ -25,8 +30,7 @@ --light-external-icon: url("data:image/svg+xml;utf8,"); /* Dark */ - --dark-color-background: #36393f; - --dark-color-secondary-background: #2f3136; + --dark-color-background: #171e21; --dark-color-text: #ffffff; --dark-color-text-aside: #e6e4e4; --dark-color-link: #00aff4; @@ -379,7 +383,8 @@ pre { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0.2em; margin: 0; - font-size: 14px; + font-size: var(--text-caption); + border-radius: 0.8em; } pre { @@ -518,8 +523,6 @@ blockquote { .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; @@ -677,7 +680,6 @@ footer .tsd-legend { .tsd-hierarchy { list-style: square; - padding: 0 0 0 20px; margin: 0; } .tsd-hierarchy .target { @@ -928,10 +930,7 @@ footer .tsd-legend { } .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: 4em; } .tsd-panel:empty { display: none; @@ -976,12 +975,6 @@ footer .tsd-legend { .tsd-panel-group { margin: 60px 0; } -.tsd-panel-group > h1, -.tsd-panel-group > h2, -.tsd-panel-group > h3 { - padding-left: 20px; - padding-right: 20px; -} #tsd-search { transition: background-color 0.2s; @@ -1178,40 +1171,29 @@ 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; + 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; From 942bb13a9728e60d3b7eebc380dc8051c725afe4 Mon Sep 17 00:00:00 2001 From: Futuristick Date: Mon, 11 Oct 2021 20:23:50 -0400 Subject: [PATCH 019/151] Update icons + relevant styling Also removed icon legend from the footer. As such, the hideLegend option now serves no purpose and should be removed. --- .../assets/typedoc/components/Search.ts | 1 - .../output/themes/default/layouts/default.tsx | 2 +- .../output/themes/default/partials/footer.tsx | 22 +- .../output/themes/default/partials/icon.tsx | 144 +++ .../output/themes/default/partials/index.tsx | 8 +- .../default/partials/member.declaration.tsx | 2 +- .../default/partials/member.getterSetter.tsx | 4 +- .../default/partials/member.signatures.tsx | 4 +- .../themes/default/partials/navigation.tsx | 7 +- .../themes/default/partials/parameter.tsx | 2 +- .../themes/default/templates/reflection.tsx | 2 +- static/icons.css | 1043 ----------------- static/icons/class.svg | 5 - static/icons/enum.svg | 5 - static/icons/function.svg | 5 - static/icons/interface.svg | 5 - static/icons/namespace.svg | 5 - static/icons/typeAlias.svg | 5 - static/icons/variable.svg | 5 - 19 files changed, 165 insertions(+), 1111 deletions(-) create mode 100644 src/lib/output/themes/default/partials/icon.tsx delete mode 100644 static/icons.css delete mode 100644 static/icons/class.svg delete mode 100644 static/icons/enum.svg delete mode 100644 static/icons/function.svg delete mode 100644 static/icons/interface.svg delete mode 100644 static/icons/namespace.svg delete mode 100644 static/icons/typeAlias.svg delete mode 100644 static/icons/variable.svg 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 1fe99fc99..67a69c071 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Search.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Search.ts @@ -171,7 +171,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); diff --git a/src/lib/output/themes/default/layouts/default.tsx b/src/lib/output/themes/default/layouts/default.tsx index 694f22eb7..eb51248c9 100644 --- a/src/lib/output/themes/default/layouts/default.tsx +++ b/src/lib/output/themes/default/layouts/default.tsx @@ -39,7 +39,7 @@ export const defaultLayout = (context: DefaultThemeRenderContext, props: PageEve
- {context.footer(props)} + {context.footer()}
diff --git a/src/lib/output/themes/default/partials/footer.tsx b/src/lib/output/themes/default/partials/footer.tsx index e8ab7da4c..5fa40fe9e 100644 --- a/src/lib/output/themes/default/partials/footer.tsx +++ b/src/lib/output/themes/default/partials/footer.tsx @@ -1,11 +1,8 @@ -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 ( <> @@ -15,23 +12,6 @@ export function footer(context: DefaultThemeRenderContext, props: PageEvent
- {!hideLegend && props.legend?.length && ( - <> -

Legend

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

Settings

Theme{" "} 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..2c6a4de44 --- /dev/null +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -0,0 +1,144 @@ +import { ReflectionKind } from "../../../../models"; +import { JSX } from "../../../../utils"; + +export const icons: Record JSX.Element | null> = { + [ReflectionKind.All]: () => null, + [ReflectionKind.Accessor]: () => ( + + + + + + ), + [ReflectionKind.CallSignature]() { + return this[ReflectionKind.Function]() + }, + [ReflectionKind.Class]: () => ( + + + + + + ), + [ReflectionKind.ClassMember]() { + return this[ReflectionKind.Property]() + }, + [ReflectionKind.ClassOrInterface]() { + return this[ReflectionKind.Class]() + }, + [ReflectionKind.Constructor]: () => ( + + + + + + ), + [ReflectionKind.ConstructorSignature]() { + return this[ReflectionKind.Constructor]() + }, + [ReflectionKind.Enum]: () => ( + + + + + + ), + [ReflectionKind.EnumMember]() { + return this[ReflectionKind.Property]() + }, + [ReflectionKind.Event]: () => ( + + + + + + ), + [ReflectionKind.Function]: () => ( + + + + + + ), + [ReflectionKind.FunctionOrMethod]() { + return this[ReflectionKind.Function]() + }, + [ReflectionKind.GetSignature]() { + return this[ReflectionKind.Accessor]() + }, + [ReflectionKind.IndexSignature]() { + return this[ReflectionKind.Property]() + }, + [ReflectionKind.Inheritable]: () => null, + [ReflectionKind.Interface]: () => ( + + + + + + ), + [ReflectionKind.Method]: () => ( + + + + + + ), + [ReflectionKind.Module]() { + return this[ReflectionKind.Namespace]() + }, + [ReflectionKind.Namespace]: () => ( + + + + + + ), + [ReflectionKind.ObjectLiteral]() { + return this[ReflectionKind.Interface]() + }, + [ReflectionKind.Parameter]() { + return this[ReflectionKind.Property]() + }, + [ReflectionKind.Project]() { + return this[ReflectionKind.Namespace]() + }, + [ReflectionKind.Property]: () => ( + + + + + + ), + [ReflectionKind.Reference]: () => null, + [ReflectionKind.SetSignature]() { + return this[ReflectionKind.Accessor]() + }, + [ReflectionKind.SomeSignature]: () => null, + [ReflectionKind.SomeModule]: () => null, + [ReflectionKind.SomeType]: () => null, + [ReflectionKind.SomeValue]: () => null, + [ReflectionKind.TypeAlias]: () => ( + + + + + + ), + [ReflectionKind.TypeLiteral]() { + return this[ReflectionKind.TypeAlias]() + }, + [ReflectionKind.TypeParameter]() { + return this[ReflectionKind.TypeAlias]() + }, + [ReflectionKind.Variable]: () => ( + + + + + + ), + [ReflectionKind.VariableOrProperty]() { + return this[ReflectionKind.Variable]() + } +} diff --git a/src/lib/output/themes/default/partials/index.tsx b/src/lib/output/themes/default/partials/index.tsx index 19ca5cf70..944762e53 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -2,6 +2,8 @@ import { 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 ( @@ -10,7 +12,8 @@ function renderCategory({ urlTo }: DefaultThemeRenderContext, item: ReflectionCa

    {item.children.map((item) => (
  • - + + {icons[item.kind]()} {item.name ? wbr(item.name) : {wbr(item.kindString!)}}
  • @@ -48,7 +51,8 @@ export function index(context: DefaultThemeRenderContext, props: ContainerReflec
      {item.children.map((item) => (
    • - + + {icons[item.kind]()} {item.name ? wbr(item.name) : {wbr(item.kindString!)}}
    • diff --git a/src/lib/output/themes/default/partials/member.declaration.tsx b/src/lib/output/themes/default/partials/member.declaration.tsx index 90c22c7ec..6b2354b32 100644 --- a/src/lib/output/themes/default/partials/member.declaration.tsx +++ b/src/lib/output/themes/default/partials/member.declaration.tsx @@ -5,7 +5,7 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; export const memberDeclaration = (context: DefaultThemeRenderContext, props: DeclarationReflection) => ( <> -
      +
      {wbr(props.name)} {renderTypeParametersSignature(props.typeParameters)} {props.type && ( diff --git a/src/lib/output/themes/default/partials/member.getterSetter.tsx b/src/lib/output/themes/default/partials/member.getterSetter.tsx index de197c8c4..b6f506ea6 100644 --- a/src/lib/output/themes/default/partials/member.getterSetter.tsx +++ b/src/lib/output/themes/default/partials/member.getterSetter.tsx @@ -6,13 +6,13 @@ export const memberGetterSetter = (context: DefaultThemeRenderContext, props: De <>
        {!!props.getSignature && ( -
      • +
      • get {props.name} {context.memberSignatureTitle(props.getSignature, { hideName: true })}
      • )} {!!props.setSignature && ( -
      • +
      • set {props.name} {context.memberSignatureTitle(props.setSignature, { hideName: true })}
      • diff --git a/src/lib/output/themes/default/partials/member.signatures.tsx b/src/lib/output/themes/default/partials/member.signatures.tsx index aa1e4df76..eb4494f59 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/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 9a32ac6b2..59bdb8230 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -3,6 +3,7 @@ import { JSX, partition } from "../../../../utils"; import type { PageEvent } from "../../../events"; import { classNames, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; +import { icons } from "./icon"; export function navigation(context: DefaultThemeRenderContext, props: PageEvent) { return ( @@ -94,7 +95,8 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven .map((child) => { return (
      • - + + {icons[child.kind]()} {wbr(child.name)}
      • @@ -111,7 +113,8 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven
      @@ -80,21 +63,15 @@ function settings() { ); } -function primaryNavigation( - context: DefaultThemeRenderContext, - props: PageEvent -) { +function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent) { // Create the navigation for the current page - const modules = props.model.project.getChildrenByKind( - ReflectionKind.SomeModule - ); + const modules = props.model.project.getChildrenByKind(ReflectionKind.SomeModule); const [ext, int] = partition(modules, (m) => m.flags.isExternal); const selected = props.model.isProject(); const current = selected || int.some((mod) => inPath(mod, props.model)); - //if (ext.length) { return ( ); - //} - - return ( - - ); function link(mod: DeclarationReflection) { const current = inPath(mod, props.model); const selected = mod.name === props.model.name; let childNav: JSX.Element | undefined; - const childModules = mod.children?.filter((m) => - m.kindOf(ReflectionKind.SomeModule) - ); + const childModules = mod.children?.filter((m) => m.kindOf(ReflectionKind.SomeModule)); if (childModules?.length) { childNav =
        {childModules.map(link)}
      ; } return ( -
    • +
    • {wbr(mod.name)} {childNav}
    • @@ -154,20 +109,11 @@ function primaryNavigation( } } -function secondaryNavigation( - context: DefaultThemeRenderContext, - props: PageEvent -) { - const children = - props.model instanceof ContainerReflection - ? props.model.children || [] - : []; +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 - ) { + if (props.model.isProject() && props.model.getChildrenByKind(ReflectionKind.Module).length) { return; } @@ -185,10 +131,7 @@ function secondaryNavigation( .map((child) => { return (
    • - + {icons[child.kind]()} {wbr(child.name)} @@ -198,14 +141,8 @@ function secondaryNavigation(
    ); - if ( - props.model.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project) - ) { - return ( - - ); + if (props.model.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project)) { + return ; } return ( @@ -223,10 +160,7 @@ function secondaryNavigation( ); } -function inPath( - thisPage: Reflection, - toCheck: Reflection | undefined -): boolean { +function inPath(thisPage: Reflection, toCheck: Reflection | undefined): boolean { while (toCheck) { if (toCheck.isProject()) return false; diff --git a/static/style.css b/static/style.css index 4c59a160b..66f0be010 100644 --- a/static/style.css +++ b/static/style.css @@ -22,7 +22,7 @@ --dark-color-background-secondary: #151619; --dark-color-icon-background: #263238; --dark-color-accent: #454545; - --dark-color-text: #ffffff; + --dark-color-text: #f5f5f5; --dark-color-text-aside: #e6e4e4; --dark-color-link: #00aff4; --dark-color-ts: #ff6492; @@ -201,7 +201,16 @@ dd { } } +/* Footer */ +.tsd-generator { + border-top: 1px solid var(--color-accent); + padding-top: 1rem; + padding-bottom: 1rem; +} + .tsd-generator > p { + margin-top: 0; + margin-bottom: 0; padding: 0 1rem; } @@ -209,7 +218,7 @@ dd { display: flex; justify-content: space-between; position: relative; - margin: 2rem auto; + margin: 0 auto; } .col-4, @@ -640,6 +649,13 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { font-weight: bold; } +.tsd-panel-group.tsd-index-group { + margin-bottom: 0; +} +.tsd-index-group details[open] { + margin-top: 4rem; + margin-bottom: 4rem; +} .tsd-index-panel .tsd-index-list { list-style: none; line-height: 1.333em; @@ -812,27 +828,25 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { padding-left: 0; } .tsd-navigation.secondary ul li li a { - padding-left: 1rem; + padding-left: 1.1rem; } .tsd-navigation.secondary ul li li li a { - padding-left: 2rem; + padding-left: 2.2rem; } .tsd-navigation.secondary ul li li li li a { - padding-left: 3rem; + padding-left: 3.3rem; } .tsd-navigation.secondary ul li li li li li a { - padding-left: 4rem; + padding-left: 4.4rem; } .tsd-navigation.secondary ul li li li li li li a { - padding-left: 5rem; -} -.tsd-navigation.secondary li.current > a { - font-weight: bold; + padding-left: 5.5rem; } a.tsd-index-link { margin: 0.1rem 0; - font-weight: 500; + font-size: 1rem; + line-height: 1.5rem; display: inline-flex; align-items: center; } @@ -868,13 +882,21 @@ a.tsd-index-link { .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.5rem; - height: 1.5rem; - min-width: 1.5rem; - min-height: 1.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-index-content .tsd-kind-icon { height: 2rem; @@ -884,6 +906,10 @@ a.tsd-index-link { } @media (min-width: 1024px) { + .col-content { + margin: 2rem auto; + } + .menu-sticky-wrap { position: sticky; height: 94vh; @@ -894,6 +920,9 @@ a.tsd-index-link { transition-property: top, padding-top, height; overflow-y: auto; } + .col-menu { + border-left: 1px solid var(--color-accent); + } .col-menu .tsd-navigation:not(:last-child) { padding-bottom: 1.75rem; } @@ -909,6 +938,9 @@ a.tsd-index-link { } .tsd-panel { + margin-bottom: 2.5rem; +} +.tsd-panel.tsd-member { margin-bottom: 4rem; } .tsd-panel:empty { @@ -1251,4 +1283,3 @@ img { border-radius: 999rem; border: 0.25rem solid var(--color-icon-background); } -} From f7805bacf2435faec58a1b9e69f516e0ea0d687c Mon Sep 17 00:00:00 2001 From: futurGH Date: Mon, 7 Feb 2022 21:17:03 -0500 Subject: [PATCH 040/151] Remove "public" visibility option --- src/lib/output/themes/default/partials/navigation.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 96363dc6c..5bc6fea31 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -18,18 +18,12 @@ export function navigation(context: DefaultThemeRenderContext, props: PageEvent< function settings() { // Settings panel above navigation - const visibilityOptions = ["public", "protected", "private", "inherited"].map((name) => { + const visibilityOptions = ["protected", "private", "inherited"].map((name) => { const value = name.charAt(0).toUpperCase() + name.slice(1); return (
  • From f5e52c2a937628ba00ff3d54926518619d05c3b9 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 13 Feb 2022 14:52:26 -0700 Subject: [PATCH 041/151] Remove Const flag for function-variables and fix 1734 test --- CHANGELOG.md | 1 + src/lib/converter/plugins/CommentPlugin.ts | 25 +++++--- src/lib/converter/symbols.ts | 13 ---- src/test/converter/alias/specs.json | 24 +++----- src/test/converter/function/specs.json | 8 +-- src/test/converter/interface/specs.json | 8 --- src/test/converter/js/specs.json | 40 ++++--------- src/test/converter/mixin/specs.json | 60 ++++++------------- src/test/converter/variables/specs.json | 16 ----- src/test/converter/variables/specs.nodoc.json | 16 ----- src/test/issueTests.ts | 2 +- 11 files changed, 59 insertions(+), 154 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eaa5bc8b7..f3e554f22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - `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. ### Features diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 3be715da2..344e40569 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -249,24 +249,35 @@ export class CommentPlugin extends ConverterComponent { } if (reflection.type instanceof ReflectionType) { - // GERRIT: This is problematic. Need to revisit and try to stop having nested reflections. - reflection.type.declaration.comment ||= reflection.comment?.clone(); - - this.processSignatureComments( + this.moveCommentToSignatures( + reflection, reflection.type.declaration.getNonIndexSignatures() ); } else { - this.processSignatureComments(reflection.getNonIndexSignatures()); + this.moveCommentToSignatures( + reflection, + reflection.getNonIndexSignatures() + ); } } - private processSignatureComments(signatures: SignatureReflection[]) { + private moveCommentToSignatures( + reflection: DeclarationReflection, + signatures: SignatureReflection[] + ) { if (!signatures.length) { return; } + const comment = reflection.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; + for (const signature of signatures) { - const childComment = signature.comment; + const childComment = (signature.comment ||= comment?.clone()); if (!childComment) continue; signature.parameters?.forEach((parameter, index) => { diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 4cd77465a..2e18a9d4b 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -910,19 +910,6 @@ function convertVariableAsFunction( exportSymbol ); setModifiers(symbol, accessDeclaration, reflection); - // Does anyone care about this? I doubt it... - if ( - declaration && - hasAllFlags(symbol.flags, ts.SymbolFlags.BlockScopedVariable) - ) { - reflection.setFlag( - ReflectionFlag.Const, - hasAllFlags( - (declaration || symbol.valueDeclaration).parent.flags, - ts.NodeFlags.Const - ) - ); - } context.finalizeDeclarationReflection(reflection); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 89394e515..4d79c6d16 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -122,14 +122,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "A type that describes a compare function, e.g. for array.sort()." - } - ] - }, "sources": [ { "fileName": "alias.ts", @@ -154,14 +146,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "A type that describes a compare function, e.g. for array.sort()." - } - ] - }, "sources": [ { "fileName": "alias.ts", @@ -176,6 +160,14 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "A type that describes a compare function, e.g. for array.sort()." + } + ] + }, "parameters": [ { "id": 4, diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 570b58acc..dcb20b315 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -425,9 +425,7 @@ "name": "all", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "function.ts", @@ -2157,9 +2155,7 @@ "name": "variableFunction", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "function.ts", diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index f9c8ab89c..e15b78565 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -1620,14 +1620,6 @@ "kind": 256, "kindString": "Interface", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "Function signature of an event listener callback" - } - ] - }, "sources": [ { "fileName": "interface-implementation.ts", diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index 1d3c73909..8c3e014c7 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -34,9 +34,7 @@ "name": "export=", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "export-eq-type.js", @@ -582,14 +580,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "even though in the same comment block" - } - ] - }, "sources": [ { "fileName": "index.js", @@ -605,14 +595,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "even though in the same comment block" - } - ] - }, "sources": [ { "fileName": "index.js", @@ -627,6 +609,14 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "even though in the same comment block" + } + ] + }, "type": { "type": "intrinsic", "name": "any" @@ -800,14 +790,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "enum comment" - } - ] - }, "children": [ { "id": 13, @@ -874,9 +856,7 @@ "name": "usedFoo", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "index.js", diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 85dd303e5..7a80c2fa0 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -1037,14 +1037,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "Any constructor function" - } - ] - }, "sources": [ { "fileName": "mixin.ts", @@ -1073,14 +1065,6 @@ "kind": 512, "kindString": "Constructor", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "Any constructor function" - } - ] - }, "signatures": [ { "id": 8, @@ -1088,6 +1072,14 @@ "kind": 16384, "kindString": "Constructor signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Any constructor function" + } + ] + }, "parameters": [ { "id": 9, @@ -1122,14 +1114,6 @@ "kind": 4194304, "kindString": "Type alias", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "Any function" - } - ] - }, "sources": [ { "fileName": "mixin.ts", @@ -1158,14 +1142,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "Any function" - } - ] - }, "sources": [ { "fileName": "mixin.ts", @@ -1180,6 +1156,14 @@ "kind": 4096, "kindString": "Call signature", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "Any function" + } + ] + }, "parameters": [ { "id": 4, @@ -1324,9 +1308,7 @@ "name": "Mixin1Func", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "mixin.ts", @@ -1440,9 +1422,7 @@ "name": "Mixin2", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "mixin.ts", @@ -1566,9 +1546,7 @@ "name": "Mixin3", "kind": 64, "kindString": "Function", - "flags": { - "isConst": true - }, + "flags": {}, "sources": [ { "fileName": "mixin.ts", diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index cd7154ee7..1224cb96e 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -1007,14 +1007,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "An object literal." - } - ] - }, "children": [ { "id": 89, @@ -1439,14 +1431,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "A typed literal without an initializer." - } - ] - }, "children": [ { "id": 48, diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index 3f9ce061f..ea61cb1dc 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -467,14 +467,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "An object literal." - } - ] - }, "sources": [ { "fileName": "literal.ts", @@ -515,14 +507,6 @@ "kind": 65536, "kindString": "Type literal", "flags": {}, - "comment": { - "summary": [ - { - "kind": "text", - "text": "A typed literal without an initializer." - } - ] - }, "sources": [ { "fileName": "literal.ts", diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index b99a87260..7837cc7d8 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -280,7 +280,7 @@ export const issueTests: { ]); }, - gh1734_skip(project) { + gh1734(project) { const alias = query(project, "Foo"); const type = alias.type; ok(type instanceof ReflectionType); From c6116de88e8bb912c0a97567bd12d7d360d0c6fe Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 13 Feb 2022 16:02:55 -0700 Subject: [PATCH 042/151] Turn the overload tests back on --- CHANGELOG.md | 3 +- src/lib/converter/comments/discovery.ts | 22 +++++--- src/lib/converter/context.ts | 2 +- src/lib/converter/plugins/CategoryPlugin.ts | 53 +++++++------------ src/lib/converter/plugins/SourcePlugin.ts | 2 - src/lib/models/reflections/kind.ts | 6 +++ .../themes/default/partials/navigation.tsx | 7 --- src/test/behaviorTests.ts | 32 +++++------ src/test/converter2/behavior/overloads.ts | 12 +++++ 9 files changed, 70 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3e554f22..f50c88131 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,11 @@ ### Currently Broken - Comment rendering +- Inline `@inheritDoc` tags ### Breaking Changes -- TODO: The behavior of `@inheritDoc` has changed... describe how. +- TODO: The behavior of `@inheritDoc` has changed... describe how - `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. diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 86fc813ff..2c5a7dcc1 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -22,19 +22,19 @@ const wantedKinds: Record = { ts.SyntaxKind.PropertyAssignment, ], [ReflectionKind.Variable]: [ts.SyntaxKind.VariableDeclaration], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Function]: [], + [ReflectionKind.Function]: [ts.SyntaxKind.FunctionDeclaration], [ReflectionKind.Class]: [ts.SyntaxKind.ClassDeclaration], [ReflectionKind.Interface]: [ts.SyntaxKind.InterfaceDeclaration], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Constructor]: [], + [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor], [ReflectionKind.Property]: [ ts.SyntaxKind.PropertyDeclaration, ts.SyntaxKind.PropertySignature, ts.SyntaxKind.BinaryExpression, ], - // Intentionally nothing here, comments will be placed on signatures. - [ReflectionKind.Method]: [], + [ReflectionKind.Method]: [ + ts.SyntaxKind.FunctionDeclaration, + ts.SyntaxKind.MethodDeclaration, + ], [ReflectionKind.CallSignature]: [ ts.SyntaxKind.FunctionDeclaration, ts.SyntaxKind.VariableDeclaration, @@ -80,6 +80,16 @@ export function discoverComment( 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. + if ( + kind & ReflectionKind.ContainsCallSignatures && + !(node as ts.FunctionDeclaration).body + ) { + continue; + } + const comments = ts.getLeadingCommentRanges(text, node.pos); if (reverse) { diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index fc20e2c47..7d014bb74 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -177,7 +177,7 @@ export class Context { "@module", "@inheritDoc", ]), - inlineTags: new Set(["@link", "@inheritDoc"]), + inlineTags: new Set(["@link", "@inheritDoc", "@label"]), modifierTags: new Set([ // TSDoc standard "@public", diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index f469ccb09..59f1ea0c0 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/ReflectionCategory"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; -import { BindOption } from "../../utils"; +import { BindOption, removeIf } from "../../utils"; /** * A handler that sorts and categorizes the found reflections in the resolving phase. @@ -178,46 +177,34 @@ export class CategoryPlugin extends ConverterComponent { * @returns The category the reflection belongs to */ static getCategories(reflection: DeclarationReflection) { - function extractCategoryTag(comment: Comment | undefined) { - const categories = new Set(); - if (!comment) return categories; - - const tags = comment.blockTags; - const commentTags: CommentTag[] = []; - tags.forEach((tag) => { - if (tag.tag !== "@category") { - commentTags.push(tag); - return; - } - const text = Comment.combineDisplayParts(tag.content).trim(); - if (!text) { - return; + 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() + ); + + return true; } - categories.add(text); + return false; }); - comment.blockTags = commentTags; - return categories; } - let categories = new Set(); - - 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); - } - } + extractCategoryTags(reflection.comment); + for (const sig of reflection.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") - ); + extractCategoryTags(reflection.type.declaration.comment); + for (const sig of reflection.type.declaration.getNonIndexSignatures()) { + extractCategoryTags(sig.comment); + } } + categories.delete(""); return categories; } diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 7ae4c536a..5904c46d9 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -83,8 +83,6 @@ export class SourcePlugin extends ConverterComponent { return; } - if (reflection.name === "constructor") debugger; - let declarations: ts.Declaration[] = []; if (reflection.kind === ReflectionKind.Constructor) { for (const decl of symbol.declarations || []) { diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index 660ba0294..1a7077664 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -69,4 +69,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/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 9a32ac6b2..63379a707 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -80,13 +80,6 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven 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 diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 74f33bfdd..b6efb82de 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -56,28 +56,22 @@ export const behaviorTests: Record< ]); }, // Disabled for now, pending https://github.com/TypeStrong/typedoc/issues/1809 - overloads_skip(project) { + overloads(project) { const foo = query(project, "foo"); - equal(foo.signatures?.length, 2); - - equal( - Comment.combineDisplayParts(foo.signatures[0].comment?.summary), - "Implementation comment" + const fooComments = foo.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) ); - equal(foo.signatures[0].comment?.blockTags, []); + equal(fooComments, [ + "No arg comment\n{@label NO_ARGS}", + "{@inheritDoc (foo:NO_ARGS)}\n{@label WITH_X}", + ]); + equal(foo.comment, undefined); - equal( - Comment.combineDisplayParts(foo.signatures[1].comment?.summary), - "Overrides summary" + const bar = query(project, "bar"); + const barComments = bar.signatures?.map((sig) => + Comment.combineDisplayParts(sig.comment?.summary) ); - equal(foo.signatures[1].comment?.blockTags, []); - equal( - Comment.combineDisplayParts( - foo.signatures[1].parameters?.[0].comment?.summary - ), - "docs for x" - ); - - equal(foo.comment, undefined); + equal(barComments, ["Implementation comment", "Custom comment"]); + equal(bar.comment, undefined); }, }; diff --git a/src/test/converter2/behavior/overloads.ts b/src/test/converter2/behavior/overloads.ts index e55f2e73f..79c4aeb2e 100644 --- a/src/test/converter2/behavior/overloads.ts +++ b/src/test/converter2/behavior/overloads.ts @@ -12,3 +12,15 @@ 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 + */ +export function bar(x?: string) { + return x || ""; +} From 71d77cf0f67d1e760f6cc5e9b3904426b5cfdee7 Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 13 Feb 2022 18:41:13 -0500 Subject: [PATCH 043/151] Linting/style --- .../themes/default/partials/navigation.tsx | 135 +++++++++++------- src/lib/utils/highlighter.tsx | 73 ++++++++-- static/style.css | 35 ++--- 3 files changed, 166 insertions(+), 77 deletions(-) diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 5bc6fea31..b46cb60fb 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -1,11 +1,19 @@ -import { ContainerReflection, DeclarationReflection, Reflection, ReflectionKind } from "../../../../models"; +import { + ContainerReflection, + DeclarationReflection, + Reflection, + ReflectionKind, +} from "../../../../models"; import { JSX, partition } from "../../../../utils"; import type { PageEvent } from "../../../events"; import { classNames, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { icons } from "./icon"; -export function navigation(context: DefaultThemeRenderContext, props: PageEvent) { +export function navigation( + context: DefaultThemeRenderContext, + props: PageEvent +) { return ( <> {settings()} @@ -18,18 +26,25 @@ export function navigation(context: DefaultThemeRenderContext, props: PageEvent< function settings() { // Settings panel above navigation - const visibilityOptions = ["protected", "private", "inherited"].map((name) => { - const value = name.charAt(0).toUpperCase() + name.slice(1); - return ( -
    • - -
    • - ); - }); + const visibilityOptions = ["protected", "private", "inherited"].map( + (name) => { + const value = name.charAt(0).toUpperCase() + name.slice(1); + return ( +
    • + +
    • + ); + } + ); return (
      @@ -40,7 +55,9 @@ function settings() {

      Member Visibility

      -
        {...visibilityOptions}
      +
        + {...visibilityOptions} +
      @@ -57,10 +74,15 @@ function settings() { ); } -function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent) { +function primaryNavigation( + context: DefaultThemeRenderContext, + props: PageEvent +) { // Create the navigation for the current page - const modules = props.model.project.getChildrenByKind(ReflectionKind.SomeModule); + const modules = props.model.project.getChildrenByKind( + ReflectionKind.SomeModule + ); const [ext, int] = partition(modules, (m) => m.flags.isExternal); const selected = props.model.isProject(); @@ -75,7 +97,9 @@ function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent<
      • - {wbr(props.project.name)} + + {wbr(props.project.name)} +
          {int.map(link)}
      • {ext.map(link)} @@ -89,13 +113,17 @@ function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent< const current = inPath(mod, props.model); const selected = mod.name === props.model.name; let childNav: JSX.Element | undefined; - const childModules = mod.children?.filter((m) => m.kindOf(ReflectionKind.SomeModule)); + const childModules = mod.children?.filter((m) => + m.kindOf(ReflectionKind.SomeModule) + ); if (childModules?.length) { childNav =
          {childModules.map(link)}
        ; } return ( -
      • +
      • {wbr(mod.name)} {childNav}
      • @@ -103,40 +131,44 @@ function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent< } } -function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEvent) { - const children = props.model instanceof ContainerReflection ? props.model.children || [] : []; +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) { + 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 = ( - - ); + 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 ( + props.model.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project) + ) { + return ( + + ); } return ( @@ -147,14 +179,17 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven {icons[props.model.kind]()} {wbr(props.model.name)} - {pageNavigation} + {!!pageNavigation.length &&
          {pageNavigation}
        }
      ); } -function inPath(thisPage: Reflection, toCheck: Reflection | undefined): boolean { +function inPath( + thisPage: Reflection, + toCheck: Reflection | undefined +): boolean { while (toCheck) { if (toCheck.isProject()) return false; diff --git a/src/lib/utils/highlighter.tsx b/src/lib/utils/highlighter.tsx index a2fd1c2a4..62b6619a9 100644 --- a/src/lib/utils/highlighter.tsx +++ b/src/lib/utils/highlighter.tsx @@ -10,16 +10,34 @@ for (const lang of BUNDLED_LANGUAGES) { } } -const supportedLanguages = unique(["text", ...aliases.keys(), ...BUNDLED_LANGUAGES.map((lang) => lang.id)]).sort(); +const supportedLanguages = unique([ + "text", + ...aliases.keys(), + ...BUNDLED_LANGUAGES.map((lang) => lang.id), +]).sort(); class DoubleHighlighter { private schemes = new Map(); - constructor(private highlighter: Highlighter, private light: Theme, private dark: Theme) {} + constructor( + private highlighter: Highlighter, + private light: Theme, + private dark: Theme + ) {} highlight(code: string, lang: string) { - const lightTokens = this.highlighter.codeToThemedTokens(code, lang, this.light, { includeExplanation: false }); - const darkTokens = this.highlighter.codeToThemedTokens(code, lang, this.dark, { includeExplanation: false }); + const lightTokens = this.highlighter.codeToThemedTokens( + code, + lang, + this.light, + { includeExplanation: false } + ); + const darkTokens = this.highlighter.codeToThemedTokens( + code, + lang, + this.dark, + { includeExplanation: false } + ); // If this fails... something went *very* wrong. assert(lightTokens.length === darkTokens.length); @@ -40,7 +58,14 @@ class DoubleHighlighter { // Simple case, same token. if (lightLine[0].content === darkLine[0].content) { lineEls.push( - {lightLine[0].content} + + {lightLine[0].content} + ); lightLine.shift(); darkLine.shift(); @@ -49,17 +74,35 @@ class DoubleHighlighter { if (lightLine[0].content.length < darkLine[0].content.length) { lineEls.push( - {lightLine[0].content} + + {lightLine[0].content} + + ); + darkLine[0].content = darkLine[0].content.substr( + lightLine[0].content.length ); - darkLine[0].content = darkLine[0].content.substr(lightLine[0].content.length); lightLine.shift(); continue; } lineEls.push( - {darkLine[0].content} + + {darkLine[0].content} + + ); + lightLine[0].content = lightLine[0].content.substr( + darkLine[0].content.length ); - lightLine[0].content = lightLine[0].content.substr(darkLine[0].content.length); darkLine.shift(); } @@ -88,8 +131,16 @@ class DoubleHighlighter { i++; } - style.push(` --dark-code-background: ${this.highlighter.getTheme(this.light).bg};`); - style.push(` --dark-code-background: ${this.highlighter.getTheme(this.dark).bg};`); + 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);`); diff --git a/static/style.css b/static/style.css index 66f0be010..668284145 100644 --- a/static/style.css +++ b/static/style.css @@ -34,6 +34,8 @@ --dark-color-ts-private: #e2e2e2; --dark-color-ts-variable: #4d68ff; --dark-external-icon: url("data:image/svg+xml;utf8,"); + + color-scheme: light dark; } @media (prefers-color-scheme: light) { @@ -99,6 +101,8 @@ body.light { --color-ts-private: var(--light-color-ts-private); --color-ts-variable: var(--light-color-ts-variable); --external-icon: var(--light-external-icon); + + color-scheme: light; } body.dark { @@ -118,6 +122,8 @@ body.dark { --color-ts-private: var(--dark-color-ts-private); --color-ts-variable: var(--dark-color-ts-variable); --external-icon: var(--dark-external-icon); + + color-scheme: dark; } h1, @@ -234,6 +240,7 @@ dd { .col-8 { flex: 1 0; flex-wrap: wrap; + padding-left: 0; } ul.tsd-descriptions > li > :first-child, @@ -652,10 +659,6 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { .tsd-panel-group.tsd-index-group { margin-bottom: 0; } -.tsd-index-group details[open] { - margin-top: 4rem; - margin-bottom: 4rem; -} .tsd-index-panel .tsd-index-list { list-style: none; line-height: 1.333em; @@ -753,9 +756,6 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { color: var(--color-ts-private); } -.tsd-navigation { - margin: 0 0 0 40px; -} .tsd-navigation a { display: block; margin: 0.4rem 0; @@ -821,6 +821,7 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { top: 0.5rem; } .tsd-navigation.secondary > ul { + display: inline; padding-right: 0.5rem; transition: opacity 0.2s; } @@ -844,9 +845,9 @@ input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { } a.tsd-index-link { - margin: 0.1rem 0; + margin: 0.25rem 0; font-size: 1rem; - line-height: 1.5rem; + line-height: 1.25rem; display: inline-flex; align-items: center; } @@ -856,6 +857,7 @@ a.tsd-index-link { .tsd-accordion-summary > h4, .tsd-accordion-summary > h5 { display: inline-flex; + align-items: center; vertical-align: middle; margin-bottom: 0; user-select: none; @@ -898,9 +900,6 @@ a.tsd-index-link { transform-origin: center; transform: scale(1.1); } -.tsd-index-content .tsd-kind-icon { - height: 2rem; -} .tsd-signature > .tsd-kind-icon { margin-right: 0.8rem; } @@ -927,13 +926,11 @@ a.tsd-index-link { padding-bottom: 1.75rem; } .col-menu.menu-sticky-wrap { - display: flex; - flex-direction: column; + padding: 0 1.5rem; } .col-menu--hide { top: 1rem; height: calc(100vh - 2rem); - padding: 0 1rem; } } @@ -960,7 +957,13 @@ a.tsd-index-link { } .tsd-panel-group { - margin: 4.5rem 0; + margin: 4rem 0; +} +.tsd-panel-group.tsd-index-group { + margin: 2rem 0; +} +.tsd-panel-group.tsd-index-group details { + margin: 4rem 0; } #tsd-search { From 1ab6d4eb43fef589009e9420322d886a4086fd27 Mon Sep 17 00:00:00 2001 From: futurGH Date: Sun, 13 Feb 2022 18:42:24 -0500 Subject: [PATCH 044/151] Functions, type aliases, & variables now have their own pages --- .../output/themes/default/DefaultTheme.tsx | 100 +++++++++-- .../assets/typedoc/components/Accordion.ts | 33 ++-- .../output/themes/default/partials/index.tsx | 70 ++++++-- .../themes/default/templates/reflection.tsx | 164 ++++++++++-------- 4 files changed, 255 insertions(+), 112 deletions(-) diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index ac077645f..1c4b9fe4a 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -52,7 +52,10 @@ export class DefaultTheme extends Theme { private _renderContext?: DefaultThemeRenderContext; getRenderContext(_pageEvent: PageEvent) { if (!this._renderContext) { - this._renderContext = new DefaultThemeRenderContext(this, this.application.options); + this._renderContext = new DefaultThemeRenderContext( + this, + this.application.options + ); } return this._renderContext; } @@ -95,6 +98,24 @@ export class DefaultTheme extends Theme { directory: "modules", template: this.reflectionTemplate, }, + { + kind: [ReflectionKind.TypeAlias], + isLeaf: false, + directory: "types", + template: this.reflectionTemplate, + }, + { + kind: [ReflectionKind.Function], + isLeaf: false, + directory: "functions", + template: this.reflectionTemplate, + }, + { + kind: [ReflectionKind.Variable], + isLeaf: false, + directory: "variables", + template: this.reflectionTemplate, + }, ]; static URL_PREFIX = /^(http|ftp)s?:\/\//; @@ -108,7 +129,12 @@ export class DefaultTheme extends Theme { constructor(renderer: Renderer) { super(renderer); this.markedPlugin = renderer.getComponent("marked") as MarkedPlugin; - this.listenTo(renderer, RendererEvent.BEGIN, this.onRendererBegin, 1024); + this.listenTo( + renderer, + RendererEvent.BEGIN, + this.onRendererBegin, + 1024 + ); } /** @@ -123,11 +149,25 @@ export class DefaultTheme extends Theme { if (false == hasReadme(this.application.options.getValue("readme"))) { project.url = "index.html"; - urls.push(new UrlMapping("index.html", project, this.reflectionTemplate)); + urls.push( + new UrlMapping( + "index.html", + project, + this.reflectionTemplate + ) + ); } else { project.url = "modules.html"; - urls.push(new UrlMapping("modules.html", project, this.reflectionTemplate)); - urls.push(new UrlMapping("index.html", project, this.indexTemplate)); + urls.push( + new UrlMapping( + "modules.html", + project, + this.reflectionTemplate + ) + ); + urls.push( + new UrlMapping("index.html", project, this.indexTemplate) + ); } project.children?.forEach((child: Reflection) => { @@ -155,7 +195,10 @@ export class DefaultTheme extends Theme { DefaultTheme.applyReflectionClasses(reflection); } - if (reflection instanceof ContainerReflection && reflection.groups) { + if ( + reflection instanceof ContainerReflection && + reflection.groups + ) { reflection.groups.forEach(DefaultTheme.applyGroupClasses); } } @@ -169,11 +212,22 @@ export class DefaultTheme extends Theme { * @param separator The separator used to generate the url. * @returns The generated url. */ - static getUrl(reflection: Reflection, relative?: Reflection, separator = "."): string { + static getUrl( + reflection: Reflection, + relative?: Reflection, + separator = "." + ): string { let url = reflection.getAlias(); - if (reflection.parent && reflection.parent !== relative && !(reflection.parent instanceof ProjectReflection)) { - url = DefaultTheme.getUrl(reflection.parent, relative, separator) + separator + url; + if ( + reflection.parent && + reflection.parent !== relative && + !(reflection.parent instanceof ProjectReflection) + ) { + url = + DefaultTheme.getUrl(reflection.parent, relative, separator) + + separator + + url; } return url; @@ -185,7 +239,9 @@ export class DefaultTheme extends Theme { * @param reflection The reflection whose mapping should be resolved. * @returns The found mapping or undefined if no mapping could be found. */ - private getMapping(reflection: DeclarationReflection): TemplateMapping | undefined { + private getMapping( + reflection: DeclarationReflection + ): TemplateMapping | undefined { return this.mappings.find((mapping) => reflection.kindOf(mapping.kind)); } @@ -196,11 +252,20 @@ export class DefaultTheme extends Theme { * @param urls The array the url should be appended to. * @returns The altered urls array. */ - buildUrls(reflection: DeclarationReflection, urls: UrlMapping[]): UrlMapping[] { + buildUrls( + reflection: DeclarationReflection, + urls: UrlMapping[] + ): UrlMapping[] { const mapping = this.getMapping(reflection); if (mapping) { - if (!reflection.url || !DefaultTheme.URL_PREFIX.test(reflection.url)) { - const url = [mapping.directory, DefaultTheme.getUrl(reflection) + ".html"].join("/"); + if ( + !reflection.url || + !DefaultTheme.URL_PREFIX.test(reflection.url) + ) { + const url = [ + mapping.directory, + DefaultTheme.getUrl(reflection) + ".html", + ].join("/"); urls.push(new UrlMapping(url, reflection, mapping.template)); reflection.url = url; @@ -272,7 +337,10 @@ export class DefaultTheme extends Theme { classes.push(DefaultTheme.toStyleClass("tsd-kind-" + kind)); } - if (reflection.parent && reflection.parent instanceof DeclarationReflection) { + if ( + reflection.parent && + reflection.parent instanceof DeclarationReflection + ) { kind = ReflectionKind[reflection.parent.kind]; classes.push(DefaultTheme.toStyleClass(`tsd-parent-kind-${kind}`)); } @@ -336,7 +404,9 @@ export class DefaultTheme extends Theme { * 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(); + return str + .replace(/(\w)([A-Z])/g, (_m, m1, m2) => m1 + "-" + m2) + .toLowerCase(); } } diff --git a/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts b/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts index 996bbc96a..02c3e04a2 100644 --- a/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts +++ b/src/lib/output/themes/default/assets/typedoc/components/Accordion.ts @@ -13,9 +13,9 @@ export class Accordion extends Component { typeof window.localStorage !== "undefined"; /** - * The heading for this accordion. + * The heading container for this accordion. */ - private heading: HTMLElement; + private summary: HTMLElement; /** * The chevron icon next to this accordion's heading. @@ -46,16 +46,16 @@ export class Accordion extends Component { super(options); this.calculateHeights(); - this.heading = this.el.querySelector(".tsd-accordion-summary")!; - this.icon = this.heading.querySelector("svg")!; - this.key = `tsd-accordion-${this.heading + 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()}`; if (this.useLocalStorage) { this.setLocalStorage(this.fromLocalStorage(), true); } - this.heading.addEventListener("click", (e: MouseEvent) => + this.summary.addEventListener("click", (e: MouseEvent) => this.toggleVisibility(e) ); this.icon.style.transform = this.getIconRotation(); @@ -74,17 +74,24 @@ export class Accordion extends Component { * @returns The accordion's expanded and collapsed heights. */ private calculateHeights() { - const isOpen = this.el.open; - this.el.style.marginLeft = "-9999px"; + 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.marginLeft = ""; + this.el.style.position = position; + this.el.style.left = left; } /** @@ -180,9 +187,11 @@ export class Accordion extends Component { * Retrieve value from localStorage. */ private fromLocalStorage(): boolean { - return this.useLocalStorage - ? window.localStorage[this.key] === "true" - : this.el.open; + if (this.useLocalStorage) { + const fromLocalStorage = window.localStorage.getItem(this.key); + if (!fromLocalStorage) return this.el.open; + return fromLocalStorage === "true"; + } else return this.el.open; } /** diff --git a/src/lib/output/themes/default/partials/index.tsx b/src/lib/output/themes/default/partials/index.tsx index 4185449da..44a07b787 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -1,7 +1,10 @@ import { wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { JSX } from "../../../../utils"; -import type { ContainerReflection, ReflectionCategory } from "../../../../models"; +import type { + ContainerReflection, + ReflectionCategory, +} from "../../../../models"; import { icons } from "./icon"; function renderCategory( @@ -12,14 +15,23 @@ function renderCategory( ) { return (
      -

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

      @@ -27,31 +39,55 @@ function renderCategory( ); } -export function index(context: DefaultThemeRenderContext, props: ContainerReflection) { - let content: JSX.Element[] = []; +export function index( + context: DefaultThemeRenderContext, + props: ContainerReflection +) { + 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.cssClasses, item.title)) + ? item.categories.map((item2) => + renderCategory( + context, + item2, + item.cssClasses, + item.title + ) + ) : renderCategory(context, item) ); } + content =
      {content}
      ; + // Accordion is only needed if any children don't have their own document. + if ( + [...(props.groups ?? []), ...(props.categories ?? [])].some( + (category) => !category.allChildrenHaveOwnDocument() + ) + ) { + content = ( +
      + + + + {content} +
      + ); + } return (
      -
      -
      - - - -
      {content}
      -
      -
      +
      {content}
      ); } diff --git a/src/lib/output/themes/default/templates/reflection.tsx b/src/lib/output/themes/default/templates/reflection.tsx index 52c942e40..fb0e6aff5 100644 --- a/src/lib/output/themes/default/templates/reflection.tsx +++ b/src/lib/output/themes/default/templates/reflection.tsx @@ -1,74 +1,102 @@ 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)} + + ); +} From 848d2aa4cd9a2fb0027ae2e8c204bfd1077aeff9 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 20:25:18 -0700 Subject: [PATCH 045/151] Warn about declarations with multiple comments Resolves #1855 --- CHANGELOG.md | 1 + src/lib/converter/comments/discovery.ts | 32 +++++++++++++++++-- src/lib/converter/comments/index.ts | 2 +- src/test/TestLogger.ts | 26 +++++++++++++++ src/test/behaviorTests.ts | 20 ++++++++++-- src/test/converter2.test.ts | 7 ++-- .../converter2/behavior/mergedDeclarations.ts | 8 +++++ 7 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 src/test/TestLogger.ts create mode 100644 src/test/converter2/behavior/mergedDeclarations.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f50c88131..f44c0736e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ ### Features - TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. +- 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. ### Bug Fixes diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 2c5a7dcc1..2b91d56fa 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -1,5 +1,7 @@ import * as ts from "typescript"; import { ReflectionKind } from "../../models"; +import type { Logger } from "../../utils"; +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 @@ -66,12 +68,15 @@ const wantedKinds: Record = { export function discoverComment( symbol: ts.Symbol, - kind: ReflectionKind + kind: ReflectionKind, + logger: Logger ): [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)) { @@ -104,10 +109,33 @@ export function discoverComment( ); if (lastDocComment) { - return [decl.getSourceFile(), lastDocComment]; + discovered.push([decl.getSourceFile(), lastDocComment]); } } } + + 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( diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index e7133ea2d..ecef6a73c 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -59,7 +59,7 @@ export function getComment( logger: Logger ): Comment | undefined { const comment = getCommentWithCache( - discoverComment(symbol, kind), + discoverComment(symbol, kind, logger), config, logger ); diff --git a/src/test/TestLogger.ts b/src/test/TestLogger.ts new file mode 100644 index 000000000..a572e19b7 --- /dev/null +++ b/src/test/TestLogger.ts @@ -0,0 +1,26 @@ +import { Logger, LogLevel } from "../lib/utils"; +import { fail } from "assert/strict"; + +const levelMap: Record = { + [LogLevel.Error]: "error: ", + [LogLevel.Warn]: "warn: ", + [LogLevel.Info]: "info: ", + [LogLevel.Verbose]: "debug: ", +}; + +export class TestLogger extends Logger { + messages: string[] = []; + + expectMessage(message: string) { + if (!this.messages.includes(message)) { + const messages = this.messages.join("\n\t"); + fail( + `Expected "${message}" to be logged. The logged messages were:\n\t${messages}` + ); + } + } + + override log(message: string, level: LogLevel): void { + this.messages.push(levelMap[level] + message); + } +} diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index b6efb82de..0017dec88 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -5,6 +5,7 @@ import { ReflectionKind, Comment, } from "../lib/models"; +import type { TestLogger } from "./TestLogger"; function query(project: ProjectReflection, name: string) { const reflection = project.getChildByName(name); @@ -14,7 +15,7 @@ function query(project: ProjectReflection, name: string) { export const behaviorTests: Record< string, - (project: ProjectReflection) => void + (project: ProjectReflection, logger: TestLogger) => void > = { asConstEnum(project) { const SomeEnumLike = query(project, "SomeEnumLike"); @@ -55,7 +56,22 @@ export const behaviorTests: Record< 'Record<"b", 1>', ]); }, - // Disabled for now, pending https://github.com/TypeStrong/typedoc/issues/1809 + + 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) { const foo = query(project, "foo"); const fooComments = foo.signatures?.map((sig) => diff --git a/src/test/converter2.test.ts b/src/test/converter2.test.ts index ecfae11be..863482846 100644 --- a/src/test/converter2.test.ts +++ b/src/test/converter2.test.ts @@ -9,6 +9,7 @@ import { getConverter2Base, getConverter2Program, } from "./programs"; +import { TestLogger } from "./TestLogger"; const base = getConverter2Base(); const app = getConverter2App(); @@ -16,7 +17,7 @@ const app = getConverter2App(); function runTest( title: string, entry: string, - check: (project: ProjectReflection) => void + check: (project: ProjectReflection, logger: TestLogger) => void ) { it(title, () => { const program = getConverter2Program(); @@ -33,6 +34,8 @@ function runTest( const sourceFile = program.getSourceFile(entryPoint); ok(sourceFile, `No source file found for ${entryPoint}`); + const logger = new TestLogger(); + app.logger = logger; const project = app.converter.convert([ { displayName: entry, @@ -40,7 +43,7 @@ function runTest( sourceFile, }, ]); - check(project); + check(project, logger); }); } 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 {} From 608c1e7ece7731bab3fd6dbffdfda481f68e03c1 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 20:57:32 -0700 Subject: [PATCH 046/151] Remove gaSite option, update Google Analytics script Closes #1846 --- CHANGELOG.md | 1 + internal-docs/custom-themes.md | 4 ++-- src/lib/output/renderer.ts | 4 ---- .../themes/default/partials/analytics.tsx | 20 +++++++++---------- src/lib/utils/options/declaration.ts | 1 - src/lib/utils/options/sources/typedoc.ts | 5 ----- src/test/capture-screenshots.ts | 1 - 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f44c0736e..43b405a7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Breaking Changes - TODO: The behavior of `@inheritDoc` has changed... describe how +- The `gaSite` option has been removed since Google Analytics now infers the site automatically. - `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. 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/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index a5cb0dc14..8fa3227b4 100644 --- a/src/lib/output/renderer.ts +++ b/src/lib/output/renderer.ts @@ -133,10 +133,6 @@ export class Renderer extends ChildableComponent< @BindOption("gaID") gaID!: string; - /** @internal */ - @BindOption("gaSite") - gaSite!: string; - /** @internal */ @BindOption("githubPages") githubPages!: boolean; 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/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index f157f3356..0c8144a38 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -97,7 +97,6 @@ export interface TypeDocOptionMap { gitRevision: string; gitRemote: string; gaID: string; - gaSite: string; githubPages: boolean; hideGenerator: boolean; hideLegend: boolean; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index f470defb6..907181199 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -258,11 +258,6 @@ export function addTypeDocOptions(options: Pick) { 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", - }); options.addDeclaration({ name: "githubPages", help: "Generate a .nojekyll file to prevent 404 errors in GitHub Pages. Defaults to `true`.", diff --git a/src/test/capture-screenshots.ts b/src/test/capture-screenshots.ts index 14d6e6e3d..ac62b8111 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -60,7 +60,6 @@ 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, From 698caa1f246ebbb1c1e2c6839396c60e3bd3f76f Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 21:21:15 -0700 Subject: [PATCH 047/151] Handle JSDoc @param comments with default value Closes #671 --- src/lib/converter/comments/parser.ts | 2 +- src/lib/validation/documentation.ts | 2 +- src/test/converter2/issues/gh671.js | 7 +++++++ src/test/issueTests.ts | 14 ++++++++++++++ 4 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 src/test/converter2/issues/gh671.js diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 862bb3c01..0a61f8595 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -77,7 +77,7 @@ function postProcessComment(comment: Comment, warning: (msg: string) => void) { tag.name = first.text.substring(0, end); if (tag.name.startsWith("[") && tag.name.endsWith("]")) { - tag.name = tag.name.slice(1, -1); + tag.name = tag.name.slice(1, tag.name.indexOf("=")); } first.text = first.text.substring(end); diff --git a/src/lib/validation/documentation.ts b/src/lib/validation/documentation.ts index 5b657f99c..57426989f 100644 --- a/src/lib/validation/documentation.ts +++ b/src/lib/validation/documentation.ts @@ -9,7 +9,7 @@ export function validateDocumentation( requiredToBeDocumented: readonly (keyof typeof ReflectionKind)[] ): void { const kinds = requiredToBeDocumented.reduce( - (prev, cur) => (prev |= ReflectionKind[cur]), + (prev, cur) => prev | ReflectionKind[cur], 0 ); 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/issueTests.ts b/src/test/issueTests.ts index 7837cc7d8..5f9e726cc 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -32,6 +32,20 @@ export const issueTests: { ); }, + 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 From 88b1c63a9ed011c5a3eabba5554db19f47adad81 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 21:48:13 -0700 Subject: [PATCH 048/151] Handle example tags like VSCode Resolves #135 --- CHANGELOG.md | 1 + src/lib/converter/comments/parser.ts | 41 +++++++++++++++++++ src/test/behaviorTests.ts | 18 ++++++++ src/test/converter/inheritance/inherit-doc.ts | 2 +- src/test/converter/inheritance/specs.json | 2 +- src/test/converter2/behavior/exampleTags.ts | 21 ++++++++++ 6 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 src/test/converter2/behavior/exampleTags.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 43b405a7d..89a493322 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ - TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. - 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. ### Bug Fixes diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 0a61f8595..fab036b70 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -63,6 +63,10 @@ const HAS_USER_IDENTIFIER: `@${string}`[] = [ "@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. @@ -90,6 +94,43 @@ function postProcessComment(comment: Comment, warning: (msg: string) => void) { } } } + + 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"); diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 0017dec88..a690e492e 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -42,6 +42,7 @@ export const behaviorTests: Record< const WithoutReadonly = query(project, "WithoutReadonly"); equal(WithoutReadonly.kind, ReflectionKind.Enum, "WithoutReadonly"); }, + duplicateHeritageClauses(project) { const b = query(project, "B"); equal(b.extendedTypes?.map(String), ["A"]); @@ -57,6 +58,23 @@ export const behaviorTests: Record< ]); }, + 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```" }], + ]); + }, + mergedDeclarations(project, logger) { const a = query(project, "SingleCommentMultiDeclaration"); equal( 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 08fa20353..46fdef62d 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -327,7 +327,7 @@ ] }, { - "tag": "@example", + "tag": "@customBlock", "content": [ { "kind": "text", 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; From 849eb0e2e30cdb98c878d89b6d21890ca4416501 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 21:51:43 -0700 Subject: [PATCH 049/151] Fix CI --- src/test/TestLogger.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/TestLogger.ts b/src/test/TestLogger.ts index a572e19b7..3e881a4e5 100644 --- a/src/test/TestLogger.ts +++ b/src/test/TestLogger.ts @@ -1,5 +1,5 @@ import { Logger, LogLevel } from "../lib/utils"; -import { fail } from "assert/strict"; +import { fail } from "assert"; const levelMap: Record = { [LogLevel.Error]: "error: ", From f3402fc079d92ee49f7e2ca88a18cb71b23fbebe Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 14 Feb 2022 22:16:59 -0700 Subject: [PATCH 050/151] Remove unused options on renderer --- src/lib/output/renderer.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index 8fa3227b4..85476935d 100644 --- a/src/lib/output/renderer.ts +++ b/src/lib/output/renderer.ts @@ -129,18 +129,10 @@ export class Renderer extends ChildableComponent< @BindOption("cname") cname!: string; - /** @internal */ - @BindOption("gaID") - gaID!: string; - /** @internal */ @BindOption("githubPages") githubPages!: boolean; - /** @internal */ - @BindOption("hideGenerator") - hideGenerator!: boolean; - /** @internal */ @BindOption("lightHighlightTheme") lightTheme!: ShikiTheme; From 7c49a6df7bf0314b9ae6ea5d96a78a21c40ca112 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 15 Feb 2022 22:04:21 -0700 Subject: [PATCH 051/151] Handle comments on destructured exported elements Resolves #1770 --- CHANGELOG.md | 1 + src/lib/converter/comments/discovery.ts | 21 +++++++++++++++++---- src/test/converter2/issues/gh1770.ts | 18 ++++++++++++++++++ src/test/issueTests.ts | 14 ++++++++++++++ 4 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 src/test/converter2/issues/gh1770.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a493322..3389f933d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ - 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. ## v0.22.11 (2022-01-18) diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 2b91d56fa..f8ec7140c 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -13,6 +13,7 @@ const wantedKinds: Record = { [ReflectionKind.Namespace]: [ ts.SyntaxKind.ModuleDeclaration, ts.SyntaxKind.SourceFile, + ts.SyntaxKind.BindingElement, ], [ReflectionKind.Enum]: [ ts.SyntaxKind.EnumDeclaration, @@ -23,9 +24,18 @@ const wantedKinds: Record = { // This is here so that @enum gets it ts.SyntaxKind.PropertyAssignment, ], - [ReflectionKind.Variable]: [ts.SyntaxKind.VariableDeclaration], - [ReflectionKind.Function]: [ts.SyntaxKind.FunctionDeclaration], - [ReflectionKind.Class]: [ts.SyntaxKind.ClassDeclaration], + [ReflectionKind.Variable]: [ + ts.SyntaxKind.VariableDeclaration, + ts.SyntaxKind.BindingElement, + ], + [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]: [ @@ -88,9 +98,12 @@ export function discoverComment( // 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 as ts.FunctionDeclaration).body && + node.kind !== ts.SyntaxKind.BindingElement ) { continue; } 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/issueTests.ts b/src/test/issueTests.ts index 5f9e726cc..dcdd85cbd 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -331,6 +331,20 @@ export const issueTests: { ); }, + 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" + ); + }, + gh1795(project) { equal( project.children?.map((c) => c.name), From fe625babbd126dd9554b4af692c21b8a61f7fbdc Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 16 Feb 2022 18:48:18 -0700 Subject: [PATCH 052/151] Fix decoration of log messages with an associated node --- .config/typedoc.json | 6 +++++- src/lib/converter/comments/index.ts | 1 - src/lib/utils/loggers.ts | 26 ++++++++++++-------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/.config/typedoc.json b/.config/typedoc.json index c66f52536..1e3a9c571 100644 --- a/.config/typedoc.json +++ b/.config/typedoc.json @@ -14,6 +14,10 @@ "excludePrivate": true, "excludeInternal": true, "treatWarningsAsErrors": false, - "validation": true, + "validation": { + "notExported": true, + "invalidLink": true, + "notDocumented": false + }, "logLevel": "Verbose" } diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index ecef6a73c..84a881914 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -27,7 +27,6 @@ function getCommentWithCache( } const line = ts.getLineAndCharacterOfPosition(file, range.pos).line + 1; - logger.verbose(`Parsing comment at ${file.fileName}:${line}`); const warning = (warning: string) => logger.warn(`${warning} in comment at ${file.fileName}:${line}.`); diff --git a/src/lib/utils/loggers.ts b/src/lib/utils/loggers.ts index c05778eb4..fbdbd63b8 100644 --- a/src/lib/utils/loggers.ts +++ b/src/lib/utils/loggers.ts @@ -24,17 +24,17 @@ const Colors = { reset: "\u001b[0m", }; -function color(text: string | number, color: keyof typeof Colors) { +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]: color("Error", "red"), - [LogLevel.Warn]: color("Warning", "yellow"), - [LogLevel.Info]: color("Info", "cyan"), - [LogLevel.Verbose]: color("Debug", "gray"), + [LogLevel.Error]: color("error", "red"), + [LogLevel.Warn]: color("warning", "yellow"), + [LogLevel.Info]: color("info", "cyan"), + [LogLevel.Verbose]: color("debug", "gray"), }; function withContext(message: string, level: LogLevel, node?: ts.Node) { @@ -44,27 +44,25 @@ function withContext(message: string, level: LogLevel, node?: ts.Node) { const file = node.getSourceFile(); const path = nicePath(file.fileName); - const { line, character } = ts.getLineAndCharacterOfPosition( - file, - node.pos - ); + const pos = node.getStart(file, false); + const { line, character } = ts.getLineAndCharacterOfPosition(file, pos); const location = `${color(path, "cyan")}:${color( - line + 1, + `${line + 1}`, "yellow" - )}:${color(character, "yellow")}`; + )}:${color(`${character}`, "yellow")}`; - const start = file.text.lastIndexOf("\n", node.pos) + 1; + 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( + const context = `${color(`${line + 1}`, "black")} ${file.text.substring( start, end )}`; - return `${prefix} ${message}\n${context}`; + return `${prefix} ${message}\n\n${context}\n`; } /** From aaeda3eb57b3dea9bb3bfcbddf9397929a11cc98 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 17 Feb 2022 20:15:51 -0700 Subject: [PATCH 053/151] Fix comment rendering - Remove listInvalidSymbolLinks - Move link validation to the normal location for validation - Add warnings for [[target]] links - Enable validation.invalidLink by default --- .config/typedoc.json | 3 +- CHANGELOG.md | 5 +- README.md | 9 - src/index.ts | 2 +- src/lib/application.ts | 12 +- src/lib/converter/index.ts | 2 +- .../converter/plugins/LinkResolverPlugin.ts | 188 +++++++++++++++ src/lib/converter/plugins/index.ts | 5 +- src/lib/models/comments/comment.ts | 13 +- src/lib/models/reflections/abstract.ts | 4 +- src/lib/models/reflections/project.ts | 36 --- src/lib/output/events.ts | 2 +- src/lib/output/plugins/MarkedLinksPlugin.ts | 217 ------------------ src/lib/output/plugins/index.ts | 1 - .../themes/default/partials/comment.tsx | 42 ++-- src/lib/serialization/schema.ts | 23 +- src/lib/serialization/serializers/comment.ts | 93 ++++++++ .../serializers/comments/comment-tag.ts | 35 --- .../serializers/comments/comment.ts | 32 --- .../serializers/comments/index.ts | 2 - src/lib/serialization/serializers/index.ts | 2 +- src/lib/utils/hooks.ts | 7 +- src/lib/utils/jsx.ts | 1 + src/lib/utils/options/declaration.ts | 2 - src/lib/utils/options/sources/typedoc.ts | 7 +- src/lib/validation/links.ts | 36 +++ src/test/behaviorTests.ts | 26 +++ .../class/specs-with-lump-categories.json | 16 +- src/test/converter/class/specs.json | 16 +- .../behavior/deprecatedBracketLinks.ts | 9 + 30 files changed, 460 insertions(+), 388 deletions(-) create mode 100644 src/lib/converter/plugins/LinkResolverPlugin.ts delete mode 100644 src/lib/output/plugins/MarkedLinksPlugin.ts create mode 100644 src/lib/serialization/serializers/comment.ts delete mode 100644 src/lib/serialization/serializers/comments/comment-tag.ts delete mode 100644 src/lib/serialization/serializers/comments/comment.ts delete mode 100644 src/lib/serialization/serializers/comments/index.ts create mode 100644 src/lib/validation/links.ts create mode 100644 src/test/converter2/behavior/deprecatedBracketLinks.ts diff --git a/.config/typedoc.json b/.config/typedoc.json index 1e3a9c571..fc52093d4 100644 --- a/.config/typedoc.json +++ b/.config/typedoc.json @@ -6,7 +6,8 @@ "ConverterComponent", "RendererComponent", "SORT_STRATEGIES", - "_ModelToObject" + "_ModelToObject", + "EventHooksMomento" ], "entryPoints": ["../src"], "entryPointStrategy": "Resolve", diff --git a/CHANGELOG.md b/CHANGELOG.md index 3389f933d..885af5bf8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,16 @@ ### Currently Broken -- Comment rendering - Inline `@inheritDoc` tags ### Breaking Changes - TODO: The behavior of `@inheritDoc` has changed... describe how - The `gaSite` option has been removed since Google Analytics now infers the site automatically. +- The deprecated `listInvalidSymbolLinks` option has been removed. Use `validation.invalidLink` instead. +- 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. +- 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. +- 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. diff --git a/README.md b/README.md index cf458f511..1c151ae59 100644 --- a/README.md +++ b/README.md @@ -87,16 +87,9 @@ For a complete list of the command line arguments run `typedoc --help` or visit - `--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 @@ -110,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`
      diff --git a/src/index.ts b/src/index.ts index fb6dc1db4..ef6eac5ab 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, diff --git a/src/lib/application.ts b/src/lib/application.ts index 5079140a3..2d4fd8ca8 100644 --- a/src/lib/application.ts +++ b/src/lib/application.ts @@ -24,7 +24,6 @@ import { import { Options, BindOption } from "./utils"; import type { TypeDocOptions } from "./utils/options/declaration"; import { flatMap, unique } from "./utils/array"; -import { validateExports } from "./validation/exports"; import { ok } from "assert"; import { DocumentationEntryPoint, @@ -34,7 +33,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 { @@ -408,6 +409,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 +427,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/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/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts new file mode 100644 index 000000000..b5598fad5 --- /dev/null +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -0,0 +1,188 @@ +import type { Reflection } from "../../models/reflections/abstract"; +import { Component, ConverterComponent } from "../components"; +import type { Context } from "../../converter"; +import { ConverterEvents } from "../converter-events"; +import type { CommentDisplayPart } from "../../models"; + +const urlPrefix = /^(http|ftp)s?:\/\//; +const brackets = /\[\[([^\]]+)\]\]/g; +/** + * A plugin that resolves `{@link Foo}` tags. + */ +@Component({ name: "link-resolver" }) +export class LinkResolverPlugin extends ConverterComponent { + /** + * 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)) { + const targetRefl = reflection.findReflectionByName(target); + if (targetRefl) { + parts.push({ + kind: "inline-tag", + tag: "@link", + text: caption, + target: targetRefl, + }); + } else { + this.application.logger.warn( + "Failed to find target: " + content + ); + parts.push({ + kind: "inline-tag", + tag: "@link", + text: content, + }); + } + } else { + parts.push({ + kind: "inline-tag", + tag: "@link", + text: caption, + target, + }); + } + } + 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); + } + } + + processReflection(reflection: Reflection) { + const comment = reflection.comment; + if (!comment) return; + + let warned = false; + const warn = () => { + if (!warned) { + warned = true; + this.application.logger.warn( + `${reflection.getFullName()}: 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" + ) { + 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; + } else { + this.application.logger.warn( + `Failed resolution for ${target} in ${reflection.getFullName()}` + ); + } + } + } + } + + 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, + }; + } + } +} diff --git a/src/lib/converter/plugins/index.ts b/src/lib/converter/plugins/index.ts index f4e6e61eb..d261be893 100644 --- a/src/lib/converter/plugins/index.ts +++ b/src/lib/converter/plugins/index.ts @@ -1,9 +1,10 @@ export { CategoryPlugin } from "./CategoryPlugin"; export { CommentPlugin } from "./CommentPlugin"; -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 { SourceLinkPlugin } from "./SourceLinkPlugin"; export { SourcePlugin } from "./SourcePlugin"; export { TypePlugin } from "./TypePlugin"; -export { InheritDocPlugin } from "./InheritDocPlugin"; diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index f118ee2b4..f28166d19 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -1,9 +1,19 @@ import { assertNever, removeIf } from "../../utils"; +import type { Reflection } from "../reflections"; +/** + * For inline tags, `@link`, `@linkcode`, and `@linkplain` may have a `target` + * property set indicating which reflection/url they link to. + */ export type CommentDisplayPart = | { kind: "text"; text: string } | { kind: "code"; text: string } - | { kind: "inline-tag"; tag: `@${string}`; text: string }; + | { + kind: "inline-tag"; + tag: `@${string}`; + text: string; + target?: Reflection | string; + }; /** * A model that represents a single TypeDoc comment tag. @@ -84,7 +94,6 @@ export class Comment { /** * Helper utility to clone {@link Comment.summary} or {@link CommentTag.content} - * @internal probably ok to expose, but waiting until someone asks. */ static cloneDisplayParts(parts: CommentDisplayPart[]) { return parts.map((p) => ({ ...p })); diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index 59ba4e4a3..7d7af1afe 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -215,8 +215,8 @@ export interface TraverseCallback { * 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 { /** diff --git a/src/lib/models/reflections/project.ts b/src/lib/models/reflections/project.ts index 979bbbad4..45d501eb9 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -1,7 +1,6 @@ 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"; @@ -85,41 +84,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/output/events.ts b/src/lib/output/events.ts index a03ba37da..0bdd89ccc 100644 --- a/src/lib/output/events.ts +++ b/src/lib/output/events.ts @@ -135,7 +135,7 @@ 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. * - * @see {@link MarkedPlugin.EVENT_PARSE_MARKDOWN} + * @see {@link PARSE} */ export class MarkdownEvent extends Event { /** diff --git a/src/lib/output/plugins/MarkedLinksPlugin.ts b/src/lib/output/plugins/MarkedLinksPlugin.ts deleted file mode 100644 index 23ac6b21b..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)!.getFullName(); - 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 - .substring(splitIndex + 1) - .replace(/\n+/, " ") - .trim(), - target: text.substring(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..3abe75902 100644 --- a/src/lib/output/plugins/index.ts +++ b/src/lib/output/plugins/index.ts @@ -1,5 +1,4 @@ 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/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index cdaec6aed..2624819b5 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -6,7 +6,7 @@ function humanize(text: string) { return text.substring(1, 2).toUpperCase() + text.substring(2).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); } -function displayPartsToMarkdown(parts: CommentDisplayPart[]) { +function displayPartsToMarkdown(parts: CommentDisplayPart[], urlTo: DefaultThemeRenderContext["urlTo"]) { const result: string[] = []; for (const part of parts) { @@ -18,13 +18,25 @@ function displayPartsToMarkdown(parts: CommentDisplayPart[]) { case "inline-tag": switch (part.tag) { case "@label": + case "@inheritdoc": // Shouldn't happen break; // Not rendered. case "@link": - // GERRIT RENDER ME PROPERLY - return part.text; + 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, do nothing. + // 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: @@ -35,22 +47,18 @@ function displayPartsToMarkdown(parts: CommentDisplayPart[]) { return result.join(""); } -export function comment({ markdown }: DefaultThemeRenderContext, props: Reflection) { +export function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: Reflection) { if (!props.comment?.hasVisibleComponent()) return; return (
      - - {props.comment.blockTags?.length > 0 && ( -
      - {props.comment.blockTags.map((item) => ( - <> -

      {humanize(item.tag)}

      - - - ))} -
      - )} + + {props.comment.blockTags.map((item) => ( + <> +

      {humanize(item.tag)}

      + + + ))}
      ); } diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index c5973e40d..ae1c14e6e 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -335,15 +335,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 {} +export interface CommentTag extends S { + content: CommentDisplayPart[]; +} -export type CommentDisplayPart = M.CommentDisplayPart; +/** + * 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 SourceReference extends S {} diff --git a/src/lib/serialization/serializers/comment.ts b/src/lib/serialization/serializers/comment.ts new file mode 100644 index 000000000..92a702da8 --- /dev/null +++ b/src/lib/serialization/serializers/comment.ts @@ -0,0 +1,93 @@ +import { Comment, CommentDisplayPart, CommentTag } from "../../models"; + +import { SerializerComponent } from "../components"; +import type { + Comment as JSONComment, + CommentTag as JSONCommentTag, + CommentDisplayPart as JSONCommentDisplayPart, +} from "../schema"; + +function serializeDisplayPart( + part: CommentDisplayPart +): JSONCommentDisplayPart { + switch (part.kind) { + case "text": + case "code": + return part; + case "inline-tag": { + let target: string | number | undefined = undefined; + if (typeof part.target === "string") { + target = part.target; + } else if (typeof part.target === "object") { + target = part.target.id; + } + return { + ...part, + target, + }; + } + } +} + +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 { + const result: JSONComment = { + ...obj, + summary: comment.summary.map(serializeDisplayPart), + }; + if (comment.blockTags.length) { + result.blockTags = comment.blockTags.map((tag) => + this.owner.toObject(tag) + ); + } + if (comment.modifierTags.size) { + result.modifierTags = Array.from(comment.modifierTags); + } + + return result; + } +} + +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.tag, + content: tag.content.map(serializeDisplayPart), + }; + + if (tag.name) { + result.name = tag.name; + } + + return Object.assign(obj, result); + } +} 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 74b59ccb7..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.tag, - content: tag.content, - }; - - if (tag.name) { - result.name = tag.name; - } - - return Object.assign(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 31deecc14..000000000 --- a/src/lib/serialization/serializers/comments/comment.ts +++ /dev/null @@ -1,32 +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 { - obj.summary = comment.summary; - if (comment.blockTags.length) { - obj.blockTags = comment.blockTags.map((tag) => - this.owner.toObject(tag) - ); - } - if (comment.modifierTags.size) { - obj.modifierTags = Array.from(comment.modifierTags); - } - 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/index.ts b/src/lib/serialization/serializers/index.ts index 6288f8dfe..b53e48df1 100644 --- a/src/lib/serialization/serializers/index.ts +++ b/src/lib/serialization/serializers/index.ts @@ -1,6 +1,6 @@ export * from "./reflections"; export * from "./types"; -export * from "./comments"; +export * from "./comment"; export * from "./sources"; export * from "./reflection-group"; export * from "./reflection-category"; 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/jsx.ts b/src/lib/utils/jsx.ts index b21e13fca..d91836d04 100644 --- a/src/lib/utils/jsx.ts +++ b/src/lib/utils/jsx.ts @@ -25,6 +25,7 @@ import { JsxFragment as Fragment } from "./jsx.elements.js"; export type { JsxElement as Element, JsxChildren as Children, + JsxComponent, } from "./jsx.elements.js"; export { JsxFragment as Fragment } from "./jsx.elements.js"; diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 0c8144a38..79ecf9dc3 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -113,8 +113,6 @@ export interface TypeDocOptionMap { // Validation treatWarningsAsErrors: boolean; intentionallyNotExported: string[]; - /** @deprecated use validation.invalidLink */ - listInvalidSymbolLinks: boolean; validation: ValidationOptions; requiredToBeDocumented: (keyof typeof ReflectionKind)[]; } diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 907181199..e56dd0369 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -336,11 +336,6 @@ export function addTypeDocOptions(options: Pick) { 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.", @@ -387,7 +382,7 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Flags, defaults: { notExported: true, - invalidLink: false, + invalidLink: true, notDocumented: false, }, }); 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/behaviorTests.ts b/src/test/behaviorTests.ts index a690e492e..4a02836ca 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -4,6 +4,7 @@ import { ProjectReflection, ReflectionKind, Comment, + CommentDisplayPart, } from "../lib/models"; import type { TestLogger } from "./TestLogger"; @@ -43,6 +44,31 @@ export const behaviorTests: Record< equal(WithoutReadonly.kind, ReflectionKind.Enum, "WithoutReadonly"); }, + 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"]); diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index cf17e2500..b84e43c19 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -994,9 +994,15 @@ { "tag": "@see", "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, { "kind": "text", - "text": "[[TestClass]] @ fixtures" + "text": " @ fixtures" } ] } @@ -4546,9 +4552,15 @@ { "tag": "@see", "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 205 + }, { "kind": "text", - "text": "[[TestClass]] @ fixtures" + "text": " @ fixtures" } ] } diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 552f1ee2c..57e69d808 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -994,9 +994,15 @@ { "tag": "@see", "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 22 + }, { "kind": "text", - "text": "[[TestClass]] @ fixtures" + "text": " @ fixtures" } ] } @@ -4542,9 +4548,15 @@ { "tag": "@see", "content": [ + { + "kind": "inline-tag", + "tag": "@link", + "text": "TestClass", + "target": 205 + }, { "kind": "text", - "text": "[[TestClass]] @ fixtures" + "text": " @ fixtures" } ] } 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; From 463a65ba114ae539940a1ac9afdbcafe2e5b5be9 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 17 Feb 2022 20:40:19 -0700 Subject: [PATCH 054/151] Fix links which refer to reference reflections Resolves #1771 --- CHANGELOG.md | 1 + src/lib/models/comments/comment.ts | 22 ++++++++++++---------- src/lib/models/reflections/reference.ts | 4 ++++ src/test/converter2/issues/gh1771.ts | 10 ++++++++++ src/test/issueTests.ts | 11 +++++++++++ 5 files changed, 38 insertions(+), 10 deletions(-) create mode 100644 src/test/converter2/issues/gh1771.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 885af5bf8..d0fdb9c96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ - 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. ## v0.22.11 (2022-01-18) diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index f28166d19..7349a4e18 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -1,19 +1,21 @@ import { assertNever, removeIf } from "../../utils"; import type { Reflection } from "../reflections"; -/** - * For inline tags, `@link`, `@linkcode`, and `@linkplain` may have a `target` - * property set indicating which reflection/url they link to. - */ export type CommentDisplayPart = | { kind: "text"; text: string } | { kind: "code"; text: string } - | { - kind: "inline-tag"; - tag: `@${string}`; - text: string; - target?: Reflection | 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; +} /** * A model that represents a single TypeDoc comment tag. diff --git a/src/lib/models/reflections/reference.ts b/src/lib/models/reflections/reference.ts index 3edcde9b7..be0db8719 100644 --- a/src/lib/models/reflections/reference.ts +++ b/src/lib/models/reflections/reference.ts @@ -90,6 +90,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; 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/issueTests.ts b/src/test/issueTests.ts index dcdd85cbd..f09da1693 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -9,6 +9,7 @@ import { Comment, CommentTag, } from "../lib/models"; +import type { InlineTagDisplayPart } from "../lib/models/comments/comment"; function query(project: ProjectReflection, name: string) { const reflection = project.getChildByName(name); @@ -345,6 +346,16 @@ export const issueTests: { ); }, + 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), From 357c9b73a8504b81cbf0c0926b8b8193219fd317 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 17 Feb 2022 21:35:30 -0700 Subject: [PATCH 055/151] Correct detection of optional parameters with JSDoc Resolves #1804 --- CHANGELOG.md | 1 + src/lib/converter/factories/signature.ts | 5 ++++- src/test/converter2/issues/gh1804.js | 4 ++++ src/test/issueTests.ts | 9 +++++++++ 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/converter2/issues/gh1804.js diff --git a/CHANGELOG.md b/CHANGELOG.md index d0fdb9c96..bc91de9f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ - 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. ## v0.22.11 (2022-01-18) diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index 6192c955d..4927bef8e 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -145,7 +145,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; } 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/issueTests.ts b/src/test/issueTests.ts index f09da1693..39bcc6772 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -364,4 +364,13 @@ export const issueTests: { ok(project.children![0].kind === ReflectionKind.Reference); 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); + }, }; From d053b92443162c144dd05edbaaa0ba3f4a5ce120 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 17 Feb 2022 22:10:11 -0700 Subject: [PATCH 056/151] Improve support for modifier tags Resolves #1381 --- CHANGELOG.md | 1 + src/lib/converter/context.ts | 3 +++ .../themes/default/partials/comment.tsx | 2 ++ .../output/themes/default/partials/index.tsx | 11 +++++++--- .../partials/member.signature.body.tsx | 2 +- .../output/themes/default/partials/member.tsx | 8 +++++--- .../themes/default/partials/navigation.tsx | 19 +++++++++++++++--- .../themes/default/partials/parameter.tsx | 6 +++--- src/lib/output/themes/lib.tsx | 20 ++++++++++++++----- src/test/converter/class/class.ts | 2 +- src/test/converter/class/type-operator.ts | 2 +- src/test/converter/comment/specs.json | 7 +++---- static/style.css | 4 ++++ 13 files changed, 63 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bc91de9f1..fcf79ec4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ - TypeDoc will now search for `typedoc.js(on)` in the `.config` folder in the current working directory. - 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. ### Bug Fixes diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 7d014bb74..25df1176e 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -186,6 +186,9 @@ export class Context { "@internal", "@readonly", "@packageDocumentation", + "@deprecated", + "@alpha", + "@beta", // TypeDoc specific tags "@hidden", "@ignore", diff --git a/src/lib/output/themes/default/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 2624819b5..76c5b7969 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -50,6 +50,8 @@ function displayPartsToMarkdown(parts: CommentDisplayPart[], urlTo: DefaultTheme export function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: Reflection) { if (!props.comment?.hasVisibleComponent()) return; + // Note: Comment modifiers are handled in `renderFlags` + return (
      diff --git a/src/lib/output/themes/default/partials/index.tsx b/src/lib/output/themes/default/partials/index.tsx index 19ca5cf70..ff34d99c9 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -1,4 +1,4 @@ -import { wbr } from "../../lib"; +import { classNames, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { JSX } from "../../../../utils"; import type { ContainerReflection, ReflectionCategory } from "../../../../models"; @@ -9,7 +9,7 @@ function renderCategory({ urlTo }: DefaultThemeRenderContext, item: ReflectionCa

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

        {item.children.map((item) => ( -
      • +
      • {item.name ? wbr(item.name) : {wbr(item.kindString!)}} @@ -47,7 +47,12 @@ export function index(context: DefaultThemeRenderContext, props: ContainerReflec

        {item.title}

          {item.children.map((item) => ( -
        • +
        • {item.name ? wbr(item.name) : {wbr(item.kindString!)}} 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 b0dfa8507..13fb084bd 100644 --- a/src/lib/output/themes/default/partials/member.signature.body.tsx +++ b/src/lib/output/themes/default/partials/member.signature.body.tsx @@ -25,7 +25,7 @@ export const memberSignatureBody = ( {props.parameters.map((item) => (
        • - {renderFlags(item.flags)} + {renderFlags(item.flags, item.comment)} {!!item.flags.isRest && ...} {item.name} {": "} diff --git a/src/lib/output/themes/default/partials/member.tsx b/src/lib/output/themes/default/partials/member.tsx index 5caeb91d5..a6e9c7133 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,10 @@ export const member = (context: DefaultThemeRenderContext, props: DeclarationRef {!!props.name && (
          )} diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index 63379a707..dd4cfc703 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -64,7 +64,7 @@ function primaryNavigation(context: DefaultThemeRenderContext, props: PageEvent< } return ( -
        • +
        • {wbr(mod.name)} {childNav}
        • @@ -86,7 +86,12 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven .filter((child) => !child.kindOf(ReflectionKind.SomeModule)) .map((child) => { return ( -
        • +
        • {wbr(child.name)} @@ -103,7 +108,15 @@ function secondaryNavigation(context: DefaultThemeRenderContext, props: PageEven return (
      {" "} +
); From 92599ca87362648fe5048c5cb05fac43dbee641f Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 20 Mar 2022 17:04:27 -0600 Subject: [PATCH 070/151] Format --- .../output/themes/default/DefaultTheme.tsx | 82 ++++--------------- .../themes/default/templates/reflection.tsx | 48 +++-------- 2 files changed, 28 insertions(+), 102 deletions(-) diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 1c4b9fe4a..c9d8f67cc 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -52,10 +52,7 @@ export class DefaultTheme extends Theme { private _renderContext?: DefaultThemeRenderContext; getRenderContext(_pageEvent: PageEvent) { if (!this._renderContext) { - this._renderContext = new DefaultThemeRenderContext( - this, - this.application.options - ); + this._renderContext = new DefaultThemeRenderContext(this, this.application.options); } return this._renderContext; } @@ -129,12 +126,7 @@ export class DefaultTheme extends Theme { constructor(renderer: Renderer) { super(renderer); this.markedPlugin = renderer.getComponent("marked") as MarkedPlugin; - this.listenTo( - renderer, - RendererEvent.BEGIN, - this.onRendererBegin, - 1024 - ); + this.listenTo(renderer, RendererEvent.BEGIN, this.onRendererBegin, 1024); } /** @@ -149,25 +141,11 @@ export class DefaultTheme extends Theme { if (false == hasReadme(this.application.options.getValue("readme"))) { project.url = "index.html"; - urls.push( - new UrlMapping( - "index.html", - project, - this.reflectionTemplate - ) - ); + urls.push(new UrlMapping("index.html", project, this.reflectionTemplate)); } else { project.url = "modules.html"; - urls.push( - new UrlMapping( - "modules.html", - project, - this.reflectionTemplate - ) - ); - urls.push( - new UrlMapping("index.html", project, this.indexTemplate) - ); + urls.push(new UrlMapping("modules.html", project, this.reflectionTemplate)); + urls.push(new UrlMapping("index.html", project, this.indexTemplate)); } project.children?.forEach((child: Reflection) => { @@ -195,10 +173,7 @@ export class DefaultTheme extends Theme { DefaultTheme.applyReflectionClasses(reflection); } - if ( - reflection instanceof ContainerReflection && - reflection.groups - ) { + if (reflection instanceof ContainerReflection && reflection.groups) { reflection.groups.forEach(DefaultTheme.applyGroupClasses); } } @@ -212,22 +187,11 @@ export class DefaultTheme extends Theme { * @param separator The separator used to generate the url. * @returns The generated url. */ - static getUrl( - reflection: Reflection, - relative?: Reflection, - separator = "." - ): string { + static getUrl(reflection: Reflection, relative?: Reflection, separator = "."): string { let url = reflection.getAlias(); - if ( - reflection.parent && - reflection.parent !== relative && - !(reflection.parent instanceof ProjectReflection) - ) { - url = - DefaultTheme.getUrl(reflection.parent, relative, separator) + - separator + - url; + if (reflection.parent && reflection.parent !== relative && !(reflection.parent instanceof ProjectReflection)) { + url = DefaultTheme.getUrl(reflection.parent, relative, separator) + separator + url; } return url; @@ -239,9 +203,7 @@ export class DefaultTheme extends Theme { * @param reflection The reflection whose mapping should be resolved. * @returns The found mapping or undefined if no mapping could be found. */ - private getMapping( - reflection: DeclarationReflection - ): TemplateMapping | undefined { + private getMapping(reflection: DeclarationReflection): TemplateMapping | undefined { return this.mappings.find((mapping) => reflection.kindOf(mapping.kind)); } @@ -252,20 +214,11 @@ export class DefaultTheme extends Theme { * @param urls The array the url should be appended to. * @returns The altered urls array. */ - buildUrls( - reflection: DeclarationReflection, - urls: UrlMapping[] - ): UrlMapping[] { + buildUrls(reflection: DeclarationReflection, urls: UrlMapping[]): UrlMapping[] { const mapping = this.getMapping(reflection); if (mapping) { - if ( - !reflection.url || - !DefaultTheme.URL_PREFIX.test(reflection.url) - ) { - const url = [ - mapping.directory, - DefaultTheme.getUrl(reflection) + ".html", - ].join("/"); + if (!reflection.url || !DefaultTheme.URL_PREFIX.test(reflection.url)) { + const url = [mapping.directory, DefaultTheme.getUrl(reflection) + ".html"].join("/"); urls.push(new UrlMapping(url, reflection, mapping.template)); reflection.url = url; @@ -337,10 +290,7 @@ export class DefaultTheme extends Theme { classes.push(DefaultTheme.toStyleClass("tsd-kind-" + kind)); } - if ( - reflection.parent && - reflection.parent instanceof DeclarationReflection - ) { + if (reflection.parent && reflection.parent instanceof DeclarationReflection) { kind = ReflectionKind[reflection.parent.kind]; classes.push(DefaultTheme.toStyleClass(`tsd-parent-kind-${kind}`)); } @@ -404,9 +354,7 @@ export class DefaultTheme extends Theme { * 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(); + return str.replace(/(\w)([A-Z])/g, (_m, m1, m2) => m1 + "-" + m2).toLowerCase(); } } diff --git a/src/lib/output/themes/default/templates/reflection.tsx b/src/lib/output/themes/default/templates/reflection.tsx index fb0e6aff5..ad4928b89 100644 --- a/src/lib/output/themes/default/templates/reflection.tsx +++ b/src/lib/output/themes/default/templates/reflection.tsx @@ -1,31 +1,19 @@ import { hasTypeParameters } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import type { PageEvent } from "../../../events"; -import { - ContainerReflection, - DeclarationReflection, - ReflectionKind, - ReflectionType, -} from "../../../../models"; +import { ContainerReflection, DeclarationReflection, ReflectionKind, ReflectionType } from "../../../../models"; import { JSX } from "../../../../utils"; -export function reflectionTemplate( - context: DefaultThemeRenderContext, - props: PageEvent -) { +export function reflectionTemplate(context: DefaultThemeRenderContext, props: PageEvent) { if ( - [ReflectionKind.TypeAlias, ReflectionKind.Variable].includes( - props.model.kind - ) && + [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)} -
+
{context.comment(props.model)}
)} {hasTypeParameters(props.model) && ( @@ -63,34 +51,24 @@ export function reflectionTemplate( )} {!!props.model.signatures && ( -
- {context.memberSignatures(props.model)} -
+
{context.memberSignatures(props.model)}
)} {!!props.model.indexSignature && (

Indexable

[ - {props.model.indexSignature.parameters!.map( - (item) => ( - <> - {item.name}:{" "} - {context.type(item.type)} - - ) - )} - - {"]: "} - + {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.indexSignature?.type instanceof ReflectionType && + context.parameter(props.model.indexSignature.type.declaration)}
)} From b27c38ac8d2532a248f56e54be1cb5bc6cfe1643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Tue, 22 Mar 2022 21:44:46 +0000 Subject: [PATCH 071/151] Improve some more code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to #1889 — improves some code to make it more readable. --- src/lib/converter/context.ts | 8 ++------ src/lib/converter/plugins/SourceLinkPlugin.ts | 17 +++++++---------- src/lib/models/reflections/utils.ts | 7 ++++--- .../output/themes/default/DefaultTheme.tsx | 3 +-- .../output/themes/default/partials/type.tsx | 2 +- src/lib/output/themes/lib.tsx | 19 +++++++++---------- 6 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 7bce96a33..672545cd5 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -122,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 ); diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/plugins/SourceLinkPlugin.ts index 61e361523..385c52f60 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/plugins/SourceLinkPlugin.ts @@ -220,7 +220,7 @@ export class SourceLinkPlugin extends ConverterComponent { /** * List of paths known to be not under git control. */ - private ignoredPaths: string[] = []; + private ignoredPaths = new Set(); @BindOption("gitRevision") readonly gitRevision!: string; @@ -252,15 +252,13 @@ export class SourceLinkPlugin extends ConverterComponent { 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; - } + if (this.ignoredPaths.has(dirName)) { + return; } // Check for known repositories for (const path of Object.keys(this.repositories)) { - if (fileName.substring(0, path.length).toLowerCase() === path) { + if (fileName.toLowerCase().startsWith(path)) { return this.repositories[path]; } } @@ -279,7 +277,7 @@ export class SourceLinkPlugin extends ConverterComponent { // 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("/")); + this.ignoredPaths.add(segments.slice(0, i).join("/")); } } @@ -298,11 +296,10 @@ export class SourceLinkPlugin extends ConverterComponent { } }); - for (const key in project.reflections) { - const reflection = project.reflections[key]; + for (const reflection of Object.values(project.reflections)) { if (reflection.sources) { reflection.sources.forEach((source: SourceReference) => { - if (source.file && source.file.url) { + if (source.file?.url) { source.url = source.file.url + "#" + 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/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index c9d8f67cc..6a0a6f57b 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -167,8 +167,7 @@ export class DefaultTheme extends Theme { event.project.groups.forEach(DefaultTheme.applyGroupClasses); } - for (const id in event.project.reflections) { - const reflection = event.project.reflections[id]; + for (const reflection of Object.values(event.project)) { if (reflection instanceof DeclarationReflection) { DefaultTheme.applyReflectionClasses(reflection); } diff --git a/src/lib/output/themes/default/partials/type.tsx b/src/lib/output/themes/default/partials/type.tsx index 9f7d1c853..6402b233f 100644 --- a/src/lib/output/themes/default/partials/type.tsx +++ b/src/lib/output/themes/default/partials/type.tsx @@ -54,7 +54,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; } diff --git a/src/lib/output/themes/lib.tsx b/src/lib/output/themes/lib.tsx index c2129fb7d..291d63789 100644 --- a/src/lib/output/themes/lib.tsx +++ b/src/lib/output/themes/lib.tsx @@ -26,12 +26,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)); @@ -70,9 +69,8 @@ export function renderFlags(flags: ReflectionFlags, comment: Comment | undefined } export function classNames(names: Record, extraCss?: string) { - const css = Object.entries(names) - .filter(([, include]) => include) - .map(([key]) => key) + const css = Object.keys(names) + .filter((key) => names[key]) .concat(extraCss || "") .join(" ") .trim() @@ -83,10 +81,11 @@ export function classNames(names: Record, ex export function hasTypeParameters( reflection: Reflection ): reflection is Reflection & { typeParameters: TypeParameterReflection[] } { - if (reflection instanceof DeclarationReflection || reflection instanceof SignatureReflection) { - return reflection.typeParameters != null && reflection.typeParameters.length > 0; - } - return false; + return ( + (reflection instanceof DeclarationReflection || reflection instanceof SignatureReflection) && + reflection.typeParameters != null && + reflection.typeParameters.length > 0 + ); } export function renderTypeParametersSignature( From 4e7f63c1842006bb361fa5a605d203e013088b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 26 Mar 2022 22:14:19 +0000 Subject: [PATCH 072/151] Update src/lib/output/themes/default/DefaultTheme.tsx Co-authored-by: Gerrit Birkeland --- src/lib/output/themes/default/DefaultTheme.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 6a0a6f57b..3af40b967 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -167,7 +167,7 @@ export class DefaultTheme extends Theme { event.project.groups.forEach(DefaultTheme.applyGroupClasses); } - for (const reflection of Object.values(event.project)) { + for (const reflection of Object.values(event.project.reflections)) { if (reflection instanceof DeclarationReflection) { DefaultTheme.applyReflectionClasses(reflection); } From 2ccaea38c4f3a537b76ab9c8aa84be426a0a0da3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sat, 26 Mar 2022 22:19:00 +0000 Subject: [PATCH 073/151] fix: Don't ignore the root of ignored paths --- src/lib/converter/plugins/SourceLinkPlugin.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/plugins/SourceLinkPlugin.ts index 385c52f60..86236ed69 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/plugins/SourceLinkPlugin.ts @@ -252,8 +252,11 @@ export class SourceLinkPlugin extends ConverterComponent { private getRepository(fileName: string): Repository | undefined { // Check for known non-repositories const dirName = Path.dirname(fileName); - if (this.ignoredPaths.has(dirName)) { - return; + const segments = dirName.split("/"); + for (let i = segments.length; i > 0; i--) { + if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) { + return; + } } // Check for known repositories @@ -275,10 +278,7 @@ export class SourceLinkPlugin extends ConverterComponent { } // No repository found, add path to ignored paths - const segments = dirName.split("/"); - for (let i = segments.length; i > 0; i--) { - this.ignoredPaths.add(segments.slice(0, i).join("/")); - } + this.ignoredPaths.add(dirName); } /** From 2681f2f2161a41026a0085eeab00fa2b60cf0a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20B=C3=B6hm?= <188768+fb55@users.noreply.github.com> Date: Sun, 27 Mar 2022 16:45:59 +0100 Subject: [PATCH 074/151] Move type serializers to models (#1890) * Move type serializers to models * Prefer `undefined` over not adding props They will be serialized as the same thing, and we gain a consistent object structure. * Fix `SerializeEvent` output type * Fix added comment * Remove unused extended interface * Flip order of `SourceReference` constructor params * Make serializedFlags a static prob * Simplify `serializeDisplayPart` * Remove useless branches * Fix previous commit * Clean up `SerializerComponent` * Remove comment * Have abstract toObject return SomeType --- src/index.ts | 2 +- src/lib/converter/plugins/SourcePlugin.ts | 15 +- src/lib/converter/types.ts | 3 +- src/lib/models/ReflectionCategory.ts | 11 + src/lib/models/ReflectionGroup.ts | 18 ++ src/lib/models/comments/comment.ts | 43 +++ src/lib/models/reflections/abstract.ts | 39 +++ src/lib/models/reflections/container.ts | 16 + src/lib/models/reflections/declaration.ts | 53 +++- src/lib/models/reflections/parameter.ts | 9 + src/lib/models/reflections/reference.ts | 8 + src/lib/models/reflections/signature.ts | 28 +- src/lib/models/reflections/type-parameter.ts | 21 +- src/lib/models/sources/file.ts | 26 +- src/lib/models/sources/index.ts | 2 +- src/lib/models/types.ts | 274 ++++++++++++++---- src/lib/serialization/components.ts | 82 +----- src/lib/serialization/events.ts | 4 +- src/lib/serialization/index.ts | 30 +- src/lib/serialization/schema.ts | 39 +-- src/lib/serialization/serializer.ts | 130 ++------- src/lib/serialization/serializers/comment.ts | 93 ------ src/lib/serialization/serializers/index.ts | 7 - .../serialization/serializers/models/index.ts | 1 - .../models/source-reference-wrapper.ts | 9 - .../serializers/reflection-category.ts | 35 --- .../serializers/reflection-group.ts | 42 --- .../serializers/reflections/abstract.ts | 56 ---- .../serializers/reflections/container.ts | 34 --- .../serializers/reflections/declaration.ts | 47 --- .../serializers/reflections/index.ts | 7 - .../serializers/reflections/parameter.ts | 26 -- .../serializers/reflections/reference.ts | 25 -- .../serializers/reflections/signature.ts | 28 -- .../serializers/reflections/type-parameter.ts | 24 -- .../serializers/sources/index.ts | 1 - .../serializers/sources/source-reference.ts | 27 -- .../serializers/types/abstract.ts | 19 -- .../serialization/serializers/types/array.ts | 22 -- .../serializers/types/conditional.ts | 25 -- .../serialization/serializers/types/index.ts | 20 -- .../serializers/types/indexed-access.ts | 23 -- .../serializers/types/inferred.ts | 23 -- .../serializers/types/intersection.ts | 25 -- .../serializers/types/intrinsic.ts | 25 -- .../serializers/types/literal.ts | 30 -- .../serialization/serializers/types/mapped.ts | 24 -- .../serializers/types/optional.ts | 25 -- .../serializers/types/predicate.ts | 23 -- .../serialization/serializers/types/query.ts | 16 - .../serializers/types/reference.ts | 35 --- .../serializers/types/reflection.ts | 22 -- .../serialization/serializers/types/rest.ts | 22 -- .../serializers/types/template-literal.ts | 23 -- .../serialization/serializers/types/tuple.ts | 44 --- .../serializers/types/type-operator.ts | 21 -- .../serialization/serializers/types/union.ts | 22 -- .../serializers/types/unknown.ts | 25 -- src/test/converter.test.ts | 2 +- 59 files changed, 532 insertions(+), 1299 deletions(-) delete mode 100644 src/lib/serialization/serializers/comment.ts delete mode 100644 src/lib/serialization/serializers/index.ts delete mode 100644 src/lib/serialization/serializers/models/index.ts delete mode 100644 src/lib/serialization/serializers/models/source-reference-wrapper.ts delete mode 100644 src/lib/serialization/serializers/reflection-category.ts delete mode 100644 src/lib/serialization/serializers/reflection-group.ts delete mode 100644 src/lib/serialization/serializers/reflections/abstract.ts delete mode 100644 src/lib/serialization/serializers/reflections/container.ts delete mode 100644 src/lib/serialization/serializers/reflections/declaration.ts delete mode 100644 src/lib/serialization/serializers/reflections/index.ts delete mode 100644 src/lib/serialization/serializers/reflections/parameter.ts delete mode 100644 src/lib/serialization/serializers/reflections/reference.ts delete mode 100644 src/lib/serialization/serializers/reflections/signature.ts delete mode 100644 src/lib/serialization/serializers/reflections/type-parameter.ts delete mode 100644 src/lib/serialization/serializers/sources/index.ts delete mode 100644 src/lib/serialization/serializers/sources/source-reference.ts delete mode 100644 src/lib/serialization/serializers/types/abstract.ts delete mode 100644 src/lib/serialization/serializers/types/array.ts delete mode 100644 src/lib/serialization/serializers/types/conditional.ts delete mode 100644 src/lib/serialization/serializers/types/index.ts delete mode 100644 src/lib/serialization/serializers/types/indexed-access.ts delete mode 100644 src/lib/serialization/serializers/types/inferred.ts delete mode 100644 src/lib/serialization/serializers/types/intersection.ts delete mode 100644 src/lib/serialization/serializers/types/intrinsic.ts delete mode 100644 src/lib/serialization/serializers/types/literal.ts delete mode 100644 src/lib/serialization/serializers/types/mapped.ts delete mode 100644 src/lib/serialization/serializers/types/optional.ts delete mode 100644 src/lib/serialization/serializers/types/predicate.ts delete mode 100644 src/lib/serialization/serializers/types/query.ts delete mode 100644 src/lib/serialization/serializers/types/reference.ts delete mode 100644 src/lib/serialization/serializers/types/reflection.ts delete mode 100644 src/lib/serialization/serializers/types/rest.ts delete mode 100644 src/lib/serialization/serializers/types/template-literal.ts delete mode 100644 src/lib/serialization/serializers/types/tuple.ts delete mode 100644 src/lib/serialization/serializers/types/type-operator.ts delete mode 100644 src/lib/serialization/serializers/types/union.ts delete mode 100644 src/lib/serialization/serializers/types/unknown.ts diff --git a/src/index.ts b/src/index.ts index ef6eac5ab..518659f97 100644 --- a/src/index.ts +++ b/src/index.ts @@ -60,7 +60,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/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 87b234937..4450b8918 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -16,6 +16,7 @@ import { isNamedNode } from "../utils/nodes"; import { getCommonDirectory, normalizePath } from "../../utils/fs"; import { relative } from "path"; import * as assert from "assert"; +import { SourceReference } from "../../models"; /** * A handler that attaches source file information to reflections. @@ -128,12 +129,14 @@ export class SourcePlugin extends ConverterComponent { } reflection.sources ||= []; - reflection.sources.push({ - file: file, - fileName: fileName, - line: position.line + 1, - character: position.character, - }); + reflection.sources.push( + new SourceReference( + fileName, + position.line + 1, + position.character, + file + ) + ); } } diff --git a/src/lib/converter/types.ts b/src/lib/converter/types.ts index 190c73e7c..93b4eb667 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, @@ -819,7 +818,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]); } 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..ba79bc427 100644 --- a/src/lib/models/ReflectionGroup.ts +++ b/src/lib/models/ReflectionGroup.ts @@ -1,6 +1,7 @@ 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. @@ -73,4 +74,21 @@ export class ReflectionGroup { allChildrenHaveOwnDocument(): boolean { return this.children.every((child) => child.hasOwnDocument); } + + toObject(serializer: Serializer): JSONOutput.ReflectionGroup { + return { + title: this.title, + kind: this.kind, + children: + this.children.length > 0 + ? this.children.map((child) => child.id) + : undefined, + categories: + this.categories && this.categories.length > 0 + ? this.categories.map((category) => + serializer.toObject(category) + ) + : undefined, + }; + } } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index bd17c0798..91f78c317 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -1,6 +1,8 @@ import { assertNever, removeIf } from "../../utils"; import type { Reflection } from "../reflections"; +import type { Serializer, JSONOutput } from "../../serialization"; + export type CommentDisplayPart = | { kind: "text"; text: string } | { kind: "code"; text: string } @@ -17,6 +19,25 @@ export interface InlineTagDisplayPart { 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. * @@ -57,6 +78,14 @@ export class CommentTag { } return tag; } + + toObject(): JSONOutput.CommentTag { + return { + name: this.name, + tag: this.tag, + content: this.content.map(serializeDisplayPart), + }; + } } /** @@ -196,4 +225,18 @@ export class Comment { removeTags(tagName: `@${string}`) { removeIf(this.blockTags, (tag) => tag.tag === tagName); } + + toObject(serializer: Serializer): JSONOutput.Comment { + return { + summary: this.summary.map(serializeDisplayPart), + blockTags: + this.blockTags.length > 0 + ? this.blockTags.map((tag) => serializer.toObject(tag)) + : undefined, + modifierTags: + this.modifierTags.size > 0 + ? Array.from(this.modifierTags) + : undefined, + }; + } } diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index d144589bc..9c60a96da 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -5,6 +5,7 @@ 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. @@ -184,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 { @@ -497,4 +520,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 840e04060..70ecf38f8 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 { /** @@ -45,4 +46,19 @@ export class ContainerReflection extends Reflection { } } } + + override toObject(serializer: Serializer): JSONOutput.ContainerReflection { + return { + ...super.toObject(serializer), + children: this.children?.map((child) => serializer.toObject(child)), + groups: this.groups?.map((group) => serializer.toObject(group)), + categories: this.categories?.map((category) => + serializer.toObject(category) + ), + sources: + this.sources && this.sources.length > 0 + ? this.sources.map((source) => serializer.toObject(source)) + : undefined, + }; + } } diff --git a/src/lib/models/reflections/declaration.ts b/src/lib/models/reflections/declaration.ts index 1381dc32e..3fcd02f72 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. @@ -106,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). @@ -116,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. @@ -244,4 +244,47 @@ export class DeclarationReflection extends ContainerReflection { return result; } + + override toObject( + serializer: Serializer + ): JSONOutput.DeclarationReflection { + return { + ...super.toObject(serializer), + typeParameter: + this.typeParameters && this.typeParameters.length > 0 + ? this.typeParameters.map((type) => + serializer.toObject(type) + ) + : undefined, + type: this.type && serializer.toObject(this.type), + signatures: this.signatures?.map((sig) => serializer.toObject(sig)), + indexSignature: + this.indexSignature && serializer.toObject(this.indexSignature), + getSignature: this.getSignature && [ + serializer.toObject(this.getSignature), + ], + setSignature: this.setSignature && [ + serializer.toObject(this.setSignature), + ], + defaultValue: this.defaultValue, + overwrites: this.overwrites && serializer.toObject(this.overwrites), + inheritedFrom: + this.inheritedFrom && serializer.toObject(this.inheritedFrom), + implementationOf: + this.implementationOf && + serializer.toObject(this.implementationOf), + extendedTypes: this.extendedTypes?.map((type) => + serializer.toObject(type) + ), + extendedBy: this.extendedBy?.map((type) => + serializer.toObject(type) + ), + implementedTypes: this.implementedTypes?.map((type) => + serializer.toObject(type) + ), + implementedBy: this.implementedBy?.map((type) => + serializer.toObject(type) + ), + }; + } } diff --git a/src/lib/models/reflections/parameter.ts b/src/lib/models/reflections/parameter.ts index e6c3ccd9f..13e6924e8 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: this.type && serializer.toObject(this.type), + defaultValue: this.defaultValue, + }; + } } diff --git a/src/lib/models/reflections/reference.ts b/src/lib/models/reflections/reference.ts index be0db8719..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. @@ -111,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 baf83b798..f0d556e36 100644 --- a/src/lib/models/reflections/signature.ts +++ b/src/lib/models/reflections/signature.ts @@ -1,9 +1,10 @@ -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 { constructor( @@ -27,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. @@ -104,4 +105,27 @@ export class SignatureReflection extends Reflection { return result; } + + override toObject(serializer: Serializer): JSONOutput.SignatureReflection { + return { + ...super.toObject(serializer), + typeParameter: + this.typeParameters && this.typeParameters.length > 0 + ? this.typeParameters.map((type) => + serializer.toObject(type) + ) + : undefined, + parameters: + this.parameters && this.parameters.length > 0 + ? this.parameters.map((type) => serializer.toObject(type)) + : undefined, + type: this.type && serializer.toObject(this.type), + overwrites: this.overwrites && serializer.toObject(this.overwrites), + inheritedFrom: + this.inheritedFrom && serializer.toObject(this.inheritedFrom), + implementationOf: + this.implementationOf && + serializer.toObject(this.implementationOf), + }; + } } diff --git a/src/lib/models/reflections/type-parameter.ts b/src/lib/models/reflections/type-parameter.ts index 7edc3304e..4be594f3e 100644 --- a/src/lib/models/reflections/type-parameter.ts +++ b/src/lib/models/reflections/type-parameter.ts @@ -1,23 +1,34 @@ -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"; export class TypeParameterReflection extends Reflection { override parent?: DeclarationReflection; - type?: Type; + type?: SomeType; - default?: Type; + default?: SomeType; constructor( name: string, - constraint?: Type, - defaultType?: Type, + constraint?: SomeType, + defaultType?: SomeType, parent?: Reflection ) { super(name, ReflectionKind.TypeParameter, parent); this.type = constraint; this.default = defaultType; } + + override toObject( + serializer: Serializer + ): JSONOutput.TypeParameterReflection { + return { + ...super.toObject(serializer), + type: this.type && serializer.toObject(this.type), + default: this.default && serializer.toObject(this.default), + }; + } } diff --git a/src/lib/models/sources/file.ts b/src/lib/models/sources/file.ts index 6fcda3b4e..ce69d0979 100644 --- a/src/lib/models/sources/file.ts +++ b/src/lib/models/sources/file.ts @@ -4,13 +4,14 @@ 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 { +export class SourceReference { /** * A reference to the corresponding file instance. */ @@ -26,12 +27,35 @@ export interface SourceReference { */ line: number; + /** + * The index of the character that emitted the declaration. + */ character: number; /** * URL for displaying the source file. */ url?: string; + + constructor( + fileName: string, + line: number, + character: number, + file?: SourceFile + ) { + this.fileName = fileName; + this.line = line; + this.character = character; + this.file = file; + } + + toObject(): JSONSourceReference { + return { + fileName: this.fileName, + line: this.line, + character: this.character, + }; + } } /** diff --git a/src/lib/models/sources/index.ts b/src/lib/models/sources/index.ts index e09c10a40..575aaed74 100644 --- a/src/lib/models/sources/index.ts +++ b/src/lib/models/sources/index.ts @@ -1,4 +1,4 @@ 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 376d1b7fc..ceba9d7b8 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. @@ -24,6 +25,8 @@ export abstract class Type { visit(visitor: TypeVisitor): T { return visitor[this.type](this as never); } + + abstract toObject(serializer: Serializer): JSONOutput.SomeType; } export interface TypeKindMap { @@ -196,18 +199,22 @@ 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; } - override toString() { + override toString(): string { return wrap(this.elementType, BINDING_POWERS.array) + "[]"; } + + override toObject(serializer: Serializer): JSONOutput.ArrayType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -221,15 +228,15 @@ 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(); } - override toString() { + override toString(): string { return [ wrap(this.checkType, BINDING_POWERS.conditionalCheckType), "extends", @@ -240,6 +247,16 @@ export class ConditionalType extends Type { this.falseType, // no need to wrap ].join(" "); } + + 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), + }; + } } /** @@ -248,13 +265,21 @@ 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(); } override toString() { return `${this.objectType}[${this.indexType}]`; } + + override toObject(serializer: Serializer): JSONOutput.IndexedAccessType { + return { + type: this.type, + indexType: serializer.toObject(this.indexType), + objectType: serializer.toObject(this.objectType), + }; + } } /** @@ -274,6 +299,13 @@ export class InferredType extends Type { override toString() { return `infer ${this.name}`; } + + override toObject(): JSONOutput.InferredType { + return { + type: this.type, + name: this.name, + }; + } } /** @@ -286,15 +318,22 @@ export class InferredType extends Type { export class IntersectionType extends Type { override readonly type = "intersection"; - constructor(public types: Type[]) { + constructor(public types: SomeType[]) { super(); } - override toString() { + override toString(): string { return this.types .map((t) => wrap(t, BINDING_POWERS.intersection)) .join(" & "); } + + override toObject(serializer: Serializer): JSONOutput.IntersectionType { + return { + type: this.type, + types: this.types.map((t) => serializer.toObject(t)), + }; + } } /** @@ -314,6 +353,13 @@ export class IntrinsicType extends Type { override toString() { return this.name; } + + override toObject(): JSONOutput.IntrinsicType { + return { + type: this.type, + name: this.name, + }; + } } /** @@ -340,6 +386,23 @@ export class LiteralType extends Type { } return JSON.stringify(this.value); } + + 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, + }; + } } /** @@ -354,11 +417,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(); } @@ -380,6 +443,18 @@ export class MappedType extends Type { return `{ ${read}[${this.parameter} in ${this.parameterType}${name}]${opt}: ${this.templateType} }`; } + + 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: this.nameType && serializer.toObject(this.nameType), + }; + } } /** @@ -392,9 +467,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; } @@ -402,6 +477,13 @@ export class OptionalType extends Type { override toString() { return wrap(this.elementType, BINDING_POWERS.optional) + "?"; } + + override toObject(serializer: Serializer): JSONOutput.OptionalType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -415,32 +497,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; } /** @@ -454,6 +526,15 @@ export class PredicateType extends Type { return out.join(" "); } + + override toObject(serializer: Serializer): JSONOutput.PredicateType { + return { + type: this.type, + name: this.name, + asserts: this.asserts, + targetType: this.targetType && serializer.toObject(this.targetType), + }; + } } /** @@ -476,6 +557,13 @@ export class QueryType extends Type { override toString() { return `typeof ${this.queryType.toString()}`; } + + override toObject(serializer: Serializer): JSONOutput.QueryType { + return { + type: this.type, + queryType: serializer.toObject(this.queryType), + }; + } } /** @@ -499,7 +587,7 @@ export class ReferenceType extends Type { /** * The type arguments of this reference. */ - typeArguments?: Type[]; + typeArguments?: SomeType[]; /** * The resolved reflection. @@ -624,6 +712,25 @@ export class ReferenceType extends Type { return name + typeArgs; } + + override toObject(serializer: Serializer): JSONOutput.ReferenceType { + const result: JSONOutput.ReferenceType = { + type: this.type, + id: this.reflection?.id, + typeArguments: + this.typeArguments && this.typeArguments.length > 0 + ? this.typeArguments?.map((t) => serializer.toObject(t)) + : undefined, + name: this.name, + }; + + if (this.qualifiedName && this.package) { + result.qualifiedName = this.qualifiedName; + result.package = this.package; + } + + return result; + } } /** @@ -653,6 +760,13 @@ export class ReflectionType extends Type { return "Object"; } } + + override toObject(serializer: Serializer): JSONOutput.ReflectionType { + return { + type: this.type, + declaration: serializer.toObject(this.declaration), + }; + } } /** @@ -665,13 +779,20 @@ export class ReflectionType extends Type { export class RestType extends Type { override readonly type = "rest"; - constructor(public elementType: Type) { + constructor(public elementType: SomeType) { super(); } override toString() { return `...${wrap(this.elementType, BINDING_POWERS.rest)}`; } + + override toObject(serializer: Serializer): JSONOutput.RestType { + return { + type: this.type, + elementType: serializer.toObject(this.elementType), + }; + } } /** @@ -683,7 +804,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(); } @@ -697,6 +818,17 @@ export class TemplateLiteralType extends Type { "`", ].join(""); } + + override toObject(serializer: Serializer): JSONOutput.TemplateLiteralType { + return { + type: this.type, + head: this.head, + tail: this.tail.map(([type, text]) => [ + serializer.toObject(type), + text, + ]), + }; + } } /** @@ -710,18 +842,25 @@ 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; } override toString() { return "[" + this.elements.join(", ") + "]"; } + + override toObject(serializer: Serializer): JSONOutput.TupleType { + return { + type: this.type, + elements: + this.elements.length > 0 + ? this.elements.map((t) => serializer.toObject(t)) + : undefined, + }; + } } /** @@ -737,7 +876,7 @@ export class NamedTupleMember extends Type { constructor( public name: string, public isOptional: boolean, - public element: Type + public element: SomeType ) { super(); } @@ -748,6 +887,15 @@ export class NamedTupleMember extends Type { override toString() { return `${this.name}${this.isOptional ? "?" : ""}: ${this.element}`; } + + override toObject(serializer: Serializer): JSONOutput.NamedTupleMemberType { + return { + type: this.type, + name: this.name, + isOptional: this.isOptional, + element: serializer.toObject(this.element), + }; + } } /** @@ -762,15 +910,23 @@ export class TypeOperatorType extends Type { override readonly type = "typeOperator"; constructor( - public target: Type, + public target: SomeType, public operator: "keyof" | "unique" | "readonly" ) { super(); } - override toString() { + override toString(): string { return `${this.operator} ${this.target.toString()}`; } + + override toObject(serializer: Serializer): JSONOutput.TypeOperatorType { + return { + type: this.type, + target: serializer.toObject(this.target), + operator: this.operator, + }; + } } /** @@ -809,6 +965,13 @@ export class UnionType extends Type { ); } } + + override toObject(serializer: Serializer): JSONOutput.UnionType { + return { + type: this.type, + types: this.types.map((t) => serializer.toObject(t)), + }; + } } /** @@ -830,4 +993,11 @@ export class UnknownType extends Type { override toString() { return this.name; } + + override toObject(): JSONOutput.UnknownType { + return { + type: this.type, + name: this.name, + }; + } } 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 c3ec80167..27f0badfb 100644 --- a/src/lib/serialization/index.ts +++ b/src/lib/serialization/index.ts @@ -1,35 +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, - 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 ae1c14e6e..2af4684e6 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 } from "./serializers"; /** * Describes the mapping from Model types to the corresponding JSON output type. @@ -75,7 +74,7 @@ type _ModelToObject = ? CommentTag : T extends M.CommentDisplayPart ? CommentDisplayPart - : T extends SourceReferenceWrapper + : T extends M.SourceReference ? SourceReference : never; @@ -172,9 +171,10 @@ 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 { @@ -185,24 +185,7 @@ export interface Reflection // 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; @@ -287,11 +270,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, @@ -320,10 +299,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 diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index 2bad0ef26..1f568d32d 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,28 @@ 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) { + 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 - } - - if (Array.isArray(value)) { - if (value.length === 0) { - return undefined; - } - return value.map((val) => this.toObject(val)); - } - - // 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 - ); + toObject }>( + value: T + ): ModelToObject { + return this.serializers + .filter((s) => s.supports(value)) + .reduce( + (val, s) => s.toObject(value, val, this) as ModelToObject, + value.toObject(this) + ); } /** @@ -74,18 +51,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,69 +73,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.ReflectionCategorySerializer, - S.ReflectionGroupSerializer, -]; - -function addSerializers(owner: Serializer) { - for (const component of serializerComponents) { - owner.addSerializer(new component(owner)); - } } diff --git a/src/lib/serialization/serializers/comment.ts b/src/lib/serialization/serializers/comment.ts deleted file mode 100644 index 92a702da8..000000000 --- a/src/lib/serialization/serializers/comment.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { Comment, CommentDisplayPart, CommentTag } from "../../models"; - -import { SerializerComponent } from "../components"; -import type { - Comment as JSONComment, - CommentTag as JSONCommentTag, - CommentDisplayPart as JSONCommentDisplayPart, -} from "../schema"; - -function serializeDisplayPart( - part: CommentDisplayPart -): JSONCommentDisplayPart { - switch (part.kind) { - case "text": - case "code": - return part; - case "inline-tag": { - let target: string | number | undefined = undefined; - if (typeof part.target === "string") { - target = part.target; - } else if (typeof part.target === "object") { - target = part.target.id; - } - return { - ...part, - target, - }; - } - } -} - -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 { - const result: JSONComment = { - ...obj, - summary: comment.summary.map(serializeDisplayPart), - }; - if (comment.blockTags.length) { - result.blockTags = comment.blockTags.map((tag) => - this.owner.toObject(tag) - ); - } - if (comment.modifierTags.size) { - result.modifierTags = Array.from(comment.modifierTags); - } - - return result; - } -} - -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.tag, - content: tag.content.map(serializeDisplayPart), - }; - - if (tag.name) { - result.name = tag.name; - } - - return Object.assign(obj, result); - } -} diff --git a/src/lib/serialization/serializers/index.ts b/src/lib/serialization/serializers/index.ts deleted file mode 100644 index b53e48df1..000000000 --- a/src/lib/serialization/serializers/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from "./reflections"; -export * from "./types"; -export * from "./comment"; -export * from "./sources"; -export * from "./reflection-group"; -export * from "./reflection-category"; -export * from "./models"; diff --git a/src/lib/serialization/serializers/models/index.ts b/src/lib/serialization/serializers/models/index.ts deleted file mode 100644 index 5492998cd..000000000 --- a/src/lib/serialization/serializers/models/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { SourceReferenceWrapper } from "./source-reference-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 9aa6407b9..000000000 --- a/src/lib/serialization/serializers/reflections/abstract.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { Reflection } from "../../../models"; - -import { ReflectionSerializerComponent } from "../../components"; -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: {}, - }; - - if (reflection.comment && !reflection.comment.isEmpty()) { - result.comment = this.owner.toObject(reflection.comment); - } - - 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 7e4c723fe..000000000 --- a/src/lib/serialization/serializers/reflections/type-parameter.ts +++ /dev/null @@ -1,24 +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), - }; - } -} 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 8f181e788..000000000 --- a/src/lib/serialization/serializers/types/inferred.ts +++ /dev/null @@ -1,23 +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, - }; - } -} 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/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, " " ); From 010aff29509c2b7acde5905baf5afca07f6f618a Mon Sep 17 00:00:00 2001 From: futurGH Date: Tue, 5 Apr 2022 21:59:36 -0400 Subject: [PATCH 075/151] Fix sidebar shifting --- static/style.css | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/static/style.css b/static/style.css index 0306428de..850871831 100644 --- a/static/style.css +++ b/static/style.css @@ -212,6 +212,7 @@ dd { border-top: 1px solid var(--color-accent); padding-top: 1rem; padding-bottom: 1rem; + max-height: 3.5rem; } .tsd-generator > p { @@ -913,26 +914,24 @@ a.tsd-index-link { .menu-sticky-wrap { position: sticky; - height: 94vh; + height: calc(100vh - 2rem); + top: 4rem; right: 0; + padding: 0 1.5rem; padding-top: 1rem; - top: 3rem; + margin-top: 3rem; transition: 0.3s ease-in-out; - transition-property: top, padding-top, height; + transition-property: top, padding-top, padding, height; overflow-y: auto; } .col-menu { border-left: 1px solid var(--color-accent); } - .col-menu .tsd-navigation:not(:last-child) { - padding-bottom: 1.75rem; - } - .col-menu.menu-sticky-wrap { - padding: 0 1.5rem; - } .col-menu--hide { top: 1rem; - height: calc(100vh - 2rem); + } + .col-menu .tsd-navigation:not(:last-child) { + padding-bottom: 1.75rem; } } From eab155b14854aeb704b0ccf6e9d15c22ef63cd88 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 12:29:16 -0600 Subject: [PATCH 076/151] Fixed most of the fallout from merge of master --- package.json | 1 + src/lib/converter/comments/discovery.ts | 3 +- src/lib/converter/factories/signature.ts | 2 +- src/lib/converter/plugins/SourcePlugin.ts | 24 +-------------- src/lib/converter/symbols.ts | 19 +++++------- src/lib/models/comments/comment.ts | 2 +- src/lib/models/types.ts | 2 +- src/lib/serialization/serializer.ts | 1 + src/test/converter/alias/specs.json | 4 +-- .../class/specs-with-lump-categories.json | 30 ++++++++++++++----- src/test/converter/class/specs.json | 30 ++++++++++++++----- src/test/converter/declaration/specs.json | 4 +-- src/test/converter/exports/specs.json | 8 ++--- src/test/converter/function/specs.json | 28 ++++++++--------- src/test/converter/inheritance/specs.json | 22 +++++++++++--- src/test/converter/interface/specs.json | 7 +++++ src/test/converter/js/specs.json | 4 +-- src/test/converter/mixin/specs.json | 15 +++++++--- src/test/converter/variables/specs.json | 8 ++--- src/test/issueTests.ts | 6 ++-- tsconfig.json | 2 +- 21 files changed, 127 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 794c65987..f1f382ec2 100644 --- a/package.json +++ b/package.json @@ -56,6 +56,7 @@ "!*.map", "/dist", "!/dist/tmp", + "!/dist/.tsbuildinfo", "!/dist/test", "/LICENSE", "/static" diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index f8ec7140c..f2feaf5bb 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -21,8 +21,9 @@ const wantedKinds: Record = { ], [ReflectionKind.EnumMember]: [ ts.SyntaxKind.EnumMember, - // This is here so that @enum gets it + // These here so that @enum gets comments ts.SyntaxKind.PropertyAssignment, + ts.SyntaxKind.PropertySignature, ], [ReflectionKind.Variable]: [ ts.SyntaxKind.VariableDeclaration, diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index 1cf7b3a14..a07f57590 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -102,7 +102,7 @@ export function createSignature( function convertParameters( context: Context, sigRef: SignatureReflection, - parameters: readonly (ts.Symbol & { type: ts.Type })[], + parameters: readonly (ts.Symbol & { type?: ts.Type })[], parameterNodes: | readonly ts.ParameterDeclaration[] | readonly ts.JSDocParameterTag[] diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 4450b8918..8d034d06d 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -5,7 +5,6 @@ import { Reflection, ProjectReflection, DeclarationReflection, - ReflectionKind, } from "../../models/reflections/index"; import { SourceDirectory, SourceFile } from "../../models/sources/index"; import { Component, ConverterComponent } from "../components"; @@ -84,28 +83,7 @@ export class SourcePlugin extends ConverterComponent { return; } - let declarations: ts.Declaration[] = []; - if (reflection.kind === ReflectionKind.Constructor) { - for (const decl of symbol.declarations || []) { - if ( - ts.isClassDeclaration(decl) || - ts.isInterfaceDeclaration(decl) - ) { - for (const child of decl.members) { - if ( - ts.isConstructorDeclaration(child) || - ts.isConstructorTypeNode(child) - ) { - declarations.push(child); - } - } - } - } - } else { - declarations = symbol.declarations || []; - } - - for (const node of declarations || []) { + for (const node of symbol.declarations || []) { const sourceFile = node.getSourceFile(); const fileName = sourceFile.fileName; this.fileNames.add(fileName); diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index fc2ae7786..4a0bca61e 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -515,18 +515,13 @@ function convertClassOrInterface( } reflectionContext.shouldBeStatic = false; - const constructMember = new DeclarationReflection( - "constructor", - ReflectionKind.Constructor, - reflection - ); - reflectionContext.addChild(constructMember); - context.registerReflection(constructMember, symbol); - 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 @@ -534,7 +529,7 @@ function convertClassOrInterface( setModifiers(symbol, ctors[0].declaration, constructMember); } - context.trigger(ConverterEvents.CREATE_DECLARATION, constructMember); + context.finalizeDeclarationReflection(constructMember); const constructContext = reflectionContext.withScope(constructMember); diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 91f78c317..835aee5b2 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -81,8 +81,8 @@ export class CommentTag { toObject(): JSONOutput.CommentTag { return { - name: this.name, tag: this.tag, + name: this.name, content: this.content.map(serializeDisplayPart), }; } diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index 790570cdf..a61a4ac82 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -926,8 +926,8 @@ export class TypeOperatorType extends Type { override toObject(serializer: Serializer): JSONOutput.TypeOperatorType { return { type: this.type, - target: serializer.toObject(this.target), operator: this.operator, + target: serializer.toObject(this.target), }; } } diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index 1f568d32d..50b59d083 100644 --- a/src/lib/serialization/serializer.ts +++ b/src/lib/serialization/serializer.ts @@ -22,6 +22,7 @@ export class Serializer extends EventDispatcher { addSerializer(serializer: SerializerComponent): void { if ("serializeGroup" in serializer) { + // Remove this check in 0.24 throw new Error( "Support for `serializeGroup` was removed. Use supports instead." ); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 4d79c6d16..a9de4e219 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -101,9 +101,9 @@ "name": "U" } ], + "name": "PromiseLike", "qualifiedName": "PromiseLike", - "package": "typescript", - "name": "PromiseLike" + "package": "typescript" }, "trueType": { "type": "reference", diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 987479215..2976b6eb1 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -2009,6 +2009,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 25 + } + ], "signatures": [ { "id": 92, @@ -2689,9 +2696,9 @@ "flags": {}, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -2728,9 +2735,9 @@ "name": "any" } ], + "name": "TypedPropertyDescriptor", "qualifiedName": "TypedPropertyDescriptor", - "package": "typescript", - "name": "TypedPropertyDescriptor" + "package": "typescript" } } ], @@ -2842,9 +2849,9 @@ ], "type": { "type": "reference", + "name": "ClassDecorator", "qualifiedName": "ClassDecorator", - "package": "typescript", - "name": "ClassDecorator" + "package": "typescript" } } ] @@ -2900,9 +2907,9 @@ ], "type": { "type": "reference", + "name": "MethodDecorator", "qualifiedName": "MethodDecorator", - "package": "typescript", - "name": "MethodDecorator" + "package": "typescript" } } ] @@ -3815,6 +3822,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4 + } + ], "signatures": [ { "id": 178, diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 9970ba4c3..b0ec7b63e 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -2005,6 +2005,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "class.ts", + "line": 130, + "character": 25 + } + ], "signatures": [ { "id": 92, @@ -2685,9 +2692,9 @@ "flags": {}, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -2724,9 +2731,9 @@ "name": "any" } ], + "name": "TypedPropertyDescriptor", "qualifiedName": "TypedPropertyDescriptor", - "package": "typescript", - "name": "TypedPropertyDescriptor" + "package": "typescript" } } ], @@ -2838,9 +2845,9 @@ ], "type": { "type": "reference", + "name": "ClassDecorator", "qualifiedName": "ClassDecorator", - "package": "typescript", - "name": "ClassDecorator" + "package": "typescript" } } ] @@ -2896,9 +2903,9 @@ ], "type": { "type": "reference", + "name": "MethodDecorator", "qualifiedName": "MethodDecorator", - "package": "typescript", - "name": "MethodDecorator" + "package": "typescript" } } ] @@ -3811,6 +3818,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "generic-class.ts", + "line": 20, + "character": 4 + } + ], "signatures": [ { "id": 178, diff --git a/src/test/converter/declaration/specs.json b/src/test/converter/declaration/specs.json index b1dd5a067..50e54554b 100644 --- a/src/test/converter/declaration/specs.json +++ b/src/test/converter/declaration/specs.json @@ -269,9 +269,9 @@ ], "type": { "type": "reference", + "name": "ts.server.ActionSet", "qualifiedName": "ts.server.ActionSet", - "package": "typescript", - "name": "ts.server.ActionSet" + "package": "typescript" } } ], diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 60c5a006a..9c0d25559 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -20,7 +20,7 @@ "sources": [ { "fileName": "mod.ts", - "line": 44, + "line": 42, "character": 12 } ], @@ -80,7 +80,7 @@ "sources": [ { "fileName": "mod.ts", - "line": 42, + "line": 40, "character": 12 } ], @@ -645,7 +645,7 @@ "sources": [ { "fileName": "mod.ts", - "line": 42, + "line": 40, "character": 12 } ], @@ -690,7 +690,7 @@ "sources": [ { "fileName": "mod.ts", - "line": 44, + "line": 42, "character": 12 } ], diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index dcb20b315..32ea26388 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -516,9 +516,9 @@ "name": "T" } ], + "name": "Iterable", "qualifiedName": "Iterable", - "package": "typescript", - "name": "Iterable" + "package": "typescript" } } ], @@ -633,9 +633,9 @@ "name": "T" } ], + "name": "Iterable", "qualifiedName": "Iterable", - "package": "typescript", - "name": "Iterable" + "package": "typescript" } } ], @@ -1012,9 +1012,9 @@ ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -1185,9 +1185,9 @@ ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -1334,9 +1334,9 @@ ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { @@ -1739,9 +1739,9 @@ }, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } } ], @@ -2474,9 +2474,9 @@ }, "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } } ], diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 266fcf851..16947b992 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -42,13 +42,13 @@ "blockTags": [ { "tag": "@typeParam", + "name": "T", "content": [ { "kind": "text", "text": "Source interface type parameter" } - ], - "name": "T" + ] } ] }, @@ -437,8 +437,8 @@ "blockTags": [ { "tag": "@inheritDoc", - "content": [], - "name": "SubClassA.printName" + "name": "SubClassA.printName", + "content": [] } ] }, @@ -637,6 +637,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 3, + "character": 4 + } + ], "signatures": [ { "id": 37, @@ -800,6 +807,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mergable-class.ts", + "line": 1, + "character": 17 + } + ], "signatures": [ { "id": 30, diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index e15b78565..344426b4d 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -24,6 +24,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "constructor-type.ts", + "line": 1, + "character": 17 + } + ], "signatures": [ { "id": 4, diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index d901f3f51..266409185 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -649,9 +649,9 @@ ], "type": { "type": "reference", + "name": "Object", "qualifiedName": "Object", - "package": "typescript", - "name": "Object" + "package": "typescript" } }, { diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 7a80c2fa0..907b8f94b 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -1065,6 +1065,13 @@ "kind": 512, "kindString": "Constructor", "flags": {}, + "sources": [ + { + "fileName": "mixin.ts", + "line": 9, + "character": 41 + } + ], "signatures": [ { "id": 8, @@ -1239,14 +1246,14 @@ "name": "T" } ], + "name": "ReturnType", "qualifiedName": "ReturnType", - "package": "typescript", - "name": "ReturnType" + "package": "typescript" } ], + "name": "InstanceType", "qualifiedName": "InstanceType", - "package": "typescript", - "name": "InstanceType" + "package": "typescript" }, "extendedBy": [ { diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 5fb8b71cd..d6102e905 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -1892,9 +1892,9 @@ "name": "string" } ], + "name": "Promise", "qualifiedName": "Promise", - "package": "typescript", - "name": "Promise" + "package": "typescript" } }, { @@ -1918,9 +1918,9 @@ "name": "object" } ], + "name": "Promise", "qualifiedName": "Promise", - "package": "typescript", - "name": "Promise" + "package": "typescript" } } ], diff --git a/src/test/issueTests.ts b/src/test/issueTests.ts index 2709088f8..7d2f4149d 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -402,7 +402,7 @@ export const issueTests: { fooSig.type.types[1].declaration.getChildByName("min")?.comment ?.summary ), - "Nested\n" + "Nested" ); const bar = query(project, "bar"); @@ -416,14 +416,14 @@ export const issueTests: { barSig.type.types[0].declaration.getChildByName("min")?.comment ?.summary ), - "Nested\n" + "Nested" ); equal( Comment.combineDisplayParts( barSig.type.types[1].declaration.getChildByName("min")?.comment ?.summary ), - "Nested\n" + "Nested" ); }, diff --git a/tsconfig.json b/tsconfig.json index 96b7610d4..5cc1bedb5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ // Speed up dev compilation time "incremental": true, - "tsBuildInfoFile": "node_modules/.cache/.tsbuildinfo", + "tsBuildInfoFile": "dist/.tsbuildinfo", "experimentalDecorators": true, From 88c0f1e7d1a5c589f44bdc3d0a729aa8f9cbafd0 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 12:32:11 -0600 Subject: [PATCH 077/151] Fix remaining fallout from master merge --- src/lib/converter/comments/discovery.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index f2feaf5bb..e96c1a754 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -28,6 +28,7 @@ const wantedKinds: Record = { [ReflectionKind.Variable]: [ ts.SyntaxKind.VariableDeclaration, ts.SyntaxKind.BindingElement, + ts.SyntaxKind.ExportAssignment, ], [ReflectionKind.Function]: [ ts.SyntaxKind.FunctionDeclaration, @@ -43,6 +44,7 @@ const wantedKinds: Record = { ts.SyntaxKind.PropertyDeclaration, ts.SyntaxKind.PropertySignature, ts.SyntaxKind.BinaryExpression, + ts.SyntaxKind.PropertyAssignment, ], [ReflectionKind.Method]: [ ts.SyntaxKind.FunctionDeclaration, From f7543125429e0c7575cee7eaa3e1f2fb59e64622 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 14:13:08 -0600 Subject: [PATCH 078/151] Fix display of index signatures Resolves #1913 --- CHANGELOG.md | 1 + src/lib/converter/symbols.ts | 6 + .../output/themes/default/partials/type.tsx | 120 ++++++++++-------- src/test/converter2/issues/gh1913.js | 4 + src/test/issueTests.ts | 12 ++ 5 files changed, 88 insertions(+), 55 deletions(-) create mode 100644 src/test/converter2/issues/gh1913.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 2618145bc..d489f839e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -81,6 +81,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Fixed `removeReflection` not completely removing reflections from the project, #1898. - Fixed `@hidden` / `@ignore` / `@exclude` comments on default exports with no associated variable, #1903. - `makeRecursiveVisitor` will now correctly call the `intersection` callback, #1910. +- JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. ### Thanks! diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 4a0bca61e..a743eb6cb 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -45,6 +45,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, }; @@ -66,6 +67,7 @@ const conversionOrder = [ // Before type alias ts.SymbolFlags.BlockScopedVariable, ts.SymbolFlags.FunctionScopedVariable, + ts.SymbolFlags.ExportValue, ts.SymbolFlags.TypeAlias, ts.SymbolFlags.Function, @@ -849,6 +851,8 @@ function convertVariable( reflection.defaultValue = convertDefaultValue(declaration); context.finalizeDeclarationReflection(reflection); + + return ts.SymbolFlags.Property; } function isEnumLike(checker: ts.TypeChecker, type: ts.Type, location: ts.Node) { @@ -934,6 +938,8 @@ function convertVariableAsFunction( signature ); } + + return ts.SymbolFlags.Property; } function convertAccessor( diff --git a/src/lib/output/themes/default/partials/type.tsx b/src/lib/output/themes/default/partials/type.tsx index 6402b233f..489ed5bb0 100644 --- a/src/lib/output/themes/default/partials/type.tsx +++ b/src/lib/output/themes/default/partials/type.tsx @@ -283,65 +283,72 @@ const typeRenderers: { return name; }, reflection(context, type, { needsParens }) { - 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)} - - ); - } + const members: JSX.Element[] = []; - if (item.getSignature) { - return ( - <> - get - {item.name} - (): - {renderType(context, item.getSignature.type)} - - ); - } + for (const item of type.declaration.children || []) { + if (item.getSignature && item.setSignature) { + members.push( + <> + {item.name} + : + {renderType(context, item.getSignature.type)} + + ); + continue; + } - if (item.setSignature) { - return ( - <> - set - {item.name} - ( - {item.setSignature.parameters?.map((item) => ( - <> - {item.name} - : - {renderType(context, item.type)} - - ))} - ) - - ); - } + if (item.getSignature) { + members.push( + <> + get + {item.name} + (): + {renderType(context, item.getSignature.type)} + + ); + continue; + } - return ( + if (item.setSignature) { + members.push( + <> + set + {item.name} + ( + {item.setSignature.parameters?.map((item) => ( <> {item.name} - {item.flags.isOptional ? "?: " : ": "} + : {renderType(context, item.type)} - ); - })} - {" }"} + ))} + ) + + ); + continue; + } + + members.push( + <> + {item.name} + {item.flags.isOptional ? "?: " : ": "} + {renderType(context, item.type)} ); } - 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)}] + : + {renderType(context, index.type)} + + ); + } + + if (!members.length && type.declaration.signatures?.length === 1) { return ( <> {needsParens && (} @@ -354,16 +361,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/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/issueTests.ts b/src/test/issueTests.ts index 7d2f4149d..ecbaf50e3 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -467,4 +467,16 @@ export const issueTests: { logger.discardDebugMessages(); logger.expectNoOtherMessages(); }, + + gh1913(project) { + const fn = query(project, "fn"); + + equal( + fn.signatures?.[0].comment, + new Comment( + [], + [new CommentTag("@returns", [{ kind: "text", text: "ret" }])] + ) + ); + }, }; From 1357984ee012ca25b0422dd00f07572daa9aeaf1 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 15:21:56 -0600 Subject: [PATCH 079/151] Only take comments from exports for references and namespaces Ref: #1901 --- CHANGELOG.md | 3 +- src/lib/converter/comments/discovery.ts | 1 + src/lib/converter/context.ts | 24 +++++++++++--- src/lib/converter/symbols.ts | 14 +++----- src/test/behaviorTests.ts | 16 ++++++++++ src/test/converter/exports/specs.json | 32 +++++++++++++++++++ .../converter2/behavior/exportComments.ts | 13 ++++++++ 7 files changed, 88 insertions(+), 15 deletions(-) create mode 100644 src/test/converter2/behavior/exportComments.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d489f839e..bfca3b706 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - Removed deprecated `removeReaderByName`, `addDeclarations` and `removeDeclarationByName` methods on `Options`. +- Comments on export declarations will only overrides comments for references and namespaces, #1901. ### Features @@ -46,6 +47,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. +- JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. ### Thanks! @@ -81,7 +83,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Fixed `removeReflection` not completely removing reflections from the project, #1898. - Fixed `@hidden` / `@ignore` / `@exclude` comments on default exports with no associated variable, #1903. - `makeRecursiveVisitor` will now correctly call the `intersection` callback, #1910. -- JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. ### Thanks! diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index e96c1a754..c290444e2 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -14,6 +14,7 @@ const wantedKinds: Record = { ts.SyntaxKind.ModuleDeclaration, ts.SyntaxKind.SourceFile, ts.SyntaxKind.BindingElement, + ts.SyntaxKind.ExportSpecifier, ], [ReflectionKind.Enum]: [ ts.SyntaxKind.EnumDeclaration, diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 672545cd5..d8b501d5e 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -209,9 +209,23 @@ 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); - if (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, @@ -232,9 +246,11 @@ export class Context { reflection.setFlag(ReflectionFlag.Static); } - reflection.escapedName = symbol?.escapedName; + if (reflection instanceof DeclarationReflection) { + reflection.escapedName = symbol?.escapedName; + this.addChild(reflection); + } - this.addChild(reflection); if (symbol && this.converter.isExternal(symbol)) { reflection.setFlag(ReflectionFlag.External); } @@ -242,8 +258,6 @@ export class Context { this.registerReflection(reflection, exportSymbol); } this.registerReflection(reflection, symbol); - - return reflection; } finalizeDeclarationReflection(reflection: DeclarationReflection) { diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index a743eb6cb..5b10998eb 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -358,7 +358,7 @@ function createTypeParamReflection( defaultType, context.scope ); - context.registerReflection(paramRefl, param.symbol); + context.postReflectionCreation(paramRefl, param.symbol, void 0); context.trigger(ConverterEvents.CREATE_TYPE_PARAMETER, paramRefl); return paramRefl; } @@ -753,10 +753,8 @@ function convertConstructSignatures(context: Context, symbol: ts.Symbol) { ReflectionKind.Constructor, context.scope ); - context.addChild(constructMember); - context.registerReflection(constructMember, symbol); - - context.trigger(ConverterEvents.CREATE_DECLARATION, constructMember); + context.postReflectionCreation(constructMember, symbol, void 0); + context.finalizeDeclarationReflection(constructMember); const constructContext = context.withScope(constructMember); @@ -802,10 +800,8 @@ function createAlias( target, context.scope ); - context.addChild(ref); - context.registerReflection(ref, symbol); - - context.trigger(ConverterEvents.CREATE_DECLARATION, ref); + context.postReflectionCreation(ref, symbol, exportSymbol); + context.finalizeDeclarationReflection(ref); } function convertVariable( diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index b9a90c7fe..240dd16b4 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -102,6 +102,22 @@ export const behaviorTests: Record< ]); }, + 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(Comment.combineDisplayParts(foo.comment?.summary), "export foo"); + }, + inheritDocBasic(project) { const target = query(project, "InterfaceTarget"); const comment = new Comment( diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 9c0d25559..2557b4027 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -47,6 +47,14 @@ "kind": 16777216, "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", @@ -107,6 +115,14 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] + }, "sources": [ { "fileName": "mod.ts", @@ -657,6 +673,14 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export of a local under a different name." + } + ] + }, "sources": [ { "fileName": "mod.ts", @@ -672,6 +696,14 @@ "kind": 16777216, "kindString": "Reference", "flags": {}, + "comment": { + "summary": [ + { + "kind": "text", + "text": "An export with a module specifier that comes from this file." + } + ] + }, "sources": [ { "fileName": "mod.ts", 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 }; From a429a0224447a94f7ee3e35b4c49607f646b5710 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 15:58:44 -0600 Subject: [PATCH 080/151] Correct getAlias to always get unique aliases ... even if there's only one entry point. Resolves #1845 --- CHANGELOG.md | 3 ++- src/lib/models/reflections/abstract.ts | 12 +++--------- .../output/themes/default/DefaultTheme.tsx | 19 +------------------ 3 files changed, 6 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bfca3b706..af3cb08e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - `@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"`. - 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. @@ -28,7 +29,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - Removed deprecated `removeReaderByName`, `addDeclarations` and `removeDeclarationByName` methods on `Options`. -- Comments on export declarations will only overrides comments for references and namespaces, #1901. ### Features @@ -47,6 +47,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. ### Thanks! diff --git a/src/lib/models/reflections/abstract.ts b/src/lib/models/reflections/abstract.ts index ac1efb756..4e8a9c243 100644 --- a/src/lib/models/reflections/abstract.ts +++ b/src/lib/models/reflections/abstract.ts @@ -414,18 +414,12 @@ export abstract class Reflection { 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)) { diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 3af40b967..38ff98701 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -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. */ @@ -73,43 +67,36 @@ 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], - isLeaf: false, directory: "types", template: this.reflectionTemplate, }, { kind: [ReflectionKind.Function], - isLeaf: false, directory: "functions", template: this.reflectionTemplate, }, { kind: [ReflectionKind.Variable], - isLeaf: false, directory: "variables", template: this.reflectionTemplate, }, @@ -225,11 +212,7 @@ export class DefaultTheme extends Theme { } for (const child of reflection.children || []) { - if (mapping.isLeaf) { - DefaultTheme.applyAnchorUrl(child, reflection); - } else { - this.buildUrls(child, urls); - } + this.buildUrls(child, urls); } } else if (reflection.parent) { DefaultTheme.applyAnchorUrl(reflection, reflection.parent); From f06aaa98778fd4ec0662b4bde3e97e99b86c45b8 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 16:22:29 -0600 Subject: [PATCH 081/151] Update changelog for #1706 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index af3cb08e0..21f6f410c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - Removed deprecated `removeReaderByName`, `addDeclarations` and `removeDeclarationByName` methods on `Options`. +- Themes are now set on the document element rather than on body, #1706. ### Features @@ -54,6 +55,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - @fb55 - @futurGH +- @Shane4368 ## v0.22.15 (2022-04-10) From 73ddbe2d74feb4daa01cf4ff62ab676a046a7a97 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 10 Apr 2022 17:47:10 -0600 Subject: [PATCH 082/151] Make it possible to link to a signature Resolves #1326. --- .vscode/settings.json | 3 ++- CHANGELOG.md | 1 + src/lib/models/comments/index.ts | 2 +- .../output/themes/default/DefaultTheme.tsx | 20 +++++++++----- .../assets/typedoc/components/Signature.ts | 26 ++++++++++++++----- .../default/partials/member.getterSetter.tsx | 4 +-- .../default/partials/member.signatures.tsx | 4 ++- .../themes/default/partials/parameter.tsx | 2 +- static/style.css | 1 - tsconfig.json | 3 +-- 10 files changed, 44 insertions(+), 22 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 07873a75b..cf883d627 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": ["tsbuildinfo"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index 21f6f410c..56d9dc1c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - TypeDoc will now render members marked with `@deprecated` with a line through their name, #1381. - 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. ### Bug Fixes diff --git a/src/lib/models/comments/index.ts b/src/lib/models/comments/index.ts index d16cfe548..15dc5eeb4 100644 --- a/src/lib/models/comments/index.ts +++ b/src/lib/models/comments/index.ts @@ -1,2 +1,2 @@ export { Comment, CommentTag } from "./comment"; -export type { CommentDisplayPart } from "./comment"; +export type { CommentDisplayPart, InlineTagDisplayPart } from "./comment"; diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 38ff98701..608c5d102 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -7,6 +7,7 @@ import { ProjectReflection, ContainerReflection, DeclarationReflection, + SignatureReflection, } from "../../../models"; import { RenderTemplate, UrlMapping } from "../../models/UrlMapping"; import { PageEvent, RendererEvent } from "../../events"; @@ -211,9 +212,14 @@ export class DefaultTheme extends Theme { reflection.hasOwnDocument = true; } - for (const child of reflection.children || []) { - this.buildUrls(child, urls); - } + 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 +239,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 +252,7 @@ export class DefaultTheme extends Theme { } reflection.traverse((child) => { - if (child instanceof DeclarationReflection) { - DefaultTheme.applyAnchorUrl(child, container); - } + DefaultTheme.applyAnchorUrl(child, container); return true; }); } 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/partials/member.getterSetter.tsx b/src/lib/output/themes/default/partials/member.getterSetter.tsx index fc158a35e..41f829820 100644 --- a/src/lib/output/themes/default/partials/member.getterSetter.tsx +++ b/src/lib/output/themes/default/partials/member.getterSetter.tsx @@ -6,7 +6,7 @@ export const memberGetterSetter = (context: DefaultThemeRenderContext, props: De <>
    {!!props.getSignature && ( -
  • +
  • get {props.name} {context.memberSignatureTitle(props.getSignature, { hideName: true, @@ -14,7 +14,7 @@ export const memberGetterSetter = (context: DefaultThemeRenderContext, props: De
  • )} {!!props.setSignature && ( -
  • +
  • set {props.name} {context.memberSignatureTitle(props.setSignature, { hideName: true, diff --git a/src/lib/output/themes/default/partials/member.signatures.tsx b/src/lib/output/themes/default/partials/member.signatures.tsx index b58a46cf4..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/parameter.tsx b/src/lib/output/themes/default/partials/parameter.tsx index a23087189..ebc17749a 100644 --- a/src/lib/output/themes/default/partials/parameter.tsx +++ b/src/lib/output/themes/default/partials/parameter.tsx @@ -10,7 +10,7 @@ export const parameter = (context: DefaultThemeRenderContext, props: Declaration
    • {props.signatures.map((item) => ( -
    • +
    • {context.memberSignatureTitle(item, { hideName: true, })} diff --git a/static/style.css b/static/style.css index f26ca2cf3..9a6d6e3eb 100644 --- a/static/style.css +++ b/static/style.css @@ -137,7 +137,6 @@ h4, h5, h6 { line-height: 1.2; - } h1 { diff --git a/tsconfig.json b/tsconfig.json index 5cc1bedb5..ae806a39b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -53,8 +53,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": { From fe53653590e624937d16cf12f5a8953abd939f6e Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 08:41:38 -0600 Subject: [PATCH 083/151] Add a test for 1896 Resolves #1896. --- package.json | 1 + src/lib/converter/comments/index.ts | 2 +- src/test/converter2/issues/gh1896.js | 16 ++++++++++++++++ src/test/issueTests.ts | 16 ++++++++++++++++ 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/test/converter2/issues/gh1896.js diff --git a/package.json b/package.json index f1f382ec2..ad79e58eb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "scripts": { "pretest": "node scripts/copy_test_files.js", "test": "mocha -r ts-node/register --config .config/mocha.fast.json", + "build:c2": "node bin/typedoc --tsconfig src/test/converter2/tsconfig.json", "pretest:full": "npm run pretest", "test:full": "nyc 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", diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index 9c80bacc7..15be4732c 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -164,6 +164,6 @@ export function getJsDocComment( declaration ); } else { - return new Comment(tag.content); + return new Comment(tag.content.slice()); } } 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/issueTests.ts b/src/test/issueTests.ts index ecbaf50e3..328e8710c 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -436,6 +436,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); From 9ef7075178ec0ef48907ae19bd85d4a8d65b1a56 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 11:43:06 -0600 Subject: [PATCH 084/151] Serialized source references now include URL if possible --- CHANGELOG.md | 1 + scripts/rebuild_specs.js | 37 +- src/lib/converter/plugins/SourceLinkPlugin.ts | 2 +- src/lib/models/sources/file.ts | 5 +- src/lib/serialization/schema.ts | 2 +- src/test/converter/alias/specs.json | 18 +- .../class/specs-with-lump-categories.json | 351 ++++++++++++------ src/test/converter/class/specs.json | 351 ++++++++++++------ src/test/converter/comment/specs.json | 27 +- src/test/converter/declaration/specs.json | 27 +- src/test/converter/enum/specs.json | 51 ++- src/test/converter/enum/specs.nodoc.json | 51 ++- src/test/converter/exports/specs.json | 93 +++-- src/test/converter/function/specs.json | 204 ++++++---- .../converter/inherit-param-doc/specs.json | 27 +- src/test/converter/inheritance/specs.json | 69 ++-- src/test/converter/interface/specs.json | 180 ++++++--- src/test/converter/js/specs.json | 105 ++++-- src/test/converter/mixin/specs.json | 120 ++++-- src/test/converter/react/specs.json | 24 +- src/test/converter/types/specs.json | 162 +++++--- src/test/converter/variables/specs.json | 219 +++++++---- src/test/converter/variables/specs.nodoc.json | 39 +- src/test/programs.ts | 5 +- 24 files changed, 1433 insertions(+), 737 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56d9dc1c0..c209f2d52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. ### Bug Fixes diff --git a/scripts/rebuild_specs.js b/scripts/rebuild_specs.js index 6fa1a5002..20d79f3b2 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: false, - tsconfig: path.join( - __dirname, - "..", - "dist", - "test", - "converter", - "tsconfig.json" - ), + 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 = [ [ @@ -89,29 +82,23 @@ function rebuildConverterTests(dirs) { .split(TypeDoc.normalizePath(base)) .join("%BASE%"); 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/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/plugins/SourceLinkPlugin.ts index 86236ed69..47575b4bb 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/plugins/SourceLinkPlugin.ts @@ -299,7 +299,7 @@ export class SourceLinkPlugin extends ConverterComponent { for (const reflection of Object.values(project.reflections)) { if (reflection.sources) { reflection.sources.forEach((source: SourceReference) => { - if (source.file?.url) { + if (source.file.url) { source.url = source.file.url + "#" + diff --git a/src/lib/models/sources/file.ts b/src/lib/models/sources/file.ts index ce69d0979..2cc57f55d 100644 --- a/src/lib/models/sources/file.ts +++ b/src/lib/models/sources/file.ts @@ -15,7 +15,7 @@ export class SourceReference { /** * A reference to the corresponding file instance. */ - file?: SourceFile; + file: SourceFile; /** * The filename of the source file. @@ -41,7 +41,7 @@ export class SourceReference { fileName: string, line: number, character: number, - file?: SourceFile + file: SourceFile ) { this.fileName = fileName; this.line = line; @@ -54,6 +54,7 @@ export class SourceReference { fileName: this.fileName, line: this.line, character: this.character, + url: this.url, }; } } diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 2af4684e6..33537b63c 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -334,4 +334,4 @@ export type CommentDisplayPart = }; export interface SourceReference - extends S {} + extends S {} diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index a9de4e219..39aa67184 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -23,7 +23,8 @@ { "fileName": "alias.ts", "line": 14, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L14" } ], "typeParameter": [ @@ -74,7 +75,8 @@ { "fileName": "alias.ts", "line": 19, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L19" } ], "typeParameter": [ @@ -126,7 +128,8 @@ { "fileName": "alias.ts", "line": 4, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" } ], "typeParameter": [ @@ -150,7 +153,8 @@ { "fileName": "alias.ts", "line": 4, - "character": 34 + "character": 34, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" } ], "signatures": [ @@ -221,7 +225,8 @@ { "fileName": "alias.ts", "line": 9, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L9" } ], "type": { @@ -255,7 +260,8 @@ { "fileName": "alias.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" } ] } \ No newline at end of file diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 2976b6eb1..5a85be5d4 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -48,7 +48,8 @@ { "fileName": "access.ts", "line": 34, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L34" } ], "type": { @@ -76,7 +77,8 @@ { "fileName": "access.ts", "line": 40, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L40" } ], "type": { @@ -97,7 +99,8 @@ { "fileName": "access.ts", "line": 59, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L59" } ], "getSignature": [ @@ -126,7 +129,8 @@ { "fileName": "access.ts", "line": 46, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L46" } ], "signatures": [ @@ -165,7 +169,8 @@ { "fileName": "access.ts", "line": 52, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L52" } ], "signatures": [ @@ -204,7 +209,8 @@ { "fileName": "access.ts", "line": 54, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L54" } ], "signatures": [ @@ -252,7 +258,8 @@ { "fileName": "access.ts", "line": 29, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L29" } ] }, @@ -277,7 +284,8 @@ { "fileName": "access.ts", "line": 5, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" } ], "type": { @@ -307,7 +315,8 @@ { "fileName": "access.ts", "line": 11, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L11" } ], "type": { @@ -328,7 +337,8 @@ { "fileName": "access.ts", "line": 17, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L17" } ], "signatures": [ @@ -367,7 +377,8 @@ { "fileName": "access.ts", "line": 23, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L23" } ], "signatures": [ @@ -424,7 +435,8 @@ { "fileName": "access.ts", "line": 5, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" } ] }, @@ -452,7 +464,8 @@ { "fileName": "class.ts", "line": 108, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L108" } ], "signatures": [ @@ -491,17 +504,20 @@ { "fileName": "class.ts", "line": 61, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" }, { "fileName": "class.ts", "line": 97, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" }, { "fileName": "class.ts", "line": 104, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" } ] }, @@ -547,7 +563,8 @@ { "fileName": "class.ts", "line": 126, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L126" } ], "signatures": [ @@ -585,7 +602,8 @@ { "fileName": "class.ts", "line": 125, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L125" } ] }, @@ -627,7 +645,8 @@ { "fileName": "class.ts", "line": 114, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L114" } ], "type": { @@ -646,7 +665,8 @@ { "fileName": "class.ts", "line": 115, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L115" } ], "type": { @@ -665,7 +685,8 @@ { "fileName": "class.ts", "line": 116, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L116" } ], "type": { @@ -684,7 +705,8 @@ { "fileName": "class.ts", "line": 117, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L117" } ], "type": { @@ -717,7 +739,8 @@ { "fileName": "class.ts", "line": 113, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L113" } ] }, @@ -763,7 +786,8 @@ { "fileName": "class.ts", "line": 86, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L86" } ], "type": { @@ -784,7 +808,8 @@ { "fileName": "class.ts", "line": 88, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L88" } ], "signatures": [ @@ -829,7 +854,8 @@ { "fileName": "class.ts", "line": 85, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L85" } ], "extendedBy": [ @@ -888,7 +914,8 @@ { "fileName": "class.ts", "line": 92, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L92" } ], "type": { @@ -913,7 +940,8 @@ { "fileName": "class.ts", "line": 94, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L94" } ], "signatures": [ @@ -968,7 +996,8 @@ { "fileName": "class.ts", "line": 91, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L91" } ], "extendedTypes": [ @@ -1021,7 +1050,8 @@ { "fileName": "class.ts", "line": 27, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L27" } ], "signatures": [ @@ -1067,7 +1097,8 @@ { "fileName": "class.ts", "line": 17, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L17" } ], "type": { @@ -1098,7 +1129,8 @@ { "fileName": "class.ts", "line": 12, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" } ], "type": { @@ -1126,7 +1158,8 @@ { "fileName": "class.ts", "line": 22, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" } ], "type": { @@ -1145,7 +1178,8 @@ { "fileName": "class.ts", "line": 58, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" } ], "signatures": [ @@ -1182,7 +1216,8 @@ { "fileName": "class.ts", "line": 48, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L48" } ], "signatures": [ @@ -1219,7 +1254,8 @@ { "fileName": "class.ts", "line": 41, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L41" } ], "signatures": [ @@ -1256,7 +1292,8 @@ { "fileName": "class.ts", "line": 34, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L34" } ], "signatures": [ @@ -1293,7 +1330,8 @@ { "fileName": "class.ts", "line": 53, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" } ], "signatures": [ @@ -1380,7 +1418,8 @@ { "fileName": "class.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" } ], "extendedBy": [ @@ -1408,7 +1447,8 @@ { "fileName": "class.ts", "line": 80, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "signatures": [ @@ -1534,7 +1574,8 @@ { "fileName": "class.ts", "line": 80, - "character": 47 + "character": 47, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "type": { @@ -1554,7 +1595,8 @@ { "fileName": "class.ts", "line": 80, - "character": 66 + "character": 66, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "type": { @@ -1582,7 +1624,8 @@ { "fileName": "class.ts", "line": 12, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" } ], "type": { @@ -1615,7 +1658,8 @@ { "fileName": "class.ts", "line": 22, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" } ], "type": { @@ -1639,7 +1683,8 @@ { "fileName": "class.ts", "line": 58, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" } ], "signatures": [ @@ -1684,7 +1729,8 @@ { "fileName": "class.ts", "line": 101, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L101" } ], "signatures": [ @@ -1721,7 +1767,8 @@ { "fileName": "class.ts", "line": 70, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L70" } ], "signatures": [ @@ -1768,7 +1815,8 @@ { "fileName": "class.ts", "line": 65, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L65" } ], "signatures": [ @@ -1815,7 +1863,8 @@ { "fileName": "class.ts", "line": 53, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" } ], "signatures": [ @@ -1885,17 +1934,20 @@ { "fileName": "class.ts", "line": 61, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" }, { "fileName": "class.ts", "line": 97, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" }, { "fileName": "class.ts", "line": 104, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" } ], "extendedTypes": [ @@ -1954,7 +2006,8 @@ { "fileName": "class.ts", "line": 122, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L122" } ], "type": { @@ -1984,7 +2037,8 @@ { "fileName": "class.ts", "line": 120, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L120" } ] }, @@ -1998,7 +2052,8 @@ { "fileName": "class.ts", "line": 130, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" } ], "type": { @@ -2013,7 +2068,8 @@ { "fileName": "class.ts", "line": 130, - "character": 25 + "character": 25, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" } ], "signatures": [ @@ -2069,7 +2125,8 @@ { "fileName": "class.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" } ] }, @@ -2105,7 +2162,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "signatures": [ @@ -2194,7 +2252,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 61 + "character": 61, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2214,7 +2273,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2234,7 +2294,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 41 + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2265,7 +2326,8 @@ { "fileName": "constructor-properties.ts", "line": 4, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" } ], "extendedBy": [ @@ -2301,7 +2363,8 @@ { "fileName": "constructor-properties.ts", "line": 23, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L23" } ], "signatures": [ @@ -2419,7 +2482,8 @@ { "fileName": "constructor-properties.ts", "line": 27, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L27" } ], "type": { @@ -2444,7 +2508,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2469,7 +2534,8 @@ { "fileName": "constructor-properties.ts", "line": 25, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L25" } ], "type": { @@ -2494,7 +2560,8 @@ { "fileName": "constructor-properties.ts", "line": 26, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L26" } ], "type": { @@ -2526,7 +2593,8 @@ { "fileName": "constructor-properties.ts", "line": 16, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L16" } ], "extendedTypes": [ @@ -2552,7 +2620,8 @@ { "fileName": "constructor-properties.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" } ] }, @@ -2609,7 +2678,8 @@ { "fileName": "decorators.ts", "line": 13, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L13" } ], "signatures": [ @@ -2655,7 +2725,8 @@ { "fileName": "decorators.ts", "line": 7, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L7" } ] }, @@ -2669,7 +2740,8 @@ { "fileName": "decorators.ts", "line": 19, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L19" } ], "signatures": [ @@ -2758,7 +2830,8 @@ { "fileName": "decorators.ts", "line": 48, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ], "signatures": [ @@ -2818,7 +2891,8 @@ { "fileName": "decorators.ts", "line": 49, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L49" } ], "type": { @@ -2840,7 +2914,8 @@ { "fileName": "decorators.ts", "line": 48, - "character": 46 + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ] } @@ -2866,7 +2941,8 @@ { "fileName": "decorators.ts", "line": 32, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L32" } ], "signatures": [ @@ -2937,7 +3013,8 @@ { "fileName": "decorators.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L4" } ] }, @@ -2996,7 +3073,8 @@ { "fileName": "events.ts", "line": 6, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L6" } ], "type": { @@ -3026,7 +3104,8 @@ { "fileName": "events.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" } ] } @@ -3044,7 +3123,8 @@ { "fileName": "events.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" } ] }, @@ -3091,22 +3171,26 @@ { "fileName": "events-overloads.ts", "line": 14, - "character": 4 + "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 + "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 + "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 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" } ], "signatures": [ @@ -3170,7 +3254,8 @@ { "fileName": "events-overloads.ts", "line": 14, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" } ], "signatures": [ @@ -3268,7 +3353,8 @@ { "fileName": "events-overloads.ts", "line": 23, - "character": 32 + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" } ], "signatures": [ @@ -3366,7 +3452,8 @@ { "fileName": "events-overloads.ts", "line": 32, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" } ], "signatures": [ @@ -3464,7 +3551,8 @@ { "fileName": "events-overloads.ts", "line": 41, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" } ], "signatures": [ @@ -3518,7 +3606,8 @@ { "fileName": "events-overloads.ts", "line": 6, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" } ] } @@ -3536,7 +3625,8 @@ { "fileName": "events-overloads.ts", "line": 6, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" } ] }, @@ -3572,7 +3662,8 @@ { "fileName": "generic-class.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" } ], "signatures": [ @@ -3656,7 +3747,8 @@ { "fileName": "generic-class.ts", "line": 9, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" } ], "type": { @@ -3685,7 +3777,8 @@ { "fileName": "generic-class.ts", "line": 14, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" } ], "type": { @@ -3707,7 +3800,8 @@ { "fileName": "generic-class.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" } ], "signatures": [ @@ -3773,7 +3867,8 @@ { "fileName": "generic-class.ts", "line": 5, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ], "typeParameter": [ @@ -3826,7 +3921,8 @@ { "fileName": "generic-class.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" } ], "signatures": [ @@ -3903,7 +3999,8 @@ { "fileName": "generic-class.ts", "line": 9, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" } ], "type": { @@ -3936,7 +4033,8 @@ { "fileName": "generic-class.ts", "line": 14, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" } ], "type": { @@ -3962,7 +4060,8 @@ { "fileName": "generic-class.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" } ], "signatures": [ @@ -4037,7 +4136,8 @@ { "fileName": "generic-class.ts", "line": 36, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L36" } ], "extendedTypes": [ @@ -4069,7 +4169,8 @@ { "fileName": "generic-class.ts", "line": 5, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ] }, @@ -4120,7 +4221,8 @@ { "fileName": "getter-setter.ts", "line": 2, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L2" } ], "type": { @@ -4138,12 +4240,14 @@ { "fileName": "getter-setter.ts", "line": 4, - "character": 8 + "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 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], "getSignature": [ @@ -4196,7 +4300,8 @@ { "fileName": "getter-setter.ts", "line": 11, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L11" } ], "getSignature": [ @@ -4223,7 +4328,8 @@ { "fileName": "getter-setter.ts", "line": 15, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L15" } ], "setSignature": [ @@ -4283,7 +4389,8 @@ { "fileName": "getter-setter.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" } ] } @@ -4301,7 +4408,8 @@ { "fileName": "getter-setter.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" } ] }, @@ -4360,7 +4468,8 @@ { "fileName": "this.ts", "line": 10, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L10" } ], "signatures": [ @@ -4407,7 +4516,8 @@ { "fileName": "this.ts", "line": 6, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" } ] } @@ -4425,7 +4535,8 @@ { "fileName": "this.ts", "line": 6, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" } ] }, @@ -4499,7 +4610,8 @@ { "fileName": "type-operator.ts", "line": 14, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L14" } ], "type": { @@ -4529,7 +4641,8 @@ { "fileName": "type-operator.ts", "line": 13, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" } ], "typeParameter": [ @@ -4614,7 +4727,8 @@ { "fileName": "type-operator.ts", "line": 9, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L9" } ], "type": { @@ -4632,7 +4746,8 @@ { "fileName": "type-operator.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L10" } ], "type": { @@ -4662,7 +4777,8 @@ { "fileName": "type-operator.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" } ] } @@ -4681,7 +4797,8 @@ { "fileName": "type-operator.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" } ] } diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index b0ec7b63e..8ccaa7560 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -48,7 +48,8 @@ { "fileName": "access.ts", "line": 34, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L34" } ], "type": { @@ -76,7 +77,8 @@ { "fileName": "access.ts", "line": 40, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L40" } ], "type": { @@ -97,7 +99,8 @@ { "fileName": "access.ts", "line": 59, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L59" } ], "getSignature": [ @@ -126,7 +129,8 @@ { "fileName": "access.ts", "line": 46, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L46" } ], "signatures": [ @@ -165,7 +169,8 @@ { "fileName": "access.ts", "line": 52, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L52" } ], "signatures": [ @@ -204,7 +209,8 @@ { "fileName": "access.ts", "line": 54, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L54" } ], "signatures": [ @@ -252,7 +258,8 @@ { "fileName": "access.ts", "line": 29, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L29" } ] }, @@ -277,7 +284,8 @@ { "fileName": "access.ts", "line": 5, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" } ], "type": { @@ -307,7 +315,8 @@ { "fileName": "access.ts", "line": 11, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L11" } ], "type": { @@ -328,7 +337,8 @@ { "fileName": "access.ts", "line": 17, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L17" } ], "signatures": [ @@ -367,7 +377,8 @@ { "fileName": "access.ts", "line": 23, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L23" } ], "signatures": [ @@ -424,7 +435,8 @@ { "fileName": "access.ts", "line": 5, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/access.ts#L5" } ] }, @@ -452,7 +464,8 @@ { "fileName": "class.ts", "line": 108, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L108" } ], "signatures": [ @@ -491,17 +504,20 @@ { "fileName": "class.ts", "line": 61, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" }, { "fileName": "class.ts", "line": 97, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" }, { "fileName": "class.ts", "line": 104, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" } ] }, @@ -547,7 +563,8 @@ { "fileName": "class.ts", "line": 126, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L126" } ], "signatures": [ @@ -585,7 +602,8 @@ { "fileName": "class.ts", "line": 125, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L125" } ] }, @@ -627,7 +645,8 @@ { "fileName": "class.ts", "line": 114, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L114" } ], "type": { @@ -646,7 +665,8 @@ { "fileName": "class.ts", "line": 115, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L115" } ], "type": { @@ -665,7 +685,8 @@ { "fileName": "class.ts", "line": 116, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L116" } ], "type": { @@ -684,7 +705,8 @@ { "fileName": "class.ts", "line": 117, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L117" } ], "type": { @@ -717,7 +739,8 @@ { "fileName": "class.ts", "line": 113, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L113" } ] }, @@ -763,7 +786,8 @@ { "fileName": "class.ts", "line": 86, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L86" } ], "type": { @@ -784,7 +808,8 @@ { "fileName": "class.ts", "line": 88, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L88" } ], "signatures": [ @@ -829,7 +854,8 @@ { "fileName": "class.ts", "line": 85, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L85" } ], "extendedBy": [ @@ -888,7 +914,8 @@ { "fileName": "class.ts", "line": 92, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L92" } ], "type": { @@ -913,7 +940,8 @@ { "fileName": "class.ts", "line": 94, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L94" } ], "signatures": [ @@ -968,7 +996,8 @@ { "fileName": "class.ts", "line": 91, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L91" } ], "extendedTypes": [ @@ -1021,7 +1050,8 @@ { "fileName": "class.ts", "line": 27, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L27" } ], "signatures": [ @@ -1067,7 +1097,8 @@ { "fileName": "class.ts", "line": 17, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L17" } ], "type": { @@ -1098,7 +1129,8 @@ { "fileName": "class.ts", "line": 12, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" } ], "type": { @@ -1126,7 +1158,8 @@ { "fileName": "class.ts", "line": 22, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" } ], "type": { @@ -1145,7 +1178,8 @@ { "fileName": "class.ts", "line": 58, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" } ], "signatures": [ @@ -1182,7 +1216,8 @@ { "fileName": "class.ts", "line": 48, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L48" } ], "signatures": [ @@ -1219,7 +1254,8 @@ { "fileName": "class.ts", "line": 41, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L41" } ], "signatures": [ @@ -1256,7 +1292,8 @@ { "fileName": "class.ts", "line": 34, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L34" } ], "signatures": [ @@ -1293,7 +1330,8 @@ { "fileName": "class.ts", "line": 53, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" } ], "signatures": [ @@ -1376,7 +1414,8 @@ { "fileName": "class.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" } ], "extendedBy": [ @@ -1404,7 +1443,8 @@ { "fileName": "class.ts", "line": 80, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "signatures": [ @@ -1530,7 +1570,8 @@ { "fileName": "class.ts", "line": 80, - "character": 47 + "character": 47, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "type": { @@ -1550,7 +1591,8 @@ { "fileName": "class.ts", "line": 80, - "character": 66 + "character": 66, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L80" } ], "type": { @@ -1578,7 +1620,8 @@ { "fileName": "class.ts", "line": 12, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L12" } ], "type": { @@ -1611,7 +1654,8 @@ { "fileName": "class.ts", "line": 22, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L22" } ], "type": { @@ -1635,7 +1679,8 @@ { "fileName": "class.ts", "line": 58, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L58" } ], "signatures": [ @@ -1680,7 +1725,8 @@ { "fileName": "class.ts", "line": 101, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L101" } ], "signatures": [ @@ -1717,7 +1763,8 @@ { "fileName": "class.ts", "line": 70, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L70" } ], "signatures": [ @@ -1764,7 +1811,8 @@ { "fileName": "class.ts", "line": 65, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L65" } ], "signatures": [ @@ -1811,7 +1859,8 @@ { "fileName": "class.ts", "line": 53, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L53" } ], "signatures": [ @@ -1881,17 +1930,20 @@ { "fileName": "class.ts", "line": 61, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L61" }, { "fileName": "class.ts", "line": 97, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L97" }, { "fileName": "class.ts", "line": 104, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L104" } ], "extendedTypes": [ @@ -1950,7 +2002,8 @@ { "fileName": "class.ts", "line": 122, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L122" } ], "type": { @@ -1980,7 +2033,8 @@ { "fileName": "class.ts", "line": 120, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L120" } ] }, @@ -1994,7 +2048,8 @@ { "fileName": "class.ts", "line": 130, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" } ], "type": { @@ -2009,7 +2064,8 @@ { "fileName": "class.ts", "line": 130, - "character": 25 + "character": 25, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L130" } ], "signatures": [ @@ -2065,7 +2121,8 @@ { "fileName": "class.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/class.ts#L8" } ] }, @@ -2101,7 +2158,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "signatures": [ @@ -2190,7 +2248,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 61 + "character": 61, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2210,7 +2269,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2230,7 +2290,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 41 + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2261,7 +2322,8 @@ { "fileName": "constructor-properties.ts", "line": 4, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" } ], "extendedBy": [ @@ -2297,7 +2359,8 @@ { "fileName": "constructor-properties.ts", "line": 23, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L23" } ], "signatures": [ @@ -2415,7 +2478,8 @@ { "fileName": "constructor-properties.ts", "line": 27, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L27" } ], "type": { @@ -2440,7 +2504,8 @@ { "fileName": "constructor-properties.ts", "line": 10, - "character": 23 + "character": 23, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L10" } ], "type": { @@ -2465,7 +2530,8 @@ { "fileName": "constructor-properties.ts", "line": 25, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L25" } ], "type": { @@ -2490,7 +2556,8 @@ { "fileName": "constructor-properties.ts", "line": 26, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L26" } ], "type": { @@ -2522,7 +2589,8 @@ { "fileName": "constructor-properties.ts", "line": 16, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L16" } ], "extendedTypes": [ @@ -2548,7 +2616,8 @@ { "fileName": "constructor-properties.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/constructor-properties.ts#L4" } ] }, @@ -2605,7 +2674,8 @@ { "fileName": "decorators.ts", "line": 13, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L13" } ], "signatures": [ @@ -2651,7 +2721,8 @@ { "fileName": "decorators.ts", "line": 7, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L7" } ] }, @@ -2665,7 +2736,8 @@ { "fileName": "decorators.ts", "line": 19, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L19" } ], "signatures": [ @@ -2754,7 +2826,8 @@ { "fileName": "decorators.ts", "line": 48, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ], "signatures": [ @@ -2814,7 +2887,8 @@ { "fileName": "decorators.ts", "line": 49, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L49" } ], "type": { @@ -2836,7 +2910,8 @@ { "fileName": "decorators.ts", "line": 48, - "character": 46 + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L48" } ] } @@ -2862,7 +2937,8 @@ { "fileName": "decorators.ts", "line": 32, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L32" } ], "signatures": [ @@ -2933,7 +3009,8 @@ { "fileName": "decorators.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/decorators.ts#L4" } ] }, @@ -2992,7 +3069,8 @@ { "fileName": "events.ts", "line": 6, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L6" } ], "type": { @@ -3022,7 +3100,8 @@ { "fileName": "events.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" } ] } @@ -3040,7 +3119,8 @@ { "fileName": "events.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events.ts#L1" } ] }, @@ -3087,22 +3167,26 @@ { "fileName": "events-overloads.ts", "line": 14, - "character": 4 + "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 + "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 + "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 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" } ], "signatures": [ @@ -3166,7 +3250,8 @@ { "fileName": "events-overloads.ts", "line": 14, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L14" } ], "signatures": [ @@ -3264,7 +3349,8 @@ { "fileName": "events-overloads.ts", "line": 23, - "character": 32 + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L23" } ], "signatures": [ @@ -3362,7 +3448,8 @@ { "fileName": "events-overloads.ts", "line": 32, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L32" } ], "signatures": [ @@ -3460,7 +3547,8 @@ { "fileName": "events-overloads.ts", "line": 41, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L41" } ], "signatures": [ @@ -3514,7 +3602,8 @@ { "fileName": "events-overloads.ts", "line": 6, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" } ] } @@ -3532,7 +3621,8 @@ { "fileName": "events-overloads.ts", "line": 6, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/events-overloads.ts#L6" } ] }, @@ -3568,7 +3658,8 @@ { "fileName": "generic-class.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" } ], "signatures": [ @@ -3652,7 +3743,8 @@ { "fileName": "generic-class.ts", "line": 9, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" } ], "type": { @@ -3681,7 +3773,8 @@ { "fileName": "generic-class.ts", "line": 14, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" } ], "type": { @@ -3703,7 +3796,8 @@ { "fileName": "generic-class.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" } ], "signatures": [ @@ -3769,7 +3863,8 @@ { "fileName": "generic-class.ts", "line": 5, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ], "typeParameter": [ @@ -3822,7 +3917,8 @@ { "fileName": "generic-class.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L20" } ], "signatures": [ @@ -3899,7 +3995,8 @@ { "fileName": "generic-class.ts", "line": 9, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L9" } ], "type": { @@ -3932,7 +4029,8 @@ { "fileName": "generic-class.ts", "line": 14, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L14" } ], "type": { @@ -3958,7 +4056,8 @@ { "fileName": "generic-class.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L28" } ], "signatures": [ @@ -4033,7 +4132,8 @@ { "fileName": "generic-class.ts", "line": 36, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L36" } ], "extendedTypes": [ @@ -4065,7 +4165,8 @@ { "fileName": "generic-class.ts", "line": 5, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ] }, @@ -4116,7 +4217,8 @@ { "fileName": "getter-setter.ts", "line": 2, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L2" } ], "type": { @@ -4134,12 +4236,14 @@ { "fileName": "getter-setter.ts", "line": 4, - "character": 8 + "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 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], "getSignature": [ @@ -4192,7 +4296,8 @@ { "fileName": "getter-setter.ts", "line": 11, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L11" } ], "getSignature": [ @@ -4219,7 +4324,8 @@ { "fileName": "getter-setter.ts", "line": 15, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L15" } ], "setSignature": [ @@ -4279,7 +4385,8 @@ { "fileName": "getter-setter.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" } ] } @@ -4297,7 +4404,8 @@ { "fileName": "getter-setter.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L1" } ] }, @@ -4356,7 +4464,8 @@ { "fileName": "this.ts", "line": 10, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L10" } ], "signatures": [ @@ -4403,7 +4512,8 @@ { "fileName": "this.ts", "line": 6, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" } ] } @@ -4421,7 +4531,8 @@ { "fileName": "this.ts", "line": 6, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/this.ts#L6" } ] }, @@ -4495,7 +4606,8 @@ { "fileName": "type-operator.ts", "line": 14, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L14" } ], "type": { @@ -4525,7 +4637,8 @@ { "fileName": "type-operator.ts", "line": 13, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" } ], "typeParameter": [ @@ -4610,7 +4723,8 @@ { "fileName": "type-operator.ts", "line": 9, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L9" } ], "type": { @@ -4628,7 +4742,8 @@ { "fileName": "type-operator.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L10" } ], "type": { @@ -4658,7 +4773,8 @@ { "fileName": "type-operator.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" } ] } @@ -4677,7 +4793,8 @@ { "fileName": "type-operator.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L8" } ] } diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index 8d5cc76e6..d5f550c7a 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -83,7 +83,8 @@ { "fileName": "comment.ts", "line": 37, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L37" } ], "type": { @@ -171,7 +172,8 @@ { "fileName": "comment.ts", "line": 33, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L33" } ] } @@ -189,7 +191,8 @@ { "fileName": "comment.ts", "line": 5, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment.ts#L5" } ] }, @@ -226,7 +229,8 @@ { "fileName": "comment2.ts", "line": 8, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment2.ts#L8" } ], "signatures": [ @@ -300,7 +304,8 @@ { "fileName": "comment2.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment2.ts#L8" } ] }, @@ -337,7 +342,8 @@ { "fileName": "comment3.ts", "line": 8, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment3.ts#L8" } ], "signatures": [ @@ -414,7 +420,8 @@ { "fileName": "comment3.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment3.ts#L8" } ] }, @@ -447,7 +454,8 @@ { "fileName": "comment4.ts", "line": 11, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment4.ts#L11" } ], "signatures": [ @@ -520,7 +528,8 @@ { "fileName": "comment4.ts", "line": 11, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/comment/comment4.ts#L11" } ] } diff --git a/src/test/converter/declaration/specs.json b/src/test/converter/declaration/specs.json index 50e54554b..1358bf621 100644 --- a/src/test/converter/declaration/specs.json +++ b/src/test/converter/declaration/specs.json @@ -49,7 +49,8 @@ { "fileName": "declaration.d.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L2" } ], "type": { @@ -78,7 +79,8 @@ { "fileName": "declaration.d.ts", "line": 1, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L1" } ] }, @@ -94,7 +96,8 @@ { "fileName": "declaration.d.ts", "line": 5, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L5" } ], "type": { @@ -123,7 +126,8 @@ { "fileName": "declaration.d.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/declaration.d.ts#L1" } ] }, @@ -176,7 +180,8 @@ { "fileName": "export-declaration.d.ts", "line": 1, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L1" } ] }, @@ -222,7 +227,8 @@ { "fileName": "export-declaration.d.ts", "line": 3, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L3" } ] } @@ -241,7 +247,8 @@ { "fileName": "export-declaration.d.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/export-declaration.d.ts#L1" } ] }, @@ -264,7 +271,8 @@ { "fileName": "external.d.ts", "line": 3, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/external.d.ts#L3" } ], "type": { @@ -288,7 +296,8 @@ { "fileName": "external.d.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/declaration/external.d.ts#L1" } ] } diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index 56bfbe676..90bfcb313 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -38,7 +38,8 @@ { "fileName": "enum.ts", "line": 48, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L48" } ], "type": { @@ -56,7 +57,8 @@ { "fileName": "enum.ts", "line": 53, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L53" } ], "signatures": [ @@ -102,12 +104,14 @@ { "fileName": "enum.ts", "line": 24, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" }, { "fileName": "enum.ts", "line": 44, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" } ] }, @@ -138,7 +142,8 @@ { "fileName": "enum.ts", "line": 60, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L60" } ], "defaultValue": "1" @@ -153,7 +158,8 @@ { "fileName": "enum.ts", "line": 61, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L61" } ], "defaultValue": "2" @@ -173,7 +179,8 @@ { "fileName": "enum.ts", "line": 59, - "character": 18 + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L59" } ] }, @@ -210,7 +217,8 @@ { "fileName": "enum.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L28" } ], "defaultValue": "1" @@ -233,7 +241,8 @@ { "fileName": "enum.ts", "line": 33, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L33" } ], "defaultValue": "2" @@ -256,7 +265,8 @@ { "fileName": "enum.ts", "line": 38, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L38" } ], "defaultValue": "4" @@ -277,12 +287,14 @@ { "fileName": "enum.ts", "line": 24, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" }, { "fileName": "enum.ts", "line": 44, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" } ] }, @@ -319,7 +331,8 @@ { "fileName": "enum.ts", "line": 8, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L8" } ], "defaultValue": "1" @@ -342,7 +355,8 @@ { "fileName": "enum.ts", "line": 13, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L13" } ], "defaultValue": "2" @@ -365,7 +379,8 @@ { "fileName": "enum.ts", "line": 18, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L18" } ], "defaultValue": "4" @@ -386,7 +401,8 @@ { "fileName": "enum.ts", "line": 4, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] } @@ -413,7 +429,8 @@ { "fileName": "enum.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] } \ No newline at end of file diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index 56bfbe676..90bfcb313 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -38,7 +38,8 @@ { "fileName": "enum.ts", "line": 48, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L48" } ], "type": { @@ -56,7 +57,8 @@ { "fileName": "enum.ts", "line": 53, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L53" } ], "signatures": [ @@ -102,12 +104,14 @@ { "fileName": "enum.ts", "line": 24, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" }, { "fileName": "enum.ts", "line": 44, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" } ] }, @@ -138,7 +142,8 @@ { "fileName": "enum.ts", "line": 60, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L60" } ], "defaultValue": "1" @@ -153,7 +158,8 @@ { "fileName": "enum.ts", "line": 61, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L61" } ], "defaultValue": "2" @@ -173,7 +179,8 @@ { "fileName": "enum.ts", "line": 59, - "character": 18 + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L59" } ] }, @@ -210,7 +217,8 @@ { "fileName": "enum.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L28" } ], "defaultValue": "1" @@ -233,7 +241,8 @@ { "fileName": "enum.ts", "line": 33, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L33" } ], "defaultValue": "2" @@ -256,7 +265,8 @@ { "fileName": "enum.ts", "line": 38, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L38" } ], "defaultValue": "4" @@ -277,12 +287,14 @@ { "fileName": "enum.ts", "line": 24, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L24" }, { "fileName": "enum.ts", "line": 44, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L44" } ] }, @@ -319,7 +331,8 @@ { "fileName": "enum.ts", "line": 8, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L8" } ], "defaultValue": "1" @@ -342,7 +355,8 @@ { "fileName": "enum.ts", "line": 13, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L13" } ], "defaultValue": "2" @@ -365,7 +379,8 @@ { "fileName": "enum.ts", "line": 18, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L18" } ], "defaultValue": "4" @@ -386,7 +401,8 @@ { "fileName": "enum.ts", "line": 4, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] } @@ -413,7 +429,8 @@ { "fileName": "enum.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] } \ No newline at end of file diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 2557b4027..997b0381e 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -21,7 +21,8 @@ { "fileName": "mod.ts", "line": 42, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L42" } ], "target": 35 @@ -36,7 +37,8 @@ { "fileName": "export.ts", "line": 5, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" } ], "target": 29 @@ -59,7 +61,8 @@ { "fileName": "export.ts", "line": 14, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L14" } ], "target": 29 @@ -74,7 +77,8 @@ { "fileName": "export.ts", "line": 5, - "character": 27 + "character": 27, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" } ], "target": 36 @@ -89,7 +93,8 @@ { "fileName": "mod.ts", "line": 40, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L40" } ], "target": 34 @@ -104,7 +109,8 @@ { "fileName": "mod.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" } ], "target": 30 @@ -127,7 +133,8 @@ { "fileName": "mod.ts", "line": 13, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" } ], "target": 31 @@ -142,7 +149,8 @@ { "fileName": "export.ts", "line": 5, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L5" } ], "target": 30 @@ -164,7 +172,8 @@ { "fileName": "export.ts", "line": 31, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L31" } ], "type": { @@ -185,7 +194,8 @@ { "fileName": "export.ts", "line": 28, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L28" } ], "type": { @@ -206,7 +216,8 @@ { "fileName": "export.ts", "line": 26, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L26" } ], "type": { @@ -228,7 +239,8 @@ { "fileName": "export.ts", "line": 29, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L29" } ], "type": { @@ -250,7 +262,8 @@ { "fileName": "export.ts", "line": 27, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L27" } ], "type": { @@ -284,7 +297,8 @@ { "fileName": "export.ts", "line": 25, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L25" } ] }, @@ -298,7 +312,8 @@ { "fileName": "export.ts", "line": 7, - "character": 9 + "character": 9, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L7" } ], "signatures": [ @@ -349,7 +364,8 @@ { "fileName": "export.ts", "line": 18, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L18" } ], "signatures": [ @@ -415,7 +431,8 @@ { "fileName": "export.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export.ts#L1" } ] }, @@ -436,7 +453,8 @@ { "fileName": "export-assignment.ts", "line": 1, - "character": 9 + "character": 9, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-assignment.ts#L1" } ], "signatures": [ @@ -491,7 +509,8 @@ { "fileName": "export-assignment.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-assignment.ts#L1" } ] }, @@ -514,7 +533,8 @@ { "fileName": "export-default.ts", "line": 1, - "character": 6 + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-default.ts#L1" } ], "type": { @@ -537,7 +557,8 @@ { "fileName": "export-default.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-default.ts#L1" } ] }, @@ -560,7 +581,8 @@ { "fileName": "export-with-local.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L1" } ], "type": { @@ -579,7 +601,8 @@ { "fileName": "export-with-local.ts", "line": 6, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L6" } ], "signatures": [ @@ -641,7 +664,8 @@ { "fileName": "export-with-local.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/export-with-local.ts#L1" } ] }, @@ -662,7 +686,8 @@ { "fileName": "mod.ts", "line": 40, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L40" } ], "target": 29 @@ -685,7 +710,8 @@ { "fileName": "mod.ts", "line": 13, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L13" } ], "target": 30 @@ -708,7 +734,8 @@ { "fileName": "mod.ts", "line": 18, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L18" } ], "target": 30 @@ -723,7 +750,8 @@ { "fileName": "mod.ts", "line": 42, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L42" } ], "type": { @@ -751,7 +779,8 @@ { "fileName": "mod.ts", "line": 8, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" } ], "type": { @@ -770,7 +799,8 @@ { "fileName": "mod.ts", "line": 23, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L23" } ], "signatures": [ @@ -832,7 +862,8 @@ { "fileName": "mod.ts", "line": 8, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/exports/mod.ts#L8" } ] } diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 32ea26388..9d60cb1c8 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -28,7 +28,8 @@ { "fileName": "function.ts", "line": 305, - "character": 7 + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" } ], "signatures": [ @@ -59,12 +60,14 @@ { "fileName": "function.ts", "line": 304, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L304" }, { "fileName": "function.ts", "line": 305, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" } ] }, @@ -101,7 +104,8 @@ { "fileName": "function.ts", "line": 264, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L264" } ], "type": { @@ -119,7 +123,8 @@ { "fileName": "function.ts", "line": 269, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L269" } ], "signatures": [ @@ -154,7 +159,8 @@ { "fileName": "function.ts", "line": 274, - "character": 20 + "character": 20, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L274" } ], "signatures": [ @@ -201,12 +207,14 @@ { "fileName": "function.ts", "line": 218, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L218" }, { "fileName": "function.ts", "line": 260, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L260" } ] }, @@ -248,7 +256,8 @@ { "fileName": "function.ts", "line": 285, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L285" } ], "signatures": [ @@ -280,7 +289,8 @@ { "fileName": "function.ts", "line": 281, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L281" } ], "signatures": [ @@ -314,7 +324,8 @@ { "fileName": "function.ts", "line": 284, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L284" } ], "signatures": [ @@ -357,7 +368,8 @@ { "fileName": "function.ts", "line": 278, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L278" } ], "signatures": [ @@ -416,7 +428,8 @@ { "fileName": "function.ts", "line": 277, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L277" } ] }, @@ -430,7 +443,8 @@ { "fileName": "function.ts", "line": 293, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L293" } ], "signatures": [ @@ -468,7 +482,8 @@ { "fileName": "function.ts", "line": 294, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L294" } ], "signatures": [ @@ -561,7 +576,8 @@ { "fileName": "function.ts", "line": 295, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L295" } ], "signatures": [ @@ -607,7 +623,8 @@ { "fileName": "function.ts", "line": 295, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L295" } ], "signatures": [ @@ -660,7 +677,8 @@ { "fileName": "function.ts", "line": 241, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L241" } ], "signatures": [ @@ -737,7 +755,8 @@ { "fileName": "function.ts", "line": 227, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L227" } ], "signatures": [ @@ -794,7 +813,8 @@ { "fileName": "function.ts", "line": 298, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L298" } ], "signatures": [ @@ -843,7 +863,8 @@ { "fileName": "function.ts", "line": 233, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L233" } ], "signatures": [ @@ -896,7 +917,8 @@ { "fileName": "function.ts", "line": 4, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L4" } ], "signatures": [ @@ -931,7 +953,8 @@ { "fileName": "function.ts", "line": 100, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L100" } ], "signatures": [ @@ -1007,7 +1030,8 @@ { "fileName": "function.ts", "line": 107, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L107" } ], "type": { @@ -1035,7 +1059,8 @@ { "fileName": "function.ts", "line": 106, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L106" } ], "type": { @@ -1061,7 +1086,8 @@ { "fileName": "function.ts", "line": 105, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L105" } ], "type": { @@ -1085,7 +1111,8 @@ { "fileName": "function.ts", "line": 104, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L104" } ] } @@ -1109,7 +1136,8 @@ { "fileName": "function.ts", "line": 166, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L166" } ], "signatures": [ @@ -1180,7 +1208,8 @@ { "fileName": "function.ts", "line": 173, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L173" } ], "type": { @@ -1200,7 +1229,8 @@ { "fileName": "function.ts", "line": 172, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L172" } ], "type": { @@ -1218,7 +1248,8 @@ { "fileName": "function.ts", "line": 171, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L171" } ], "type": { @@ -1242,7 +1273,8 @@ { "fileName": "function.ts", "line": 170, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L170" } ] } @@ -1266,7 +1298,8 @@ { "fileName": "function.ts", "line": 131, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L131" } ], "signatures": [ @@ -1329,7 +1362,8 @@ { "fileName": "function.ts", "line": 139, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L139" } ], "type": { @@ -1349,7 +1383,8 @@ { "fileName": "function.ts", "line": 138, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L138" } ], "type": { @@ -1367,7 +1402,8 @@ { "fileName": "function.ts", "line": 137, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L137" } ], "type": { @@ -1391,7 +1427,8 @@ { "fileName": "function.ts", "line": 136, - "character": 7 + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L136" } ] } @@ -1426,7 +1463,8 @@ { "fileName": "function.ts", "line": 62, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L62" } ], "signatures": [ @@ -1574,7 +1612,8 @@ { "fileName": "function.ts", "line": 47, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L47" } ], "signatures": [ @@ -1651,7 +1690,8 @@ { "fileName": "function.ts", "line": 23, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L23" } ], "signatures": [ @@ -1762,7 +1802,8 @@ { "fileName": "function.ts", "line": 78, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L78" } ], "signatures": [ @@ -1834,7 +1875,8 @@ { "fileName": "function.ts", "line": 253, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L253" } ], "signatures": [ @@ -1911,12 +1953,14 @@ { "fileName": "function.ts", "line": 304, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L304" }, { "fileName": "function.ts", "line": 305, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L305" } ], "signatures": [ @@ -1943,12 +1987,14 @@ { "fileName": "function.ts", "line": 218, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L218" }, { "fileName": "function.ts", "line": 260, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L260" } ], "signatures": [ @@ -2004,17 +2050,20 @@ { "fileName": "function.ts", "line": 183, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L183" }, { "fileName": "function.ts", "line": 191, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" }, { "fileName": "function.ts", "line": 201, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L201" } ], "signatures": [ @@ -2114,7 +2163,8 @@ { "fileName": "function.ts", "line": 191, - "character": 44 + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" } ], "type": { @@ -2136,7 +2186,8 @@ { "fileName": "function.ts", "line": 191, - "character": 42 + "character": 42, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L191" } ] } @@ -2160,7 +2211,8 @@ { "fileName": "function.ts", "line": 37, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L37" } ], "signatures": [ @@ -2236,7 +2288,8 @@ { "fileName": "function.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/function.ts#L4" } ] }, @@ -2257,7 +2310,8 @@ { "fileName": "generic-function.ts", "line": 18, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L18" } ], "signatures": [ @@ -2361,7 +2415,8 @@ { "fileName": "generic-function.ts", "line": 29, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L29" } ], "signatures": [ @@ -2428,7 +2483,8 @@ { "fileName": "generic-function.ts", "line": 7, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L7" } ], "signatures": [ @@ -2526,7 +2582,8 @@ { "fileName": "generic-function.ts", "line": 7, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/generic-function.ts#L7" } ] }, @@ -2554,7 +2611,8 @@ { "fileName": "implicit-types.ts", "line": 3, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L3" } ], "type": { @@ -2572,7 +2630,8 @@ { "fileName": "implicit-types.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L2" } ], "type": { @@ -2595,7 +2654,8 @@ { "fileName": "implicit-types.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L1" } ] }, @@ -2609,7 +2669,8 @@ { "fileName": "implicit-types.ts", "line": 14, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L14" } ], "signatures": [ @@ -2638,7 +2699,8 @@ { "fileName": "implicit-types.ts", "line": 9, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L9" } ], "type": { @@ -2657,7 +2719,8 @@ { "fileName": "implicit-types.ts", "line": 8, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L8" } ], "type": { @@ -2676,7 +2739,8 @@ { "fileName": "implicit-types.ts", "line": 7, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L7" } ], "type": { @@ -2695,7 +2759,8 @@ { "fileName": "implicit-types.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L10" } ], "type": { @@ -2714,7 +2779,8 @@ { "fileName": "implicit-types.ts", "line": 11, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L11" } ], "type": { @@ -2741,7 +2807,8 @@ { "fileName": "implicit-types.ts", "line": 6, - "character": 18 + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L6" } ] } @@ -2770,7 +2837,8 @@ { "fileName": "implicit-types.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/function/implicit-types.ts#L1" } ] } diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index 49bf05254..c31fd5618 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -43,7 +43,8 @@ { "fileName": "inherit-param-doc.ts", "line": 11, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L11" } ], "signatures": [ @@ -131,7 +132,8 @@ { "fileName": "inherit-param-doc.ts", "line": 9, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L9" } ], "implementedTypes": [ @@ -180,7 +182,8 @@ { "fileName": "inherit-param-doc.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L20" } ], "signatures": [ @@ -268,7 +271,8 @@ { "fileName": "inherit-param-doc.ts", "line": 14, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L14" } ], "implementedTypes": [ @@ -317,7 +321,8 @@ { "fileName": "inherit-param-doc.ts", "line": 29, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L29" } ], "signatures": [ @@ -405,7 +410,8 @@ { "fileName": "inherit-param-doc.ts", "line": 23, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L23" } ], "implementedTypes": [ @@ -433,7 +439,8 @@ { "fileName": "inherit-param-doc.ts", "line": 6, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L6" } ], "signatures": [ @@ -504,7 +511,8 @@ { "fileName": "inherit-param-doc.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L1" } ], "implementedBy": [ @@ -548,7 +556,8 @@ { "fileName": "inherit-param-doc.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L1" } ] } \ No newline at end of file diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 16947b992..79b3b108c 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -56,7 +56,8 @@ { "fileName": "inherit-doc.ts", "line": 12, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L12" } ], "type": { @@ -75,7 +76,8 @@ { "fileName": "inherit-doc.ts", "line": 19, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L19" } ], "signatures": [ @@ -135,7 +137,8 @@ { "fileName": "inherit-doc.ts", "line": 6, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L6" } ], "typeParameter": [ @@ -189,7 +192,8 @@ { "fileName": "inherit-doc.ts", "line": 30, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L30" } ], "type": { @@ -208,7 +212,8 @@ { "fileName": "inherit-doc.ts", "line": 37, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L37" } ], "signatures": [ @@ -268,7 +273,8 @@ { "fileName": "inherit-doc.ts", "line": 26, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L26" } ], "typeParameter": [ @@ -299,7 +305,8 @@ { "fileName": "inherit-doc.ts", "line": 58, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L58" } ], "signatures": [ @@ -422,7 +429,8 @@ { "fileName": "inherit-doc.ts", "line": 68, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L68" } ], "signatures": [ @@ -459,7 +467,8 @@ { "fileName": "inherit-doc.ts", "line": 85, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L85" } ], "signatures": [ @@ -613,7 +622,8 @@ { "fileName": "inherit-doc.ts", "line": 6, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L6" } ] }, @@ -641,7 +651,8 @@ { "fileName": "mergable-class.ts", "line": 3, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L3" } ], "signatures": [ @@ -677,7 +688,8 @@ { "fileName": "mergable-class.ts", "line": 7, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L7" } ], "type": { @@ -701,7 +713,8 @@ { "fileName": "mergable-class.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L2" } ], "type": { @@ -735,7 +748,8 @@ { "fileName": "mergable-class.ts", "line": 12, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L12" } ], "extendedTypes": [ @@ -763,7 +777,8 @@ { "fileName": "mergable-class.ts", "line": 7, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L7" } ], "type": { @@ -785,12 +800,14 @@ { "fileName": "mergable-class.ts", "line": 6, - "character": 17 + "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 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L10" } ] }, @@ -811,7 +828,8 @@ { "fileName": "mergable-class.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" } ], "signatures": [ @@ -839,7 +857,8 @@ { "fileName": "mergable-class.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L2" } ], "type": { @@ -868,7 +887,8 @@ { "fileName": "mergable-class.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" } ] }, @@ -882,12 +902,14 @@ { "fileName": "mergable-class.ts", "line": 6, - "character": 17 + "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 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L10" } ], "type": { @@ -932,7 +954,8 @@ { "fileName": "mergable-class.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/mergable-class.ts#L1" } ] } diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index 344426b4d..4b0d95ce2 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -28,7 +28,8 @@ { "fileName": "constructor-type.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" } ], "signatures": [ @@ -155,7 +156,8 @@ { "fileName": "constructor-type.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" } ] }, @@ -169,7 +171,8 @@ { "fileName": "constructor-type.ts", "line": 12, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L12" } ] } @@ -188,7 +191,8 @@ { "fileName": "constructor-type.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/constructor-type.ts#L1" } ] }, @@ -209,7 +213,8 @@ { "fileName": "index-signature.ts", "line": 10, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L10" } ], "indexSignature": { @@ -246,7 +251,8 @@ { "fileName": "index-signature.ts", "line": 5, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L5" } ], "indexSignature": { @@ -283,7 +289,8 @@ { "fileName": "index-signature.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L1" } ], "indexSignature": { @@ -320,7 +327,8 @@ { "fileName": "index-signature.ts", "line": 15, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L15" } ], "type": { @@ -335,7 +343,8 @@ { "fileName": "index-signature.ts", "line": 15, - "character": 24 + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L15" } ], "indexSignature": { @@ -387,7 +396,8 @@ { "fileName": "index-signature.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/index-signature.ts#L1" } ] }, @@ -446,7 +456,8 @@ { "fileName": "interface-empty.ts", "line": 10, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L10" } ], "type": { @@ -466,7 +477,8 @@ { "fileName": "interface-empty.ts", "line": 11, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L11" } ], "signatures": [ @@ -511,7 +523,8 @@ { "fileName": "interface-empty.ts", "line": 9, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L9" } ], "implementedTypes": [ @@ -540,7 +553,8 @@ { "fileName": "interface-empty.ts", "line": 4, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L4" } ], "implementedBy": [ @@ -572,7 +586,8 @@ { "fileName": "interface-empty.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-empty.ts#L4" } ] }, @@ -665,7 +680,8 @@ { "fileName": "interface-implementation.ts", "line": 57, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L57" } ], "type": { @@ -694,7 +710,8 @@ { "fileName": "interface-implementation.ts", "line": 59, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L59" } ], "signatures": [ @@ -784,7 +801,8 @@ { "fileName": "interface-implementation.ts", "line": 73, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L73" } ], "signatures": [ @@ -821,7 +839,8 @@ { "fileName": "interface-implementation.ts", "line": 69, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L69" } ], "signatures": [ @@ -872,7 +891,8 @@ { "fileName": "interface-implementation.ts", "line": 75, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L75" } ], "signatures": [ @@ -909,7 +929,8 @@ { "fileName": "interface-implementation.ts", "line": 67, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L67" } ], "signatures": [ @@ -989,7 +1010,8 @@ { "fileName": "interface-implementation.ts", "line": 56, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L56" } ], "typeParameter": [ @@ -1033,7 +1055,8 @@ { "fileName": "interface-implementation.ts", "line": 25, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L25" } ], "signatures": [ @@ -1141,7 +1164,8 @@ { "fileName": "interface-implementation.ts", "line": 29, - "character": 19 + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L29" } ], "type": { @@ -1169,7 +1193,8 @@ { "fileName": "interface-implementation.ts", "line": 27, - "character": 19 + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L27" } ], "type": { @@ -1194,7 +1219,8 @@ { "fileName": "interface-implementation.ts", "line": 26, - "character": 19 + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L26" } ], "type": { @@ -1227,7 +1253,8 @@ { "fileName": "interface-implementation.ts", "line": 28, - "character": 19 + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L28" } ], "type": { @@ -1250,7 +1277,8 @@ { "fileName": "interface-implementation.ts", "line": 32, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L32" } ], "signatures": [ @@ -1316,7 +1344,8 @@ { "fileName": "interface-implementation.ts", "line": 24, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L24" } ], "typeParameter": [ @@ -1368,7 +1397,8 @@ { "fileName": "interface-implementation.ts", "line": 41, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L41" } ], "signatures": [ @@ -1450,7 +1480,8 @@ { "fileName": "interface-implementation.ts", "line": 48, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L48" } ], "signatures": [ @@ -1477,7 +1508,8 @@ { "fileName": "interface-implementation.ts", "line": 47, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L47" } ], "signatures": [ @@ -1518,7 +1550,8 @@ { "fileName": "interface-implementation.ts", "line": 49, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L49" } ], "signatures": [ @@ -1545,7 +1578,8 @@ { "fileName": "interface-implementation.ts", "line": 46, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L46" } ], "signatures": [ @@ -1601,7 +1635,8 @@ { "fileName": "interface-implementation.ts", "line": 40, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L40" } ], "typeParameter": [ @@ -1631,7 +1666,8 @@ { "fileName": "interface-implementation.ts", "line": 5, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L5" } ], "typeParameter": [ @@ -1704,7 +1740,8 @@ { "fileName": "interface-implementation.ts", "line": 16, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L16" } ], "type": { @@ -1722,7 +1759,8 @@ { "fileName": "interface-implementation.ts", "line": 14, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L14" } ], "type": { @@ -1748,7 +1786,8 @@ { "fileName": "interface-implementation.ts", "line": 15, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L15" } ], "type": { @@ -1766,7 +1805,8 @@ { "fileName": "interface-implementation.ts", "line": 21, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L21" } ], "signatures": [ @@ -1814,7 +1854,8 @@ { "fileName": "interface-implementation.ts", "line": 13, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L13" } ], "typeParameter": [ @@ -1858,7 +1899,8 @@ { "fileName": "interface-implementation.ts", "line": 1, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L1" } ] } @@ -1876,7 +1918,8 @@ { "fileName": "interface-implementation.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L1" } ] }, @@ -1904,7 +1947,8 @@ { "fileName": "merging.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" } ], "type": { @@ -1926,7 +1970,8 @@ { "fileName": "merging.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L1" } ], "extendedBy": [ @@ -1959,7 +2004,8 @@ { "fileName": "merging.ts", "line": 6, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" } ], "type": { @@ -1981,7 +2027,8 @@ { "fileName": "merging.ts", "line": 5, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L5" } ], "extendedBy": [ @@ -2009,7 +2056,8 @@ { "fileName": "merging.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" } ], "type": { @@ -2032,7 +2080,8 @@ { "fileName": "merging.ts", "line": 6, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" } ], "type": { @@ -2055,7 +2104,8 @@ { "fileName": "merging.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L10" } ], "type": { @@ -2073,7 +2123,8 @@ { "fileName": "merging.ts", "line": 15, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L15" } ], "type": { @@ -2098,12 +2149,14 @@ { "fileName": "merging.ts", "line": 9, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L9" }, { "fileName": "merging.ts", "line": 14, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L14" } ], "extendedTypes": [ @@ -2143,7 +2196,8 @@ { "fileName": "merging.ts", "line": 2, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L2" } ], "type": { @@ -2166,7 +2220,8 @@ { "fileName": "merging.ts", "line": 6, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L6" } ], "type": { @@ -2189,7 +2244,8 @@ { "fileName": "merging.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L10" } ], "type": { @@ -2212,7 +2268,8 @@ { "fileName": "merging.ts", "line": 19, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L19" } ], "type": { @@ -2230,7 +2287,8 @@ { "fileName": "merging.ts", "line": 15, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L15" } ], "type": { @@ -2261,7 +2319,8 @@ { "fileName": "merging.ts", "line": 18, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L18" } ], "extendedTypes": [ @@ -2294,7 +2353,8 @@ { "fileName": "merging.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/merging.ts#L1" } ] } diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index 266409185..efd64f3ff 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -21,7 +21,8 @@ { "fileName": "export-eq-type.js", "line": 1, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L1" } ], "type": { @@ -39,7 +40,8 @@ { "fileName": "export-eq-type.js", "line": 4, - "character": 6 + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L4" } ], "signatures": [ @@ -90,7 +92,8 @@ { "fileName": "export-eq-type.js", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/export-eq-type.js#L4" } ] }, @@ -126,7 +129,8 @@ { "fileName": "index.js", "line": 13, - "character": 18 + "character": 18, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L13" } ], "type": { @@ -144,7 +148,8 @@ { "fileName": "index.js", "line": 12, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L12" } ], "type": { @@ -167,7 +172,8 @@ { "fileName": "index.js", "line": 11, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L11" } ] }, @@ -188,7 +194,8 @@ { "fileName": "index.js", "line": 6, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L6" } ], "type": { @@ -210,7 +217,8 @@ { "fileName": "index.js", "line": 5, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L5" } ] }, @@ -224,12 +232,14 @@ { "fileName": "index.js", "line": 60, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L60" }, { "fileName": "index.js", "line": 58, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L58" } ], "type": { @@ -247,7 +257,8 @@ { "fileName": "index.js", "line": 49, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L49" } ], "type": { @@ -262,7 +273,8 @@ { "fileName": "index.js", "line": 49, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L49" } ], "signatures": [ @@ -309,7 +321,8 @@ { "fileName": "index.js", "line": 27, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L27" } ], "type": { @@ -324,7 +337,8 @@ { "fileName": "index.js", "line": 27, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L27" } ], "signatures": [ @@ -361,7 +375,8 @@ { "fileName": "index.js", "line": 45, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L45" } ], "typeParameter": [ @@ -397,7 +412,8 @@ { "fileName": "index.js", "line": 33, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L33" } ], "typeParameter": [ @@ -421,7 +437,8 @@ { "fileName": "index.js", "line": 33, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L33" } ], "signatures": [ @@ -473,7 +490,8 @@ { "fileName": "index.js", "line": 22, - "character": 44 + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" } ], "type": { @@ -498,7 +516,8 @@ { "fileName": "index.js", "line": 22, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" } ], "type": { @@ -520,7 +539,8 @@ { "fileName": "index.js", "line": 22, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" } ] } @@ -544,7 +564,8 @@ { "fileName": "index.js", "line": 22, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" } ], "type": { @@ -566,7 +587,8 @@ { "fileName": "index.js", "line": 22, - "character": 29 + "character": 29, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L22" } ] } @@ -584,7 +606,8 @@ { "fileName": "index.js", "line": 26, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L26" } ], "type": { @@ -599,7 +622,8 @@ { "fileName": "index.js", "line": 26, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L26" } ], "signatures": [ @@ -644,7 +668,8 @@ { "fileName": "index.js", "line": 17, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L17" } ], "type": { @@ -664,7 +689,8 @@ { "fileName": "index.js", "line": 39, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L39" } ], "type": { @@ -679,7 +705,8 @@ { "fileName": "index.js", "line": 39, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L39" } ], "signatures": [ @@ -739,7 +766,8 @@ { "fileName": "index.js", "line": 21, - "character": 30 + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L21" } ], "type": { @@ -776,12 +804,14 @@ { "fileName": "index.js", "line": 60, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L60" }, { "fileName": "index.js", "line": 58, - "character": 3 + "character": 3, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L58" } ], "type": { @@ -803,7 +833,8 @@ { "fileName": "index.js", "line": 62, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L62" } ], "type": { @@ -822,7 +853,8 @@ { "fileName": "index.js", "line": 61, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L61" } ], "type": { @@ -846,7 +878,8 @@ { "fileName": "index.js", "line": 60, - "character": 26 + "character": 26, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L60" } ] } @@ -863,7 +896,8 @@ { "fileName": "index.js", "line": 55, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L55" } ], "signatures": [ @@ -943,7 +977,8 @@ { "fileName": "index.js", "line": 55, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L55" } ] } diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 907b8f94b..db4afb32e 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -51,7 +51,8 @@ { "fileName": "mixin.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" } ], "type": { @@ -70,7 +71,8 @@ { "fileName": "mixin.ts", "line": 22, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" } ], "signatures": [ @@ -115,7 +117,8 @@ { "fileName": "mixin.ts", "line": 19, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L19" } ] }, @@ -173,7 +176,8 @@ { "fileName": "mixin.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" } ], "type": { @@ -196,7 +200,8 @@ { "fileName": "mixin.ts", "line": 86, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L86" } ], "type": { @@ -215,7 +220,8 @@ { "fileName": "mixin.ts", "line": 35, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" } ], "type": { @@ -238,7 +244,8 @@ { "fileName": "mixin.ts", "line": 55, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L55" } ], "type": { @@ -261,7 +268,8 @@ { "fileName": "mixin.ts", "line": 22, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" } ], "signatures": [ @@ -296,7 +304,8 @@ { "fileName": "mixin.ts", "line": 88, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L88" } ], "signatures": [ @@ -323,7 +332,8 @@ { "fileName": "mixin.ts", "line": 37, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" } ], "signatures": [ @@ -379,7 +389,8 @@ { "fileName": "mixin.ts", "line": 57, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L57" } ], "signatures": [ @@ -453,7 +464,8 @@ { "fileName": "mixin.ts", "line": 85, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L85" } ], "extendedTypes": [ @@ -508,7 +520,8 @@ { "fileName": "mixin.ts", "line": 34, - "character": 10 + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L34" } ] } @@ -589,7 +602,8 @@ { "fileName": "mixin.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" } ], "type": { @@ -612,7 +626,8 @@ { "fileName": "mixin.ts", "line": 35, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" } ], "type": { @@ -635,7 +650,8 @@ { "fileName": "mixin.ts", "line": 22, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" } ], "signatures": [ @@ -670,7 +686,8 @@ { "fileName": "mixin.ts", "line": 37, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" } ], "signatures": [ @@ -739,7 +756,8 @@ { "fileName": "mixin.ts", "line": 45, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L45" } ], "extendedTypes": [ @@ -785,7 +803,8 @@ { "fileName": "mixin.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L20" } ], "type": { @@ -808,7 +827,8 @@ { "fileName": "mixin.ts", "line": 35, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L35" } ], "type": { @@ -831,7 +851,8 @@ { "fileName": "mixin.ts", "line": 55, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L55" } ], "type": { @@ -854,7 +875,8 @@ { "fileName": "mixin.ts", "line": 22, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L22" } ], "signatures": [ @@ -889,7 +911,8 @@ { "fileName": "mixin.ts", "line": 37, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L37" } ], "signatures": [ @@ -945,7 +968,8 @@ { "fileName": "mixin.ts", "line": 57, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L57" } ], "signatures": [ @@ -1010,7 +1034,8 @@ { "fileName": "mixin.ts", "line": 65, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L65" } ], "extendedTypes": [ @@ -1041,7 +1066,8 @@ { "fileName": "mixin.ts", "line": 9, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L9" } ], "typeParameter": [ @@ -1069,7 +1095,8 @@ { "fileName": "mixin.ts", "line": 9, - "character": 41 + "character": 41, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L9" } ], "signatures": [ @@ -1125,7 +1152,8 @@ { "fileName": "mixin.ts", "line": 4, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" } ], "typeParameter": [ @@ -1153,7 +1181,8 @@ { "fileName": "mixin.ts", "line": 4, - "character": 35 + "character": 35, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" } ], "signatures": [ @@ -1217,7 +1246,8 @@ { "fileName": "mixin.ts", "line": 14, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L14" } ], "typeParameter": [ @@ -1286,12 +1316,14 @@ { "fileName": "mixin.ts", "line": 70, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L70" }, { "fileName": "mixin.ts", "line": 80, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L80" } ], "type": { @@ -1320,7 +1352,8 @@ { "fileName": "mixin.ts", "line": 30, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L30" } ], "signatures": [ @@ -1409,7 +1442,8 @@ { "fileName": "mixin.ts", "line": 34, - "character": 10 + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L34" } ] } @@ -1434,7 +1468,8 @@ { "fileName": "mixin.ts", "line": 50, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L50" } ], "signatures": [ @@ -1533,7 +1568,8 @@ { "fileName": "mixin.ts", "line": 54, - "character": 10 + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L54" } ] } @@ -1558,12 +1594,14 @@ { "fileName": "mixin.ts", "line": 70, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L70" }, { "fileName": "mixin.ts", "line": 80, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L80" } ], "signatures": [ @@ -1651,7 +1689,8 @@ { "fileName": "mixin.ts", "line": 74, - "character": 10 + "character": 10, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L74" } ] } @@ -1708,7 +1747,8 @@ { "fileName": "mixin.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" } ] } \ No newline at end of file diff --git a/src/test/converter/react/specs.json b/src/test/converter/react/specs.json index 3c93d89dd..9f44162b4 100644 --- a/src/test/converter/react/specs.json +++ b/src/test/converter/react/specs.json @@ -22,7 +22,8 @@ { "fileName": "react.tsx", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L20" } ], "signatures": [ @@ -66,7 +67,8 @@ { "fileName": "react.tsx", "line": 18, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L18" } ], "type": { @@ -84,7 +86,8 @@ { "fileName": "react.tsx", "line": 25, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L25" } ], "signatures": [ @@ -129,7 +132,8 @@ { "fileName": "react.tsx", "line": 17, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L17" } ] }, @@ -150,7 +154,8 @@ { "fileName": "react.tsx", "line": 14, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L14" } ], "type": { @@ -168,7 +173,8 @@ { "fileName": "react.tsx", "line": 13, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L13" } ], "type": { @@ -191,7 +197,8 @@ { "fileName": "react.tsx", "line": 12, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L12" } ] } @@ -216,7 +223,8 @@ { "fileName": "react.tsx", "line": 2, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L2" } ] } \ No newline at end of file diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index 1cb972a8a..693f474cf 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -21,7 +21,8 @@ { "fileName": "general.ts", "line": 12, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L12" } ], "type": { @@ -39,7 +40,8 @@ { "fileName": "general.ts", "line": 3, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L3" } ], "type": { @@ -60,7 +62,8 @@ { "fileName": "general.ts", "line": 6, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L6" } ], "type": { @@ -81,7 +84,8 @@ { "fileName": "general.ts", "line": 14, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L14" } ], "type": { @@ -99,7 +103,8 @@ { "fileName": "general.ts", "line": 9, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L9" } ], "type": { @@ -122,7 +127,8 @@ { "fileName": "general.ts", "line": 4, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L4" } ], "type": { @@ -146,7 +152,8 @@ { "fileName": "general.ts", "line": 7, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L7" } ], "type": { @@ -170,7 +177,8 @@ { "fileName": "general.ts", "line": 15, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L15" } ], "type": { @@ -191,7 +199,8 @@ { "fileName": "general.ts", "line": 10, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L10" } ], "type": { @@ -231,7 +240,8 @@ { "fileName": "general.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L1" } ] }, @@ -252,7 +262,8 @@ { "fileName": "index-signature.ts", "line": 5, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L5" } ], "indexSignature": { @@ -298,7 +309,8 @@ { "fileName": "index-signature.ts", "line": 1, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L1" } ], "indexSignature": { @@ -335,7 +347,8 @@ { "fileName": "index-signature.ts", "line": 9, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L9" } ], "indexSignature": { @@ -387,7 +400,8 @@ { "fileName": "index-signature.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/index-signature.ts#L1" } ] }, @@ -408,7 +422,8 @@ { "fileName": "mapped.ts", "line": 7, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L7" } ], "typeParameter": [ @@ -485,7 +500,8 @@ { "fileName": "mapped.ts", "line": 5, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L5" } ], "typeParameter": [ @@ -533,7 +549,8 @@ { "fileName": "mapped.ts", "line": 9, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L9" } ], "signatures": [ @@ -619,7 +636,8 @@ { "fileName": "mapped.ts", "line": 1, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L1" } ], "signatures": [ @@ -705,7 +723,8 @@ { "fileName": "mapped.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L1" } ] }, @@ -726,7 +745,8 @@ { "fileName": "parens.ts", "line": 3, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" } ], "type": { @@ -755,7 +775,8 @@ { "fileName": "parens.ts", "line": 3, - "character": 24 + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" } ], "type": { @@ -777,7 +798,8 @@ { "fileName": "parens.ts", "line": 3, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" } ] } @@ -799,7 +821,8 @@ { "fileName": "parens.ts", "line": 3, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/parens.ts#L3" } ] }, @@ -820,7 +843,8 @@ { "fileName": "query.ts", "line": 3, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L3" } ], "type": { @@ -844,7 +868,8 @@ { "fileName": "query.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L1" } ], "type": { @@ -874,7 +899,8 @@ { "fileName": "query.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/query.ts#L1" } ] }, @@ -895,7 +921,8 @@ { "fileName": "tuple.ts", "line": 14, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L14" } ], "type": { @@ -928,7 +955,8 @@ { "fileName": "tuple.ts", "line": 1, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L1" } ], "type": { @@ -965,7 +993,8 @@ { "fileName": "tuple.ts", "line": 11, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L11" } ], "type": { @@ -1002,7 +1031,8 @@ { "fileName": "tuple.ts", "line": 5, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L5" } ], "type": { @@ -1035,7 +1065,8 @@ { "fileName": "tuple.ts", "line": 8, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L8" } ], "type": { @@ -1077,7 +1108,8 @@ { "fileName": "tuple.ts", "line": 16, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L16" } ], "type": { @@ -1113,7 +1145,8 @@ { "fileName": "tuple.ts", "line": 3, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L3" } ], "type": { @@ -1153,7 +1186,8 @@ { "fileName": "tuple.ts", "line": 12, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L12" } ], "type": { @@ -1193,7 +1227,8 @@ { "fileName": "tuple.ts", "line": 6, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L6" } ], "type": { @@ -1229,7 +1264,8 @@ { "fileName": "tuple.ts", "line": 9, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L9" } ], "type": { @@ -1292,7 +1328,8 @@ { "fileName": "tuple.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/tuple.ts#L1" } ] }, @@ -1313,7 +1350,8 @@ { "fileName": "type-operator.ts", "line": 2, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L2" } ], "type": { @@ -1338,7 +1376,8 @@ { "fileName": "type-operator.ts", "line": 3, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L3" } ], "type": { @@ -1360,7 +1399,8 @@ { "fileName": "type-operator.ts", "line": 4, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L4" } ], "type": { @@ -1378,7 +1418,8 @@ { "fileName": "type-operator.ts", "line": 5, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L5" } ], "type": { @@ -1401,7 +1442,8 @@ { "fileName": "type-operator.ts", "line": 3, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L3" } ] } @@ -1417,7 +1459,8 @@ { "fileName": "type-operator.ts", "line": 7, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L7" } ], "type": { @@ -1442,7 +1485,8 @@ { "fileName": "type-operator.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L1" } ], "type": { @@ -1478,7 +1522,8 @@ { "fileName": "type-operator.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/type-operator.ts#L1" } ] }, @@ -1522,7 +1567,8 @@ { "fileName": "union-or-intersection.ts", "line": 8, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L8" } ], "type": { @@ -1544,7 +1590,8 @@ { "fileName": "union-or-intersection.ts", "line": 4, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L4" } ] }, @@ -1581,7 +1628,8 @@ { "fileName": "union-or-intersection.ts", "line": 18, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L18" } ], "type": { @@ -1603,7 +1651,8 @@ { "fileName": "union-or-intersection.ts", "line": 14, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L14" } ] }, @@ -1640,7 +1689,8 @@ { "fileName": "union-or-intersection.ts", "line": 38, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L38" } ], "type": { @@ -1692,7 +1742,8 @@ { "fileName": "union-or-intersection.ts", "line": 33, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L33" } ], "type": { @@ -1729,7 +1780,8 @@ { "fileName": "union-or-intersection.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L28" } ], "type": { @@ -1764,7 +1816,8 @@ { "fileName": "union-or-intersection.ts", "line": 24, - "character": 17 + "character": 17, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L24" } ] } @@ -1784,7 +1837,8 @@ { "fileName": "union-or-intersection.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/union-or-intersection.ts#L4" } ] } diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index d6102e905..643ec0314 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -77,7 +77,8 @@ { "fileName": "array.ts", "line": 4, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ], "typeParameter": [ @@ -147,7 +148,8 @@ { "fileName": "array.ts", "line": 19, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L19" } ] }, @@ -211,7 +213,8 @@ { "fileName": "array.ts", "line": 24, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L24" } ], "extendedTypes": [ @@ -249,7 +252,8 @@ { "fileName": "array.ts", "line": 9, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L9" } ], "type": { @@ -318,7 +322,8 @@ { "fileName": "array.ts", "line": 14, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L14" } ], "type": { @@ -358,7 +363,8 @@ { "fileName": "array.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ] }, @@ -379,7 +385,8 @@ { "fileName": "destructuring.ts", "line": 13, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" } ], "type": { @@ -397,7 +404,8 @@ { "fileName": "destructuring.ts", "line": 13, - "character": 30 + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" } ], "type": { @@ -415,7 +423,8 @@ { "fileName": "destructuring.ts", "line": 13, - "character": 46 + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L13" } ], "type": { @@ -443,7 +452,8 @@ { "fileName": "destructuring.ts", "line": 31, - "character": 14 + "character": 14, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L31" } ], "type": { @@ -461,7 +471,8 @@ { "fileName": "destructuring.ts", "line": 31, - "character": 46 + "character": 46, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L31" } ], "type": { @@ -488,7 +499,8 @@ { "fileName": "destructuring.ts", "line": 25, - "character": 7 + "character": 7, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L25" } ], "type": { @@ -515,7 +527,8 @@ { "fileName": "destructuring.ts", "line": 23, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L23" } ], "type": { @@ -533,7 +546,8 @@ { "fileName": "destructuring.ts", "line": 24, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L24" } ], "type": { @@ -551,7 +565,8 @@ { "fileName": "destructuring.ts", "line": 4, - "character": 15 + "character": 15, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" } ], "type": { @@ -569,7 +584,8 @@ { "fileName": "destructuring.ts", "line": 4, - "character": 32 + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" } ], "type": { @@ -587,7 +603,8 @@ { "fileName": "destructuring.ts", "line": 4, - "character": 49 + "character": 49, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" } ], "type": { @@ -605,7 +622,8 @@ { "fileName": "destructuring.ts", "line": 38, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L38" } ], "signatures": [ @@ -674,7 +692,8 @@ { "fileName": "destructuring.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" } ] }, @@ -697,7 +716,8 @@ { "fileName": "literal.ts", "line": 43, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L43" } ], "type": { @@ -719,7 +739,8 @@ { "fileName": "literal.ts", "line": 48, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" } ], "type": { @@ -734,7 +755,8 @@ { "fileName": "literal.ts", "line": 48, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" } ], "signatures": [ @@ -763,7 +785,8 @@ { "fileName": "literal.ts", "line": 48, - "character": 27 + "character": 27, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L48" } ], "signatures": [ @@ -803,7 +826,8 @@ { "fileName": "literal.ts", "line": 52, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" } ], "type": { @@ -818,7 +842,8 @@ { "fileName": "literal.ts", "line": 52, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" } ], "signatures": [ @@ -847,7 +872,8 @@ { "fileName": "literal.ts", "line": 52, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L52" } ], "signatures": [ @@ -887,7 +913,8 @@ { "fileName": "literal.ts", "line": 44, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" } ], "type": { @@ -902,7 +929,8 @@ { "fileName": "literal.ts", "line": 44, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" } ], "signatures": [ @@ -931,7 +959,8 @@ { "fileName": "literal.ts", "line": 44, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L44" } ], "signatures": [ @@ -977,7 +1006,8 @@ { "fileName": "literal.ts", "line": 43, - "character": 30 + "character": 30, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L43" } ] } @@ -1004,7 +1034,8 @@ { "fileName": "literal.ts", "line": 5, - "character": 6 + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" } ], "type": { @@ -1026,7 +1057,8 @@ { "fileName": "literal.ts", "line": 19, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L19" } ], "type": { @@ -1045,7 +1077,8 @@ { "fileName": "literal.ts", "line": 20, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L20" } ], "type": { @@ -1064,7 +1097,8 @@ { "fileName": "literal.ts", "line": 21, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L21" } ], "type": { @@ -1083,7 +1117,8 @@ { "fileName": "literal.ts", "line": 17, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L17" } ], "type": { @@ -1102,7 +1137,8 @@ { "fileName": "literal.ts", "line": 18, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L18" } ], "type": { @@ -1121,7 +1157,8 @@ { "fileName": "literal.ts", "line": 10, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" } ], "type": { @@ -1143,7 +1180,8 @@ { "fileName": "literal.ts", "line": 15, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L15" } ], "type": { @@ -1165,7 +1203,8 @@ { "fileName": "literal.ts", "line": 12, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" } ], "type": { @@ -1180,7 +1219,8 @@ { "fileName": "literal.ts", "line": 12, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L12" } ], "signatures": [ @@ -1222,7 +1262,8 @@ { "fileName": "literal.ts", "line": 13, - "character": 21 + "character": 21, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" } ], "type": { @@ -1241,7 +1282,8 @@ { "fileName": "literal.ts", "line": 13, - "character": 32 + "character": 32, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" } ], "type": { @@ -1265,7 +1307,8 @@ { "fileName": "literal.ts", "line": 13, - "character": 19 + "character": 19, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L13" } ] } @@ -1286,7 +1329,8 @@ { "fileName": "literal.ts", "line": 11, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L11" } ], "type": { @@ -1311,7 +1355,8 @@ { "fileName": "literal.ts", "line": 10, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L10" } ] } @@ -1328,7 +1373,8 @@ { "fileName": "literal.ts", "line": 7, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" } ], "type": { @@ -1343,7 +1389,8 @@ { "fileName": "literal.ts", "line": 7, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L7" } ], "signatures": [ @@ -1373,7 +1420,8 @@ { "fileName": "literal.ts", "line": 6, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L6" } ], "type": { @@ -1403,7 +1451,8 @@ { "fileName": "literal.ts", "line": 5, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" } ] } @@ -1428,7 +1477,8 @@ { "fileName": "literal.ts", "line": 27, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" } ], "type": { @@ -1452,7 +1502,8 @@ { "fileName": "literal.ts", "line": 35, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L35" } ], "type": { @@ -1472,7 +1523,8 @@ { "fileName": "literal.ts", "line": 36, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L36" } ], "type": { @@ -1490,7 +1542,8 @@ { "fileName": "literal.ts", "line": 30, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" } ], "type": { @@ -1512,7 +1565,8 @@ { "fileName": "literal.ts", "line": 33, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L33" } ], "type": { @@ -1533,7 +1587,8 @@ { "fileName": "literal.ts", "line": 32, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" } ], "type": { @@ -1548,7 +1603,8 @@ { "fileName": "literal.ts", "line": 32, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" } ], "signatures": [ @@ -1590,7 +1646,8 @@ { "fileName": "literal.ts", "line": 32, - "character": 33 + "character": 33, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" } ], "type": { @@ -1608,7 +1665,8 @@ { "fileName": "literal.ts", "line": 32, - "character": 44 + "character": 44, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" } ], "type": { @@ -1631,7 +1689,8 @@ { "fileName": "literal.ts", "line": 32, - "character": 31 + "character": 31, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L32" } ] } @@ -1651,7 +1710,8 @@ { "fileName": "literal.ts", "line": 31, - "character": 8 + "character": 8, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L31" } ], "type": { @@ -1675,7 +1735,8 @@ { "fileName": "literal.ts", "line": 30, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L30" } ] } @@ -1691,7 +1752,8 @@ { "fileName": "literal.ts", "line": 29, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" } ], "type": { @@ -1706,7 +1768,8 @@ { "fileName": "literal.ts", "line": 29, - "character": 12 + "character": 12, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L29" } ], "signatures": [ @@ -1735,7 +1798,8 @@ { "fileName": "literal.ts", "line": 28, - "character": 4 + "character": 4, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L28" } ], "type": { @@ -1761,7 +1825,8 @@ { "fileName": "literal.ts", "line": 27, - "character": 24 + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" } ] } @@ -1783,7 +1848,8 @@ { "fileName": "literal.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L1" } ] }, @@ -1806,7 +1872,8 @@ { "fileName": "variable.ts", "line": 1, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L1" } ], "type": { @@ -1825,7 +1892,8 @@ { "fileName": "variable.ts", "line": 2, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L2" } ], "type": { @@ -1844,7 +1912,8 @@ { "fileName": "variable.ts", "line": 3, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L3" } ], "type": { @@ -1863,7 +1932,8 @@ { "fileName": "variable.ts", "line": 5, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L5" } ], "type": { @@ -1881,7 +1951,8 @@ { "fileName": "variable.ts", "line": 6, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L6" } ], "type": { @@ -1907,7 +1978,8 @@ { "fileName": "variable.ts", "line": 7, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L7" } ], "type": { @@ -1942,7 +2014,8 @@ { "fileName": "variable.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/variable.ts#L1" } ] } diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index 1ec6de949..cc11db744 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -77,7 +77,8 @@ { "fileName": "array.ts", "line": 4, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ], "typeParameter": [ @@ -147,7 +148,8 @@ { "fileName": "array.ts", "line": 19, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L19" } ] }, @@ -211,7 +213,8 @@ { "fileName": "array.ts", "line": 24, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L24" } ], "extendedTypes": [ @@ -249,7 +252,8 @@ { "fileName": "array.ts", "line": 9, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L9" } ], "type": { @@ -318,7 +322,8 @@ { "fileName": "array.ts", "line": 14, - "character": 13 + "character": 13, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L14" } ], "type": { @@ -358,7 +363,8 @@ { "fileName": "array.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ] }, @@ -379,7 +385,8 @@ { "fileName": "destructuring.ts", "line": 38, - "character": 16 + "character": 16, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L38" } ], "signatures": [ @@ -431,7 +438,8 @@ { "fileName": "destructuring.ts", "line": 4, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/destructuring.ts#L4" } ] }, @@ -462,7 +470,8 @@ { "fileName": "literal.ts", "line": 5, - "character": 6 + "character": 6, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" } ], "type": { @@ -477,7 +486,8 @@ { "fileName": "literal.ts", "line": 5, - "character": 22 + "character": 22, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L5" } ] } @@ -502,7 +512,8 @@ { "fileName": "literal.ts", "line": 27, - "character": 11 + "character": 11, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" } ], "type": { @@ -517,7 +528,8 @@ { "fileName": "literal.ts", "line": 27, - "character": 24 + "character": 24, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L27" } ] } @@ -538,7 +550,8 @@ { "fileName": "literal.ts", "line": 1, - "character": 0 + "character": 0, + "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/literal.ts#L1" } ] } diff --git a/src/test/programs.ts b/src/test/programs.ts index 9a42ffa76..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() { @@ -25,6 +25,7 @@ export function getConverterApp() { 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() { From 6e30001309f105cead0019168c87d656d6b52edb Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 11:49:48 -0600 Subject: [PATCH 085/151] Remove unused ProjectReflection.directory --- .vscode/settings.json | 2 +- CHANGELOG.md | 1 + src/lib/converter/plugins/GroupPlugin.ts | 12 ---- src/lib/converter/plugins/SourcePlugin.ts | 30 +------- src/lib/models/reflections/project.ts | 7 +- src/lib/models/sources/directory.ts | 88 ----------------------- src/lib/models/sources/file.ts | 6 -- src/lib/models/sources/index.ts | 1 - 8 files changed, 5 insertions(+), 142 deletions(-) delete mode 100644 src/lib/models/sources/directory.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index cf883d627..bb69beb90 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,5 +11,5 @@ "prettier.ignorePath": ".config/.prettierignore", "eslint.workingDirectories": [".", "./example"], "mochaExplorer.configFile": ".config/mocha.test-explorer.json", - "cSpell.words": ["tsbuildinfo"] + "cSpell.words": ["cname", "tsbuildinfo", "tsdoc"] } diff --git a/CHANGELOG.md b/CHANGELOG.md index c209f2d52..5c9638d1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - Removed deprecated `removeReaderByName`, `addDeclarations` and `removeDeclarationByName` methods on `Options`. +- Removed `ProjectReflection.directory`, it was unused by TypeDoc and not properly tested. - Themes are now set on the document element rather than on body, #1706. ### Features diff --git a/src/lib/converter/plugins/GroupPlugin.ts b/src/lib/converter/plugins/GroupPlugin.ts index 322dbacb3..772cd7a62 100644 --- a/src/lib/converter/plugins/GroupPlugin.ts +++ b/src/lib/converter/plugins/GroupPlugin.ts @@ -5,7 +5,6 @@ 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"; @@ -72,20 +71,9 @@ 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() - ); - - for (const dir of Object.values(directory.directories)) { - walkDirectory(dir); - } - } - const project = context.project; this.group(project); - walkDirectory(project.directory); project.files.forEach((file) => { file.groups = GroupPlugin.getReflectionGroups(file.reflections); }); diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index 8d034d06d..b83c5d66d 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -1,4 +1,3 @@ -import * as Path from "path"; import * as ts from "typescript"; import { @@ -6,7 +5,7 @@ import { ProjectReflection, DeclarationReflection, } from "../../models/reflections/index"; -import { SourceDirectory, SourceFile } from "../../models/sources/index"; +import { SourceFile } from "../../models/sources/index"; import { Component, ConverterComponent } from "../components"; import { Converter } from "../converter"; import type { Context } from "../context"; @@ -155,33 +154,8 @@ export class SourcePlugin extends ConverterComponent { */ private onEndResolve(context: Context) { const project = context.project; - const home = project.directory; project.files.forEach((file) => { - const reflections: DeclarationReflection[] = - file.reflections.slice(); - - 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]; - }); - } - - directory.files.push(file); - file.parent = directory; - file.reflections = reflections; + file.reflections = file.reflections.slice(); }); } } diff --git a/src/lib/models/reflections/project.ts b/src/lib/models/reflections/project.ts index 45d501eb9..4efe31509 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -1,4 +1,4 @@ -import { SourceFile, SourceDirectory } from "../sources/index"; +import type { SourceFile } from "../sources/index"; import { Reflection, TraverseProperty } from "./abstract"; import { ContainerReflection } from "./container"; import { ReferenceReflection } from "./reference"; @@ -33,11 +33,6 @@ export class ProjectReflection extends ContainerReflection { */ reflections: { [id: number]: Reflection } = {}; - /** - * The root directory of the project. - */ - directory: SourceDirectory = new SourceDirectory(); - /** * A list of all source files within the project. */ diff --git a/src/lib/models/sources/directory.ts b/src/lib/models/sources/directory.ts deleted file mode 100644 index 4775a096e..000000000 --- a/src/lib/models/sources/directory.ts +++ /dev/null @@ -1,88 +0,0 @@ -import type { ReflectionGroup } from "../ReflectionGroup"; -import type { SourceFile } from "./file"; -import type { DeclarationReflection } from ".."; - -/** - * 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 this.files.flatMap((file) => file.reflections); - } -} diff --git a/src/lib/models/sources/file.ts b/src/lib/models/sources/file.ts index 2cc57f55d..a7ad9ee57 100644 --- a/src/lib/models/sources/file.ts +++ b/src/lib/models/sources/file.ts @@ -1,7 +1,6 @@ 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"; @@ -96,11 +95,6 @@ export class SourceFile { */ 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. */ diff --git a/src/lib/models/sources/index.ts b/src/lib/models/sources/index.ts index 575aaed74..0e0d59d5b 100644 --- a/src/lib/models/sources/index.ts +++ b/src/lib/models/sources/index.ts @@ -1,4 +1,3 @@ -export { SourceDirectory } from "./directory"; export { SourceFile } from "./file"; export { SourceReference } from "./file"; export { RepositoryType } from "./repository"; From 69027250d17d3961c1b9771d8fb30c065eab27c8 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 12:18:16 -0600 Subject: [PATCH 086/151] Remove ProjectReflection.files How tangled are the webs we weave, when first we optimize, then never measure. --- CHANGELOG.md | 1 + src/lib/converter/plugins/GroupPlugin.ts | 9 +- src/lib/converter/plugins/SourceLinkPlugin.ts | 22 ++--- src/lib/converter/plugins/SourcePlugin.ts | 91 +++---------------- src/lib/models/reflections/project.ts | 6 -- src/lib/models/sources/file.ts | 81 ++--------------- src/lib/models/sources/index.ts | 1 - 7 files changed, 31 insertions(+), 180 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c9638d1a..370d59a3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Constant variables which are interpreted as functions will no longer have the `ReflectionFlag.Const` flag set. - 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. - Themes are now set on the document element rather than on body, #1706. ### Features diff --git a/src/lib/converter/plugins/GroupPlugin.ts b/src/lib/converter/plugins/GroupPlugin.ts index 772cd7a62..6f158773a 100644 --- a/src/lib/converter/plugins/GroupPlugin.ts +++ b/src/lib/converter/plugins/GroupPlugin.ts @@ -14,7 +14,7 @@ import { BindOption } from "../../utils"; /** * 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 { @@ -71,12 +71,7 @@ export class GroupPlugin extends ConverterComponent { * @param context The context object describing the current state the converter is in. */ private onEndResolve(context: Context) { - const project = context.project; - this.group(project); - - project.files.forEach((file) => { - file.groups = GroupPlugin.getReflectionGroups(file.reflections); - }); + this.group(context.project); } private group(reflection: ContainerReflection) { diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/plugins/SourceLinkPlugin.ts index 47575b4bb..f969ef117 100644 --- a/src/lib/converter/plugins/SourceLinkPlugin.ts +++ b/src/lib/converter/plugins/SourceLinkPlugin.ts @@ -288,25 +288,17 @@ export class SourceLinkPlugin extends ConverterComponent { */ 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 reflection of Object.values(project.reflections)) { if (reflection.sources) { reflection.sources.forEach((source: SourceReference) => { - if (source.file.url) { - source.url = - source.file.url + - "#" + - Repository.getLineNumberAnchor( - source.line, - source.file.repositoryType - ); + const repo = this.getRepository(source.fullFileName); + const url = repo?.getURL(source.fullFileName); + if (url) { + source.url = `${url}#${Repository.getLineNumberAnchor( + source.line, + repo!.type + )}`; } }); } diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index b83c5d66d..d49e63f2f 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -1,11 +1,6 @@ import * as ts from "typescript"; -import { - Reflection, - ProjectReflection, - DeclarationReflection, -} from "../../models/reflections/index"; -import { 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"; @@ -13,7 +8,6 @@ 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 { SourceReference } from "../../models"; /** @@ -24,16 +18,10 @@ export class SourcePlugin extends ConverterComponent { @BindOption("disableSources") readonly disableSources!: boolean; - /** - * A map of all generated {@link SourceFile} instances. - */ - private fileMappings: { [name: string]: SourceFile } = {}; - /** * All file names to find the base path from. */ private fileNames = new Set(); - private basePath?: string; /** * Create a new SourceHandler instance. @@ -44,28 +32,11 @@ 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 = {}; this.fileNames.clear(); - this.basePath = void 0; } /** @@ -73,20 +44,17 @@ 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. */ - private onDeclaration(context: Context, reflection: Reflection) { - const symbol = reflection.project.getSymbolFromReflection(reflection); - if (!symbol || this.disableSources) { - return; - } + private onDeclaration(_context: Context, reflection: Reflection) { + if (this.disableSources) return; - for (const node of symbol.declarations || []) { + const symbol = reflection.project.getSymbolFromReflection(reflection); + for (const node of symbol?.declarations || []) { const sourceFile = node.getSourceFile(); const fileName = sourceFile.fileName; this.fileNames.add(fileName); - const file = this.getSourceFile(fileName, context.project); let position: ts.LineAndCharacter; if (isNamedNode(node)) { @@ -101,17 +69,12 @@ export class SourcePlugin extends ConverterComponent { ); } - if (reflection instanceof DeclarationReflection) { - file.reflections.push(reflection); - } - reflection.sources ||= []; reflection.sources.push( new SourceReference( fileName, position.line + 1, - position.character, - file + position.character ) ); } @@ -123,39 +86,15 @@ 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]); - /** - * 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: Reflection) { - assert(this.basePath != null); - for (const source of reflection.sources ?? []) { - source.fileName = normalizePath( - relative(this.basePath, source.fileName) - ); + for (const refl of Object.values(context.project.reflections)) { + for (const source of refl.sources || []) { + source.fileName = normalizePath( + relative(basePath, source.fullFileName) + ); + } } } - - /** - * 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((file) => { - file.reflections = file.reflections.slice(); - }); - } } diff --git a/src/lib/models/reflections/project.ts b/src/lib/models/reflections/project.ts index 4efe31509..f37d8dcbc 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -1,4 +1,3 @@ -import type { SourceFile } from "../sources/index"; import { Reflection, TraverseProperty } from "./abstract"; import { ContainerReflection } from "./container"; import { ReferenceReflection } from "./reference"; @@ -33,11 +32,6 @@ export class ProjectReflection extends ContainerReflection { */ reflections: { [id: number]: Reflection } = {}; - /** - * A list of all source files within the project. - */ - files: SourceFile[] = []; - /** * The name of the project. * diff --git a/src/lib/models/sources/file.ts b/src/lib/models/sources/file.ts index a7ad9ee57..5753aecc6 100644 --- a/src/lib/models/sources/file.ts +++ b/src/lib/models/sources/file.ts @@ -1,8 +1,3 @@ -import * as Path from "path"; - -import type { ReflectionGroup } from "../ReflectionGroup"; -import type { RepositoryType } from "./repository"; -import type { DeclarationReflection } from ".."; import type { SourceReference as JSONSourceReference } from "../../serialization/schema"; /** @@ -12,14 +7,14 @@ import type { SourceReference as JSONSourceReference } from "../../serialization */ export class SourceReference { /** - * A reference to the corresponding file instance. + * The filename of the source file. */ - file: SourceFile; + fileName: string; /** - * The filename of the source file. + * The absolute filename of the source file. */ - fileName: string; + fullFileName: string; /** * The number of the line that emitted the declaration. @@ -36,16 +31,11 @@ export class SourceReference { */ url?: string; - constructor( - fileName: string, - line: number, - character: number, - file: SourceFile - ) { + constructor(fileName: string, line: number, character: number) { this.fileName = fileName; + this.fullFileName = fileName; this.line = line; this.character = character; - this.file = file; } toObject(): JSONSourceReference { @@ -57,62 +47,3 @@ export class SourceReference { }; } } - -/** - * 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. - */ - fullFileName: string; - - /** - * A trimmed version of the file name. Contains only the path relative to the - * determined base path. - */ - fileName: string; - - /** - * The base name of the file. - */ - name: string; - - /** - * A URL pointing to a page displaying the contents of this file. - */ - url?: string; - - /** - * The type of repository where this file is hosted. - */ - repositoryType?: RepositoryType; - - /** - * 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[]; - - /** - * 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); - } -} diff --git a/src/lib/models/sources/index.ts b/src/lib/models/sources/index.ts index 0e0d59d5b..28f44711b 100644 --- a/src/lib/models/sources/index.ts +++ b/src/lib/models/sources/index.ts @@ -1,3 +1,2 @@ -export { SourceFile } from "./file"; export { SourceReference } from "./file"; export { RepositoryType } from "./repository"; From f09a1e9b383bc18965a04b7ac9312e00234e6b6d Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 18:50:05 -0600 Subject: [PATCH 087/151] Move SourceLinkPlugin into SourcePlugin ... it belonged there anyways, since it was the only other thing touching SourceReference instances. Also add some benchmark helper functions. --- .eslintrc | 12 +- .github/workflows/ci.yml | 2 +- package.json | 3 - scripts/copy_test_files.js | 25 --- src/lib/converter/jsdoc.ts | 3 - src/lib/converter/plugins/SourcePlugin.ts | 69 +++++++- src/lib/converter/plugins/index.ts | 1 - .../repository.ts} | 147 +++--------------- src/lib/utils/loggers.ts | 1 + src/lib/utils/perf.ts | 70 +++++++++ ...eLinkPlugin.test.ts => Repository.test.ts} | 2 +- src/test/capture-screenshots.ts | 1 + 12 files changed, 177 insertions(+), 159 deletions(-) delete mode 100644 scripts/copy_test_files.js rename src/lib/converter/{plugins/SourceLinkPlugin.ts => utils/repository.ts} (61%) create mode 100644 src/lib/utils/perf.ts rename src/test/{SourceLinkPlugin.test.ts => Repository.test.ts} (98%) diff --git a/.eslintrc b/.eslintrc index 09bdeba12..91de3e34e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -51,9 +51,19 @@ // 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..78ea3470e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,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/package.json b/package.json index ad79e58eb..52ca4b83c 100644 --- a/package.json +++ b/package.json @@ -62,14 +62,11 @@ "/static" ], "scripts": { - "pretest": "node scripts/copy_test_files.js", "test": "mocha -r ts-node/register --config .config/mocha.fast.json", "build:c2": "node bin/typedoc --tsconfig src/test/converter2/tsconfig.json", - "pretest:full": "npm run pretest", "test:full": "nyc 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 .", 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/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index 7284161c6..6f38daef4 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -92,9 +92,6 @@ function convertJsDocInterface( symbol, exportSymbol ); - if (reflection.name === "ColumnType") { - console.log(declaration); - } reflection.comment = getJsDocComment( declaration, context.config, diff --git a/src/lib/converter/plugins/SourcePlugin.ts b/src/lib/converter/plugins/SourcePlugin.ts index d49e63f2f..8a9971226 100644 --- a/src/lib/converter/plugins/SourcePlugin.ts +++ b/src/lib/converter/plugins/SourcePlugin.ts @@ -7,8 +7,9 @@ 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 { dirname, relative } from "path"; import { SourceReference } from "../../models"; +import { gitIsInstalled, Repository } from "../utils/repository"; /** * A handler that attaches source file information to reflections. @@ -18,11 +19,27 @@ export class SourcePlugin extends ConverterComponent { @BindOption("disableSources") readonly disableSources!: boolean; + @BindOption("gitRevision") + readonly gitRevision!: string; + + @BindOption("gitRemote") + readonly gitRemote!: string; + /** * All file names to find the base path from. */ private fileNames = new Set(); + /** + * 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. */ @@ -36,6 +53,7 @@ export class SourcePlugin extends ConverterComponent { } private onEnd() { + // Should probably clear repositories/ignoredPaths here, but these aren't likely to change between runs... this.fileNames.clear(); } @@ -87,14 +105,63 @@ export class SourcePlugin extends ConverterComponent { */ private onBeginResolve(context: Context) { 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) ); } } } + + /** + * 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 = dirname(fileName); + const segments = dirName.split("/"); + for (let i = segments.length; i > 0; i--) { + if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) { + return; + } + } + + // Check for known repositories + for (const path of Object.keys(this.repositories)) { + if (fileName.toLowerCase().startsWith(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 + this.ignoredPaths.add(dirName); + } } diff --git a/src/lib/converter/plugins/index.ts b/src/lib/converter/plugins/index.ts index d261be893..29564d1f4 100644 --- a/src/lib/converter/plugins/index.ts +++ b/src/lib/converter/plugins/index.ts @@ -5,6 +5,5 @@ export { ImplementsPlugin } from "./ImplementsPlugin"; export { InheritDocPlugin } from "./InheritDocPlugin"; export { LinkResolverPlugin } from "./LinkResolverPlugin"; export { PackagePlugin } from "./PackagePlugin"; -export { SourceLinkPlugin } from "./SourceLinkPlugin"; export { SourcePlugin } from "./SourcePlugin"; export { TypePlugin } from "./TypePlugin"; diff --git a/src/lib/converter/plugins/SourceLinkPlugin.ts b/src/lib/converter/utils/repository.ts similarity index 61% rename from src/lib/converter/plugins/SourceLinkPlugin.ts rename to src/lib/converter/utils/repository.ts index f969ef117..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. * @@ -146,11 +143,15 @@ 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, @@ -161,6 +162,20 @@ export class Repository { ] .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; + } } /** @@ -190,118 +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 = new Set(); - - @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); - const segments = dirName.split("/"); - for (let i = segments.length; i > 0; i--) { - if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) { - return; - } - } - - // Check for known repositories - for (const path of Object.keys(this.repositories)) { - if (fileName.toLowerCase().startsWith(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 - this.ignoredPaths.add(dirName); - } - - /** - * 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; - - for (const reflection of Object.values(project.reflections)) { - if (reflection.sources) { - reflection.sources.forEach((source: SourceReference) => { - const repo = this.getRepository(source.fullFileName); - const url = repo?.getURL(source.fullFileName); - if (url) { - source.url = `${url}#${Repository.getLineNumberAnchor( - source.line, - repo!.type - )}`; - } - }); - } - } - } } diff --git a/src/lib/utils/loggers.ts b/src/lib/utils/loggers.ts index fbdbd63b8..a1d5632b7 100644 --- a/src/lib/utils/loggers.ts +++ b/src/lib/utils/loggers.ts @@ -254,6 +254,7 @@ export class ConsoleLogger extends Logger { } as const )[level]; + // eslint-disable-next-line no-console console[method](withContext(message, level, node)); } } 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/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/capture-screenshots.ts b/src/test/capture-screenshots.ts index 48963c313..66f8c83dd 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -128,6 +128,7 @@ export async function captureScreenshots( if (require.main == module) { captureRegressionScreenshots().catch((err) => { + // eslint-disable-next-line no-console console.error(err); process.exit(1); }); From e9c143f110dc31b5b53bdd7f09cd49acf9f768c5 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 19:32:21 -0600 Subject: [PATCH 088/151] Add support for the `@group` tag Resolves #1652 --- CHANGELOG.md | 6 +- src/lib/converter/comments/discovery.ts | 1 - src/lib/converter/context.ts | 2 + src/lib/converter/converter.ts | 84 ------------------ src/lib/converter/plugins/CategoryPlugin.ts | 3 + src/lib/converter/plugins/CommentPlugin.ts | 16 ++-- src/lib/converter/plugins/GroupPlugin.ts | 74 +++++++++++----- src/lib/models/ReflectionGroup.ts | 11 +-- src/lib/models/comments/comment.ts | 7 ++ src/lib/models/reflections/kind.ts | 4 +- .../output/themes/default/partials/icon.tsx | 9 -- src/lib/serialization/schema.ts | 2 +- src/lib/utils/sort.ts | 1 - src/test/behaviorTests.ts | 16 ++++ src/test/converter/alias/specs.json | 1 - .../class/specs-with-lump-categories.json | 87 +++---------------- src/test/converter/class/specs.json | 87 +++---------------- src/test/converter/comment/specs.json | 8 -- src/test/converter/declaration/specs.json | 9 -- src/test/converter/enum/specs.json | 7 -- src/test/converter/enum/specs.nodoc.json | 7 -- src/test/converter/exports/specs.json | 14 --- src/test/converter/function/specs.json | 18 ---- .../converter/inherit-param-doc/specs.json | 9 -- src/test/converter/inheritance/specs.json | 15 ---- src/test/converter/interface/specs.json | 27 ------ src/test/converter/js/specs.json | 12 --- src/test/converter/mixin/specs.json | 18 ---- src/test/converter/react/specs.json | 6 -- src/test/converter/types/specs.json | 19 ---- src/test/converter/variables/specs.json | 17 ---- src/test/converter/variables/specs.nodoc.json | 8 -- src/test/converter2/behavior/groupTag.ts | 15 ++++ src/test/issueTests.ts | 4 +- src/test/utils/sort.test.ts | 29 +++---- 35 files changed, 150 insertions(+), 503 deletions(-) create mode 100644 src/test/converter2/behavior/groupTag.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 370d59a3f..6b6f388d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Make comment parser options configurable (read tsdoc.json?). - Full support for declaration references, #262, #488, #1326, #1845. - Add support for additional comment styles, #1433. -- Add support for `@group` tags, #1652. - - Add support for `@eventProperty`, and rework `@event` to be equivalent, in defining an element to be part of the "Events" group. - Theme: Custom rendering for `@see` tags. - Theme: Show toggles for all modifier tags used in a project to allow users to filter by deprecated/alpha/beta, etc. - Add option to control default values (merge #1816. Same option? Different one since it's based on comments?) @@ -30,11 +28,13 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Constant variables which are interpreted as functions will no longer have the `ReflectionFlag.Const` flag set. - 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. +- 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 `ReflectionKind.Event`, the `@event` tag is now an alias for `@group Events`. - 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. - 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. diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index c290444e2..8f15590c2 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -73,7 +73,6 @@ const wantedKinds: Record = { [ReflectionKind.SetSignature]: [ts.SyntaxKind.SetAccessor], [ReflectionKind.ObjectLiteral]: [ts.SyntaxKind.ObjectLiteralExpression], [ReflectionKind.TypeAlias]: [ts.SyntaxKind.TypeAliasDeclaration], - [ReflectionKind.Event]: [], /// this needs to go away [ReflectionKind.Reference]: [ ts.SyntaxKind.NamespaceExport, ts.SyntaxKind.ExportSpecifier, diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index d8b501d5e..bcd4cb2ab 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -175,6 +175,7 @@ export class Context { // TypeDoc specific "@module", "@inheritDoc", + "@group", ]), inlineTags: new Set(["@link", "@inheritDoc", "@label"]), modifierTags: new Set([ @@ -185,6 +186,7 @@ export class Context { "@internal", "@readonly", "@packageDocumentation", + "@eventProperty", "@deprecated", "@alpha", "@beta", diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index df7004618..f49bd9348 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -171,90 +171,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. * diff --git a/src/lib/converter/plugins/CategoryPlugin.ts b/src/lib/converter/plugins/CategoryPlugin.ts index 59f1ea0c0..0f9dde1a8 100644 --- a/src/lib/converter/plugins/CategoryPlugin.ts +++ b/src/lib/converter/plugins/CategoryPlugin.ts @@ -175,6 +175,9 @@ 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) { const categories = new Set(); diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index b0ba3ddd9..5b5b40449 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -13,6 +13,7 @@ import { ReflectionType, SourceReference, TypeVisitor, + CommentTag, } from "../../models"; import { BindOption, @@ -97,14 +98,15 @@ export class CommentPlugin extends ConverterComponent { comment.removeModifier("@public"); } - if (comment.hasModifier("@event")) { - if (reflection.kindOf(ReflectionKind.CallSignature)) { - if (reflection.parent) { - reflection.parent.kind = ReflectionKind.Event; - } - } - reflection.kind = ReflectionKind.Event; + if ( + comment.hasModifier("@event") || + comment.hasModifier("@eventProperty") + ) { + comment.blockTags.push( + new CommentTag("@group", [{ kind: "text", text: "Events" }]) + ); comment.removeModifier("@event"); + comment.removeModifier("@eventProperty"); } if ( diff --git a/src/lib/converter/plugins/GroupPlugin.ts b/src/lib/converter/plugins/GroupPlugin.ts index 6f158773a..b17474410 100644 --- a/src/lib/converter/plugins/GroupPlugin.ts +++ b/src/lib/converter/plugins/GroupPlugin.ts @@ -9,7 +9,8 @@ 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. @@ -87,6 +88,45 @@ export class GroupPlugin extends ConverterComponent { } } + /** + * Extracts the groups for a given reflection. + * + * @privateRemarks + * If you change this, also update getCategories in CategoryPlugin accordingly. + */ + static 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)); + } + return groups; + } + /** * Create a grouped representation of the given list of reflections. * @@ -98,24 +138,17 @@ export class GroupPlugin extends ConverterComponent { static 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 GroupPlugin.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) => { @@ -125,14 +158,13 @@ export class GroupPlugin extends ConverterComponent { 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; + allPrivate &&= child.flags.isPrivate; + allProtected &&= + child.flags.isPrivate || child.flags.isProtected; + allExternal &&= child.flags.isExternal; if (child instanceof DeclarationReflection) { - allInherited = !!child.inheritedFrom && allInherited; + allInherited &&= !!child.inheritedFrom; } else { allInherited = false; } @@ -144,7 +176,7 @@ export class GroupPlugin extends ConverterComponent { group.allChildrenAreExternal = allExternal; }); - return groups; + return Array.from(groups.values()); } /** diff --git a/src/lib/models/ReflectionGroup.ts b/src/lib/models/ReflectionGroup.ts index ba79bc427..1625f11bd 100644 --- a/src/lib/models/ReflectionGroup.ts +++ b/src/lib/models/ReflectionGroup.ts @@ -1,4 +1,3 @@ -import type { ReflectionKind } from "./reflections/kind"; import type { ReflectionCategory } from "./ReflectionCategory"; import type { DeclarationReflection } from "."; import type { Serializer, JSONOutput } from "../serialization"; @@ -16,11 +15,6 @@ export class ReflectionGroup { */ title: string; - /** - * The original typescript kind of the children of this group. - */ - kind: ReflectionKind; - /** * All reflections of this group. */ @@ -61,11 +55,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; } /** @@ -78,7 +70,6 @@ export class ReflectionGroup { toObject(serializer: Serializer): JSONOutput.ReflectionGroup { return { title: this.title, - kind: this.kind, children: this.children.length > 0 ? this.children.map((child) => child.id) diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 835aee5b2..2f27d7dd8 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -212,6 +212,13 @@ export class Comment { return this.blockTags.find((tag) => tag.tag === tagName); } + /** + * Get all tags with the given tag name. + */ + 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 diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index 1a7077664..d9c7f5696 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -25,7 +25,6 @@ export enum ReflectionKind { SetSignature = 0x100000, ObjectLiteral = 0x200000, TypeAlias = 0x400000, - Event = 0x800000, Reference = 0x1000000, } @@ -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 | diff --git a/src/lib/output/themes/default/partials/icon.tsx b/src/lib/output/themes/default/partials/icon.tsx index 838524645..4474e46f6 100644 --- a/src/lib/output/themes/default/partials/icon.tsx +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -70,15 +70,6 @@ export const icons: Record JSX.Element | null> & UtilityIc [ReflectionKind.EnumMember]() { return this[ReflectionKind.Property](); }, - [ReflectionKind.Event]: () => - kindIcon( - , - "#7FDE21", - true - ), [ReflectionKind.Function]: () => kindIcon( , diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 33537b63c..b7063a4b3 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -100,7 +100,7 @@ type S = { // Reflections export interface ReflectionGroup - extends S { + extends S { children?: M.ReflectionGroup["children"][number]["id"][]; } diff --git a/src/lib/utils/sort.ts b/src/lib/utils/sort.ts index 0fb40a6a1..72b248043 100644 --- a/src/lib/utils/sort.ts +++ b/src/lib/utils/sort.ts @@ -115,7 +115,6 @@ const sorts: Record< ReflectionKind.TypeAlias, ReflectionKind.Constructor, - ReflectionKind.Event, ReflectionKind.Property, ReflectionKind.Variable, ReflectionKind.Function, diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 240dd16b4..8e0125269 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -118,6 +118,22 @@ export const behaviorTests: Record< 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( diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 39aa67184..a92caed4f 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -247,7 +247,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 8, 10, diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 5a85be5d4..3684d9696 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -231,7 +231,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 13, 14 @@ -239,14 +238,12 @@ }, { "title": "Accessors", - "kind": 262144, "children": [ 9 ] }, { "title": "Methods", - "kind": 2048, "children": [ 15, 17, @@ -409,14 +406,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8 ] }, { "title": "Variables", - "kind": 32, "children": [ 6, 7 @@ -424,7 +419,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 4 @@ -494,7 +488,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 60 ] @@ -585,14 +578,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 86 ] }, { "title": "Methods", - "kind": 2048, "children": [ 88 ] @@ -719,14 +710,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 75 ] }, { "title": "Properties", - "kind": 1024, "children": [ 79, 80, @@ -830,21 +819,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 63 ] }, { "title": "Properties", - "kind": 1024, "children": [ 65 ] }, { "title": "Methods", - "kind": 2048, "children": [ 66 ] @@ -972,21 +958,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 69 ] }, { "title": "Properties", - "kind": 1024, "children": [ 71 ] }, { "title": "Methods", - "kind": 2048, "children": [ 72 ] @@ -1360,14 +1343,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 26 ] }, { "title": "Properties", - "kind": 1024, "children": [ 29, 28, @@ -1376,7 +1357,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 36, 34, @@ -1903,14 +1883,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 42 ] }, { "title": "Properties", - "kind": 1024, "children": [ 52, 53, @@ -1920,7 +1898,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 57, 54, @@ -2020,14 +1997,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 84 ] @@ -2095,14 +2070,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 59 ] }, { "title": "Classes", - "kind": 128, "children": [ 85, 74, @@ -2115,7 +2088,6 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 90 ] @@ -2307,14 +2279,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 95 ] }, { "title": "Properties", - "kind": 1024, "children": [ 102, 100, @@ -2573,14 +2543,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 104 ] }, { "title": "Properties", - "kind": 1024, "children": [ 112, 113, @@ -2609,7 +2577,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 94, 103 @@ -2708,14 +2675,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 129 ] }, { "title": "Methods", - "kind": 2048, "children": [ 131 ] @@ -2904,7 +2869,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 127 ] @@ -2994,14 +2958,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 128 ] }, { "title": "Functions", - "kind": 64, "children": [ 115, 123, @@ -3056,8 +3018,8 @@ { "id": 162, "name": "EVENT_CLICK", - "kind": 8388608, - "kindString": "Event", + "kind": 1024, + "kindString": "Property", "flags": { "isStatic": true }, @@ -3087,14 +3049,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 163 ] }, { "title": "Events", - "kind": 8388608, "children": [ 162 ] @@ -3113,7 +3073,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 161 ] @@ -3164,8 +3123,8 @@ { "id": 135, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 2048, + "kindString": "Method", "flags": {}, "sources": [ { @@ -3197,8 +3156,8 @@ { "id": 136, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3296,8 +3255,8 @@ { "id": 142, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3395,8 +3354,8 @@ { "id": 148, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3494,8 +3453,8 @@ { "id": 154, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3596,7 +3555,6 @@ "groups": [ { "title": "Events", - "kind": 8388608, "children": [ 135 ] @@ -3615,7 +3573,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 134 ] @@ -3842,14 +3799,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 167 ] }, { "title": "Properties", - "kind": 1024, "children": [ 171, 172 @@ -3857,7 +3812,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 173 ] @@ -4111,14 +4065,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 177 ] }, { "title": "Properties", - "kind": 1024, "children": [ 180, 181 @@ -4126,7 +4078,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 182 ] @@ -4158,7 +4109,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 166, 176 @@ -4363,21 +4313,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 186 ] }, { "title": "Properties", - "kind": 1024, "children": [ 188 ] }, { "title": "Accessors", - "kind": 262144, "children": [ 189, 193, @@ -4398,7 +4345,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 185 ] @@ -4499,14 +4445,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 200 ] }, { "title": "Methods", - "kind": 2048, "children": [ 202 ] @@ -4525,7 +4469,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 199 ] @@ -4624,14 +4567,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 211 ] }, { "title": "Properties", - "kind": 1024, "children": [ 214 ] @@ -4759,14 +4700,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 206 ] }, { "title": "Properties", - "kind": 1024, "children": [ 208, 209 @@ -4786,7 +4725,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 210, 205 @@ -4806,7 +4744,6 @@ "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 8ccaa7560..01668a0e8 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -231,7 +231,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 13, 14 @@ -239,14 +238,12 @@ }, { "title": "Accessors", - "kind": 262144, "children": [ 9 ] }, { "title": "Methods", - "kind": 2048, "children": [ 15, 17, @@ -409,14 +406,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8 ] }, { "title": "Variables", - "kind": 32, "children": [ 6, 7 @@ -424,7 +419,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 4 @@ -494,7 +488,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 60 ] @@ -585,14 +578,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 86 ] }, { "title": "Methods", - "kind": 2048, "children": [ 88 ] @@ -719,14 +710,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 75 ] }, { "title": "Properties", - "kind": 1024, "children": [ 79, 80, @@ -830,21 +819,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 63 ] }, { "title": "Properties", - "kind": 1024, "children": [ 65 ] }, { "title": "Methods", - "kind": 2048, "children": [ 66 ] @@ -972,21 +958,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 69 ] }, { "title": "Properties", - "kind": 1024, "children": [ 71 ] }, { "title": "Methods", - "kind": 2048, "children": [ 72 ] @@ -1360,14 +1343,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 26 ] }, { "title": "Properties", - "kind": 1024, "children": [ 29, 28, @@ -1376,7 +1357,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 36, 34, @@ -1899,14 +1879,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 42 ] }, { "title": "Properties", - "kind": 1024, "children": [ 52, 53, @@ -1916,7 +1894,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 57, 54, @@ -2016,14 +1993,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 84 ] @@ -2091,14 +2066,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 59 ] }, { "title": "Classes", - "kind": 128, "children": [ 85, 74, @@ -2111,7 +2084,6 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 90 ] @@ -2303,14 +2275,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 95 ] }, { "title": "Properties", - "kind": 1024, "children": [ 102, 100, @@ -2569,14 +2539,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 104 ] }, { "title": "Properties", - "kind": 1024, "children": [ 112, 113, @@ -2605,7 +2573,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 94, 103 @@ -2704,14 +2671,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 129 ] }, { "title": "Methods", - "kind": 2048, "children": [ 131 ] @@ -2900,7 +2865,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 127 ] @@ -2990,14 +2954,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 128 ] }, { "title": "Functions", - "kind": 64, "children": [ 115, 123, @@ -3052,8 +3014,8 @@ { "id": 162, "name": "EVENT_CLICK", - "kind": 8388608, - "kindString": "Event", + "kind": 1024, + "kindString": "Property", "flags": { "isStatic": true }, @@ -3083,14 +3045,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 163 ] }, { "title": "Events", - "kind": 8388608, "children": [ 162 ] @@ -3109,7 +3069,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 161 ] @@ -3160,8 +3119,8 @@ { "id": 135, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 2048, + "kindString": "Method", "flags": {}, "sources": [ { @@ -3193,8 +3152,8 @@ { "id": 136, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3292,8 +3251,8 @@ { "id": 142, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3391,8 +3350,8 @@ { "id": 148, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3490,8 +3449,8 @@ { "id": 154, "name": "on", - "kind": 8388608, - "kindString": "Event", + "kind": 4096, + "kindString": "Call signature", "flags": {}, "comment": { "summary": [ @@ -3592,7 +3551,6 @@ "groups": [ { "title": "Events", - "kind": 8388608, "children": [ 135 ] @@ -3611,7 +3569,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 134 ] @@ -3838,14 +3795,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 167 ] }, { "title": "Properties", - "kind": 1024, "children": [ 171, 172 @@ -3853,7 +3808,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 173 ] @@ -4107,14 +4061,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 177 ] }, { "title": "Properties", - "kind": 1024, "children": [ 180, 181 @@ -4122,7 +4074,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 182 ] @@ -4154,7 +4105,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 166, 176 @@ -4359,21 +4309,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 186 ] }, { "title": "Properties", - "kind": 1024, "children": [ 188 ] }, { "title": "Accessors", - "kind": 262144, "children": [ 189, 193, @@ -4394,7 +4341,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 185 ] @@ -4495,14 +4441,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 200 ] }, { "title": "Methods", - "kind": 2048, "children": [ 202 ] @@ -4521,7 +4465,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 199 ] @@ -4620,14 +4563,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 211 ] }, { "title": "Properties", - "kind": 1024, "children": [ 214 ] @@ -4755,14 +4696,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 206 ] }, { "title": "Properties", - "kind": 1024, "children": [ 208, 209 @@ -4782,7 +4721,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 210, 205 @@ -4802,7 +4740,6 @@ "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 21, diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index d5f550c7a..4ec768082 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -148,21 +148,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] }, { "title": "Properties", - "kind": 1024, "children": [ 5 ] }, { "title": "Methods", - "kind": 2048, "children": [ 19 ] @@ -181,7 +178,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2 ] @@ -294,7 +290,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 27 ] @@ -410,7 +405,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 32 ] @@ -518,7 +512,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 37 ] @@ -537,7 +530,6 @@ "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 1358bf621..266b0ccd4 100644 --- a/src/test/converter/declaration/specs.json +++ b/src/test/converter/declaration/specs.json @@ -62,14 +62,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] }, { "title": "Properties", - "kind": 1024, "children": [ 5 ] @@ -109,14 +107,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2 ] }, { "title": "Variables", - "kind": 32, "children": [ 6 ] @@ -170,7 +166,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 9 ] @@ -217,7 +212,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 12 ] @@ -236,7 +230,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 8, 11 @@ -286,7 +279,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 15 ] @@ -305,7 +297,6 @@ "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 90bfcb313..9e964666c 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -87,14 +87,12 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 12 ] }, { "title": "Functions", - "kind": 64, "children": [ 10 ] @@ -168,7 +166,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 14, 15 @@ -275,7 +272,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 6, 7, @@ -389,7 +385,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 2, 3, @@ -410,14 +405,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 9 ] }, { "title": "Enumerations", - "kind": 8, "children": [ 13, 5, diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index 90bfcb313..9e964666c 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -87,14 +87,12 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 12 ] }, { "title": "Functions", - "kind": 64, "children": [ 10 ] @@ -168,7 +166,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 14, 15 @@ -275,7 +272,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 6, 7, @@ -389,7 +385,6 @@ "groups": [ { "title": "Enumeration members", - "kind": 16, "children": [ 2, 3, @@ -410,14 +405,12 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 9 ] }, { "title": "Enumerations", - "kind": 8, "children": [ 13, 5, diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 997b0381e..292000bfc 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -277,14 +277,12 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 25 ] }, { "title": "Variables", - "kind": 32, "children": [ 23, 21, @@ -399,7 +397,6 @@ "groups": [ { "title": "References", - "kind": 16777216, "children": [ 46, 39, @@ -413,14 +410,12 @@ }, { "title": "Namespaces", - "kind": 4, "children": [ 20 ] }, { "title": "Functions", - "kind": 64, "children": [ 15, 26 @@ -499,7 +494,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 2 ] @@ -547,7 +541,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 7 ] @@ -647,14 +640,12 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 13 ] }, { "title": "Functions", - "kind": 64, "children": [ 9 ] @@ -829,7 +820,6 @@ "groups": [ { "title": "References", - "kind": 16777216, "children": [ 34, 31, @@ -838,21 +828,18 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 35 ] }, { "title": "Variables", - "kind": 32, "children": [ 30 ] }, { "title": "Functions", - "kind": 64, "children": [ 36 ] @@ -871,7 +858,6 @@ "groups": [ { "title": "Modules", - "kind": 2, "children": [ 14, 1, diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 9d60cb1c8..990c03b79 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -50,7 +50,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 81 ] @@ -189,14 +188,12 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 60 ] }, { "title": "Functions", - "kind": 64, "children": [ 56, 58 @@ -408,14 +405,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 93 ] }, { "title": "Methods", - "kind": 2048, "children": [ 97, 95, @@ -1099,7 +1094,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 29, 28, @@ -1261,7 +1255,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 44, 43, @@ -1415,7 +1408,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 36, 35, @@ -2176,7 +2168,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 51 ] @@ -2246,7 +2237,6 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 80, 55 @@ -2254,14 +2244,12 @@ }, { "title": "Classes", - "kind": 128, "children": [ 86 ] }, { "title": "Functions", - "kind": 64, "children": [ 99, 67, @@ -2570,7 +2558,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 121, 126, @@ -2643,7 +2630,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 141, 140 @@ -2793,7 +2779,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 136, 135, @@ -2820,14 +2805,12 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 139 ] }, { "title": "Functions", - "kind": 64, "children": [ 131 ] @@ -2846,7 +2829,6 @@ "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 c31fd5618..96cb13b16 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -115,14 +115,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 7 ] }, { "title": "Methods", - "kind": 2048, "children": [ 9 ] @@ -254,14 +252,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 14 ] }, { "title": "Methods", - "kind": 2048, "children": [ 16 ] @@ -393,14 +389,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 21 ] }, { "title": "Methods", - "kind": 2048, "children": [ 23 ] @@ -501,7 +495,6 @@ "groups": [ { "title": "Methods", - "kind": 2048, "children": [ 2 ] @@ -537,7 +530,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 6, 13, @@ -546,7 +538,6 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 1 ] diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 79b3b108c..5d4454dd7 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -120,14 +120,12 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 15 ] }, { "title": "Methods", - "kind": 2048, "children": [ 16 ] @@ -256,14 +254,12 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 21 ] }, { "title": "Methods", - "kind": 2048, "children": [ 22 ] @@ -602,7 +598,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 14, 20 @@ -610,7 +605,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 2, 7, @@ -730,14 +724,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 36 ] }, { "title": "Properties", - "kind": 1024, "children": [ 38, 35 @@ -790,7 +782,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 33 ] @@ -870,14 +861,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 29 ] }, { "title": "Properties", - "kind": 1024, "children": [ 28 ] @@ -929,14 +918,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 34 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 32, 27 @@ -944,7 +931,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 31 ] @@ -963,7 +949,6 @@ "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 4b0d95ce2..e159ddda7 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -146,7 +146,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] @@ -180,7 +179,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 2, 13 @@ -377,7 +375,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 21, 18, @@ -386,7 +383,6 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 24 ] @@ -499,21 +495,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 31 ] }, { "title": "Properties", - "kind": 1024, "children": [ 33 ] }, { "title": "Methods", - "kind": 2048, "children": [ 34 ] @@ -569,14 +562,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 30 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 29 ] @@ -982,21 +973,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 82 ] }, { "title": "Properties", - "kind": 1024, "children": [ 85 ] }, { "title": "Methods", - "kind": 2048, "children": [ 86, 97, @@ -1317,14 +1305,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 50 ] }, { "title": "Properties", - "kind": 1024, "children": [ 60, 58, @@ -1334,7 +1320,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 61 ] @@ -1621,7 +1606,6 @@ "groups": [ { "title": "Methods", - "kind": 2048, "children": [ 65, 76, @@ -1835,7 +1819,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 45, 43, @@ -1844,7 +1827,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 46 ] @@ -1879,7 +1861,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 81, 49 @@ -1887,7 +1868,6 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 64, 38, @@ -1908,7 +1888,6 @@ "groups": [ { "title": "Namespaces", - "kind": 4, "children": [ 37 ] @@ -1960,7 +1939,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 104 ] @@ -2017,7 +1995,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 106 ] @@ -2136,7 +2113,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 110, 111, @@ -2305,7 +2281,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 116, 117, @@ -2340,7 +2315,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 103, 105, @@ -2362,7 +2336,6 @@ "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 14, diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index efd64f3ff..d7e727172 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -75,14 +75,12 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 5 ] }, { "title": "Functions", - "kind": 64, "children": [ 2 ] @@ -161,7 +159,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 19, 18 @@ -207,7 +204,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 16 ] @@ -529,7 +525,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 24 ] @@ -577,7 +572,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 26 ] @@ -867,7 +861,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 13, 12 @@ -936,7 +929,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 17, 15 @@ -944,7 +936,6 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 14, 44, @@ -960,14 +951,12 @@ }, { "title": "Variables", - "kind": 32, "children": [ 10 ] }, { "title": "Functions", - "kind": 64, "children": [ 7 ] @@ -986,7 +975,6 @@ "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 db4afb32e..941e557d4 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -93,21 +93,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 14 ] }, { "title": "Properties", - "kind": 1024, "children": [ 16 ] }, { "title": "Methods", - "kind": 2048, "children": [ 17 ] @@ -434,14 +431,12 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 61 ] }, { "title": "Properties", - "kind": 1024, "children": [ 74, 63, @@ -451,7 +446,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 75, 64, @@ -510,7 +504,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 60 ] @@ -737,7 +730,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 30, 26 @@ -745,7 +737,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 31, 27 @@ -1013,7 +1004,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 48, 44, @@ -1022,7 +1012,6 @@ }, { "title": "Methods", - "kind": 2048, "children": [ 49, 45, @@ -1432,7 +1421,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 24 ] @@ -1558,7 +1546,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 38 ] @@ -1679,7 +1666,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 56 ] @@ -1709,7 +1695,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 13, 58 @@ -1717,7 +1702,6 @@ }, { "title": "Interfaces", - "kind": 256, "children": [ 25, 39 @@ -1725,7 +1709,6 @@ }, { "title": "Type aliases", - "kind": 4194304, "children": [ 6, 1, @@ -1735,7 +1718,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 19, 33, diff --git a/src/test/converter/react/specs.json b/src/test/converter/react/specs.json index 9f44162b4..6e9cdfb88 100644 --- a/src/test/converter/react/specs.json +++ b/src/test/converter/react/specs.json @@ -108,21 +108,18 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 5 ] }, { "title": "Properties", - "kind": 1024, "children": [ 8 ] }, { "title": "Methods", - "kind": 2048, "children": [ 9 ] @@ -186,7 +183,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 3, 2 @@ -206,14 +202,12 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 4 ] }, { "title": "Interfaces", - "kind": 256, "children": [ 1 ] diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index 693f474cf..f706bafe6 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -216,7 +216,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 8, 2, @@ -227,7 +226,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 3, 5, @@ -388,7 +386,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 15, 12, @@ -704,7 +701,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 32, 30 @@ -712,7 +708,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 26, 22 @@ -788,7 +783,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 37 ] @@ -811,7 +805,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 35 ] @@ -882,14 +875,12 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 40 ] }, { "title": "Variables", - "kind": 32, "children": [ 39 ] @@ -1303,7 +1294,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 50, 42, @@ -1314,7 +1304,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 51, 43, @@ -1431,7 +1420,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 57, 58 @@ -1503,7 +1491,6 @@ "groups": [ { "title": "Type aliases", - "kind": 4194304, "children": [ 54, 55, @@ -1512,7 +1499,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 53 ] @@ -1580,7 +1566,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 62 ] @@ -1641,7 +1626,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 64 ] @@ -1804,7 +1788,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 68, 67, @@ -1825,7 +1808,6 @@ "groups": [ { "title": "Interfaces", - "kind": 256, "children": [ 61, 63, @@ -1846,7 +1828,6 @@ "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 11, diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 643ec0314..11eb727a5 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -67,7 +67,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] @@ -138,7 +137,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 10 ] @@ -203,7 +201,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 13 ] @@ -343,7 +340,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2, 9, @@ -352,7 +348,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 7, 8 @@ -665,7 +660,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 22, 23, @@ -682,7 +676,6 @@ }, { "title": "Functions", - "kind": 64, "children": [ 16 ] @@ -994,7 +987,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 58, 64, @@ -1296,7 +1288,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 84, 85 @@ -1343,7 +1334,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 86, 79, @@ -1434,7 +1424,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 89, 90, @@ -1678,7 +1667,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 45, 46 @@ -1723,7 +1711,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 47, 40, @@ -1811,7 +1798,6 @@ "groups": [ { "title": "Properties", - "kind": 1024, "children": [ 48, 49, @@ -1836,7 +1822,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 50, 70, @@ -1999,7 +1984,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 93, 94, @@ -2023,7 +2007,6 @@ "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 cc11db744..d4a1a6d7b 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -67,7 +67,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 3 ] @@ -138,7 +137,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 10 ] @@ -203,7 +201,6 @@ "groups": [ { "title": "Constructors", - "kind": 512, "children": [ 13 ] @@ -343,7 +340,6 @@ "groups": [ { "title": "Classes", - "kind": 128, "children": [ 2, 9, @@ -352,7 +348,6 @@ }, { "title": "Variables", - "kind": 32, "children": [ 7, 8 @@ -428,7 +423,6 @@ "groups": [ { "title": "Functions", - "kind": 64, "children": [ 16 ] @@ -539,7 +533,6 @@ "groups": [ { "title": "Variables", - "kind": 32, "children": [ 22, 20 @@ -559,7 +552,6 @@ "groups": [ { "title": "Modules", - "kind": 2, "children": [ 1, 15, 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/issueTests.ts b/src/test/issueTests.ts index 328e8710c..b7ffe4708 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -316,9 +316,7 @@ export const issueTests: { const Foo = query(project, "Foo"); ok(Foo.type instanceof ReflectionType); - const group = project.groups?.find( - (g) => g.kind === ReflectionKind.TypeAlias - ); + const group = project.groups?.find((g) => g.title === "Type aliases"); ok(group); const cat = group.categories?.find( (cat) => cat.title === "My category" diff --git a/src/test/utils/sort.test.ts b/src/test/utils/sort.test.ts index 562144b2a..bbb78e0a8 100644 --- a/src/test/utils/sort.test.ts +++ b/src/test/utils/sort.test.ts @@ -163,33 +163,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"]); From 777fef346303e2f7b104b1d7889f442879b59759 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 19:34:06 -0600 Subject: [PATCH 089/151] Remove gap in ReflectionKind enum --- CHANGELOG.md | 2 +- src/lib/models/reflections/kind.ts | 2 +- src/test/converter/exports/specs.json | 22 +++++++++++----------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6f388d7..f69fff1b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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 `ReflectionKind.Event`, the `@event` tag is now an alias for `@group Events`. +- 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 diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index d9c7f5696..a59a65626 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -25,7 +25,7 @@ export enum ReflectionKind { SetSignature = 0x100000, ObjectLiteral = 0x200000, TypeAlias = 0x400000, - Reference = 0x1000000, + Reference = 0x800000, } /** @hidden */ diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 292000bfc..36d8780e1 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -14,7 +14,7 @@ { "id": 46, "name": "GH1453Helper", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -30,7 +30,7 @@ { "id": 39, "name": "Mod", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -46,7 +46,7 @@ { "id": 41, "name": "Mod2", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { @@ -70,7 +70,7 @@ { "id": 40, "name": "ModDefault", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -86,7 +86,7 @@ { "id": 45, "name": "ThisModule", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -102,7 +102,7 @@ { "id": 42, "name": "a", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -118,7 +118,7 @@ { "id": 43, "name": "b", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { @@ -142,7 +142,7 @@ { "id": 38, "name": "c", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -670,7 +670,7 @@ { "id": 34, "name": "ThisModule", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "sources": [ @@ -686,7 +686,7 @@ { "id": 31, "name": "b", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { @@ -710,7 +710,7 @@ { "id": 32, "name": "c", - "kind": 16777216, + "kind": 8388608, "kindString": "Reference", "flags": {}, "comment": { From 520c5a4b9f596ae3b0f7fe19caf7fe6ec5a5d125 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 19:42:26 -0600 Subject: [PATCH 090/151] Drop support for Node 12 --- .github/workflows/ci.yml | 4 +--- CHANGELOG.md | 1 + package.json | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 78ea3470e..cc0862450 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", "16", "17"] name: Node ${{ matrix.node }} steps: - name: Checkout repository diff --git a/CHANGELOG.md b/CHANGELOG.md index f69fff1b4..193c4ab02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi ### Breaking Changes +- Node 12 is no longer officially supported as it is has gone end of life as of 2022-04-30. It might still work, but may stop working at any time. - `@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. diff --git a/package.json b/package.json index 52ca4b83c..214fe44b0 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,7 @@ "url": "https://github.com/TypeStrong/TypeDoc/issues" }, "engines": { - "node": ">= 12.10.0" + "node": ">= 14" }, "dependencies": { "lunr": "^2.3.9", From d8f0a0b87f3a56f48d27b48f591777a621332bc7 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 16 Apr 2022 19:47:49 -0600 Subject: [PATCH 091/151] [skip ci] Fixed missing entry in changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 193c4ab02..aaa25753c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. From 59301b1820870d28ca81138aa5a61bce7259d2c2 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 17 Apr 2022 16:21:42 -0600 Subject: [PATCH 092/151] Update target for Node 14 --- tsconfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tsconfig.json b/tsconfig.json index ae806a39b..e3b46f43b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "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"], From 9f846e16f89cdd60302c93e272de671744cd662f Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 17 Apr 2022 16:25:18 -0600 Subject: [PATCH 093/151] Bump version to 0.23.0-beta.0 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3b4e6e5a6..59d4ea29e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.22.15", + "version": "0.23.0-beta.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.22.15", + "version": "0.23.0-beta.0", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", @@ -40,7 +40,7 @@ "typescript": "^4.6.3" }, "engines": { - "node": ">= 12.10.0" + "node": ">= 14" }, "peerDependencies": { "typescript": "4.0.x || 4.1.x || 4.2.x || 4.3.x || 4.4.x || 4.5.x || 4.6.x" diff --git a/package.json b/package.json index 214fe44b0..c26afe2f0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.22.15", + "version": "0.23.0-beta.0", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": "./dist/index.js", From 3dd21595582c16fc2d0010bac541db5e486fcffa Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 19 Apr 2022 15:59:17 -0600 Subject: [PATCH 094/151] Added support for custom filters based on modifier tags --- .config/typedoc.json | 10 +- CHANGELOG.md | 3 +- scripts/generate_options_schema.js | 32 ++++++- .../output/themes/default/DefaultTheme.tsx | 36 ++++--- .../themes/default/partials/comment.tsx | 7 +- .../themes/default/partials/navigation.tsx | 93 ++++++++++--------- src/lib/output/themes/lib.tsx | 4 + src/lib/utils/options/declaration.ts | 7 +- src/lib/utils/options/sources/typedoc.ts | 26 +++++- 9 files changed, 141 insertions(+), 77 deletions(-) diff --git a/.config/typedoc.json b/.config/typedoc.json index d7c076691..68a9dec97 100644 --- a/.config/typedoc.json +++ b/.config/typedoc.json @@ -12,13 +12,19 @@ "entryPoints": ["../src"], "entryPointStrategy": "Resolve", "excludeExternals": true, - "excludePrivate": false, - "excludeInternal": true, + "excludeInternal": false, "treatWarningsAsErrors": false, "validation": { "notExported": true, "invalidLink": true, "notDocumented": false }, + "visibilityFilters": { + "protected": false, + "private": false, + "inherited": true, + "external": false, + "@internal": false + }, "logLevel": "Verbose" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 050e318b8..2cab2a298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Full support for declaration references, #262, #488, #1326, #1845. - Add support for additional comment styles, #1433. - Theme: Custom rendering for `@see` tags. -- Theme: Show toggles for all modifier tags used in a project to allow users to filter by deprecated/alpha/beta, etc. - - Add option to control default values (merge #1816. Same option? Different one since it's based on comments?) ### Breaking Changes @@ -57,6 +55,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - Correctly detect optional parameters in JavaScript projects using JSDoc, #1804. - Fixed identical anchor links for reflections with the same name, #1845. - JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. +- Corrected schema generation for https://typedoc.org/schema.json ### Thanks! diff --git a/scripts/generate_options_schema.js b/scripts/generate_options_schema.js index 460ef817d..ba378ffe7 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,21 @@ 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"; + const output = JSON.stringify(schema, null, "\t"); if (process.argv.length > 2) { diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index 8c634a965..acd139170 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -150,9 +150,10 @@ export class DefaultTheme extends Theme { * @param event An event object describing the current render operation. */ private onRendererBegin(event: RendererEvent) { + 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); + DefaultTheme.applyReflectionClasses(reflection, filters); } } } @@ -254,7 +255,7 @@ 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[] = []; classes.push(DefaultTheme.toStyleClass("tsd-kind-" + ReflectionKind[reflection.kind])); @@ -265,17 +266,24 @@ export class DefaultTheme extends Theme { // Filter classes should match up with the settings function in // partials/navigation.tsx. - 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.isExternal) { - classes.push("tsd-is-external"); + 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 (reflection.comment?.hasModifier(key as `@${string}`)) { + classes.push(DefaultTheme.toStyleClass(`tsd-is-${key.substring(1)}`)); + } + } } reflection.cssClasses = classes.join(" "); @@ -283,7 +291,7 @@ export class DefaultTheme extends Theme { /** * 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/partials/comment.tsx b/src/lib/output/themes/default/partials/comment.tsx index 76c5b7969..6bc82646c 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -1,10 +1,7 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; import { assertNever, JSX, Raw } from "../../../../utils"; import type { CommentDisplayPart, Reflection } from "../../../../models"; - -function humanize(text: string) { - return text.substring(1, 2).toUpperCase() + text.substring(2).replace(/[a-z][A-Z]/g, (x) => `${x[0]} ${x[1]}`); -} +import { camelToTitleCase } from "../../lib"; function displayPartsToMarkdown(parts: CommentDisplayPart[], urlTo: DefaultThemeRenderContext["urlTo"]) { const result: string[] = []; @@ -57,7 +54,7 @@ export function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: R {props.comment.blockTags.map((item) => ( <> -

      {humanize(item.tag)}

      +

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

      ))} diff --git a/src/lib/output/themes/default/partials/navigation.tsx b/src/lib/output/themes/default/partials/navigation.tsx index e2afe5168..8283eaadd 100644 --- a/src/lib/output/themes/default/partials/navigation.tsx +++ b/src/lib/output/themes/default/partials/navigation.tsx @@ -1,7 +1,7 @@ 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"; @@ -15,42 +15,45 @@ export function navigation(context: DefaultThemeRenderContext, props: PageEvent< ); } +function buildFilterItem(name: string, displayName: string, defaultValue: boolean) { + return ( +
    • + +
    • + ); +} + function settings(context: DefaultThemeRenderContext) { - const defaultFilters = context.options.getValue("visibilityFilters"); + const defaultFilters = context.options.getValue("visibilityFilters") as Record; - const filters: Array = []; - if (!context.options.getValue("excludeProtected")) { - filters.push("protected"); - } - if (!context.options.getValue("excludePrivate")) { - filters.push("private"); - } - if (!context.options.getValue("excludeExternals")) { - filters.push("external"); + 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])); + } } - filters.push("inherited"); // Settings panel above navigation - const visibilityOptions = filters.map((name) => { - const value = name.charAt(0).toUpperCase() + name.slice(1); - return ( -
    • - -
    • - ); - }); - return (
      @@ -58,21 +61,23 @@ function settings(context: DefaultThemeRenderContext) {

      {icons.chevronDown()} Settings

      -
      -

      Member Visibility

      -
      -
        {...visibilityOptions}
      -
      + {visibilityOptions.length && ( +
      +

      Member Visibility

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

      Theme

      +
      -
      -

      Theme

      - -
      ); diff --git a/src/lib/output/themes/lib.tsx b/src/lib/output/themes/lib.tsx index 291d63789..4df586a4c 100644 --- a/src/lib/output/themes/lib.tsx +++ b/src/lib/output/themes/lib.tsx @@ -107,3 +107,7 @@ 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]}`); +} diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index fa9496822..110521f27 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -82,12 +82,7 @@ export interface TypeDocOptionMap { lightHighlightTheme: ShikiTheme; darkHighlightTheme: ShikiTheme; customCss: string; - visibilityFilters: { - private: boolean; - protected: boolean; - inherited: boolean; - external: boolean; - }; + visibilityFilters: unknown; name: string; includeVersion: boolean; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 92a0e1e87..246b00f09 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -37,13 +37,35 @@ export function addTypeDocOptions(options: Pick) { options.addDeclaration({ name: "visibilityFilters", help: "Specify the default visibility for builtin filters and additional filters according to modifier tags.", - type: ParameterType.Flags, - defaults: { + 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({ From 606f6f7b3a8a6bd4eb5fcd4e956e231a100371f8 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 19 Apr 2022 16:03:58 -0600 Subject: [PATCH 095/151] Bump version to 0.23.0-beta.1 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 59d4ea29e..ccb731e08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.23.0-beta.0", + "version": "0.23.0-beta.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.23.0-beta.0", + "version": "0.23.0-beta.1", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index 7595af348..9f6aff0c9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.23.0-beta.0", + "version": "0.23.0-beta.1", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": "./dist/index.js", From 2f44a70e7b7e38ca3a7cc440951815f5677edb39 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 23 Apr 2022 12:43:52 -0600 Subject: [PATCH 096/151] Add more line breaks in output and a cache for icons Resolves #1923 --- CHANGELOG.md | 1 + src/lib/output/renderer.ts | 2 + .../output/themes/default/partials/icon.tsx | 77 +++++++++++++------ .../output/themes/default/partials/index.tsx | 23 +++--- src/lib/utils/jsx.elements.ts | 18 +++++ src/lib/utils/jsx.ts | 20 +++++ src/test/capture-screenshots.ts | 5 +- 7 files changed, 109 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cab2a298..000dcb489 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. ### Bug Fixes diff --git a/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index 472336a5b..9b37f00d9 100644 --- a/src/lib/output/renderer.ts +++ b/src/lib/output/renderer.ts @@ -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. @@ -250,6 +251,7 @@ export class Renderer extends ChildableComponent< if (!output.isDefaultPrevented) { output.urls.forEach((mapping: UrlMapping) => { + clearSeenIconCache(); this.renderDocument(output.createPageEvent(mapping)); }); diff --git a/src/lib/output/themes/default/partials/icon.tsx b/src/lib/output/themes/default/partials/icon.tsx index 4474e46f6..ab861313b 100644 --- a/src/lib/output/themes/default/partials/icon.tsx +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -3,26 +3,53 @@ import { JSX } from "../../../../utils"; type UtilityIcons = Record<"chevronDown" | "checkbox" | "menu" | "search" | "chevronSmall", () => JSX.Element>; -const kindIcon = (letterPath: JSX.Element, color: string, circular = false) => ( - - - {letterPath} - -); +const seenIcons = new Set(); + +export function clearSeenIconCache() { + seenIcons.clear(); +} + +const kindIcon = (kind: ReflectionKind, letterPath: JSX.Element, color: string, circular = false) => { + const content: JSX.Element[] = []; + + if (seenIcons.has(kind)) { + content.push(); + content.push(); + } else { + seenIcons.add(kind); + content.push( + + ); + content.push({ + ...letterPath, + props: { + ...letterPath.props, + id: `icon-text-${kind}`, + }, + }); + } + + return ( + + {content} + + ); +}; export const icons: Record JSX.Element | null> & UtilityIcons = { - [ReflectionKind.All]: () => null, [ReflectionKind.Accessor]: () => kindIcon( + ReflectionKind.Accessor, JSX.Element | null> & UtilityIc }, [ReflectionKind.Class]: () => kindIcon( + ReflectionKind.Class, JSX.Element | null> & UtilityIc }, [ReflectionKind.Constructor]: () => kindIcon( + ReflectionKind.Constructor, JSX.Element | null> & UtilityIc }, [ReflectionKind.Enum]: () => kindIcon( + ReflectionKind.Enum, JSX.Element | null> & UtilityIc }, [ReflectionKind.Function]: () => kindIcon( + ReflectionKind.Function, , "var(--color-ts-function)" ), @@ -84,9 +115,9 @@ export const icons: Record JSX.Element | null> & UtilityIc [ReflectionKind.IndexSignature]() { return this[ReflectionKind.Property](); }, - [ReflectionKind.Inheritable]: () => null, [ReflectionKind.Interface]: () => kindIcon( + ReflectionKind.Interface, JSX.Element | null> & UtilityIc ), [ReflectionKind.Method]: () => kindIcon( + ReflectionKind.Method, JSX.Element | null> & UtilityIc [ReflectionKind.Namespace]: () => kindIcon( + ReflectionKind.Namespace, JSX.Element | null> & UtilityIc }, [ReflectionKind.Property]: () => kindIcon( + ReflectionKind.Property, JSX.Element | null> & UtilityIc [ReflectionKind.SetSignature]() { return this[ReflectionKind.Accessor](); }, - [ReflectionKind.SomeSignature]: () => null, - [ReflectionKind.SomeModule]: () => null, - [ReflectionKind.SomeType]: () => null, - [ReflectionKind.SomeValue]: () => null, [ReflectionKind.TypeAlias]: () => kindIcon( + ReflectionKind.TypeAlias, , "var(--color-ts)" ), @@ -153,15 +184,13 @@ export const icons: Record JSX.Element | null> & UtilityIc }, [ReflectionKind.Variable]: () => kindIcon( + ReflectionKind.Variable, , "var(--color-ts-variable)" ), - [ReflectionKind.VariableOrProperty]() { - return this[ReflectionKind.Variable](); - }, chevronDown: () => ( {prependName ? `${prependName} - ${item.title}` : item.title} diff --git a/src/lib/utils/jsx.elements.ts b/src/lib/utils/jsx.elements.ts index 883b2698b..bf91cb55d 100644 --- a/src/lib/utils/jsx.elements.ts +++ b/src/lib/utils/jsx.elements.ts @@ -117,6 +117,7 @@ export interface IntrinsicElements { svg: JsxSvgElementProps; path: JsxPathElementProps; rect: JsxRectElementProps; + use: JsxUseElementProps; } export const JsxFragment = Symbol(); @@ -1058,3 +1059,20 @@ export interface JsxRectElementProps 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 0f8156add..3aff70359 100644 --- a/src/lib/utils/jsx.ts +++ b/src/lib/utils/jsx.ts @@ -83,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 @@ -114,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/test/capture-screenshots.ts b/src/test/capture-screenshots.ts index 66f8c83dd..274ee194f 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -1,6 +1,6 @@ import * as fs from "fs"; 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"; @@ -63,7 +63,6 @@ export async function captureRegressionScreenshots() { logger: "console", readme: join(src, "..", "README.md"), name: "typedoc", - disableSources: true, cleanOutputDir: true, tsconfig: join(src, "..", "tsconfig.json"), plugin: [], @@ -95,7 +94,7 @@ export async function captureScreenshots( const absPath = resolve(baseDirectory, file); const outputPath = resolve( outputDirectory, - file.replace(".html", "") + relative(baseDirectory, file).replace(".html", "") ); fs.mkdirSync(dirname(outputPath), { recursive: true }); From 1e542e3b1551c4519761ec0e74473e322a3e565b Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 12:46:04 -0600 Subject: [PATCH 097/151] Add rawLexer for treating README files as comment-like Also add icon for Reference (By @futurGH) and experiment with adding a cache for icons to reduce page sizes. --- .gitignore | 3 +- src/lib/converter/comments/blockLexer.ts | 15 +- src/lib/converter/comments/lexer.ts | 14 + src/lib/converter/comments/parser.ts | 2 +- src/lib/converter/comments/rawLexer.ts | 301 ++++++++++++++++++ .../converter/plugins/LinkResolverPlugin.ts | 18 ++ src/lib/converter/plugins/PackagePlugin.ts | 37 ++- src/lib/models/reflections/project.ts | 24 +- .../themes/default/partials/anchor-icon.tsx | 16 +- .../themes/default/partials/comment.tsx | 47 +-- .../output/themes/default/partials/icon.tsx | 91 +++--- .../output/themes/default/partials/index.tsx | 11 +- .../output/themes/default/templates/index.tsx | 5 +- .../themes/default/templates/reflection.tsx | 2 +- src/lib/output/themes/lib.tsx | 45 ++- src/test/comments.test.ts | 283 +++++++++++++++- src/test/slow/visual.test.ts | 7 +- static/style.css | 10 +- 18 files changed, 777 insertions(+), 154 deletions(-) create mode 100644 src/lib/converter/comments/lexer.ts create mode 100644 src/lib/converter/comments/rawLexer.ts diff --git a/.gitignore b/.gitignore index 368472d53..d9be0ac51 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ yarn-error.log **/node_modules/ /coverage/ /dist/ +/docs typedoc*.tgz tmp @@ -22,4 +23,4 @@ src/test/renderer/specs/specs.json # Built theme JS static/main.js -/example/docs/ \ No newline at end of file +/example/docs/ diff --git a/src/lib/converter/comments/blockLexer.ts b/src/lib/converter/comments/blockLexer.ts index 531da3211..0680c2ca6 100644 --- a/src/lib/converter/comments/blockLexer.ts +++ b/src/lib/converter/comments/blockLexer.ts @@ -1,17 +1,4 @@ -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; -} +import { Token, TokenSyntaxKind } from "./lexer"; export function* lexBlockComment( file: string, 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/parser.ts b/src/lib/converter/comments/parser.ts index d135335d3..70cf7c726 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -2,7 +2,7 @@ import { ok } from "assert"; import type { CommentParserConfig } from "."; import { Comment, CommentDisplayPart, CommentTag } from "../../models"; import { assertNever, removeIf } from "../../utils"; -import { Token, TokenSyntaxKind } from "./blockLexer"; +import { Token, TokenSyntaxKind } from "./lexer"; interface LookaheadGenerator { done(): boolean; diff --git a/src/lib/converter/comments/rawLexer.ts b/src/lib/converter/comments/rawLexer.ts new file mode 100644 index 000000000..e66318e20 --- /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/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts index b5598fad5..2d83c7e76 100644 --- a/src/lib/converter/plugins/LinkResolverPlugin.ts +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -86,6 +86,24 @@ export class LinkResolverPlugin extends ConverterComponent { 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) { diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts index c39dff91e..acdf2ffda 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); + if (project.comment) { + this.application.logger.verbose( + `Not applying readme as project comment since it already has a comment.` + ); + } else { + const readme = readFile(this.readmeFile); + const comment = parseComment( + lexCommentString(readme), + context.config, + (msg) => { + this.application.logger.warn( + `${msg} in ${this.readmeFile}` + ); + } + ); + + if (comment.blockTags.length || comment.modifierTags.size) { + this.application.logger.warn( + `Block and modifier tags will be ignored within the readme.` + ); + } + + 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/models/reflections/project.ts b/src/lib/models/reflections/project.ts index f37d8dcbc..3d25107d5 100644 --- a/src/lib/models/reflections/project.ts +++ b/src/lib/models/reflections/project.ts @@ -9,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. @@ -26,29 +27,18 @@ 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 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; - - /** - * The parsed data of the package.json file of the project when found. - */ - packageInfo: any; + readme?: CommentDisplayPart[]; constructor(name: string) { super(name, ReflectionKind.Project); 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 6bc82646c..e5ba21dc3 100644 --- a/src/lib/output/themes/default/partials/comment.tsx +++ b/src/lib/output/themes/default/partials/comment.tsx @@ -1,48 +1,7 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; -import { assertNever, JSX, Raw } from "../../../../utils"; -import type { CommentDisplayPart, Reflection } from "../../../../models"; -import { camelToTitleCase } from "../../lib"; - -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(""); -} +import { JSX, Raw } from "../../../../utils"; +import type { Reflection } from "../../../../models"; +import { camelToTitleCase, displayPartsToMarkdown } from "../../lib"; export function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: Reflection) { if (!props.comment?.hasVisibleComponent()) return; diff --git a/src/lib/output/themes/default/partials/icon.tsx b/src/lib/output/themes/default/partials/icon.tsx index ab861313b..914a6105c 100644 --- a/src/lib/output/themes/default/partials/icon.tsx +++ b/src/lib/output/themes/default/partials/icon.tsx @@ -1,25 +1,37 @@ import { ReflectionKind } from "../../../../models"; import { JSX } from "../../../../utils"; -type UtilityIcons = Record<"chevronDown" | "checkbox" | "menu" | "search" | "chevronSmall", () => JSX.Element>; +type UtilityIcons = Record< + "chevronDown" | "checkbox" | "menu" | "search" | "chevronSmall" | "anchor", + () => JSX.Element +>; -const seenIcons = new Set(); +const seenIcons = new Set(); export function clearSeenIconCache() { seenIcons.clear(); } -const kindIcon = (kind: ReflectionKind, letterPath: JSX.Element, color: string, circular = false) => { - const content: JSX.Element[] = []; +function cachedPart(key: string, svgPart: JSX.Element) { + if (seenIcons.has(key)) { + return ; + } + + seenIcons.add(key); + return { + ...svgPart, + props: { + ...svgPart.props, + id: `icon-${key}`, + }, + }; +} - if (seenIcons.has(kind)) { - content.push(); - content.push(); - } else { - seenIcons.add(kind); - content.push( +const kindIcon = (kind: ReflectionKind, letterPath: JSX.Element, color: string, circular = false) => ( + + {cachedPart( + `${kind}-path`, - ); - content.push({ - ...letterPath, - props: { - ...letterPath.props, - id: `icon-text-${kind}`, - }, - }); - } - - return ( - - {content} - - ); -}; + )} + {cachedPart(`${kind}-text`, letterPath)} + +); -export const icons: Record JSX.Element | null> & UtilityIcons = { +export const icons: Record JSX.Element> & UtilityIcons = { [ReflectionKind.Accessor]: () => kindIcon( ReflectionKind.Accessor, @@ -69,12 +69,6 @@ export const icons: Record JSX.Element | null> & UtilityIc />, "var(--color-ts-class)" ), - [ReflectionKind.ClassMember]() { - return this[ReflectionKind.Property](); - }, - [ReflectionKind.ClassOrInterface]() { - return this[ReflectionKind.Class](); - }, [ReflectionKind.Constructor]: () => kindIcon( ReflectionKind.Constructor, @@ -106,9 +100,6 @@ export const icons: Record JSX.Element | null> & UtilityIc , "var(--color-ts-function)" ), - [ReflectionKind.FunctionOrMethod]() { - return this[ReflectionKind.Function](); - }, [ReflectionKind.GetSignature]() { return this[ReflectionKind.Accessor](); }, @@ -166,7 +157,16 @@ export const icons: Record JSX.Element | null> & UtilityIc "#FF984D", true ), - [ReflectionKind.Reference]: () => null, + [ReflectionKind.Reference]: () => + kindIcon( + ReflectionKind.Reference, + , + "#FF4D82", // extract into a CSS variable potentially? + true + ), [ReflectionKind.SetSignature]() { return this[ReflectionKind.Accessor](); }, @@ -235,4 +235,19 @@ export const icons: Record JSX.Element | null> & UtilityIc /> ), + 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 1ae7d76c0..816791c2a 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -41,7 +41,6 @@ export function index(context: DefaultThemeRenderContext, props: ContainerReflec : renderCategory(context, item) ); } - content =
      {content}
      ; // Accordion is only needed if any children don't have their own document. if ( @@ -56,10 +55,18 @@ export function index(context: DefaultThemeRenderContext, props: ContainerReflec {icons.chevronSmall()} Index - {content} +
      {content}
      ); + } else { + content = ( + <> +

      Index

      + {content} + + ); } + return (
      {content}
      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 ad4928b89..51ad034be 100644 --- a/src/lib/output/themes/default/templates/reflection.tsx +++ b/src/lib/output/themes/default/templates/reflection.tsx @@ -63,7 +63,7 @@ export function reflectionTemplate(context: DefaultThemeRenderContext, props: Pa {item.name}: {context.type(item.type)} ))} - {"]: "} + ]: {context.type(props.model.indexSignature.type)}
{context.comment(props.model.indexSignature)} diff --git a/src/lib/output/themes/lib.tsx b/src/lib/output/themes/lib.tsx index 4df586a4c..0c9500fe0 100644 --- a/src/lib/output/themes/lib.tsx +++ b/src/lib/output/themes/lib.tsx @@ -1,12 +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") { @@ -111,3 +113,44 @@ 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/test/comments.test.ts b/src/test/comments.test.ts index 7df55247f..b1f58927b 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -1,12 +1,10 @@ import { deepStrictEqual as equal, fail } from "assert"; import type { CommentParserConfig } from "../lib/converter/comments"; -import { - lexBlockComment, - Token, - TokenSyntaxKind, -} from "../lib/converter/comments/blockLexer"; +import { lexBlockComment } from "../lib/converter/comments/blockLexer"; +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) { @@ -19,7 +17,8 @@ function dedent(text: string) { } const minIndent = lines.reduce( - (indent, line) => Math.min(indent, line.search(/\S/)), + (indent, line) => + line.length ? Math.min(indent, line.search(/\S/)) : indent, Infinity ); @@ -511,6 +510,278 @@ describe("Block Comment Lexer", () => { }); }); +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" }, + ]); + }); + + 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"]), 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/static/style.css b/static/style.css index 4f8b78c30..5468d2534 100644 --- a/static/style.css +++ b/static/style.css @@ -545,15 +545,15 @@ dl.tsd-comment-tag-group dd { margin: 0; } code.tsd-tag { - padding: 0.33em 0.66em; + padding: 0.25em 0.4em; border: 0.1em solid var(--color-accent); margin-right: 0.25em; + font-size: 70%; } -h1 code.tsd-tag, -h2 code.tsd-tag, -h3 code.tsd-tag { - margin-right: 0.5em; +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: " "; From f811d407293e2d0e85b22d068d54a83ba3465b7f Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 12:46:58 -0600 Subject: [PATCH 098/151] Update changelog --- CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 000dcb489..f5b41ce7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://github.com/TypeStrong/typedoc/projects/11)) -- Restore support for `{@link}` and `[[link]]` tags in markdown documents. - Make comment parser options configurable (read tsdoc.json?). - Full support for declaration references, #262, #488, #1326, #1845. - Add support for additional comment styles, #1433. From bad91d508fcaf6b25a6a0a7e9b95fcf94ebb833b Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 13:23:13 -0600 Subject: [PATCH 099/151] Correct semantics for `@readonly` tag --- src/lib/converter/plugins/CommentPlugin.ts | 60 ++++++++++++--------- src/lib/utils/array.ts | 10 ++-- src/test/behaviorTests.ts | 8 +++ src/test/converter2/behavior/readonlyTag.ts | 20 +++++++ 4 files changed, 69 insertions(+), 29 deletions(-) create mode 100644 src/test/converter2/behavior/readonlyTag.ts diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 5b5b40449..8cf226672 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -54,6 +54,15 @@ export class CommentPlugin extends ConverterComponent { @BindOption("excludeTags") excludeTags!: `@${string}`[]; + @BindOption("excludeInternal") + excludeInternal!: boolean; + + @BindOption("excludePrivate") + excludePrivate!: boolean; + + @BindOption("excludeProtected") + excludeProtected!: boolean; + /** * Create a new CommentPlugin instance. */ @@ -98,6 +107,14 @@ export class CommentPlugin extends ConverterComponent { comment.removeModifier("@public"); } + 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") @@ -189,25 +206,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 @@ -356,24 +373,19 @@ 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) { 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; } @@ -385,7 +397,7 @@ export class CommentPlugin extends ConverterComponent { return ( comment.hasModifier("@hidden") || comment.hasModifier("@ignore") || - (comment.hasModifier("@internal") && excludeInternal) + (comment.hasModifier("@internal") && this.excludeInternal) ); } } diff --git a/src/lib/utils/array.ts b/src/lib/utils/array.ts index a7a8ebbb2..a2401c8fb 100644 --- a/src/lib/utils/array.ts +++ b/src/lib/utils/array.ts @@ -131,17 +131,17 @@ export function* zip[]>( } export function filterMap( - arr: readonly T[], - fn: (item: T, index: number) => U | undefined + iter: Iterable, + fn: (item: T) => U | undefined ): U[] { const result: U[] = []; - arr.forEach((item, index) => { - const newItem = fn(item, index); + for (const item of iter) { + const newItem = fn(item); if (newItem !== void 0) { result.push(newItem); } - }); + } return result; } diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 8e0125269..4c3b4d351 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -260,6 +260,14 @@ export const behaviorTests: Record< equal(bar.comment, undefined); }, + readonlyTag(project) { + const title = query(project, "Book.title"); + const author = query(project, "Book.author"); + + ok(!title.setSignature); + ok(author.flags.isReadonly); + }, + removeReflection(project) { const foo = query(project, "foo"); project.removeReflection(foo); 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; +} From f74840d75c1a42b342762827afe97a7541c3759d Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 17:23:12 -0600 Subject: [PATCH 100/151] Make comment parser configurable --- .config/typedoc.json | 4 +- CHANGELOG.md | 4 +- src/index.ts | 1 + src/lib/converter/context.ts | 44 +------ src/lib/converter/converter.ts | 20 ++++ src/lib/converter/factories/signature.ts | 8 +- src/lib/converter/jsdoc.ts | 6 +- .../converter/plugins/LinkResolverPlugin.ts | 4 - src/lib/converter/plugins/PackagePlugin.ts | 2 +- src/lib/output/events.ts | 3 +- .../output/themes/default/DefaultTheme.tsx | 1 + src/lib/utils/index.ts | 3 + src/lib/utils/options/declaration.ts | 24 +++- src/lib/utils/options/index.ts | 1 + src/lib/utils/options/sources/typedoc.ts | 111 ++++++++++++++---- src/lib/utils/validation.ts | 110 +++++++++++++++++ src/test/utils/validation.test.ts | 59 ++++++++++ 17 files changed, 321 insertions(+), 84 deletions(-) create mode 100644 src/lib/utils/validation.ts create mode 100644 src/test/utils/validation.test.ts diff --git a/.config/typedoc.json b/.config/typedoc.json index 68a9dec97..8c5fa9b53 100644 --- a/.config/typedoc.json +++ b/.config/typedoc.json @@ -7,12 +7,14 @@ "RendererComponent", "SORT_STRATEGIES", "_ModelToObject", - "EventHooksMomento" + "EventHooksMomento", + "MarkedPlugin" ], "entryPoints": ["../src"], "entryPointStrategy": "Resolve", "excludeExternals": true, "excludeInternal": false, + "excludePrivate": true, "treatWarningsAsErrors": false, "validation": { "notExported": true, diff --git a/CHANGELOG.md b/CHANGELOG.md index f5b41ce7e..d5ee7c4bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://github.com/TypeStrong/typedoc/projects/11)) -- Make comment parser options configurable (read tsdoc.json?). +- Make comment parser options configurable from tsdoc.json. - Full support for declaration references, #262, #488, #1326, #1845. - Add support for additional comment styles, #1433. - Theme: Custom rendering for `@see` tags. @@ -44,6 +44,8 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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 diff --git a/src/index.ts b/src/index.ts index 518659f97..64b430322 100644 --- a/src/index.ts +++ b/src/index.ts @@ -53,6 +53,7 @@ export type { SortStrategy, ParameterTypeToOptionTypeMap, DocumentationEntryPoint, + ManuallyValidatedOption, } from "./lib/utils"; export type { EventMap, EventCallback } from "./lib/utils/events"; diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index bcd4cb2ab..751b7177a 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 { CommentParserConfig, getComment } from "./comments"; +import { getComment } from "./comments"; /** * The context describes the current state the converter is in. @@ -163,44 +163,6 @@ export class Context { return resolveAliasedSymbol(symbol, this.checker); } - // GERRIT: This needs to live on Application, and get constructed based on user input. - config: CommentParserConfig = { - blockTags: new Set([ - // TSDoc standard - "@param", - "@remarks", - "@throws", - "@privateRemarks", - "@defaultValue", - // TypeDoc specific - "@module", - "@inheritDoc", - "@group", - ]), - inlineTags: new Set(["@link", "@inheritDoc", "@label"]), - modifierTags: new Set([ - // TSDoc standard - "@public", - "@private", - "@protected", - "@internal", - "@readonly", - "@packageDocumentation", - "@eventProperty", - "@deprecated", - "@alpha", - "@beta", - "@sealed", - "@override", - "@virtual", - // TypeDoc specific tags - "@hidden", - "@ignore", - "@enum", - "@event", - ]), - }; - createDeclarationReflection( kind: ReflectionKind, symbol: ts.Symbol | undefined, @@ -231,7 +193,7 @@ export class Context { reflection.comment = getComment( exportSymbol, reflection.kind, - this.config, + this.converter.config, this.logger ); } @@ -239,7 +201,7 @@ export class Context { reflection.comment = getComment( symbol, reflection.kind, - this.config, + this.converter.config, this.logger ); } diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index f49bd9348..d99aa82a7 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -14,6 +14,7 @@ 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"; /** * Compiles source files using TypeScript and converts compiler symbols to reflections. @@ -50,6 +51,12 @@ export class Converter extends ChildableComponent< @BindOption("excludeProtected") excludeProtected!: boolean; + private _config?: CommentParserConfig; + + get config(): CommentParserConfig { + return this._config || this._buildCommentParserConfig(); + } + /** * General events */ @@ -329,6 +336,19 @@ export class Converter extends ChildableComponent< matchesAny(cache, node.getSourceFile().fileName) ); } + + 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; + } } function getSymbolForModuleLike( diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index a07f57590..d4bca55a1 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -43,7 +43,7 @@ export function createSignature( if (declaration) { sigRef.comment = getSignatureComment( declaration, - context.config, + context.converter.config, context.logger ); } @@ -125,7 +125,7 @@ function convertParameters( if (declaration && ts.isJSDocParameterTag(declaration)) { paramRefl.comment = getJsDocComment( declaration, - context.config, + context.converter.config, context.logger ); } @@ -195,7 +195,7 @@ export function convertParameterNodes( if (ts.isJSDocParameterTag(param)) { paramRefl.comment = getJsDocComment( param, - context.config, + context.converter.config, context.logger ); } @@ -280,7 +280,7 @@ export function convertTypeParameterNodes( if (ts.isJSDocTemplateTag(param.parent)) { paramRefl.comment = getJsDocComment( param.parent, - context.config, + context.converter.config, context.logger ); } diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts index 6f38daef4..9f6ace5a6 100644 --- a/src/lib/converter/jsdoc.ts +++ b/src/lib/converter/jsdoc.ts @@ -40,7 +40,7 @@ export function convertJsDocAlias( ); reflection.comment = getJsDocComment( declaration, - context.config, + context.converter.config, context.logger ); @@ -70,7 +70,7 @@ export function convertJsDocCallback( ); alias.comment = getJsDocComment( declaration, - context.config, + context.converter.config, context.logger ); context.finalizeDeclarationReflection(alias); @@ -94,7 +94,7 @@ function convertJsDocInterface( ); reflection.comment = getJsDocComment( declaration, - context.config, + context.converter.config, context.logger ); context.finalizeDeclarationReflection(reflection); diff --git a/src/lib/converter/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts index 2d83c7e76..c4e7b9b6d 100644 --- a/src/lib/converter/plugins/LinkResolverPlugin.ts +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -164,10 +164,6 @@ export class LinkResolverPlugin extends ConverterComponent { if (targetRefl) { part.text = caption; part.target = targetRefl; - } else { - this.application.logger.warn( - `Failed resolution for ${target} in ${reflection.getFullName()}` - ); } } } diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts index acdf2ffda..a37e17cfc 100644 --- a/src/lib/converter/plugins/PackagePlugin.ts +++ b/src/lib/converter/plugins/PackagePlugin.ts @@ -108,7 +108,7 @@ export class PackagePlugin extends ConverterComponent { const readme = readFile(this.readmeFile); const comment = parseComment( lexCommentString(readme), - context.config, + context.converter.config, (msg) => { this.application.logger.warn( `${msg} in ${this.readmeFile}` diff --git a/src/lib/output/events.ts b/src/lib/output/events.ts index cc5fc3ec1..989d1914b 100644 --- a/src/lib/output/events.ts +++ b/src/lib/output/events.ts @@ -125,8 +125,7 @@ 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 PARSE} */ diff --git a/src/lib/output/themes/default/DefaultTheme.tsx b/src/lib/output/themes/default/DefaultTheme.tsx index acd139170..1128b0165 100644 --- a/src/lib/output/themes/default/DefaultTheme.tsx +++ b/src/lib/output/themes/default/DefaultTheme.tsx @@ -43,6 +43,7 @@ interface TemplateMapping { export class DefaultTheme extends Theme { /** @internal */ markedPlugin: MarkedPlugin; + private _renderContext?: DefaultThemeRenderContext; getRenderContext(_pageEvent: PageEvent) { if (!this._renderContext) { diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index ba1f1db9e..43a760e5b 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -49,6 +49,7 @@ export type { ValidationOptions, TypeDocOptionValues, ParameterTypeToOptionTypeMap, + ManuallyValidatedOption, } from "./options"; export { discoverPlugins, loadPlugins } from "./plugins"; export { sortReflections } from "./sort"; @@ -61,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/options/declaration.ts b/src/lib/utils/options/declaration.ts index 110521f27..45268cfcc 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -33,7 +33,7 @@ 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] @@ -82,11 +82,16 @@ export interface TypeDocOptionMap { lightHighlightTheme: ShikiTheme; darkHighlightTheme: ShikiTheme; customCss: string; - visibilityFilters: unknown; + 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[]; @@ -100,6 +105,11 @@ export interface TypeDocOptionMap { hideGenerator: boolean; cleanOutputDir: boolean; + excludeTags: `@${string}`[]; + blockTags: `@${string}`[]; + inlineTags: `@${string}`[]; + modifierTags: `@${string}`[]; + help: boolean; version: boolean; showConfig: boolean; @@ -116,6 +126,12 @@ export interface TypeDocOptionMap { 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, @@ -146,6 +162,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 diff --git a/src/lib/utils/options/index.ts b/src/lib/utils/options/index.ts index 4583415df..9e7b18e0a 100644 --- a/src/lib/utils/options/index.ts +++ b/src/lib/utils/options/index.ts @@ -20,4 +20,5 @@ export type { DeclarationOptionToOptionType, TypeDocOptionValues, ParameterTypeToOptionTypeMap, + ManuallyValidatedOption, } from "./declaration"; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 246b00f09..3e8f5ad06 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -5,6 +5,7 @@ import { BUNDLED_THEMES, Theme } from "shiki"; import { SORT_STRATEGIES } from "../../sort"; import { EntryPointStrategy } from "../../entry-point"; import { ReflectionKind } from "../../../models/reflections/kind"; +import { Validation } from "../.."; export function addTypeDocOptions(options: Pick) { options.addDeclaration({ @@ -217,20 +218,6 @@ export function addTypeDocOptions(options: Pick) { help: "Add the package version to the project name.", type: ParameterType.Boolean, }); - options.addDeclaration({ - name: "excludeTags", - help: "Remove the listed tags from doc comments.", - type: ParameterType.Array, - defaultValue: ["@override", "@virtual", "@privateRemarks"], - validate(value) { - const missingAt = value.filter((tag) => !tag.startsWith("@")); - if (missingAt.length) { - throw new Error( - `excludeTags must specify tags with a leading "@"` - ); - } - }, - }); options.addDeclaration({ name: "readme", help: "Path to the readme file that should be displayed on the index page. Pass `none` to disable the index page and start the documentation on the globals page.", @@ -311,6 +298,90 @@ export function addTypeDocOptions(options: Pick) { defaultValue: true, }); + options.addDeclaration({ + name: "excludeTags", + 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: "blockTags", + help: "Block tags which TypeDoc should recognize when parsing comments.", + type: ParameterType.Array, + defaultValue: [ + // TSDoc standard + "@param", + "@remarks", + "@throws", + "@privateRemarks", + "@defaultValue", + // TypeDoc specific + "@module", + "@inheritDoc", + "@group", + ], + 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: ["@link", "@inheritDoc", "@label"], + 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: [ + // TSDoc standard + "@public", + "@private", + "@protected", + "@internal", + "@readonly", + "@packageDocumentation", + "@eventProperty", + "@deprecated", + "@alpha", + "@beta", + "@sealed", + "@override", + "@virtual", + // TypeDoc specific tags + "@hidden", + "@ignore", + "@enum", + "@event", + ], + validate(value) { + if (!Validation.validate([Array, Validation.isTagString], value)) { + throw new Error( + `modifierTags must be an array of valid tag names.` + ); + } + }, + }); + options.addDeclaration({ name: "help", help: "Print this message.", @@ -349,11 +420,7 @@ export function addTypeDocOptions(options: Pick) { help: "Specify the options passed to Marked, the Markdown parser used by TypeDoc.", type: ParameterType.Mixed, validate(value) { - if ( - typeof value !== "object" || - Array.isArray(value) || - value == null - ) { + if (!Validation.validate({}, value)) { throw new Error( "The 'markedOptions' option must be a non-array object." ); @@ -365,11 +432,7 @@ export function addTypeDocOptions(options: Pick) { help: "Selectively override the TypeScript compiler options used by TypeDoc.", type: ParameterType.Mixed, validate(value) { - if ( - typeof value !== "object" || - Array.isArray(value) || - value == null - ) { + if (!Validation.validate({}, value)) { throw new Error( "The 'compilerOptions' option must be a non-array object." ); diff --git a/src/lib/utils/validation.ts b/src/lib/utils/validation.ts new file mode 100644 index 000000000..40b6bafde --- /dev/null +++ b/src/lib/utils/validation.ts @@ -0,0 +1,110 @@ +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>]: Infer< + Extract + >; + }; + +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(); + +export type Schema = + | typeof String + | typeof Number + | typeof Boolean + | readonly string[] + | readonly [typeof Array, Schema] + | { readonly [k: string]: Schema } + | Guard + | Optional + | Optional + | Optional + | Optional + | Optional + | Optional<{ readonly [k: string]: Schema }> + | 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); + } + + return ( + !!obj && + typeof obj === "object" && + 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/test/utils/validation.test.ts b/src/test/utils/validation.test.ts new file mode 100644 index 000000000..44be69f41 --- /dev/null +++ b/src/test/utils/validation.test.ts @@ -0,0 +1,59 @@ +import { ok } from "assert"; +import { Validation } from "../../lib/utils"; + +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)); + }); +}); From abd4d155f2a6219a0577ecceabb0b262f669ae3f Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 17:28:05 -0600 Subject: [PATCH 101/151] Add a check for arrays too --- src/lib/utils/validation.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/utils/validation.ts b/src/lib/utils/validation.ts index 40b6bafde..4d32baff5 100644 --- a/src/lib/utils/validation.ts +++ b/src/lib/utils/validation.ts @@ -95,6 +95,7 @@ export function validate(schema: Schema, obj: any): boolean { return ( !!obj && typeof obj === "object" && + !Array.isArray(obj) && Object.entries(type).every(([key, prop]) => validate(prop, obj[key]) ) From ff2849efd72c53c37376f63ea1fb278887fa5bcc Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 17:37:41 -0600 Subject: [PATCH 102/151] Add custom munging to combine `@see` tags --- src/lib/converter/plugins/CommentPlugin.ts | 18 ++++++++++++++++++ src/test/behaviorTests.ts | 14 ++++++++++++++ src/test/converter2/behavior/seeTags.ts | 10 ++++++++++ 3 files changed, 42 insertions(+) create mode 100644 src/test/converter2/behavior/seeTags.ts diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index 8cf226672..ebf095925 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -265,6 +265,8 @@ export class CommentPlugin extends ConverterComponent { private onResolve(_context: Context, reflection: Reflection) { if (reflection.comment) { reflection.label = extractLabelTag(reflection.comment); + + mergeSeeTags(reflection.comment); } if (!(reflection instanceof DeclarationReflection)) { @@ -445,3 +447,19 @@ function extractLabelTag(comment: Comment): string | undefined { 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/test/behaviorTests.ts b/src/test/behaviorTests.ts index 4c3b4d351..3341353c7 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -276,4 +276,18 @@ 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" + ); + }, }; 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; From 76377fc618577d037a5c006858674ab0967615ed Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 17:39:46 -0600 Subject: [PATCH 103/151] Fix circular import --- src/lib/utils/options/sources/typedoc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 3e8f5ad06..6a97f8abe 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -5,7 +5,7 @@ import { BUNDLED_THEMES, Theme } from "shiki"; import { SORT_STRATEGIES } from "../../sort"; import { EntryPointStrategy } from "../../entry-point"; import { ReflectionKind } from "../../../models/reflections/kind"; -import { Validation } from "../.."; +import * as Validation from "../../validation"; export function addTypeDocOptions(options: Pick) { options.addDeclaration({ From 03d948ee9c68e47885e8629901ef0e5441a3ce1a Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 24 Apr 2022 17:49:15 -0600 Subject: [PATCH 104/151] Revert missed part of rejected experiment --- src/lib/converter/plugins/PackagePlugin.ts | 32 +++++++++------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts index a37e17cfc..ee26dde85 100644 --- a/src/lib/converter/plugins/PackagePlugin.ts +++ b/src/lib/converter/plugins/PackagePlugin.ts @@ -100,30 +100,24 @@ export class PackagePlugin extends ConverterComponent { private onBeginResolve(context: Context) { const project = context.project; if (this.readmeFile) { - if (project.comment) { - this.application.logger.verbose( - `Not applying readme as project comment since it already has a comment.` - ); - } else { - 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 readme = readFile(this.readmeFile); + const comment = parseComment( + lexCommentString(readme), + context.converter.config, + (msg) => { this.application.logger.warn( - `Block and modifier tags will be ignored within the readme.` + `${msg} in ${this.readmeFile}` ); } + ); - project.readme = comment.summary; + if (comment.blockTags.length || comment.modifierTags.size) { + this.application.logger.warn( + `Block and modifier tags will be ignored within the readme.` + ); } + + project.readme = comment.summary; } if (this.packageFile) { From 49fda24697fd8a42d718eaedea57475e62be02ed Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 1 May 2022 08:48:26 -0600 Subject: [PATCH 105/151] Try fixing visual regression workflow --- .github/workflows/visual-regression.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index a93249fac..79bc94d24 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -28,4 +28,4 @@ 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 From 6eb93d29af7f51e21331c1aec68397e1fa82480e Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 1 May 2022 08:50:47 -0600 Subject: [PATCH 106/151] Add artifact collection --- .github/workflows/visual-regression.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/visual-regression.yml b/.github/workflows/visual-regression.yml index 79bc94d24..435d8231f 100644 --- a/.github/workflows/visual-regression.yml +++ b/.github/workflows/visual-regression.yml @@ -29,3 +29,8 @@ jobs: node dist/test/capture-screenshots.js - name: 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 From be6363a2221aa734cdeddf6098d6b84bc50391da Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 15 May 2022 15:02:15 -0600 Subject: [PATCH 107/151] Fixes for JSDoc style `@inheritDoc` handling Resolves #1927 --- .eslintrc | 3 + CHANGELOG.md | 2 + scripts/rebuild_specs.js | 8 +- src/lib/converter/comments/parser.ts | 6 + src/lib/converter/plugins/ImplementsPlugin.ts | 200 ++++++++++++------ src/lib/converter/plugins/InheritDocPlugin.ts | 9 +- src/lib/converter/utils/reflections.ts | 57 +---- src/test/behaviorTests.ts | 32 +++ src/test/comments.test.ts | 13 ++ src/test/converter/alias/specs.json | 2 +- .../class/specs-with-lump-categories.json | 27 ++- src/test/converter/class/specs.json | 27 ++- src/test/converter/comment/specs.json | 2 +- src/test/converter/declaration/specs.json | 2 +- src/test/converter/enum/specs.json | 2 +- src/test/converter/enum/specs.nodoc.json | 2 +- src/test/converter/exports/specs.json | 2 +- src/test/converter/function/specs.json | 2 +- .../converter/inherit-param-doc/specs.json | 24 +-- src/test/converter/inheritance/specs.json | 2 +- src/test/converter/interface/specs.json | 10 +- src/test/converter/js/specs.json | 2 +- src/test/converter/mixin/specs.json | 2 +- src/test/converter/react/specs.json | 2 +- src/test/converter/types/specs.json | 2 +- src/test/converter/variables/specs.json | 2 +- src/test/converter/variables/specs.nodoc.json | 2 +- src/test/converter2.test.ts | 5 +- .../converter2/behavior/inheritDocJsdoc.ts | 19 ++ src/test/converter2/issues/gh1927.ts | 15 ++ src/test/issueTests.ts | 9 + 31 files changed, 335 insertions(+), 159 deletions(-) create mode 100644 src/test/converter2/behavior/inheritDocJsdoc.ts create mode 100644 src/test/converter2/issues/gh1927.ts diff --git a/.eslintrc b/.eslintrc index 91de3e34e..dcde5f5c2 100644 --- a/.eslintrc +++ b/.eslintrc @@ -45,6 +45,9 @@ "@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, diff --git a/CHANGELOG.md b/CHANGELOG.md index d5ee7c4bf..9784d5cdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -56,6 +56,8 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - Corrected schema generation for https://typedoc.org/schema.json diff --git a/scripts/rebuild_specs.js b/scripts/rebuild_specs.js index 20d79f3b2..a47ed5091 100644 --- a/scripts/rebuild_specs.js +++ b/scripts/rebuild_specs.js @@ -78,9 +78,11 @@ function rebuildConverterTests(dirs) { ); const serialized = app.serializer.toObject(result); - const data = JSON.stringify(serialized, null, " ") - .split(TypeDoc.normalizePath(base)) - .join("%BASE%"); + const data = + JSON.stringify(serialized, null, " ") + .split(TypeDoc.normalizePath(base)) + .join("%BASE%") + .trim() + "\n"; after(); fs.writeFileSync(out, data); } diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts index 70cf7c726..d180917f2 100644 --- a/src/lib/converter/comments/parser.ts +++ b/src/lib/converter/comments/parser.ts @@ -228,6 +228,12 @@ function blockContent( 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; diff --git a/src/lib/converter/plugins/ImplementsPlugin.ts b/src/lib/converter/plugins/ImplementsPlugin.ts index c458b734a..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); @@ -460,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 2ebfe1597..a4929716e 100644 --- a/src/lib/converter/plugins/InheritDocPlugin.ts +++ b/src/lib/converter/plugins/InheritDocPlugin.ts @@ -11,7 +11,9 @@ import { DefaultMap } from "../../utils"; import { zip } from "../../utils/array"; /** - * 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 @@ -32,13 +34,12 @@ export class InheritDocPlugin extends ConverterComponent { override initialize() { this.owner.on( Converter.EVENT_RESOLVE_END, - this.processInheritDoc.bind(this) + 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 is used to determine a source reflection * that will provide actual comment. diff --git a/src/lib/converter/utils/reflections.ts b/src/lib/converter/utils/reflections.ts index 5776c9d56..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,50 +16,3 @@ export function removeUndefined(type: SomeType): SomeType { } return type; } - -/** - * Copy the comment of the source reflection to the target reflection. - * Performs the copy according to the specification at https://tsdoc.org/pages/tags/inheritdoc/. - * Mostly. - * - * @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.getTag("@inheritDoc") - ) { - // GERRIT This seems wrong. Shouldn't be overwriting parameters or type parameters... - if ( - target instanceof DeclarationReflection && - source instanceof DeclarationReflection - ) { - target.typeParameters = source.typeParameters; - } else if ( - target instanceof SignatureReflection && - source instanceof SignatureReflection - ) { - target.parameters = source.parameters; - target.typeParameters = source.typeParameters; - } - target.comment.summary = Comment.cloneDisplayParts( - source.comment.summary - ); - target.comment.removeTags("@remarks"); - target.comment.removeTags("@inheritDoc"); // Remove block level inheritDoc - const remarks = source.comment.getTag("@remarks"); - if (remarks) { - target.comment.blockTags.push(remarks.clone()); - } - } else if (!target.comment && source.comment) { - if ( - target instanceof DeclarationReflection && - source instanceof DeclarationReflection - ) { - target.typeParameters = source.typeParameters; - } - target.comment = source.comment.clone(); - } -} diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 3341353c7..52c754980 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -168,6 +168,38 @@ export const behaviorTests: Record< 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"); diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index b1f58927b..2c43d533b 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -797,6 +797,19 @@ describe("Comment Parser", () => { ]), }; + 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); diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index a92caed4f..f656862b9 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -263,4 +263,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index 3684d9696..43217bc15 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -1416,6 +1416,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, @@ -4758,4 +4783,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 01668a0e8..8a1066082 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -1412,6 +1412,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, @@ -4754,4 +4779,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index 4ec768082..fc3f55faf 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -538,4 +538,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/declaration/specs.json b/src/test/converter/declaration/specs.json index 266b0ccd4..ffe21ba1d 100644 --- a/src/test/converter/declaration/specs.json +++ b/src/test/converter/declaration/specs.json @@ -304,4 +304,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index 9e964666c..e3f903617 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -426,4 +426,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index 9e964666c..e3f903617 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -426,4 +426,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/enum/enum.ts#L4" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 36d8780e1..1ffb59164 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -867,4 +867,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json index 990c03b79..ee92e7b76 100644 --- a/src/test/converter/function/specs.json +++ b/src/test/converter/function/specs.json @@ -2836,4 +2836,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/inherit-param-doc/specs.json b/src/test/converter/inherit-param-doc/specs.json index 96cb13b16..a3ee632ed 100644 --- a/src/test/converter/inherit-param-doc/specs.json +++ b/src/test/converter/inherit-param-doc/specs.json @@ -56,7 +56,7 @@ "flags": {}, "parameters": [ { - "id": 4, + "id": 11, "name": "a", "kind": 32768, "kindString": "Parameter", @@ -65,7 +65,7 @@ "summary": [ { "kind": "text", - "text": "Custom parameter A doc." + "text": "Parameter A." } ] }, @@ -75,7 +75,7 @@ } }, { - "id": 5, + "id": 12, "name": "b", "kind": 32768, "kindString": "Parameter", @@ -193,7 +193,7 @@ "flags": {}, "parameters": [ { - "id": 4, + "id": 18, "name": "a", "kind": 32768, "kindString": "Parameter", @@ -212,7 +212,7 @@ } }, { - "id": 5, + "id": 19, "name": "b", "kind": 32768, "kindString": "Parameter", @@ -330,7 +330,7 @@ "flags": {}, "parameters": [ { - "id": 4, + "id": 25, "name": "a", "kind": 32768, "kindString": "Parameter", @@ -339,7 +339,7 @@ "summary": [ { "kind": "text", - "text": "Custom parameter A doc." + "text": "Parameter A." } ] }, @@ -349,8 +349,8 @@ } }, { - "id": 5, - "name": "b", + "id": 26, + "name": "c", "kind": 32768, "kindString": "Parameter", "flags": {}, @@ -358,7 +358,7 @@ "summary": [ { "kind": "text", - "text": "Parameter B." + "text": "Custom second parameter doc with name change." } ] }, @@ -455,7 +455,7 @@ "summary": [ { "kind": "text", - "text": "Custom parameter A doc." + "text": "Parameter A." } ] }, @@ -551,4 +551,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inherit-param-doc/inherit-param-doc.ts#L1" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index 5d4454dd7..d90be87a6 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -955,4 +955,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index e159ddda7..cffbc13f8 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -1032,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, @@ -2345,4 +2353,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index d7e727172..705ede218 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -981,4 +981,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 941e557d4..7b9686742 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -1733,4 +1733,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/react/specs.json b/src/test/converter/react/specs.json index 6e9cdfb88..8a3d1b30c 100644 --- a/src/test/converter/react/specs.json +++ b/src/test/converter/react/specs.json @@ -221,4 +221,4 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/react/react.tsx#L2" } ] -} \ No newline at end of file +} diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index f706bafe6..d5f40fabc 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -1840,4 +1840,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 11eb727a5..20f2105fc 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -2015,4 +2015,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index d4a1a6d7b..dc121e85d 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -559,4 +559,4 @@ ] } ] -} \ No newline at end of file +} diff --git a/src/test/converter2.test.ts b/src/test/converter2.test.ts index 1760a4e1a..f01a37bd4 100644 --- a/src/test/converter2.test.ts +++ b/src/test/converter2.test.ts @@ -54,8 +54,9 @@ describe("Converter2", () => { }); for (const [entry, check] of Object.entries(issueTests)) { - const link = `https://github.com/TypeStrong/typedoc/issues/${entry.substring( - 2 + const link = `https://github.com/TypeStrong/typedoc/issues/${entry.replace( + /[^\d]/g, + "" )}`; const name = `Issue ${entry 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/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/issueTests.ts b/src/test/issueTests.ts index b7ffe4708..84da6cf35 100644 --- a/src/test/issueTests.ts +++ b/src/test/issueTests.ts @@ -493,4 +493,13 @@ export const issueTests: { ) ); }, + + gh1927(project) { + const ref = query(project, "Derived.getter"); + + equal( + ref.getSignature?.comment, + new Comment([{ kind: "text", text: "Base" }]) + ); + }, }; From 0c172b3517df0ada25e65cc256837f906f4c6b1c Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 30 May 2022 15:51:53 -0600 Subject: [PATCH 108/151] Clean up some TODOs pending breaking version update --- .config/.prettierignore | 1 + CHANGELOG.md | 5 +- src/lib/models/ReflectionGroup.ts | 7 +- src/lib/models/comments/comment.ts | 5 +- src/lib/models/reflections/container.ts | 13 +- src/lib/models/reflections/declaration.ts | 47 ++---- src/lib/models/reflections/parameter.ts | 2 +- src/lib/models/reflections/signature.ts | 23 +-- src/lib/models/reflections/type-parameter.ts | 4 +- src/lib/models/types.ts | 16 +- src/lib/serialization/schema.ts | 14 +- src/lib/serialization/serializer.ts | 24 ++- src/test/converter/alias/specs.json | 6 +- .../class/specs-with-lump-categories.json | 158 ++++++++---------- src/test/converter/class/specs.json | 158 ++++++++---------- src/test/converter/inheritance/specs.json | 4 +- src/test/converter/interface/specs.json | 10 +- src/test/converter/js/specs.json | 4 +- src/test/converter/mixin/specs.json | 6 +- src/test/converter/types/specs.json | 6 +- src/test/converter/variables/specs.json | 2 +- src/test/converter/variables/specs.nodoc.json | 2 +- 22 files changed, 233 insertions(+), 284 deletions(-) diff --git a/.config/.prettierignore b/.config/.prettierignore index 6eb33261f..07ddd32a6 100644 --- a/.config/.prettierignore +++ b/.config/.prettierignore @@ -8,6 +8,7 @@ ../src/test/renderer/testProject ../static/main.js ../example/docs/ +**/.vs # Turn this back on once supported by Prettier ../src/test/converter2/behavior/instantiationExpressions.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa5d163e..1d5f43e5e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,10 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi ### Breaking Changes -- Node 12 is no longer officially supported as it is has gone end of life as of 2022-04-30. It might still work, but may stop working at any time. +- 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. +- 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` - `@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. diff --git a/src/lib/models/ReflectionGroup.ts b/src/lib/models/ReflectionGroup.ts index d8af8cfad..be3ce0f5e 100644 --- a/src/lib/models/ReflectionGroup.ts +++ b/src/lib/models/ReflectionGroup.ts @@ -48,12 +48,7 @@ export class ReflectionGroup { this.children.length > 0 ? this.children.map((child) => child.id) : undefined, - categories: - this.categories && this.categories.length > 0 - ? this.categories.map((category) => - serializer.toObject(category) - ) - : undefined, + categories: serializer.toObjectsOptional(this.categories), }; } } diff --git a/src/lib/models/comments/comment.ts b/src/lib/models/comments/comment.ts index 2f27d7dd8..37079324c 100644 --- a/src/lib/models/comments/comment.ts +++ b/src/lib/models/comments/comment.ts @@ -236,10 +236,7 @@ export class Comment { toObject(serializer: Serializer): JSONOutput.Comment { return { summary: this.summary.map(serializeDisplayPart), - blockTags: - this.blockTags.length > 0 - ? this.blockTags.map((tag) => serializer.toObject(tag)) - : undefined, + blockTags: serializer.toObjectsOptional(this.blockTags), modifierTags: this.modifierTags.size > 0 ? Array.from(this.modifierTags) diff --git a/src/lib/models/reflections/container.ts b/src/lib/models/reflections/container.ts index 6c97cfaac..e62622796 100644 --- a/src/lib/models/reflections/container.ts +++ b/src/lib/models/reflections/container.ts @@ -56,15 +56,10 @@ export class ContainerReflection extends Reflection { override toObject(serializer: Serializer): JSONOutput.ContainerReflection { return { ...super.toObject(serializer), - children: this.children?.map((child) => serializer.toObject(child)), - groups: this.groups?.map((group) => serializer.toObject(group)), - categories: this.categories?.map((category) => - serializer.toObject(category) - ), - sources: - this.sources && this.sources.length > 0 - ? this.sources.map((source) => serializer.toObject(source)) - : undefined, + 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 13a7cecbf..f5f288905 100644 --- a/src/lib/models/reflections/declaration.ts +++ b/src/lib/models/reflections/declaration.ts @@ -252,41 +252,22 @@ export class DeclarationReflection extends ContainerReflection { ): JSONOutput.DeclarationReflection { return { ...super.toObject(serializer), - typeParameter: - this.typeParameters && this.typeParameters.length > 0 - ? this.typeParameters.map((type) => - serializer.toObject(type) - ) - : undefined, - type: this.type && serializer.toObject(this.type), - signatures: this.signatures?.map((sig) => serializer.toObject(sig)), - indexSignature: - this.indexSignature && serializer.toObject(this.indexSignature), - getSignature: this.getSignature && [ - serializer.toObject(this.getSignature), - ], - setSignature: this.setSignature && [ - serializer.toObject(this.setSignature), - ], + 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: this.overwrites && serializer.toObject(this.overwrites), - inheritedFrom: - this.inheritedFrom && serializer.toObject(this.inheritedFrom), - implementationOf: - this.implementationOf && - serializer.toObject(this.implementationOf), - extendedTypes: this.extendedTypes?.map((type) => - serializer.toObject(type) - ), - extendedBy: this.extendedBy?.map((type) => - serializer.toObject(type) - ), - implementedTypes: this.implementedTypes?.map((type) => - serializer.toObject(type) - ), - implementedBy: this.implementedBy?.map((type) => - serializer.toObject(type) + 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/parameter.ts b/src/lib/models/reflections/parameter.ts index 13e6924e8..9bfa6b69d 100644 --- a/src/lib/models/reflections/parameter.ts +++ b/src/lib/models/reflections/parameter.ts @@ -44,7 +44,7 @@ export class ParameterReflection extends Reflection { override toObject(serializer: Serializer): JSONOutput.ParameterReflection { return { ...super.toObject(serializer), - type: this.type && serializer.toObject(this.type), + type: serializer.toObject(this.type), defaultValue: this.defaultValue, }; } diff --git a/src/lib/models/reflections/signature.ts b/src/lib/models/reflections/signature.ts index 57b4f5d4e..73660275d 100644 --- a/src/lib/models/reflections/signature.ts +++ b/src/lib/models/reflections/signature.ts @@ -109,23 +109,12 @@ export class SignatureReflection extends Reflection { override toObject(serializer: Serializer): JSONOutput.SignatureReflection { return { ...super.toObject(serializer), - typeParameter: - this.typeParameters && this.typeParameters.length > 0 - ? this.typeParameters.map((type) => - serializer.toObject(type) - ) - : undefined, - parameters: - this.parameters && this.parameters.length > 0 - ? this.parameters.map((type) => serializer.toObject(type)) - : undefined, - type: this.type && serializer.toObject(this.type), - overwrites: this.overwrites && serializer.toObject(this.overwrites), - inheritedFrom: - this.inheritedFrom && serializer.toObject(this.inheritedFrom), - implementationOf: - this.implementationOf && - serializer.toObject(this.implementationOf), + 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 4ae96aadb..1b64089cb 100644 --- a/src/lib/models/reflections/type-parameter.ts +++ b/src/lib/models/reflections/type-parameter.ts @@ -43,8 +43,8 @@ export class TypeParameterReflection extends Reflection { ): JSONOutput.TypeParameterReflection { return { ...super.toObject(serializer), - type: this.type && serializer.toObject(this.type), - default: this.default && serializer.toObject(this.default), + type: serializer.toObject(this.type), + default: serializer.toObject(this.default), varianceModifier: this.varianceModifier, }; } diff --git a/src/lib/models/types.ts b/src/lib/models/types.ts index 92f0519f0..241f96999 100644 --- a/src/lib/models/types.ts +++ b/src/lib/models/types.ts @@ -399,7 +399,7 @@ export class InferredType extends Type { return { type: this.type, name: this.name, - constraint: this.constraint ? serializer.toObject(this.constraint) : undefined + constraint: serializer.toObject(this.constraint), }; } } @@ -608,7 +608,7 @@ export class MappedType extends Type { templateType: serializer.toObject(this.templateType), readonlyModifier: this.readonlyModifier, optionalModifier: this.optionalModifier, - nameType: this.nameType && serializer.toObject(this.nameType), + nameType: serializer.toObject(this.nameType), }; } } @@ -699,7 +699,7 @@ export class PredicateType extends Type { type: this.type, name: this.name, asserts: this.asserts, - targetType: this.targetType && serializer.toObject(this.targetType), + targetType: serializer.toObject(this.targetType), }; } } @@ -900,10 +900,7 @@ export class ReferenceType extends Type { const result: JSONOutput.ReferenceType = { type: this.type, id: this.reflection?.id, - typeArguments: - this.typeArguments && this.typeArguments.length > 0 - ? this.typeArguments?.map((t) => serializer.toObject(t)) - : undefined, + typeArguments: serializer.toObjectsOptional(this.typeArguments), name: this.name, }; @@ -1068,10 +1065,7 @@ export class TupleType extends Type { override toObject(serializer: Serializer): JSONOutput.TupleType { return { type: this.type, - elements: - this.elements.length > 0 - ? this.elements.map((t) => serializer.toObject(t)) - : undefined, + elements: serializer.toObjectsOptional(this.elements), }; } } diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts index 02e87df2d..db21d9729 100644 --- a/src/lib/serialization/schema.ts +++ b/src/lib/serialization/schema.ts @@ -151,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, diff --git a/src/lib/serialization/serializer.ts b/src/lib/serialization/serializer.ts index 50b59d083..7d020d3ba 100644 --- a/src/lib/serialization/serializer.ts +++ b/src/lib/serialization/serializer.ts @@ -34,15 +34,35 @@ export class Serializer extends EventDispatcher { toObject }>( value: T - ): ModelToObject { + ): ModelToObject; + toObject }>( + value: T | undefined + ): ModelToObject | undefined; + toObject( + value: { toObject(serializer: Serializer): any } | undefined + ): unknown { + if (value === undefined) { + return undefined; + } + return this.serializers .filter((s) => s.supports(value)) .reduce( - (val, s) => s.toObject(value, val, this) as ModelToObject, + (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; + } + + return value.map((val) => this.toObject(val)); + } + /** * Same as toObject but emits {@link Serializer.EVENT_BEGIN} and {@link Serializer.EVENT_END} events. * @param value diff --git a/src/test/converter/alias/specs.json b/src/test/converter/alias/specs.json index 9b77f8558..2bf65bb0c 100644 --- a/src/test/converter/alias/specs.json +++ b/src/test/converter/alias/specs.json @@ -27,7 +27,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L14" } ], - "typeParameter": [ + "typeParameters": [ { "id": 9, "name": "T", @@ -79,7 +79,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L19" } ], - "typeParameter": [ + "typeParameters": [ { "id": 11, "name": "T", @@ -132,7 +132,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/alias/alias.ts#L4" } ], - "typeParameter": [ + "typeParameters": [ { "id": 6, "name": "T", diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json index d9e3df077..09e844248 100644 --- a/src/test/converter/class/specs-with-lump-categories.json +++ b/src/test/converter/class/specs-with-lump-categories.json @@ -103,19 +103,17 @@ "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" - } + "getSignature": { + "id": 10, + "name": "privateStaticGetter", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "number" } - ] + } }, { "id": 15, @@ -3850,7 +3848,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ], - "typeParameter": [ + "typeParameters": [ { "id": 175, "name": "T", @@ -4225,45 +4223,41 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], - "getSignature": [ - { - "id": 190, - "name": "name", - "kind": 524288, - "kindString": "Get signature", - "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" - } + }, + "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, @@ -4279,19 +4273,17 @@ "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" - } + "getSignature": { + "id": 194, + "name": "readOnlyName", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ] + } }, { "id": 195, @@ -4307,32 +4299,30 @@ "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" - } + "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": [ @@ -4611,7 +4601,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" } ], - "typeParameter": [ + "typeParameters": [ { "id": 215, "name": "T", diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json index 6e1cc1bc3..f1b092a15 100644 --- a/src/test/converter/class/specs.json +++ b/src/test/converter/class/specs.json @@ -103,19 +103,17 @@ "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" - } + "getSignature": { + "id": 10, + "name": "privateStaticGetter", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "number" } - ] + } }, { "id": 15, @@ -3846,7 +3844,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/generic-class.ts#L5" } ], - "typeParameter": [ + "typeParameters": [ { "id": 175, "name": "T", @@ -4221,45 +4219,41 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/getter-setter.ts#L7" } ], - "getSignature": [ - { - "id": 190, - "name": "name", - "kind": 524288, - "kindString": "Get signature", - "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" - } + }, + "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, @@ -4275,19 +4269,17 @@ "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" - } + "getSignature": { + "id": 194, + "name": "readOnlyName", + "kind": 524288, + "kindString": "Get signature", + "flags": {}, + "type": { + "type": "intrinsic", + "name": "string" } - ] + } }, { "id": 195, @@ -4303,32 +4295,30 @@ "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" - } + "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": [ @@ -4607,7 +4597,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/class/type-operator.ts#L13" } ], - "typeParameter": [ + "typeParameters": [ { "id": 215, "name": "T", diff --git a/src/test/converter/inheritance/specs.json b/src/test/converter/inheritance/specs.json index d90be87a6..7cf03133f 100644 --- a/src/test/converter/inheritance/specs.json +++ b/src/test/converter/inheritance/specs.json @@ -139,7 +139,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L6" } ], - "typeParameter": [ + "typeParameters": [ { "id": 19, "name": "T", @@ -273,7 +273,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/inheritance/inherit-doc.ts#L26" } ], - "typeParameter": [ + "typeParameters": [ { "id": 25, "name": "T", diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json index 86e9555a4..88f73abc0 100644 --- a/src/test/converter/interface/specs.json +++ b/src/test/converter/interface/specs.json @@ -1002,7 +1002,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L56" } ], - "typeParameter": [ + "typeParameters": [ { "id": 101, "name": "T", @@ -1341,7 +1341,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L24" } ], - "typeParameter": [ + "typeParameters": [ { "id": 63, "name": "V", @@ -1631,7 +1631,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L40" } ], - "typeParameter": [ + "typeParameters": [ { "id": 80, "name": "U", @@ -1662,7 +1662,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L5" } ], - "typeParameter": [ + "typeParameters": [ { "id": 39, "name": "T", @@ -1848,7 +1848,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/interface/interface-implementation.ts#L13" } ], - "typeParameter": [ + "typeParameters": [ { "id": 48, "name": "T", diff --git a/src/test/converter/js/specs.json b/src/test/converter/js/specs.json index 421655f64..0767d248f 100644 --- a/src/test/converter/js/specs.json +++ b/src/test/converter/js/specs.json @@ -375,7 +375,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L45" } ], - "typeParameter": [ + "typeParameters": [ { "id": 43, "name": "T", @@ -412,7 +412,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/js/index.js#L33" } ], - "typeParameter": [ + "typeParameters": [ { "id": 37, "name": "T", diff --git a/src/test/converter/mixin/specs.json b/src/test/converter/mixin/specs.json index 34fee8ffb..8ba5e8c41 100644 --- a/src/test/converter/mixin/specs.json +++ b/src/test/converter/mixin/specs.json @@ -1059,7 +1059,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L9" } ], - "typeParameter": [ + "typeParameters": [ { "id": 10, "name": "A", @@ -1145,7 +1145,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L4" } ], - "typeParameter": [ + "typeParameters": [ { "id": 5, "name": "A", @@ -1239,7 +1239,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/mixin/mixin.ts#L14" } ], - "typeParameter": [ + "typeParameters": [ { "id": 12, "name": "T", diff --git a/src/test/converter/types/specs.json b/src/test/converter/types/specs.json index 363d47940..33710b84c 100644 --- a/src/test/converter/types/specs.json +++ b/src/test/converter/types/specs.json @@ -66,7 +66,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/general.ts#L17" } ], - "typeParameter": [ + "typeParameters": [ { "id": 12, "name": "T", @@ -494,7 +494,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L7" } ], - "typeParameter": [ + "typeParameters": [ { "id": 35, "name": "T", @@ -572,7 +572,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/types/mapped.ts#L5" } ], - "typeParameter": [ + "typeParameters": [ { "id": 33, "name": "T", diff --git a/src/test/converter/variables/specs.json b/src/test/converter/variables/specs.json index 20f2105fc..dcfc30e50 100644 --- a/src/test/converter/variables/specs.json +++ b/src/test/converter/variables/specs.json @@ -80,7 +80,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ], - "typeParameter": [ + "typeParameters": [ { "id": 6, "name": "T", diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index dc121e85d..de99e9d70 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -80,7 +80,7 @@ "url": "https://github.com/TypeStrong/typedoc/blob/fake/src/test/converter/variables/array.ts#L4" } ], - "typeParameter": [ + "typeParameters": [ { "id": 6, "name": "T", From c58772812dffcfa05f4882335304d202673835bc Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 30 May 2022 16:00:52 -0600 Subject: [PATCH 109/151] Bump version to 0.23.0-beta.2 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9d156bae..1e0188019 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.23.0-beta.1", + "version": "0.23.0-beta.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.23.0-beta.1", + "version": "0.23.0-beta.2", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index d0cfd6353..3b2798d0f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.23.0-beta.1", + "version": "0.23.0-beta.2", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": "./dist/index.js", From 176a4f380ea9a92060fb018dfd0afeaa6e9a8622 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 31 May 2022 19:50:57 -0600 Subject: [PATCH 110/151] Remove `defaultValue` setting on enums --- CHANGELOG.md | 1 + src/lib/application.ts | 11 --------- src/lib/converter/symbols.ts | 2 -- src/lib/models/reflections/declaration.ts | 4 +--- .../default/partials/member.declaration.tsx | 4 ++-- .../partials/member.signature.body.tsx | 1 + src/lib/utils/component.ts | 7 ------ src/lib/utils/options/sources/typedoc.ts | 2 +- src/test/behaviorTests.ts | 4 ++-- src/test/converter/comment/specs.json | 7 +++--- src/test/converter/enum/specs.json | 24 +++++++------------ src/test/converter/enum/specs.nodoc.json | 24 +++++++------------ 12 files changed, 28 insertions(+), 63 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d5f43e5e..3396f1dbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. diff --git a/src/lib/application.ts b/src/lib/application.ts index a66c743c6..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"; @@ -158,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. */ diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index b98e03050..847c3c57d 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -251,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); @@ -874,7 +873,6 @@ function convertVariableAsEnum( ); assert(propType.isStringLiteral() || propType.isNumberLiteral()); - reflection.defaultValue = JSON.stringify(propType.value); reflection.type = new LiteralType(propType.value); rc.finalizeDeclarationReflection(reflection); diff --git a/src/lib/models/reflections/declaration.ts b/src/lib/models/reflections/declaration.ts index f5f288905..540918a5b 100644 --- a/src/lib/models/reflections/declaration.ts +++ b/src/lib/models/reflections/declaration.ts @@ -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; diff --git a/src/lib/output/themes/default/partials/member.declaration.tsx b/src/lib/output/themes/default/partials/member.declaration.tsx index 28c17cbad..da9dd70c2 100644 --- a/src/lib/output/themes/default/partials/member.declaration.tsx +++ b/src/lib/output/themes/default/partials/member.declaration.tsx @@ -1,4 +1,4 @@ -import { DeclarationReflection, ReflectionKind, ReflectionType } from "../../../../models"; +import { DeclarationReflection, ReflectionType } from "../../../../models"; import { JSX } from "../../../../utils"; import { hasTypeParameters, renderTypeParametersSignature, wbr } from "../../lib"; import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext"; @@ -14,7 +14,7 @@ export const memberDeclaration = (context: DefaultThemeRenderContext, props: Dec {context.type(props.type)} )} - {!!props.defaultValue && props.kind !== ReflectionKind.EnumMember && ( + {!!props.defaultValue && ( <> {" = "} 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 a644ad9b4..419f28f3a 100644 --- a/src/lib/output/themes/default/partials/member.signature.body.tsx +++ b/src/lib/output/themes/default/partials/member.signature.body.tsx @@ -9,6 +9,7 @@ export const memberSignatureBody = ( { hideSources = false }: { hideSources?: boolean } = {} ) => ( <> + {renderFlags(props.flags, props.comment)} {context.comment(props)} {hasTypeParameters(props) && ( 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/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 0d1575f85..1ae1a08be 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -367,6 +367,7 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Array, defaultValue: [ // TSDoc standard + "@deprecated", "@param", "@remarks", "@throws", @@ -411,7 +412,6 @@ export function addTypeDocOptions(options: Pick) { "@readonly", "@packageDocumentation", "@eventProperty", - "@deprecated", "@alpha", "@beta", "@sealed", diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 86927b0f7..4008a0636 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -31,7 +31,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"); @@ -63,7 +63,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"); diff --git a/src/test/converter/comment/specs.json b/src/test/converter/comment/specs.json index fc3f55faf..8b5ec6e22 100644 --- a/src/test/converter/comment/specs.json +++ b/src/test/converter/comment/specs.json @@ -29,6 +29,10 @@ } ], "blockTags": [ + { + "tag": "@deprecated", + "content": [] + }, { "tag": "@todo", "content": [ @@ -38,9 +42,6 @@ } ] } - ], - "modifierTags": [ - "@deprecated" ] }, "children": [ diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json index e61fc028e..bedf333e7 100644 --- a/src/test/converter/enum/specs.json +++ b/src/test/converter/enum/specs.json @@ -147,8 +147,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 15, @@ -167,8 +166,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } } ], "groups": [ @@ -229,8 +227,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 7, @@ -257,8 +254,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 8, @@ -285,8 +281,7 @@ "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ @@ -354,8 +349,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 3, @@ -382,8 +376,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 4, @@ -410,8 +403,7 @@ "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json index e61fc028e..bedf333e7 100644 --- a/src/test/converter/enum/specs.nodoc.json +++ b/src/test/converter/enum/specs.nodoc.json @@ -147,8 +147,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 15, @@ -167,8 +166,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } } ], "groups": [ @@ -229,8 +227,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 7, @@ -257,8 +254,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 8, @@ -285,8 +281,7 @@ "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ @@ -354,8 +349,7 @@ "type": { "type": "literal", "value": 1 - }, - "defaultValue": "1" + } }, { "id": 3, @@ -382,8 +376,7 @@ "type": { "type": "literal", "value": 2 - }, - "defaultValue": "2" + } }, { "id": 4, @@ -410,8 +403,7 @@ "type": { "type": "literal", "value": 4 - }, - "defaultValue": "4" + } } ], "groups": [ From f636b8f55940a3f805c8ef67fc2c9fe745a0ff73 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 31 May 2022 20:48:56 -0600 Subject: [PATCH 111/151] Drop support for TS < 4.6 --- CHANGELOG.md | 1 + package-lock.json | 2 +- package.json | 2 +- src/lib/converter/context.ts | 9 +-------- src/lib/converter/symbols.ts | 5 +---- src/lib/types/ts-internal/index.d.ts | 3 +-- 6 files changed, 6 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51e5bf944..6db0a1cf7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi ### 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. - 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` diff --git a/package-lock.json b/package-lock.json index 1e0188019..1d0cf1ba0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -43,7 +43,7 @@ "node": ">= 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": { diff --git a/package.json b/package.json index 3b2798d0f..07ef2a6ae 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "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", diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 751b7177a..40312ab13 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -288,17 +288,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/symbols.ts b/src/lib/converter/symbols.ts index 1227b0644..847c3c57d 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -656,13 +656,10 @@ 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) { 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 { From 2e0cd8cb5f7be36745609e9620a33ecb771a78aa Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 1 Jun 2022 20:22:09 -0600 Subject: [PATCH 112/151] Support for comments in typedoc.json --- CHANGELOG.md | 1 + package.json | 2 +- src/lib/utils/options/readers/typedoc.ts | 35 ++++++++++++++++--- .../utils/options/readers/data/invalid2.json | 3 ++ src/test/utils/options/readers/data/td.js | 1 + .../utils/options/readers/data/valid.json | 1 + .../utils/options/readers/typedoc.test.ts | 33 ++++++++++------- 7 files changed, 58 insertions(+), 18 deletions(-) create mode 100644 src/test/utils/options/readers/data/invalid2.json create mode 100644 src/test/utils/options/readers/data/td.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 6db0a1cf7..a5db97ddc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. +- `typedoc.json` now supports comments like `tsconfig.json`. - 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. diff --git a/package.json b/package.json index 07ef2a6ae..efe21617d 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "/static" ], "scripts": { - "test": "mocha -r ts-node/register --config .config/mocha.fast.json", + "test": "nyc mocha -r ts-node/register --config .config/mocha.fast.json", "build:c2": "node bin/typedoc --tsconfig src/test/converter2/tsconfig.json", "test:full": "nyc 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", diff --git a/src/lib/utils/options/readers/typedoc.ts b/src/lib/utils/options/readers/typedoc.ts index af5224903..315ed328c 100644 --- a/src/lib/utils/options/readers/typedoc.ts +++ b/src/lib/utils/options/readers/typedoc.ts @@ -1,10 +1,13 @@ 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"; /** * Obtains option values from typedoc.json @@ -54,22 +57,44 @@ 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) { diff --git a/src/test/utils/options/readers/data/invalid2.json b/src/test/utils/options/readers/data/invalid2.json new file mode 100644 index 000000000..c7864a585 --- /dev/null +++ b/src/test/utils/options/readers/data/invalid2.json @@ -0,0 +1,3 @@ +{ + / oops +} diff --git a/src/test/utils/options/readers/data/td.js b/src/test/utils/options/readers/data/td.js new file mode 100644 index 000000000..5c6ad6e2d --- /dev/null +++ b/src/test/utils/options/readers/data/td.js @@ -0,0 +1 @@ +module.exports = { gitRevision: "a" }; diff --git a/src/test/utils/options/readers/data/valid.json b/src/test/utils/options/readers/data/valid.json index 33431cb09..8f6c84892 100644 --- a/src/test/utils/options/readers/data/valid.json +++ b/src/test/utils/options/readers/data/valid.json @@ -1,4 +1,5 @@ { + // With comments! "$schema": "https://typedoc.org/schema.json", "gitRevision": "master" } diff --git a/src/test/utils/options/readers/typedoc.test.ts b/src/test/utils/options/readers/typedoc.test.ts index cb7f8f58e..e51328a43 100644 --- a/src/test/utils/options/readers/typedoc.test.ts +++ b/src/test/utils/options/readers/typedoc.test.ts @@ -1,8 +1,9 @@ -import { join } from "path"; +import { join, relative } from "path"; import { deepStrictEqual as equal } from "assert"; import { TypeDocReader } from "../../../../lib/utils/options/readers"; import { Logger, Options, ConsoleLogger } from "../../../../lib/utils"; +import { TestLogger } from "../../../TestLogger"; describe("Options - TypeDocReader", () => { const options = new Options(new Logger()); @@ -12,44 +13,52 @@ describe("Options - TypeDocReader", () => { function test(name: string, input: string, cb: () => void) { it(name, () => { options.reset(); - options.setValue("options", input); + options.setValue("options", input, __dirname); options.read(new ConsoleLogger()); cb(); }); } - test("Supports extends", join(__dirname, "data/extends.json"), () => { + test("Supports extends", "data/extends.json", () => { equal(options.getValue("name"), "extends"); equal(options.getValue("gitRevision"), "master"); }); - function testError(name: string, file: string) { + test("Supports js files", "data/td.js", () => { + equal(options.getValue("gitRevision"), "a"); + }); + + function testError(name: string, file: string, message: string) { it(name, () => { options.reset(); - options.setValue("options", file); - const logger = new Logger(); + options.setValue("options", file, __dirname); + const logger = new TestLogger(); options.read(logger); - equal(logger.hasErrors(), true, "No error was logged"); + logger.expectMessage(message); }); } testError( "Errors if the file cannot be found", - join(__dirname, "data/non-existent-file.json") + "data/non-existent-file.json", + "error: The options file could not be found with the given path " + + join(__dirname, "data/non-existent-file.json") ); testError( "Errors if the data is invalid", - join(__dirname, "data/invalid.json") + "data/invalid.json", + "error: Failed to parse ./src/test/utils/options/readers/data/invalid.json, ensure it exists and contains an object." ); testError( "Errors if any set option errors", - join(__dirname, "data/unknown.json") + "data/unknown.json", + "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") + "data/circular-extends.json", + "error: Tried to load the options file ./src/test/utils/options/readers/data/circular-extends.json multiple times." ); - it("Does not error if the option file cannot be found but was not set.", () => { const options = new (class LyingOptions extends Options { override isSet() { From c381deee5337d41556c6aa6bf57c227058dc0544 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 2 Jun 2022 20:03:57 -0600 Subject: [PATCH 113/151] Support for reading tags from tsdoc.json Need a test scaffolding tool badly... --- .config/typedoc-default.tsdoc.json | 33 ++++ CHANGELOG.md | 2 + package.json | 8 +- src/lib/utils/options/declaration.ts | 4 +- src/lib/utils/options/readers/tsconfig.ts | 179 +++++++++++++++++- src/lib/utils/options/readers/typedoc.ts | 2 +- src/lib/utils/options/sources/typedoc.ts | 38 +--- src/lib/utils/options/tsdoc-defaults.ts | 43 +++++ src/lib/utils/validation.ts | 29 ++- src/test/TestLogger.ts | 9 +- .../options/readers/data/tsdoc1/tsconfig.json | 3 + .../options/readers/data/tsdoc1/tsdoc.json | 1 + .../options/readers/data/tsdoc2/tsconfig.json | 3 + .../options/readers/data/tsdoc2/tsdoc.json | 3 + .../options/readers/data/tsdoc3/tsconfig.json | 3 + .../options/readers/data/tsdoc3/tsdoc.json | 1 + .../options/readers/data/tsdoc4/tsconfig.json | 3 + .../options/readers/data/tsdoc4/tsdoc.json | 18 ++ .../options/readers/data/tsdoc5/tsconfig.json | 3 + .../options/readers/data/tsdoc5/tsdoc.json | 4 + .../options/readers/data/tsdoc5/tsdoc2.json | 10 + .../options/readers/data/tsdoc6/tsconfig.json | 3 + .../options/readers/data/tsdoc6/tsdoc.json | 21 ++ .../options/readers/data/tsdoc7/tsconfig.json | 3 + .../options/readers/data/tsdoc7/tsdoc.json | 4 + .../utils/options/readers/tsconfig.test.ts | 69 +++++++ .../utils/options/readers/typedoc.test.ts | 8 +- src/test/utils/validation.test.ts | 21 ++ 28 files changed, 475 insertions(+), 53 deletions(-) create mode 100644 .config/typedoc-default.tsdoc.json create mode 100644 src/lib/utils/options/tsdoc-defaults.ts create mode 100644 src/test/utils/options/readers/data/tsdoc1/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc1/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc2/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc2/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc3/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc3/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc4/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc4/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc5/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc5/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc5/tsdoc2.json create mode 100644 src/test/utils/options/readers/data/tsdoc6/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc6/tsdoc.json create mode 100644 src/test/utils/options/readers/data/tsdoc7/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc7/tsdoc.json diff --git a/.config/typedoc-default.tsdoc.json b/.config/typedoc-default.tsdoc.json new file mode 100644 index 000000000..0c090ce7f --- /dev/null +++ b/.config/typedoc-default.tsdoc.json @@ -0,0 +1,33 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": false, + "tagDefinitions": [ + { + "tagName": "@module", + "syntaxKind": "block" + }, + // 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": "@hidden", + "syntaxKind": "modifier" + }, + { + "tagName": "@ignore", + "syntaxKind": "modifier" + }, + { + "tagName": "@enum", + "syntaxKind": "modifier" + }, + { + "tagName": "@event", + "syntaxKind": "modifier" + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index a5db97ddc..66b1c6376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. - `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. diff --git a/package.json b/package.json index efe21617d..21668473e 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,10 @@ "version": "0.23.0-beta.2", "homepage": "https://typedoc.org", "main": "./dist/index.js", - "exports": "./dist/index.js", + "exports": { + ".": "./dist/index.js", + "./tsdoc.json": "./.config/typedoc-default.tsdoc.json" + }, "types": "./dist/index.d.ts", "bin": { "typedoc": "bin/typedoc" @@ -59,7 +62,8 @@ "!/dist/.tsbuildinfo", "!/dist/test", "/LICENSE", - "/static" + "/static", + "/.config/typedoc-default.tsdoc.json" ], "scripts": { "test": "nyc mocha -r ts-node/register --config .config/mocha.fast.json", diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 3c90749eb..b7fd09914 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -298,7 +298,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. @@ -578,7 +578,7 @@ const defaultGetters: { return option.defaultValue; }, [ParameterType.Array](option) { - return option.defaultValue ?? []; + return option.defaultValue?.slice() ?? []; }, [ParameterType.PathArray](option) { return ( diff --git a/src/lib/utils/options/readers/tsconfig.ts b/src/lib/utils/options/readers/tsconfig.ts index 8f03ac967..2d18244b8 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,12 +101,15 @@ 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( @@ -111,4 +166,122 @@ 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 path of config.extends) { + const parentConfig = this.readTsDoc( + logger, + resolver.resolve(path) + ); + + 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 315ed328c..d15f47cbd 100644 --- a/src/lib/utils/options/readers/typedoc.ts +++ b/src/lib/utils/options/readers/typedoc.ts @@ -33,7 +33,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; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 1ae1a08be..8f6a49b6e 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -6,6 +6,7 @@ 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"; export function addTypeDocOptions(options: Pick) { options.addDeclaration({ @@ -365,19 +366,7 @@ export function addTypeDocOptions(options: Pick) { name: "blockTags", help: "Block tags which TypeDoc should recognize when parsing comments.", type: ParameterType.Array, - defaultValue: [ - // TSDoc standard - "@deprecated", - "@param", - "@remarks", - "@throws", - "@privateRemarks", - "@defaultValue", - // TypeDoc specific - "@module", - "@inheritDoc", - "@group", - ], + defaultValue: blockTags, validate(value) { if (!Validation.validate([Array, Validation.isTagString], value)) { throw new Error( @@ -390,7 +379,7 @@ export function addTypeDocOptions(options: Pick) { name: "inlineTags", help: "Inline tags which TypeDoc should recognize when parsing comments.", type: ParameterType.Array, - defaultValue: ["@link", "@inheritDoc", "@label"], + defaultValue: inlineTags, validate(value) { if (!Validation.validate([Array, Validation.isTagString], value)) { throw new Error( @@ -403,26 +392,7 @@ export function addTypeDocOptions(options: Pick) { name: "modifierTags", help: "Modifier tags which TypeDoc should recognize when parsing comments.", type: ParameterType.Array, - defaultValue: [ - // TSDoc standard - "@public", - "@private", - "@protected", - "@internal", - "@readonly", - "@packageDocumentation", - "@eventProperty", - "@alpha", - "@beta", - "@sealed", - "@override", - "@virtual", - // TypeDoc specific tags - "@hidden", - "@ignore", - "@enum", - "@event", - ], + defaultValue: modifierTags, validate(value) { if (!Validation.validate([Array, Validation.isTagString], value)) { throw new Error( diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts new file mode 100644 index 000000000..85eb64ff8 --- /dev/null +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -0,0 +1,43 @@ +// If updating these lists, also see .config/typedoc-default.tsdoc.json + +export const tsdocBlockTags = [ + "@deprecated", + "@param", + "@remarks", + "@throws", + "@privateRemarks", + "@defaultValue", +] as const; + +export const blockTags = [ + ...tsdocBlockTags, + "@module", + "@inheritDoc", + "@group", +] as const; + +export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; +export const inlineTags = tsdocInlineTags; + +export const tsdocModifierTags = [ + "@public", + "@private", + "@protected", + "@internal", + "@readonly", + "@packageDocumentation", + "@eventProperty", + "@alpha", + "@beta", + "@sealed", + "@override", + "@virtual", +] as const; + +export const modifierTags = [ + ...tsdocModifierTags, + "@hidden", + "@ignore", + "@enum", + "@event", +] as const; diff --git a/src/lib/utils/validation.ts b/src/lib/utils/validation.ts index 4d32baff5..9c060185a 100644 --- a/src/lib/utils/validation.ts +++ b/src/lib/utils/validation.ts @@ -17,9 +17,10 @@ export type Infer = T extends Optional Extract >; } & { - -readonly [K in Exclude>]: Infer< - Extract - >; + -readonly [K in Exclude< + keyof T, + OptionalKeys | typeof additionalProperties + >]: Infer>; }; export type Optional = Record; @@ -31,20 +32,29 @@ type OptionalKeys = keyof { 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 } + | { readonly [k: string]: Schema; [additionalProperties]?: boolean } | Guard | Optional | Optional | Optional | Optional | Optional - | Optional<{ readonly [k: string]: Schema }> + | Optional<{ + readonly [k: string]: Schema; + [additionalProperties]?: boolean; + }> | Optional>; /** @@ -92,6 +102,15 @@ export function validate(schema: Schema, obj: any): boolean { 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" && diff --git a/src/test/TestLogger.ts b/src/test/TestLogger.ts index aa62239b5..65fe0b7c4 100644 --- a/src/test/TestLogger.ts +++ b/src/test/TestLogger.ts @@ -16,7 +16,8 @@ export class TestLogger extends Logger { } 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( @@ -35,3 +36,9 @@ export class TestLogger extends Logger { this.messages.push(levelMap[level] + message); } } + +function createRegex(s: string) { + return new RegExp( + "^" + s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$" + ); +} diff --git a/src/test/utils/options/readers/data/tsdoc1/tsconfig.json b/src/test/utils/options/readers/data/tsdoc1/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc1/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc1/tsdoc.json b/src/test/utils/options/readers/data/tsdoc1/tsdoc.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc1/tsdoc.json @@ -0,0 +1 @@ +[] diff --git a/src/test/utils/options/readers/data/tsdoc2/tsconfig.json b/src/test/utils/options/readers/data/tsdoc2/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc2/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc2/tsdoc.json b/src/test/utils/options/readers/data/tsdoc2/tsdoc.json new file mode 100644 index 000000000..c54ab4c96 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc2/tsdoc.json @@ -0,0 +1,3 @@ +{ + "doesNotMatchSchema": true +} diff --git a/src/test/utils/options/readers/data/tsdoc3/tsconfig.json b/src/test/utils/options/readers/data/tsdoc3/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc3/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc3/tsdoc.json b/src/test/utils/options/readers/data/tsdoc3/tsdoc.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc3/tsdoc.json @@ -0,0 +1 @@ +{} diff --git a/src/test/utils/options/readers/data/tsdoc4/tsconfig.json b/src/test/utils/options/readers/data/tsdoc4/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc4/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc4/tsdoc.json b/src/test/utils/options/readers/data/tsdoc4/tsdoc.json new file mode 100644 index 000000000..b35d76967 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc4/tsdoc.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": true, + "tagDefinitions": [ + { + "tagName": "@tag", + "syntaxKind": "block" + }, + { + "tagName": "@tag2", + "syntaxKind": "inline" + }, + { + "tagName": "@tag3", + "syntaxKind": "modifier" + } + ] +} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsconfig.json b/src/test/utils/options/readers/data/tsdoc5/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc5/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsdoc.json b/src/test/utils/options/readers/data/tsdoc5/tsdoc.json new file mode 100644 index 000000000..aa9ed7edf --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc5/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["./tsdoc2.json"] +} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json b/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json new file mode 100644 index 000000000..0370d531e --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json @@ -0,0 +1,10 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": true, + "tagDefinitions": [ + { + "tagName": "@tag", + "syntaxKind": "block" + } + ] +} diff --git a/src/test/utils/options/readers/data/tsdoc6/tsconfig.json b/src/test/utils/options/readers/data/tsdoc6/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc6/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc6/tsdoc.json b/src/test/utils/options/readers/data/tsdoc6/tsdoc.json new file mode 100644 index 000000000..f7748e59f --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc6/tsdoc.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "noStandardTags": true, + "tagDefinitions": [ + { + "tagName": "@tag", + "syntaxKind": "block" + }, + { + "tagName": "@tag2", + "syntaxKind": "inline" + }, + { + "tagName": "@tag3", + "syntaxKind": "modifier" + } + ], + "supportForTags": { + "@tag": true + } +} diff --git a/src/test/utils/options/readers/data/tsdoc7/tsconfig.json b/src/test/utils/options/readers/data/tsdoc7/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc7/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc7/tsdoc.json b/src/test/utils/options/readers/data/tsdoc7/tsdoc.json new file mode 100644 index 000000000..8c41562b9 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc7/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["./tsdoc.json"] +} diff --git a/src/test/utils/options/readers/tsconfig.test.ts b/src/test/utils/options/readers/tsconfig.test.ts index f4319edd7..d40e0e8d5 100644 --- a/src/test/utils/options/readers/tsconfig.test.ts +++ b/src/test/utils/options/readers/tsconfig.test.ts @@ -4,6 +4,7 @@ import { deepStrictEqual as equal } from "assert"; import { TSConfigReader } from "../../../../lib/utils/options/readers"; import { Logger, Options } from "../../../../lib/utils"; import { tmpdir } from "os"; +import { TestLogger } from "../../../TestLogger"; describe("Options - TSConfigReader", () => { const options = new Options(new Logger()); @@ -96,4 +97,72 @@ describe("Options - TSConfigReader", () => { options.read(new Logger()); equal(options.getCompilerOptions().strict, true); }); + + function testTsdoc(path: string, cb?: (logger: TestLogger) => void) { + options.reset(); + options.setValue("tsconfig", join(__dirname, path)); + const logger = new TestLogger(); + options.read(logger); + cb?.(logger); + logger.expectNoOtherMessages(); + } + + it("Handles failed tsdoc reads", () => { + testTsdoc("data/tsdoc1", (logger) => { + logger.expectMessage( + "error: Failed to read tsdoc.json file at */tsdoc1/tsdoc.json." + ); + }); + }); + + it("Handles invalid tsdoc files", () => { + testTsdoc("data/tsdoc2", (logger) => { + logger.expectMessage( + `error: The file */tsdoc2/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", []); + options.setValue("tsconfig", join(__dirname, "data/tsdoc3")); + const logger = new TestLogger(); + options.read(logger); + logger.expectMessage( + "warn: The blockTags, modifierTags defined in typedoc.json " + + "will be overwritten by configuration in tsdoc.json." + ); + logger.expectNoOtherMessages(); + }); + + it("Reads tsdoc.json", () => { + testTsdoc("data/tsdoc4"); + + equal(options.getValue("blockTags"), ["@tag"]); + equal(options.getValue("inlineTags"), ["@tag2"]); + equal(options.getValue("modifierTags"), ["@tag3"]); + }); + + it("Handles extends in tsdoc.json", () => { + testTsdoc("data/tsdoc5"); + equal(options.getValue("blockTags"), ["@tag"]); + }); + + it("Handles supportForTags in tsdoc.json", () => { + testTsdoc("data/tsdoc6"); + + equal(options.getValue("blockTags"), ["@tag"]); + equal(options.getValue("inlineTags"), []); + equal(options.getValue("modifierTags"), []); + }); + + it("Handles circular extends", () => { + testTsdoc("data/tsdoc7", (logger) => { + logger.expectMessage( + 'error: Circular reference encountered for "extends" field of */tsdoc7/tsdoc.json' + ); + }); + }); }); diff --git a/src/test/utils/options/readers/typedoc.test.ts b/src/test/utils/options/readers/typedoc.test.ts index e51328a43..c48fd1b94 100644 --- a/src/test/utils/options/readers/typedoc.test.ts +++ b/src/test/utils/options/readers/typedoc.test.ts @@ -1,4 +1,3 @@ -import { join, relative } from "path"; import { deepStrictEqual as equal } from "assert"; import { TypeDocReader } from "../../../../lib/utils/options/readers"; @@ -41,13 +40,12 @@ describe("Options - TypeDocReader", () => { testError( "Errors if the file cannot be found", "data/non-existent-file.json", - "error: The options file could not be found with the given path " + - join(__dirname, "data/non-existent-file.json") + "error: The options file */non-existent-file.json does not exist." ); testError( "Errors if the data is invalid", "data/invalid.json", - "error: Failed to parse ./src/test/utils/options/readers/data/invalid.json, ensure it exists and contains an object." + "error: Failed to parse */invalid.json, ensure it exists and contains an object." ); testError( "Errors if any set option errors", @@ -57,7 +55,7 @@ describe("Options - TypeDocReader", () => { testError( "Errors if extends results in a loop", "data/circular-extends.json", - "error: Tried to load the options file ./src/test/utils/options/readers/data/circular-extends.json multiple times." + "error: Tried to load the options file */circular-extends.json multiple times." ); it("Does not error if the option file cannot be found but was not set.", () => { const options = new (class LyingOptions extends Options { diff --git a/src/test/utils/validation.test.ts b/src/test/utils/validation.test.ts index 44be69f41..046f61d56 100644 --- a/src/test/utils/validation.test.ts +++ b/src/test/utils/validation.test.ts @@ -1,5 +1,6 @@ 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", () => { @@ -56,4 +57,24 @@ describe("Validation Utils", () => { 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: "" })); + }); }); From 6da5b3f4a0612c5d26f0c72a073312f27e98c6b7 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 2 Jun 2022 20:06:41 -0600 Subject: [PATCH 114/151] Ignore intentionally broken files in prettier --- .config/.prettierignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.config/.prettierignore b/.config/.prettierignore index 07ddd32a6..cb6b9eb03 100644 --- a/.config/.prettierignore +++ b/.config/.prettierignore @@ -6,6 +6,7 @@ ../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/ **/.vs From b14eedefb764b9cd5949218a225c70e35e9d7b4c Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Thu, 2 Jun 2022 20:10:24 -0600 Subject: [PATCH 115/151] Bump version to 0.23.0-beta.3 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1d0cf1ba0..66c89ea57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.23.0-beta.2", + "version": "0.23.0-beta.3", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.23.0-beta.2", + "version": "0.23.0-beta.3", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index 21668473e..cae2e28f3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.23.0-beta.2", + "version": "0.23.0-beta.3", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": { From 861388215c2fd4a595c95ce26e61379f654539c6 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 3 Jun 2022 20:08:20 -0600 Subject: [PATCH 116/151] Extends in typedoc.json is now resolved like modules Also start replacing massive data directory with programmatically created fixtures. --- .config/.prettierignore | 1 + .config/typedoc-default.tsdoc.json | 5 + CHANGELOG.md | 1 + scripts/generate_options_schema.js | 5 + src/lib/utils/options/readers/tsconfig.ts | 18 ++- src/lib/utils/options/readers/typedoc.ts | 21 ++- src/lib/utils/options/tsdoc-defaults.ts | 1 + src/test/fs-helpers.ts | 109 ++++++++++++++++ .../readers/data/circular-extends.json | 3 - .../utils/options/readers/data/extends.json | 4 - .../utils/options/readers/data/invalid.json | 1 - .../utils/options/readers/data/invalid2.json | 3 - src/test/utils/options/readers/data/td.js | 1 - .../options/readers/data/tsdoc8/tsconfig.json | 3 + .../options/readers/data/tsdoc8/tsdoc.json | 4 + .../utils/options/readers/data/unknown.json | 3 - .../utils/options/readers/data/valid.json | 5 - .../utils/options/readers/tsconfig.test.ts | 8 ++ .../utils/options/readers/typedoc.test.ts | 123 ++++++++++++++---- 19 files changed, 265 insertions(+), 54 deletions(-) create mode 100644 src/test/fs-helpers.ts delete mode 100644 src/test/utils/options/readers/data/circular-extends.json delete mode 100644 src/test/utils/options/readers/data/extends.json delete mode 100644 src/test/utils/options/readers/data/invalid.json delete mode 100644 src/test/utils/options/readers/data/invalid2.json delete mode 100644 src/test/utils/options/readers/data/td.js create mode 100644 src/test/utils/options/readers/data/tsdoc8/tsconfig.json create mode 100644 src/test/utils/options/readers/data/tsdoc8/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/unknown.json delete mode 100644 src/test/utils/options/readers/data/valid.json diff --git a/.config/.prettierignore b/.config/.prettierignore index cb6b9eb03..a5c72aa5d 100644 --- a/.config/.prettierignore +++ b/.config/.prettierignore @@ -9,6 +9,7 @@ ../src/test/utils/options/readers/data/invalid2.json ../static/main.js ../example/docs/ +**/tmp **/.vs # Turn this back on once supported by Prettier diff --git a/.config/typedoc-default.tsdoc.json b/.config/typedoc-default.tsdoc.json index 0c090ce7f..b7a04591d 100644 --- a/.config/typedoc-default.tsdoc.json +++ b/.config/typedoc-default.tsdoc.json @@ -13,6 +13,11 @@ "syntaxKind": "block", "allowMultiple": true }, + { + "tagName": "@category", + "syntaxKind": "block", + "allowMultiple": true + }, { "tagName": "@hidden", "syntaxKind": "modifier" diff --git a/CHANGELOG.md b/CHANGELOG.md index 66b1c6376..250b46d95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. +- `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` diff --git a/scripts/generate_options_schema.js b/scripts/generate_options_schema.js index ba378ffe7..6929bf8eb 100644 --- a/scripts/generate_options_schema.js +++ b/scripts/generate_options_schema.js @@ -143,6 +143,11 @@ 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/src/lib/utils/options/readers/tsconfig.ts b/src/lib/utils/options/readers/tsconfig.ts index 2d18244b8..4414eb739 100644 --- a/src/lib/utils/options/readers/tsconfig.ts +++ b/src/lib/utils/options/readers/tsconfig.ts @@ -257,11 +257,19 @@ export class TSConfigReader implements OptionsReader { if (config.extends) { const resolver = createRequire(path); - for (const path of config.extends) { - const parentConfig = this.readTsDoc( - logger, - resolver.resolve(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); diff --git a/src/lib/utils/options/readers/typedoc.ts b/src/lib/utils/options/readers/typedoc.ts index d15f47cbd..5a3ea92af 100644 --- a/src/lib/utils/options/readers/typedoc.ts +++ b/src/lib/utils/options/readers/typedoc.ts @@ -8,6 +8,7 @@ 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 @@ -98,15 +99,21 @@ export class TypeDocReader implements OptionsReader { 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"]; } diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts index 85eb64ff8..80e287867 100644 --- a/src/lib/utils/options/tsdoc-defaults.ts +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -14,6 +14,7 @@ export const blockTags = [ "@module", "@inheritDoc", "@group", + "@category", ] as const; export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; diff --git a/src/test/fs-helpers.ts b/src/test/fs-helpers.ts new file mode 100644 index 000000000..fdc933574 --- /dev/null +++ b/src/test/fs-helpers.ts @@ -0,0 +1,109 @@ +// Originally from ts-node, MIT license, extracted to https://github.com/TypeStrong/fs-fixture-builder + +import * as fs from "fs"; +import * as Path from "path"; + +// Helpers to describe a bunch of files in a project programmatically, +// then write them to disk in a temp directory. + +let fixturesRootDir = process.cwd(); +export function setFixturesRootDir(path: string) { + fixturesRootDir = path; +} + +export interface File { + path: string; + content: string; +} +export interface JsonFile extends File { + obj: T; +} +export interface DirectoryApi { + add(file: File): File; + addFile(...args: Parameters): File; + addJsonFile(...args: Parameters): JsonFile; + dir(dirPath: string, cb?: (dir: DirectoryApi) => void): DirectoryApi; +} + +export type ProjectAPI = ReturnType; + +export function file(path: string, content = "") { + return { path, content }; +} +export function jsonFile(path: string, obj: T) { + const file: JsonFile = { + path, + obj, + get content() { + return JSON.stringify(obj, null, 2); + }, + }; + return file; +} + +export function tempdirProject(name = "") { + const rootTmpDir = `${fixturesRootDir}/tmp/`; + fs.mkdirSync(rootTmpDir, { recursive: true }); + const tmpdir = fs.mkdtempSync(`${fixturesRootDir}/tmp/${name}`); + return projectInternal(tmpdir); +} + +export type Project = ReturnType; +export function project(name: string) { + return projectInternal(`${fixturesRootDir}/tmp/${name}`); +} + +function projectInternal(cwd: string) { + const files: File[] = []; + function write() { + for (const file of files) { + fs.mkdirSync(Path.dirname(file.path), { recursive: true }); + fs.writeFileSync(file.path, file.content); + } + } + function rm() { + try { + fs.rmdirSync(cwd, { recursive: true }); + } catch (err) { + if (fs.existsSync(cwd)) throw err; + } + } + const { add, addFile, addJsonFile, dir } = createDirectory(cwd); + function createDirectory( + dirPath: string, + cb?: (dir: DirectoryApi) => void + ): DirectoryApi { + function add(file: File) { + file.path = Path.join(dirPath, file.path); + files.push(file); + return file; + } + function addFile(...args: Parameters) { + return add(file(...args)); + } + function addJsonFile(...args: Parameters) { + return add(jsonFile(...args)) as JsonFile; + } + function dir(path: string, cb?: (dir: DirectoryApi) => void) { + return createDirectory(Path.join(dirPath, path), cb); + } + const _dir: DirectoryApi = { + add, + addFile, + addJsonFile, + dir, + }; + cb?.(_dir); + return _dir; + } + return { + cwd, + files: [], + dir, + add, + addFile, + addJsonFile, + write, + rm, + }; +} 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/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/invalid2.json b/src/test/utils/options/readers/data/invalid2.json deleted file mode 100644 index c7864a585..000000000 --- a/src/test/utils/options/readers/data/invalid2.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - / oops -} diff --git a/src/test/utils/options/readers/data/td.js b/src/test/utils/options/readers/data/td.js deleted file mode 100644 index 5c6ad6e2d..000000000 --- a/src/test/utils/options/readers/data/td.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { gitRevision: "a" }; diff --git a/src/test/utils/options/readers/data/tsdoc8/tsconfig.json b/src/test/utils/options/readers/data/tsdoc8/tsconfig.json new file mode 100644 index 000000000..fa78b4751 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc8/tsconfig.json @@ -0,0 +1,3 @@ +{ + "files": ["../file.ts"] +} diff --git a/src/test/utils/options/readers/data/tsdoc8/tsdoc.json b/src/test/utils/options/readers/data/tsdoc8/tsdoc.json new file mode 100644 index 000000000..c5690da60 --- /dev/null +++ b/src/test/utils/options/readers/data/tsdoc8/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["typedoc/nope"] +} 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/valid.json b/src/test/utils/options/readers/data/valid.json deleted file mode 100644 index 8f6c84892..000000000 --- a/src/test/utils/options/readers/data/valid.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - // With comments! - "$schema": "https://typedoc.org/schema.json", - "gitRevision": "master" -} diff --git a/src/test/utils/options/readers/tsconfig.test.ts b/src/test/utils/options/readers/tsconfig.test.ts index d40e0e8d5..9b850fa95 100644 --- a/src/test/utils/options/readers/tsconfig.test.ts +++ b/src/test/utils/options/readers/tsconfig.test.ts @@ -165,4 +165,12 @@ describe("Options - TSConfigReader", () => { ); }); }); + + it("Handles extends which reference invalid files", () => { + testTsdoc("data/tsdoc8", (logger) => { + logger.expectMessage( + "error: Failed to resolve typedoc/nope to a file in */tsdoc8/tsdoc.json" + ); + }); + }); }); diff --git a/src/test/utils/options/readers/typedoc.test.ts b/src/test/utils/options/readers/typedoc.test.ts index c48fd1b94..5e019f0f8 100644 --- a/src/test/utils/options/readers/typedoc.test.ts +++ b/src/test/utils/options/readers/typedoc.test.ts @@ -1,7 +1,8 @@ import { deepStrictEqual as equal } from "assert"; +import { project as fsProject } from "../../../fs-helpers"; 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", () => { @@ -9,54 +10,132 @@ describe("Options - TypeDocReader", () => { options.addDefaultDeclarations(); options.addReader(new TypeDocReader()); - function test(name: string, input: string, cb: () => void) { - it(name, () => { - options.reset(); - options.setValue("options", input, __dirname); - 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", "data/extends.json", () => { + logger.expectNoOtherMessages(); equal(options.getValue("name"), "extends"); equal(options.getValue("gitRevision"), "master"); }); - test("Supports js files", "data/td.js", () => { - equal(options.getValue("gitRevision"), "a"); + 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: string, message: string) { + 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, __dirname); + options.setValue("options", project.cwd); const logger = new TestLogger(); + project.write(); options.read(logger); + project.rm(); logger.expectMessage(message); }); } testError( - "Errors if the file cannot be found", - "data/non-existent-file.json", - "error: The options file */non-existent-file.json does not exist." + "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", - "data/invalid.json", - "error: Failed to parse */invalid.json, ensure it exists and contains an object." + "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", - "data/unknown.json", + { + someOptionThatDoesNotExist: true, + }, "error: Tried to set an option (someOptionThatDoesNotExist) that was not declared." ); testError( "Errors if extends results in a loop", - "data/circular-extends.json", - "error: Tried to load the options file */circular-extends.json multiple times." + { + 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.", () => { const options = new (class LyingOptions extends Options { override isSet() { From a001e89d9a2151f806d4503816c124eb0cff0215 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Fri, 3 Jun 2022 21:30:09 -0600 Subject: [PATCH 117/151] Cleanup remaining option tests --- package.json | 3 +- src/lib/utils/options/readers/tsconfig.ts | 9 +- src/test/TestLogger.ts | 33 ++- src/test/utils/options/readers/data/file.ts | 2 - .../readers/data/folder.json/tsconfig.json | 5 - .../readers/data/invalid.tsconfig.json | 3 - .../readers/data/options-file.tsconfig.json | 5 - .../readers/data/stripInternal.tsconfig.json | 6 - .../options/readers/data/tsdoc1/tsconfig.json | 3 - .../options/readers/data/tsdoc1/tsdoc.json | 1 - .../options/readers/data/tsdoc2/tsconfig.json | 3 - .../options/readers/data/tsdoc2/tsdoc.json | 3 - .../options/readers/data/tsdoc3/tsconfig.json | 3 - .../options/readers/data/tsdoc3/tsdoc.json | 1 - .../options/readers/data/tsdoc4/tsconfig.json | 3 - .../options/readers/data/tsdoc4/tsdoc.json | 18 -- .../options/readers/data/tsdoc5/tsconfig.json | 3 - .../options/readers/data/tsdoc5/tsdoc.json | 4 - .../options/readers/data/tsdoc5/tsdoc2.json | 10 - .../options/readers/data/tsdoc6/tsconfig.json | 3 - .../options/readers/data/tsdoc6/tsdoc.json | 21 -- .../options/readers/data/tsdoc7/tsconfig.json | 3 - .../options/readers/data/tsdoc7/tsdoc.json | 4 - .../options/readers/data/tsdoc8/tsconfig.json | 3 - .../options/readers/data/tsdoc8/tsdoc.json | 4 - .../readers/data/unknown.tsconfig.json | 5 - .../options/readers/data/valid.tsconfig.json | 13 - .../utils/options/readers/tsconfig.test.ts | 275 ++++++++++++------ 28 files changed, 231 insertions(+), 218 deletions(-) delete mode 100644 src/test/utils/options/readers/data/file.ts delete mode 100644 src/test/utils/options/readers/data/folder.json/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/invalid.tsconfig.json delete mode 100644 src/test/utils/options/readers/data/options-file.tsconfig.json delete mode 100644 src/test/utils/options/readers/data/stripInternal.tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc1/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc1/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc2/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc2/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc3/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc3/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc4/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc4/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc5/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc5/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc5/tsdoc2.json delete mode 100644 src/test/utils/options/readers/data/tsdoc6/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc6/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc7/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc7/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/tsdoc8/tsconfig.json delete mode 100644 src/test/utils/options/readers/data/tsdoc8/tsdoc.json delete mode 100644 src/test/utils/options/readers/data/unknown.tsconfig.json delete mode 100644 src/test/utils/options/readers/data/valid.tsconfig.json diff --git a/package.json b/package.json index cae2e28f3..01c1d8d9f 100644 --- a/package.json +++ b/package.json @@ -98,7 +98,8 @@ ], "exclude": [ "**/*.d.ts", - "src/test" + "src/test", + "tmp" ] } } diff --git a/src/lib/utils/options/readers/tsconfig.ts b/src/lib/utils/options/readers/tsconfig.ts index 4414eb739..042226119 100644 --- a/src/lib/utils/options/readers/tsconfig.ts +++ b/src/lib/utils/options/readers/tsconfig.ts @@ -111,20 +111,17 @@ export class TSConfigReader implements OptionsReader { 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; } diff --git a/src/test/TestLogger.ts b/src/test/TestLogger.ts index 65fe0b7c4..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,6 +13,12 @@ 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")); } @@ -31,6 +39,25 @@ 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); @@ -39,6 +66,10 @@ export class TestLogger extends Logger { function createRegex(s: string) { return new RegExp( - "^" + s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$" + [ + "^", + s.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/\*/g, "[\\s\\S]*"), + "$", + ].join("") ); } 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.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/tsdoc1/tsconfig.json b/src/test/utils/options/readers/data/tsdoc1/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc1/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc1/tsdoc.json b/src/test/utils/options/readers/data/tsdoc1/tsdoc.json deleted file mode 100644 index fe51488c7..000000000 --- a/src/test/utils/options/readers/data/tsdoc1/tsdoc.json +++ /dev/null @@ -1 +0,0 @@ -[] diff --git a/src/test/utils/options/readers/data/tsdoc2/tsconfig.json b/src/test/utils/options/readers/data/tsdoc2/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc2/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc2/tsdoc.json b/src/test/utils/options/readers/data/tsdoc2/tsdoc.json deleted file mode 100644 index c54ab4c96..000000000 --- a/src/test/utils/options/readers/data/tsdoc2/tsdoc.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "doesNotMatchSchema": true -} diff --git a/src/test/utils/options/readers/data/tsdoc3/tsconfig.json b/src/test/utils/options/readers/data/tsdoc3/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc3/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc3/tsdoc.json b/src/test/utils/options/readers/data/tsdoc3/tsdoc.json deleted file mode 100644 index 0967ef424..000000000 --- a/src/test/utils/options/readers/data/tsdoc3/tsdoc.json +++ /dev/null @@ -1 +0,0 @@ -{} diff --git a/src/test/utils/options/readers/data/tsdoc4/tsconfig.json b/src/test/utils/options/readers/data/tsdoc4/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc4/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc4/tsdoc.json b/src/test/utils/options/readers/data/tsdoc4/tsdoc.json deleted file mode 100644 index b35d76967..000000000 --- a/src/test/utils/options/readers/data/tsdoc4/tsdoc.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "noStandardTags": true, - "tagDefinitions": [ - { - "tagName": "@tag", - "syntaxKind": "block" - }, - { - "tagName": "@tag2", - "syntaxKind": "inline" - }, - { - "tagName": "@tag3", - "syntaxKind": "modifier" - } - ] -} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsconfig.json b/src/test/utils/options/readers/data/tsdoc5/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc5/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsdoc.json b/src/test/utils/options/readers/data/tsdoc5/tsdoc.json deleted file mode 100644 index aa9ed7edf..000000000 --- a/src/test/utils/options/readers/data/tsdoc5/tsdoc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["./tsdoc2.json"] -} diff --git a/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json b/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json deleted file mode 100644 index 0370d531e..000000000 --- a/src/test/utils/options/readers/data/tsdoc5/tsdoc2.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "noStandardTags": true, - "tagDefinitions": [ - { - "tagName": "@tag", - "syntaxKind": "block" - } - ] -} diff --git a/src/test/utils/options/readers/data/tsdoc6/tsconfig.json b/src/test/utils/options/readers/data/tsdoc6/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc6/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc6/tsdoc.json b/src/test/utils/options/readers/data/tsdoc6/tsdoc.json deleted file mode 100644 index f7748e59f..000000000 --- a/src/test/utils/options/readers/data/tsdoc6/tsdoc.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "noStandardTags": true, - "tagDefinitions": [ - { - "tagName": "@tag", - "syntaxKind": "block" - }, - { - "tagName": "@tag2", - "syntaxKind": "inline" - }, - { - "tagName": "@tag3", - "syntaxKind": "modifier" - } - ], - "supportForTags": { - "@tag": true - } -} diff --git a/src/test/utils/options/readers/data/tsdoc7/tsconfig.json b/src/test/utils/options/readers/data/tsdoc7/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc7/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc7/tsdoc.json b/src/test/utils/options/readers/data/tsdoc7/tsdoc.json deleted file mode 100644 index 8c41562b9..000000000 --- a/src/test/utils/options/readers/data/tsdoc7/tsdoc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["./tsdoc.json"] -} diff --git a/src/test/utils/options/readers/data/tsdoc8/tsconfig.json b/src/test/utils/options/readers/data/tsdoc8/tsconfig.json deleted file mode 100644 index fa78b4751..000000000 --- a/src/test/utils/options/readers/data/tsdoc8/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "files": ["../file.ts"] -} diff --git a/src/test/utils/options/readers/data/tsdoc8/tsdoc.json b/src/test/utils/options/readers/data/tsdoc8/tsdoc.json deleted file mode 100644 index c5690da60..000000000 --- a/src/test/utils/options/readers/data/tsdoc8/tsdoc.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json", - "extends": ["typedoc/nope"] -} 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.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 9b850fa95..d15b1a34d 100644 --- a/src/test/utils/options/readers/tsconfig.test.ts +++ b/src/test/utils/options/readers/tsconfig.test.ts @@ -1,144 +1,213 @@ -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 { tmpdir } from "os"; import { TestLogger } from "../../../TestLogger"; +import { tempdirProject, Project } from "../../../fs-helpers"; +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(path: string, cb?: (logger: TestLogger) => void) { - options.reset(); - options.setValue("tsconfig", join(__dirname, path)); - const logger = new TestLogger(); - options.read(logger); - cb?.(logger); + 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("data/tsdoc1", (logger) => { + testTsdoc([], () => { logger.expectMessage( - "error: Failed to read tsdoc.json file at */tsdoc1/tsdoc.json." + "error: Failed to read tsdoc.json file at */tsdoc.json." ); }); }); it("Handles invalid tsdoc files", () => { - testTsdoc("data/tsdoc2", (logger) => { - logger.expectMessage( - `error: The file */tsdoc2/tsdoc.json is not a valid tsdoc.json file.` - ); - }); + 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", []); - options.setValue("tsconfig", join(__dirname, "data/tsdoc3")); - const logger = new TestLogger(); - options.read(logger); - logger.expectMessage( - "warn: The blockTags, modifierTags defined in typedoc.json " + - "will be overwritten by configuration in tsdoc.json." + testTsdoc( + {}, + () => { + logger.expectMessage( + "warn: The blockTags, modifierTags defined in typedoc.json " + + "will be overwritten by configuration in tsdoc.json." + ); + }, + false ); - logger.expectNoOtherMessages(); }); it("Reads tsdoc.json", () => { - testTsdoc("data/tsdoc4"); + 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"]); @@ -146,12 +215,46 @@ describe("Options - TSConfigReader", () => { }); it("Handles extends in tsdoc.json", () => { - testTsdoc("data/tsdoc5"); + 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("data/tsdoc6"); + 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"), []); @@ -159,18 +262,28 @@ describe("Options - TSConfigReader", () => { }); it("Handles circular extends", () => { - testTsdoc("data/tsdoc7", (logger) => { - logger.expectMessage( - 'error: Circular reference encountered for "extends" field of */tsdoc7/tsdoc.json' - ); - }); + testTsdoc( + { + extends: ["./tsdoc.json"], + }, + () => { + logger.expectMessage( + 'error: Circular reference encountered for "extends" field of */tsdoc.json' + ); + } + ); }); it("Handles extends which reference invalid files", () => { - testTsdoc("data/tsdoc8", (logger) => { - logger.expectMessage( - "error: Failed to resolve typedoc/nope to a file in */tsdoc8/tsdoc.json" - ); - }); + testTsdoc( + { + extends: ["typedoc/nope"], + }, + () => { + logger.expectMessage( + "error: Failed to resolve typedoc/nope to a file in */tsdoc.json" + ); + } + ); }); }); From 99cfa21f4f096fd88b27ee1abe4102f18b610c65 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 07:33:28 -0600 Subject: [PATCH 118/151] Pull fs-helpers from official repo --- package-lock.json | 13 +++ package.json | 1 + src/test/fs-helpers.ts | 109 ------------------ .../utils/options/readers/tsconfig.test.ts | 2 +- .../utils/options/readers/typedoc.test.ts | 2 +- 5 files changed, 16 insertions(+), 111 deletions(-) delete mode 100644 src/test/fs-helpers.ts diff --git a/package-lock.json b/package-lock.json index 66c89ea57..6b398657f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "@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#301b5a485fae455c064706c9636a87e58e61d7ab", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", @@ -936,6 +937,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#301b5a485fae455c064706c9636a87e58e61d7ab", + "integrity": "sha512-b1K5HbWlVyFtrJN6xtzi6aGugPmulAYC8ct5Iw1wH7fbG7xh29NPoc81/aRBIwXRuaYYU7ModanY9mYJdRMTzQ==", + "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", @@ -9691,6 +9698,12 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@typestrong/fs-fixture-builder": { + "version": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#301b5a485fae455c064706c9636a87e58e61d7ab", + "integrity": "sha512-b1K5HbWlVyFtrJN6xtzi6aGugPmulAYC8ct5Iw1wH7fbG7xh29NPoc81/aRBIwXRuaYYU7ModanY9mYJdRMTzQ==", + "dev": true, + "from": "@typestrong/fs-fixture-builder@github:TypeStrong/fs-fixture-builder#301b5a485fae455c064706c9636a87e58e61d7ab" + }, "@ungap/promise-all-settled": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz", diff --git a/package.json b/package.json index 01c1d8d9f..6ae25d441 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@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#301b5a485fae455c064706c9636a87e58e61d7ab", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", diff --git a/src/test/fs-helpers.ts b/src/test/fs-helpers.ts deleted file mode 100644 index fdc933574..000000000 --- a/src/test/fs-helpers.ts +++ /dev/null @@ -1,109 +0,0 @@ -// Originally from ts-node, MIT license, extracted to https://github.com/TypeStrong/fs-fixture-builder - -import * as fs from "fs"; -import * as Path from "path"; - -// Helpers to describe a bunch of files in a project programmatically, -// then write them to disk in a temp directory. - -let fixturesRootDir = process.cwd(); -export function setFixturesRootDir(path: string) { - fixturesRootDir = path; -} - -export interface File { - path: string; - content: string; -} -export interface JsonFile extends File { - obj: T; -} -export interface DirectoryApi { - add(file: File): File; - addFile(...args: Parameters): File; - addJsonFile(...args: Parameters): JsonFile; - dir(dirPath: string, cb?: (dir: DirectoryApi) => void): DirectoryApi; -} - -export type ProjectAPI = ReturnType; - -export function file(path: string, content = "") { - return { path, content }; -} -export function jsonFile(path: string, obj: T) { - const file: JsonFile = { - path, - obj, - get content() { - return JSON.stringify(obj, null, 2); - }, - }; - return file; -} - -export function tempdirProject(name = "") { - const rootTmpDir = `${fixturesRootDir}/tmp/`; - fs.mkdirSync(rootTmpDir, { recursive: true }); - const tmpdir = fs.mkdtempSync(`${fixturesRootDir}/tmp/${name}`); - return projectInternal(tmpdir); -} - -export type Project = ReturnType; -export function project(name: string) { - return projectInternal(`${fixturesRootDir}/tmp/${name}`); -} - -function projectInternal(cwd: string) { - const files: File[] = []; - function write() { - for (const file of files) { - fs.mkdirSync(Path.dirname(file.path), { recursive: true }); - fs.writeFileSync(file.path, file.content); - } - } - function rm() { - try { - fs.rmdirSync(cwd, { recursive: true }); - } catch (err) { - if (fs.existsSync(cwd)) throw err; - } - } - const { add, addFile, addJsonFile, dir } = createDirectory(cwd); - function createDirectory( - dirPath: string, - cb?: (dir: DirectoryApi) => void - ): DirectoryApi { - function add(file: File) { - file.path = Path.join(dirPath, file.path); - files.push(file); - return file; - } - function addFile(...args: Parameters) { - return add(file(...args)); - } - function addJsonFile(...args: Parameters) { - return add(jsonFile(...args)) as JsonFile; - } - function dir(path: string, cb?: (dir: DirectoryApi) => void) { - return createDirectory(Path.join(dirPath, path), cb); - } - const _dir: DirectoryApi = { - add, - addFile, - addJsonFile, - dir, - }; - cb?.(_dir); - return _dir; - } - return { - cwd, - files: [], - dir, - add, - addFile, - addJsonFile, - write, - rm, - }; -} diff --git a/src/test/utils/options/readers/tsconfig.test.ts b/src/test/utils/options/readers/tsconfig.test.ts index d15b1a34d..b77a0ea0c 100644 --- a/src/test/utils/options/readers/tsconfig.test.ts +++ b/src/test/utils/options/readers/tsconfig.test.ts @@ -4,7 +4,7 @@ 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 "../../../fs-helpers"; +import { tempdirProject, Project } from "@typestrong/fs-fixture-builder"; import { tmpdir } from "os"; describe("Options - TSConfigReader", () => { diff --git a/src/test/utils/options/readers/typedoc.test.ts b/src/test/utils/options/readers/typedoc.test.ts index 5e019f0f8..7f3937ca4 100644 --- a/src/test/utils/options/readers/typedoc.test.ts +++ b/src/test/utils/options/readers/typedoc.test.ts @@ -1,5 +1,5 @@ import { deepStrictEqual as equal } from "assert"; -import { project as fsProject } from "../../../fs-helpers"; +import { project as fsProject } from "@typestrong/fs-fixture-builder"; import { TypeDocReader } from "../../../../lib/utils/options/readers"; import { Logger, Options } from "../../../../lib/utils"; From 651b290ad90c81d4da893f1521067e72600208d3 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 07:36:35 -0600 Subject: [PATCH 119/151] Fix deprecation warning --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6b398657f..bd7a75b1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "@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#301b5a485fae455c064706c9636a87e58e61d7ab", + "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", @@ -939,8 +939,8 @@ }, "node_modules/@typestrong/fs-fixture-builder": { "version": "0.0.0", - "resolved": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#301b5a485fae455c064706c9636a87e58e61d7ab", - "integrity": "sha512-b1K5HbWlVyFtrJN6xtzi6aGugPmulAYC8ct5Iw1wH7fbG7xh29NPoc81/aRBIwXRuaYYU7ModanY9mYJdRMTzQ==", + "resolved": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#b88cd06fe814614a0d924af9d10d04ff95a551de", + "integrity": "sha512-pPa8hDfxdpjyoKMlYlORl7yQTz6JwPUdTmZGBzsxeU7dJSTVGRXalGhSnKeCQSaUeenf0IAHW4PSuDwv/dXY1Q==", "dev": true }, "node_modules/@ungap/promise-all-settled": { @@ -9699,10 +9699,10 @@ } }, "@typestrong/fs-fixture-builder": { - "version": "git+ssh://git@github.com/TypeStrong/fs-fixture-builder.git#301b5a485fae455c064706c9636a87e58e61d7ab", - "integrity": "sha512-b1K5HbWlVyFtrJN6xtzi6aGugPmulAYC8ct5Iw1wH7fbG7xh29NPoc81/aRBIwXRuaYYU7ModanY9mYJdRMTzQ==", + "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#301b5a485fae455c064706c9636a87e58e61d7ab" + "from": "@typestrong/fs-fixture-builder@github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de" }, "@ungap/promise-all-settled": { "version": "1.1.2", diff --git a/package.json b/package.json index 6ae25d441..dfd94076a 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@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#301b5a485fae455c064706c9636a87e58e61d7ab", + "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de", "esbuild": "^0.14.39", "eslint": "^8.16.0", "mocha": "^9.2.1", From 3edb4478f5a7f06aeb9e0b829fc30393fbb2a04d Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 07:38:58 -0600 Subject: [PATCH 120/151] Remove remove helper --- package.json | 2 +- src/lib/output/renderer.ts | 7 +++++-- src/lib/utils/fs.ts | 14 -------------- src/lib/utils/index.ts | 1 - src/test/capture-screenshots.ts | 3 +-- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index dfd94076a..966147949 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "url": "https://github.com/TypeStrong/TypeDoc/issues" }, "engines": { - "node": ">= 14" + "node": ">= 14.14" }, "dependencies": { "lunr": "^2.3.9", diff --git a/src/lib/output/renderer.ts b/src/lib/output/renderer.ts index 9b37f00d9..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"; @@ -337,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/utils/fs.ts b/src/lib/utils/fs.ts index 769779851..8e0ecf658 100644 --- a/src/lib/utils/fs.ts +++ b/src/lib/utils/fs.ts @@ -133,20 +133,6 @@ export function copySync(src: string, dest: string): void { } } -/** - * Equivalent to rm -rf - * @param target - */ -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 }); - } -} - /** * Simpler version of `glob.sync` that only covers our use cases, only ever matching files, and ignoring node_modules. */ diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 43a760e5b..f7a8e508a 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -14,7 +14,6 @@ export { getCommonDirectory, normalizePath, readFile, - remove, writeFile, writeFileSync, } from "./fs"; diff --git a/src/test/capture-screenshots.ts b/src/test/capture-screenshots.ts index 274ee194f..eb303b801 100644 --- a/src/test/capture-screenshots.ts +++ b/src/test/capture-screenshots.ts @@ -2,7 +2,6 @@ import * as fs from "fs"; import { platform } from "os"; 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. @@ -71,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); From 7918fba658f92b8c585ae0c05add6cb645140d81 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 09:39:28 -0600 Subject: [PATCH 121/151] Correct behavior of excludeNotDocumented Resolves #1752 Resolves #1948 --- CHANGELOG.md | 4 +- src/lib/converter/context.ts | 2 +- src/lib/converter/converter.ts | 33 +- src/lib/converter/plugins/CommentPlugin.ts | 39 +- src/lib/converter/symbols.ts | 3 +- src/test/converter/exports/no-doc-members.ts | 6 + src/test/converter/exports/specs.json | 120 ++- src/test/converter/exports/specs.nodoc.json | 333 +++++++ src/test/converter/variables/specs.nodoc.json | 862 +++++++++++++++--- 9 files changed, 1232 insertions(+), 170 deletions(-) create mode 100644 src/test/converter/exports/no-doc-members.ts create mode 100644 src/test/converter/exports/specs.nodoc.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 250b46d95..cfbb06b23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. +- 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. @@ -23,7 +24,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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"`. - 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. -- 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. - 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. @@ -68,6 +68,8 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. +- 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. - Corrected schema generation for https://typedoc.org/schema.json ### Thanks! diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts index 40312ab13..aba377e9b 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -240,7 +240,7 @@ export class Context { } shouldIgnore(symbol: ts.Symbol) { - return this.converter.shouldIgnore(symbol, this.checker); + return this.converter.shouldIgnore(symbol); } /** diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index c093f0854..9385ef994 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -12,7 +12,6 @@ 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"; @@ -224,11 +223,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; } @@ -292,28 +289,18 @@ 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) { diff --git a/src/lib/converter/plugins/CommentPlugin.ts b/src/lib/converter/plugins/CommentPlugin.ts index ebf095925..bad7f66f1 100644 --- a/src/lib/converter/plugins/CommentPlugin.ts +++ b/src/lib/converter/plugins/CommentPlugin.ts @@ -63,6 +63,9 @@ export class CommentPlugin extends ConverterComponent { @BindOption("excludeProtected") excludeProtected!: boolean; + @BindOption("excludeNotDocumented") + excludeNotDocumented!: boolean; + /** * Create a new CommentPlugin instance. */ @@ -375,7 +378,7 @@ export class CommentPlugin extends ConverterComponent { * * @param reflection Reflection to check if hidden */ - private isHidden(reflection: Reflection) { + private isHidden(reflection: Reflection): boolean { const comment = reflection.comment; if ( @@ -393,6 +396,30 @@ export class CommentPlugin extends ConverterComponent { } 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; } @@ -404,6 +431,16 @@ export class CommentPlugin extends ConverterComponent { } } +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 = { diff --git a/src/lib/converter/symbols.ts b/src/lib/converter/symbols.ts index 847c3c57d..9701fa5e5 100644 --- a/src/lib/converter/symbols.ts +++ b/src/lib/converter/symbols.ts @@ -336,8 +336,7 @@ function convertTypeAlias( 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)) ); 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 0205c3de4..52bc3e298 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -12,7 +12,7 @@ "flags": {}, "children": [ { - "id": 46, + "id": 48, "name": "GH1453Helper", "kind": 8388608, "kindString": "Reference", @@ -28,7 +28,7 @@ "target": 35 }, { - "id": 39, + "id": 41, "name": "Mod", "kind": 8388608, "kindString": "Reference", @@ -44,7 +44,7 @@ "target": 29 }, { - "id": 41, + "id": 43, "name": "Mod2", "kind": 8388608, "kindString": "Reference", @@ -68,7 +68,7 @@ "target": 29 }, { - "id": 40, + "id": 42, "name": "ModDefault", "kind": 8388608, "kindString": "Reference", @@ -84,7 +84,7 @@ "target": 36 }, { - "id": 45, + "id": 47, "name": "ThisModule", "kind": 8388608, "kindString": "Reference", @@ -100,7 +100,7 @@ "target": 34 }, { - "id": 42, + "id": 44, "name": "a", "kind": 8388608, "kindString": "Reference", @@ -116,7 +116,7 @@ "target": 30 }, { - "id": 43, + "id": 45, "name": "b", "kind": 8388608, "kindString": "Reference", @@ -140,7 +140,7 @@ "target": 31 }, { - "id": 38, + "id": 40, "name": "c", "kind": 8388608, "kindString": "Reference", @@ -398,14 +398,14 @@ { "title": "References", "children": [ - 46, - 39, + 48, 41, - 40, - 45, - 42, 43, - 38 + 42, + 47, + 44, + 45, + 40 ] }, { @@ -853,6 +853,95 @@ "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 + }, + "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" + } + ] + }, + { + "tag": "@module", + "content": [] + } + ] + }, + "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": [ @@ -863,7 +952,8 @@ 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..02ffd820a --- /dev/null +++ b/src/test/converter/exports/specs.nodoc.json @@ -0,0 +1,333 @@ +{ + "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" + } + ] + } + ] + }, + "children": [ + { + "id": 39, + "name": "abc", + "kind": 32, + "kindString": "Variable", + "flags": { + "isConst": true + }, + "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" + } + ] + }, + { + "tag": "@module", + "content": [] + } + ] + }, + "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", + "children": [ + 14, + 29, + 38 + ] + } + ] +} diff --git a/src/test/converter/variables/specs.nodoc.json b/src/test/converter/variables/specs.nodoc.json index de99e9d70..423f4542a 100644 --- a/src/test/converter/variables/specs.nodoc.json +++ b/src/test/converter/variables/specs.nodoc.json @@ -25,53 +25,6 @@ } ] }, - "children": [ - { - "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" - } - } - ] - } - ], - "groups": [ - { - "title": "Constructors", - "children": [ - 3 - ] - } - ], "sources": [ { "fileName": "array.ts", @@ -111,37 +64,6 @@ } ] }, - "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": [ - { - "title": "Constructors", - "children": [ - 10 - ] - } - ], "sources": [ { "fileName": "array.ts", @@ -165,47 +87,6 @@ } ] }, - "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" - } - } - ], - "groups": [ - { - "title": "Constructors", - "children": [ - 13 - ] - } - ], "sources": [ { "fileName": "array.ts", @@ -438,14 +319,14 @@ ] }, { - "id": 19, + "id": 30, "name": "literal", "kind": 2, "kindString": "Module", "flags": {}, "children": [ { - "id": 22, + "id": 70, "name": "objectLiteral", "kind": 32, "kindString": "Variable", @@ -471,11 +352,409 @@ "type": { "type": "reflection", "declaration": { - "id": 23, + "id": 71, "name": "__type", "kind": 65536, "kindString": "Type literal", "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", @@ -489,7 +768,7 @@ "defaultValue": "..." }, { - "id": 20, + "id": 31, "name": "typeLiteral", "kind": 32, "kindString": "Variable", @@ -513,11 +792,340 @@ "type": { "type": "reflection", "declaration": { - "id": 21, + "id": 32, "name": "__type", "kind": 65536, "kindString": "Type literal", "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", @@ -534,8 +1142,8 @@ { "title": "Variables", "children": [ - 22, - 20 + 70, + 31 ] } ], @@ -555,7 +1163,7 @@ "children": [ 1, 15, - 19 + 30 ] } ] From f57c81293ae36fbf4e45923da856f201e8eaabbe Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 09:46:20 -0600 Subject: [PATCH 122/151] Do not attach module comments to non-modules --- src/lib/converter/comments/index.ts | 10 ++++ src/test/converter/exports/specs.json | 23 --------- src/test/converter/exports/specs.nodoc.json | 55 --------------------- 3 files changed, 10 insertions(+), 78 deletions(-) diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts index 15be4732c..d476eea64 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -77,6 +77,16 @@ export function getComment( } } + 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; } diff --git a/src/test/converter/exports/specs.json b/src/test/converter/exports/specs.json index 52bc3e298..1ab1fdc2f 100644 --- a/src/test/converter/exports/specs.json +++ b/src/test/converter/exports/specs.json @@ -888,29 +888,6 @@ "flags": { "isConst": true }, - "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" - } - ] - }, - { - "tag": "@module", - "content": [] - } - ] - }, "sources": [ { "fileName": "no-doc-members.ts", diff --git a/src/test/converter/exports/specs.nodoc.json b/src/test/converter/exports/specs.nodoc.json index 02ffd820a..3698dffe5 100644 --- a/src/test/converter/exports/specs.nodoc.json +++ b/src/test/converter/exports/specs.nodoc.json @@ -255,61 +255,6 @@ } ] }, - "children": [ - { - "id": 39, - "name": "abc", - "kind": 32, - "kindString": "Variable", - "flags": { - "isConst": true - }, - "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" - } - ] - }, - { - "tag": "@module", - "content": [] - } - ] - }, - "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", From 902977724f70e77a26fb4913e08c8c9f48bbff97 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 10:17:25 -0600 Subject: [PATCH 123/151] Support for specifying globs in entry points Resolves #1926. --- CHANGELOG.md | 1 + src/lib/utils/entry-point.ts | 18 +++++++++-- src/lib/utils/fs.ts | 23 +++++++++----- src/lib/utils/options/sources/typedoc.ts | 2 +- src/test/slow/entry-point.test.ts | 38 +++++++++++++++++++++--- src/test/slow/entry-points/extra.ts | 3 -- src/test/slow/entry-points/index.ts | 3 -- src/test/slow/entry-points/tsconfig.json | 3 -- 8 files changed, 67 insertions(+), 24 deletions(-) delete mode 100644 src/test/slow/entry-points/extra.ts delete mode 100644 src/test/slow/entry-points/index.ts delete mode 100644 src/test/slow/entry-points/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cfbb06b23..2a9641724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. 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/fs.ts b/src/lib/utils/fs.ts index 8e0ecf658..e761b9f30 100644 --- a/src/lib/utils/fs.ts +++ b/src/lib/utils/fs.ts @@ -134,9 +134,13 @@ export function copySync(src: string, dest: string): void { } /** - * Simpler version of `glob.sync` that only covers our use cases, only ever matching files, and ignoring node_modules. + * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules. */ -export function glob(pattern: string, root: string): string[] { +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("/")]; @@ -147,6 +151,16 @@ export function glob(pattern: string, root: string): string[] { 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 ( @@ -156,11 +170,6 @@ export function glob(pattern: string, root: string): string[] { ) { dirs.push(childPath); } - } else if (child.isFile()) { - const childPath = [...dir, child.name].join("/"); - if (mini.match(childPath)) { - result.push(childPath); - } } } } while (dirs.length); diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 8f6a49b6e..8996e3ae8 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -26,7 +26,7 @@ export function addTypeDocOptions(options: Pick) { options.addDeclaration({ name: "entryPoints", help: "The entry points of your documentation.", - type: ParameterType.PathArray, + type: ParameterType.GlobArray, }); options.addDeclaration({ name: "entryPointStrategy", diff --git a/src/test/slow/entry-point.test.ts b/src/test/slow/entry-point.test.ts index a7ed33528..fb884e75f 100644 --- a/src/test/slow/entry-point.test.ts +++ b/src/test/slow/entry-point.test.ts @@ -1,18 +1,48 @@ +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.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 +58,7 @@ describe("Entry Points", () => { it("Supports resolving directories", () => { app.bootstrap({ tsconfig, - entryPoints: [root], + entryPoints: [fixture.cwd], entryPointStrategy: EntryPointStrategy.Resolve, }); 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": ["."] -} From 683de98c13f3df8b9636775350dc9d6c70190620 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 10:24:08 -0600 Subject: [PATCH 124/151] Update changelog to reflect remaining work --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a9641724..92be85d1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,10 @@ These TODOs will be resolved before a full release. ([GitHub project](https://github.com/TypeStrong/typedoc/projects/11)) -- Make comment parser options configurable from tsdoc.json. - Full support for declaration references, #262, #488, #1326, #1845. - Add support for additional comment styles, #1433. -- Theme: Custom rendering for `@see` tags. +- (Maybe) `@copyDoc` tag to copy parts of documentation from other entries. +- (Maybe) `--commentDiscovery` option to delegate discovery to TypeScript. ### Breaking Changes From 3a8e8981164d6f01ece2d5abd164f80aa2cd69f2 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 14:11:14 -0600 Subject: [PATCH 125/151] Add support for multiple comment styles Resolves #1433. --- src/lib/converter/comments/discovery.ts | 106 +++++-- src/lib/converter/comments/index.ts | 49 +-- src/lib/converter/comments/lineLexer.ts | 317 +++++++++++++++++++ src/lib/converter/context.ts | 6 +- src/lib/converter/converter.ts | 4 + src/lib/converter/factories/signature.ts | 3 +- src/lib/utils/options/declaration.ts | 14 + src/lib/utils/options/options.ts | 33 ++ src/lib/utils/options/sources/typedoc.ts | 15 +- src/test/behaviorTests.ts | 71 ++++- src/test/comments.test.ts | 282 +++++++++++++++++ src/test/converter2.test.ts | 31 +- src/test/converter2/behavior/blockComment.ts | 5 + src/test/converter2/behavior/lineComment.ts | 9 + src/test/issueTests.ts | 7 +- 15 files changed, 899 insertions(+), 53 deletions(-) create mode 100644 src/lib/converter/comments/lineLexer.ts create mode 100644 src/test/converter2/behavior/blockComment.ts create mode 100644 src/test/converter2/behavior/lineComment.ts diff --git a/src/lib/converter/comments/discovery.ts b/src/lib/converter/comments/discovery.ts index 8f15590c2..facd7dcbe 100644 --- a/src/lib/converter/comments/discovery.ts +++ b/src/lib/converter/comments/discovery.ts @@ -1,6 +1,7 @@ import * as ts from "typescript"; import { ReflectionKind } from "../../models"; -import type { Logger } from "../../utils"; +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! @@ -82,13 +83,14 @@ const wantedKinds: Record = { export function discoverComment( symbol: ts.Symbol, kind: ReflectionKind, - logger: Logger -): [ts.SourceFile, ts.CommentRange] | undefined { + 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][] = []; + const discovered: [ts.SourceFile, ts.CommentRange[]][] = []; for (const decl of symbol.declarations || []) { const text = decl.getSourceFile().text; @@ -111,21 +113,20 @@ export function discoverComment( continue; } - const comments = ts.getLeadingCommentRanges(text, node.pos); + const comments = collectCommentRanges( + ts.getLeadingCommentRanges(text, node.pos) + ); if (reverse) { comments?.reverse(); } - const lastDocComment = comments?.find( - (c) => - text[c.pos] === "/" && - text[c.pos + 1] === "*" && - text[c.pos + 2] === "*" + const selectedDocComment = comments.find((ranges) => + permittedRange(text, ranges, commentStyle) ); - if (lastDocComment) { - discovered.push([decl.getSourceFile(), lastDocComment]); + if (selectedDocComment) { + discovered.push([decl.getSourceFile(), selectedDocComment]); } } } @@ -139,7 +140,7 @@ export function discoverComment( logger.warn( `${symbol.name} has multiple declarations with a comment. An arbitrary comment will be used.` ); - const locations = discovered.map(([sf, { pos }]) => { + const locations = discovered.map(([sf, [{ pos }]]) => { const path = nicePath(sf.fileName); const line = ts.getLineAndCharacterOfPosition(sf, pos).line + 1; return `${path}:${line}`; @@ -155,23 +156,23 @@ export function discoverComment( } export function discoverSignatureComment( - declaration: ts.SignatureDeclaration | ts.JSDocSignature -): [ts.SourceFile, ts.CommentRange] | undefined { + 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 = ts.getLeadingCommentRanges(text, node.pos); - const comment = comments?.find( - (c) => - text[c.pos] === "/" && - text[c.pos + 1] === "*" && - text[c.pos + 2] === "*" + const comments = collectCommentRanges( + ts.getLeadingCommentRanges(text, node.pos) ); + const comment = comments.find((ranges) => + permittedRange(text, ranges, commentStyle) + ); if (comment) { return [node.getSourceFile(), comment]; } @@ -181,7 +182,7 @@ export function discoverSignatureComment( * 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. + * the following example this would be the case only for module `C`. * * ``` * module A.B.C { } @@ -198,7 +199,7 @@ function isTopmostModuleDeclaration(node: ts.ModuleDeclaration): boolean { * 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. + * `A` no matter which of the modules was passed in. * * ``` * module A.B.C { } @@ -251,3 +252,62 @@ function declarationToCommentNode(node: ts.Declaration): ts.Node | undefined { 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 index d476eea64..86e2aca4d 100644 --- a/src/lib/converter/comments/index.ts +++ b/src/lib/converter/comments/index.ts @@ -1,9 +1,11 @@ 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 { @@ -15,40 +17,45 @@ export interface CommentParserConfig { const commentCache = new WeakMap>(); function getCommentWithCache( - discovered: [ts.SourceFile, ts.CommentRange] | undefined, + discovered: [ts.SourceFile, ts.CommentRange[]] | undefined, config: CommentParserConfig, logger: Logger ) { if (!discovered) return; - const [file, range] = discovered; + const [file, ranges] = discovered; const cache = commentCache.get(file) || new Map(); - if (cache?.has(range.pos)) { - return cache.get(range.pos)!.clone(); + if (cache?.has(ranges[0].pos)) { + return cache.get(ranges[0].pos)!.clone(); } - const line = ts.getLineAndCharacterOfPosition(file, range.pos).line + 1; + 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 (range.kind) { + switch (ranges[0].kind) { case ts.SyntaxKind.MultiLineCommentTrivia: comment = parseComment( - lexBlockComment(file.text, range.pos, range.end), + lexBlockComment(file.text, ranges[0].pos, ranges[0].end), config, warning ); break; case ts.SyntaxKind.SingleLineCommentTrivia: - throw "GERRIT FIX ME"; // GERRIT + comment = parseComment( + lexLineComments(file.text, ranges), + config, + warning + ); + break; default: - assertNever(range.kind); + assertNever(ranges[0].kind); } - cache.set(range.pos, comment); + cache.set(ranges[0].pos, comment); commentCache.set(file, cache); return comment.clone(); @@ -58,10 +65,11 @@ export function getComment( symbol: ts.Symbol, kind: ReflectionKind, config: CommentParserConfig, - logger: Logger + logger: Logger, + commentStyle: CommentStyle ): Comment | undefined { const comment = getCommentWithCache( - discoverComment(symbol, kind, logger), + discoverComment(symbol, kind, logger, commentStyle), config, logger ); @@ -93,10 +101,11 @@ export function getComment( export function getSignatureComment( declaration: ts.SignatureDeclaration | ts.JSDocSignature, config: CommentParserConfig, - logger: Logger + logger: Logger, + commentStyle: CommentStyle ): Comment | undefined { return getCommentWithCache( - discoverSignatureComment(declaration), + discoverSignatureComment(declaration, commentStyle), config, logger ); @@ -124,11 +133,13 @@ export function getJsDocComment( const comment = getCommentWithCache( [ file, - { - kind: ts.SyntaxKind.MultiLineCommentTrivia, - pos: parent.pos, - end: parent.end, - }, + [ + { + kind: ts.SyntaxKind.MultiLineCommentTrivia, + pos: parent.pos, + end: parent.end, + }, + ], ], config, logger diff --git a/src/lib/converter/comments/lineLexer.ts b/src/lib/converter/comments/lineLexer.ts new file mode 100644 index 000000000..f753a137a --- /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/context.ts b/src/lib/converter/context.ts index aba377e9b..f27187ea2 100644 --- a/src/lib/converter/context.ts +++ b/src/lib/converter/context.ts @@ -194,7 +194,8 @@ export class Context { exportSymbol, reflection.kind, this.converter.config, - this.logger + this.logger, + this.converter.commentStyle ); } if (symbol && !reflection.comment) { @@ -202,7 +203,8 @@ export class Context { symbol, reflection.kind, this.converter.config, - this.logger + this.logger, + this.converter.commentStyle ); } diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts index 9385ef994..1c8c889c3 100644 --- a/src/lib/converter/converter.ts +++ b/src/lib/converter/converter.ts @@ -14,6 +14,7 @@ import type { IMinimatch } from "minimatch"; import { hasAllFlags, hasAnyFlag } from "../utils/enum"; 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,9 @@ export class Converter extends ChildableComponent< @BindOption("excludeProtected") excludeProtected!: boolean; + @BindOption("commentStyle") + commentStyle!: CommentStyle; + private _config?: CommentParserConfig; get config(): CommentParserConfig { diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts index 8a4d90665..513144027 100644 --- a/src/lib/converter/factories/signature.ts +++ b/src/lib/converter/factories/signature.ts @@ -45,7 +45,8 @@ export function createSignature( sigRef.comment = getSignatureComment( declaration, context.converter.config, - context.logger + context.logger, + context.converter.commentStyle ); } diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index b7fd09914..b8d1fc0b5 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -5,6 +5,7 @@ import { isAbsolute, join, resolve } from "path"; import type { EntryPointStrategy } from "../entry-point"; import { ReflectionKind } from "../../models/reflections/kind"; +/** @enum */ export const EmitStrategy = { both: "both", // Emit both documentation and JS docs: "docs", // Emit documentation, but not JS (default) @@ -13,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 @@ -111,6 +124,7 @@ export interface TypeDocOptionMap { hideGenerator: boolean; cleanOutputDir: boolean; + commentStyle: typeof CommentStyle; excludeTags: `@${string}`[]; blockTags: `@${string}`[]; inlineTags: `@${string}`[]; diff --git a/src/lib/utils/options/options.ts b/src/lib/utils/options/options.ts index e4421e698..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 diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 8996e3ae8..584efb947 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -1,6 +1,11 @@ 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"; @@ -349,6 +354,14 @@ export function addTypeDocOptions(options: Pick) { defaultValue: true, }); + options.addDeclaration({ + name: "commentStyle", + help: "Determines how TypeDoc searches for comments.", + type: ParameterType.Map, + map: CommentStyle, + defaultValue: CommentStyle.JSDoc, + }); + options.addDeclaration({ name: "excludeTags", help: "Remove the listed block/modifier tags from doc comments.", diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 0527996d6..7702bc137 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -1,4 +1,5 @@ import { deepStrictEqual as equal, ok } from "assert"; +import type { Application } from "../lib/application"; import { DeclarationReflection, LiteralType, @@ -8,6 +9,7 @@ import { CommentDisplayPart, CommentTag, } from "../lib/models"; +import { CommentStyle } from "../lib/utils/options/declaration"; import type { TestLogger } from "./TestLogger"; function query(project: ProjectReflection, name: string) { @@ -16,10 +18,41 @@ function query(project: ProjectReflection, name: string) { return reflection; } -export const behaviorTests: Record< - string, - (project: ProjectReflection, logger: TestLogger) => void -> = { +type Letters = + | "a" + | "b" + | "c" + | "d" + | "e" + | "f" + | "g" + | "h" + | "i" + | "j" + | "k" + | "l" + | "m" + | "n" + | "o" + | "p" + | "q" + | "r" + | "s" + | "t" + | "u" + | "v" + | "w" + | "x" + | "y" + | "z"; + +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"); @@ -86,6 +119,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), @@ -301,6 +348,22 @@ export const behaviorTests: Record< ); }, + _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), ""); + }, + mergedDeclarations(project, logger) { const a = query(project, "SingleCommentMultiDeclaration"); equal( diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts index 2c43d533b..50ad48285 100644 --- a/src/test/comments.test.ts +++ b/src/test/comments.test.ts @@ -1,7 +1,9 @@ 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"; @@ -510,6 +512,286 @@ describe("Block Comment Lexer", () => { }); }); +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)); diff --git a/src/test/converter2.test.ts b/src/test/converter2.test.ts index f01a37bd4..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,8 +36,11 @@ function runTest( const sourceFile = program.getSourceFile(entryPoint); ok(sourceFile, `No source file found for ${entryPoint}`); + const snap = app.options.snapshot(); + const logger = new TestLogger(); app.logger = logger; + pre?.(app); app.options.setValue("entryPoints", [entryPoint]); const project = app.converter.convert([ { @@ -44,6 +49,8 @@ function runTest( sourceFile, }, ]); + + app.options.restore(snap); check(project, logger); }); } @@ -54,6 +61,8 @@ describe("Converter2", () => { }); for (const [entry, check] of Object.entries(issueTests)) { + if (entry.startsWith("pre")) continue; + const link = `https://github.com/TypeStrong/typedoc/issues/${entry.replace( /[^\d]/g, "" @@ -67,7 +76,15 @@ describe("Converter2", () => { if (entry.endsWith("_skip")) { it.skip(name); } else { - runTest(name, join("issues", entry), check); + runTest( + name, + issueTests[`pre${entry}`], + join("issues", entry), + check as ( + project: ProjectReflection, + logger: TestLogger + ) => void + ); } } @@ -76,10 +93,20 @@ describe("Converter2", () => { .replace(/([a-z][A-Z])/g, (x) => `${x[0]} ${x[1].toLowerCase()}`) .replace("_skip", "")}`; + if (entry.startsWith("_")) continue; + if (entry.endsWith("_skip")) { it.skip(entry); } else { - runTest(title, join("behavior", entry), check); + 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/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/issueTests.ts b/src/test/issueTests.ts index 4167d9ceb..ce32a0db2 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, @@ -23,7 +24,11 @@ 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"); From 735f74820d2c2fbf3bfd74c9df28f33624754179 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 14:28:35 -0600 Subject: [PATCH 126/151] Update changelog --- CHANGELOG.md | 10 +++++++++- src/lib/utils/options/declaration.ts | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92be85d1e..eade31cb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,6 @@ These TODOs will be resolved before a full release. ([GitHub project](https://github.com/TypeStrong/typedoc/projects/11)) - Full support for declaration references, #262, #488, #1326, #1845. -- Add support for additional comment styles, #1433. - (Maybe) `@copyDoc` tag to copy parts of documentation from other entries. - (Maybe) `--commentDiscovery` option to delegate discovery to TypeScript. @@ -48,6 +47,15 @@ These TODOs will be resolved before a full release. ([GitHub project](https://gi - 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. diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index b8d1fc0b5..80dd90996 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -22,7 +22,7 @@ export const CommentStyle = { JSDoc: "JSDoc", Block: "Block", Line: "Line", - All: "all", + All: "All", } as const; export type CommentStyle = typeof CommentStyle[keyof typeof CommentStyle]; From 19413c879916a38625b00712c5a1d80d60d3e8d0 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 14:32:48 -0600 Subject: [PATCH 127/151] Bump version to 0.23.0-beta.4 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index bd7a75b1e..925bf82a1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.23.0-beta.3", + "version": "0.23.0-beta.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.23.0-beta.3", + "version": "0.23.0-beta.4", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", @@ -41,7 +41,7 @@ "typescript": "^4.7.2" }, "engines": { - "node": ">= 14" + "node": ">= 14.14" }, "peerDependencies": { "typescript": "4.6.x || 4.7.x" diff --git a/package.json b/package.json index 966147949..eb8c7d686 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.23.0-beta.3", + "version": "0.23.0-beta.4", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": { From b8f2eaaef5fe9b65d9355ce33a91cc87976e6fac Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sat, 4 Jun 2022 14:36:33 -0600 Subject: [PATCH 128/151] Explicitly test on Node 14.14 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc0862450..d02348cb6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node: ["14", "16", "17"] + node: ["14.14", "14", "16", "18"] name: Node ${{ matrix.node }} steps: - name: Checkout repository From 533f33deeccbc58cd519c7d9e6d9bc8df0981c25 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 12 Jun 2022 13:35:34 -0600 Subject: [PATCH 129/151] WIP: Declaration reference parser --- .../comments/declarationReference.ts | 280 ++++++++++++++++++ 1 file changed, 280 insertions(+) create mode 100644 src/lib/converter/comments/declarationReference.ts diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts new file mode 100644 index 000000000..896e53b74 --- /dev/null +++ b/src/lib/converter/comments/declarationReference.ts @@ -0,0 +1,280 @@ +/** + * 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 + */ + +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 +]; + +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"; + +function skipWs(source: string, pos: number, end: number) { + while (pos < end && /\s/.test(source[pos])) { + pos++; + } + return pos; +} + +// 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 [source[pos], 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) { + console.log("nope u"); + 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 +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 +function parseModuleSource( + source: string, + pos: number, + end: number +): [string, number] | undefined { + pos = skipWs(source, pos, end); + 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 +// ComponentPath: +// Component +// ComponentPath `.` Component // Navigate via 'exports' of |ComponentPath| +// ComponentPath `#` Component // Navigate via 'members' of |ComponentPath| +// ComponentPath `~` Component // Navigate via 'locals' of |ComponentPath| +// 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') +function parseSymbolReference(source: string, pos: number, end: number) { + // +} + +// // 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 +): [DeclarationReference, number] | undefined { + const end = source.length; + let pos = skipWs(source, 0, end); + + let moduleSource: string | 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]; + } + } + + const symbolReference = parseSymbolReference(source, pos, end); + + return [ + { + moduleSource, + resolutionStart, + }, + pos, + ]; +} + +export interface DeclarationReference { + resolutionStart: "global" | "local"; + moduleSource?: string; +} + +if (require.main === module) { + const strings = [ + '"abc\\x41\\u0041\\u{42}z"!', + "!a", + "abc.def", + "ab:var", + "abcdefghi | hi", + ]; + + for (const str of strings) { + console.log(str); + console.log(parseDeclarationReference(str)); + } +} From 8b156beb506b3dfd2cd7c95d7bb021dd2cdcfbcd Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 12 Jun 2022 17:34:45 -0600 Subject: [PATCH 130/151] WIP: Declaration reference parsing nearly there --- .../comments/declarationReference.ts | 239 ++++++++++++++---- src/test/declarationReference.test.ts | 156 ++++++++++++ 2 files changed, 345 insertions(+), 50 deletions(-) create mode 100644 src/test/declarationReference.test.ts diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts index 896e53b74..6acb0764b 100644 --- a/src/lib/converter/comments/declarationReference.ts +++ b/src/lib/converter/comments/declarationReference.ts @@ -7,22 +7,45 @@ */ 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 -]; + "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 SymbolReference { + path?: ComponentPath[]; + meaning?: { keyword?: MeaningKeyword; index?: number }; +} + +export interface ComponentPath { + navigation: "." | "#" | "~"; + path: string; +} + +type Chars = T extends `${infer C}${infer R}` + ? C | Chars + : never; + +// +const WhiteSpace = /[\t\u2B7F\u240C \u00A0\uFEFF\p{White_Space}]/u; const LineTerminator = "\r\n\u2028\u2029"; const Punctuators = "{}()[]!.#~:,"; const FutureReservedPunctuator = "{}@"; @@ -32,12 +55,17 @@ const HexDigit = DecimalDigit + "abcdefABCDEF"; const SingleEscapeCharacter = `'"\\bfnrtv`; const EscapeCharacter = SingleEscapeCharacter + DecimalDigit + "xu"; -function skipWs(source: string, pos: number, end: number) { - while (pos < end && /\s/.test(source[pos])) { - pos++; - } - return pos; -} +const SingleEscapeChars: Record, string> = { + "'": "'", + '"': '"', + "\\": "\\", + b: "\b", + f: "\f", + n: "\n", + r: "\r", + t: "\t", + v: "\v", +}; // EscapeSequence:: // SingleEscapeCharacter @@ -52,7 +80,7 @@ function parseEscapeSequence( ): [string, number] | undefined { // SingleEscapeCharacter if (SingleEscapeCharacter.includes(source[pos])) { - return [source[pos], pos + 1]; + return [SingleEscapeChars[source[pos] as "b"], pos + 1]; } // NonEscapeCharacter:: SourceCharacter but not one of EscapeCharacter or LineTerminator @@ -97,7 +125,6 @@ function parseUnicodeEscapeSequence( end: number ): [string, number] | undefined { if (source[pos] !== "u" || pos + 1 >= end) { - console.log("nope u"); return; } @@ -144,7 +171,7 @@ function parseUnicodeEscapeSequence( // StringCharacter:: // SourceCharacter but not one of `"` or `\` or LineTerminator // `\` EscapeSequence -function parseString( +export function parseString( source: string, pos: number, end: number @@ -174,12 +201,11 @@ function parseString( } // ModuleSource:: String | ModuleSourceCharacters -function parseModuleSource( +export function parseModuleSource( source: string, pos: number, end: number ): [string, number] | undefined { - pos = skipWs(source, pos, end); if (pos >= end) return; if (source[pos] === '"') { @@ -202,18 +228,142 @@ function parseModuleSource( // 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; +} + // 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') -function parseSymbolReference(source: string, pos: number, end: number) { - // +export function parseMeaning( + source: string, + pos: number, + end: number +): [{ keyword?: MeaningKeyword; index?: number }, 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 ( + 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)), + }, + pos, + ]; + } + } + + 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)), + }, + pos, + ]; + } + + if (keyword) { + return [{ keyword }, pos]; + } } // // NOTE: The following grammar is incorrect as |SymbolReference| and |ModuleSource| have an @@ -230,9 +380,10 @@ export function parseDeclarationReference( source: string ): [DeclarationReference, number] | undefined { const end = source.length; - let pos = skipWs(source, 0, end); + let pos = 0; let moduleSource: string | undefined; + let symbolReference: SymbolReference | undefined; let resolutionStart: "global" | "local" = "local"; const moduleSourceOrSymbolRef = parseModuleSource(source, pos, end); @@ -246,35 +397,23 @@ export function parseDeclarationReference( resolutionStart = "global"; moduleSource = moduleSourceOrSymbolRef[0]; } + } else if (source[pos] === "!") { + pos++; + resolutionStart = "global"; } - const symbolReference = parseSymbolReference(source, pos, end); + const ref = parseSymbolReference(source, pos, end); + if (ref) { + symbolReference = ref[0]; + pos = ref[1]; + } return [ { moduleSource, resolutionStart, + symbolReference, }, pos, ]; } - -export interface DeclarationReference { - resolutionStart: "global" | "local"; - moduleSource?: string; -} - -if (require.main === module) { - const strings = [ - '"abc\\x41\\u0041\\u{42}z"!', - "!a", - "abc.def", - "ab:var", - "abcdefghi | hi", - ]; - - for (const str of strings) { - console.log(str); - console.log(parseDeclarationReference(str)); - } -} diff --git a/src/test/declarationReference.test.ts b/src/test/declarationReference.test.ts new file mode 100644 index 000000000..dd2ecdcbe --- /dev/null +++ b/src/test/declarationReference.test.ts @@ -0,0 +1,156 @@ +import { deepStrictEqual as equal } from "assert"; +import { + parseComponent, + parseComponentPath, + 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) => parseMeaning(s, 0, s.length)?.[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", () => { + equal(parse(":class(123"), { keyword: "class" }); + }); + + it("Parses an index", () => { + equal(parse(":(123)"), { keyword: undefined, index: 123 }); + }); + + it("Parses a bare index", () => { + equal(parse(":123"), { index: 123 }); + }); + }); + + 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"); + }); + }); +}); From 61bbbd8fea3bffa7a67291b2e429a8ed6b7270bd Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 13 Jun 2022 18:50:12 -0600 Subject: [PATCH 131/151] WIP: Add tests for declaration reference parsing --- src/test/declarationReference.test.ts | 49 +++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/test/declarationReference.test.ts b/src/test/declarationReference.test.ts index dd2ecdcbe..8d5afc21a 100644 --- a/src/test/declarationReference.test.ts +++ b/src/test/declarationReference.test.ts @@ -2,6 +2,7 @@ import { deepStrictEqual as equal } from "assert"; import { parseComponent, parseComponentPath, + parseDeclarationReference, parseMeaning, parseModuleSource, parseString, @@ -153,4 +154,52 @@ describe("Declaration References", () => { equal(parse("abc.def"), "abc.def"); }); }); + + describe("Full reference parsing", () => { + const parse = (s: string) => parseDeclarationReference(s)?.[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, + }); + }); + }); }); From fee67b0bbd273ca047a02f2fce325c3d966060ae Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 13 Jun 2022 20:16:53 -0600 Subject: [PATCH 132/151] WIP: Resolution for declaration references --- .../comments/declarationReference.ts | 13 +- .../converter/plugins/LinkResolverPlugin.ts | 148 ++++++++++++++++-- src/lib/models/reflections/kind.ts | 6 + src/test/declarationReference.test.ts | 3 +- 4 files changed, 149 insertions(+), 21 deletions(-) diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts index 6acb0764b..a21b7516e 100644 --- a/src/lib/converter/comments/declarationReference.ts +++ b/src/lib/converter/comments/declarationReference.ts @@ -36,6 +36,12 @@ export interface SymbolReference { } 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; } @@ -377,11 +383,10 @@ export function parseMeaning( // ModuleSource `!` `~` SymbolReference // Reference to a local of a module // `!` SymbolReference // Reference to global symbol export function parseDeclarationReference( - source: string + source: string, + pos: number, + end: number ): [DeclarationReference, number] | undefined { - const end = source.length; - let pos = 0; - let moduleSource: string | undefined; let symbolReference: SymbolReference | undefined; let resolutionStart: "global" | "local" = "local"; diff --git a/src/lib/converter/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts index c4e7b9b6d..c79f0d7c4 100644 --- a/src/lib/converter/plugins/LinkResolverPlugin.ts +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -2,7 +2,18 @@ import type { Reflection } from "../../models/reflections/abstract"; import { Component, ConverterComponent } from "../components"; import type { Context } from "../../converter"; import { ConverterEvents } from "../converter-events"; -import type { CommentDisplayPart } from "../../models"; +import { + CommentDisplayPart, + ContainerReflection, + InlineTagDisplayPart, + ReflectionKind, +} from "../../models"; +import { + ComponentPath, + DeclarationReference, + parseDeclarationReference, +} from "../comments/declarationReference"; +import ts = require("typescript"); const urlPrefix = /^(http|ftp)s?:\/\//; const brackets = /\[\[([^\]]+)\]\]/g; @@ -115,7 +126,7 @@ export class LinkResolverPlugin extends ConverterComponent { if (!warned) { warned = true; this.application.logger.warn( - `${reflection.getFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24` + `${reflection.getFriendlyFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24` ); } }; @@ -152,20 +163,7 @@ export class LinkResolverPlugin extends ConverterComponent { part.tag === "@linkcode" || part.tag === "@linkplain" ) { - 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 resolveLinkTag(reflection, part); } } @@ -200,3 +198,121 @@ export class LinkResolverPlugin extends ConverterComponent { } } } + +function resolveLinkTag(reflection: Reflection, part: InlineTagDisplayPart) { + let pos = 0; + const end = part.text.length; + + // Skip any leading white space, which isn't allowed in a declaration reference. + while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) { + pos++; + } + + // 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... should probably warn here. + if (!target) return legacyResolveLinkTag(reflection, part); + + // 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; +} + +function resolveDeclarationReference( + reflection: Reflection, + ref: DeclarationReference +): Reflection | undefined { + let refl: Reflection | undefined = reflection; + + if (ref.moduleSource) { + refl = refl.project.children?.find((c) => c.name === ref.moduleSource); + } else if (ref.resolutionStart === "global") { + refl = refl.project; + } + + if (!refl) return; + + if (ref.symbolReference) { + let targets = [refl]; + for (const part of ref.symbolReference.path || []) { + targets = targets.flatMap((refl) => + resolveSymbolReferencePart(refl, part) + ); + } + + // TODO: meaning + return targets[0]; + } + + return refl; +} + +function resolveSymbolReferencePart( + refl: Reflection, + path: ComponentPath +): Reflection[] { + if (!(refl instanceof ContainerReflection) || !refl.children) return []; + + 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 ".": + return []; // TODO: Finish me + + // Resolve via "members", interface children, class instance properties/accessors/methods, + // enum members, type literal properties + case "#": + return refl.children.filter((r) => { + return r.kindOf(ReflectionKind.SomeMember) && !r.flags.isStatic; + }); + + // 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)) { + return refl.children.filter((r) => r.name === path.path) || []; + } + return []; + } +} diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index a59a65626..3a12c1567 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -60,6 +60,12 @@ export namespace ReflectionKind { ReflectionKind.Function | ReflectionKind.ObjectLiteral; + export const SomeMember = + ReflectionKind.EnumMember | + ReflectionKind.Property | + ReflectionKind.Method | + ReflectionKind.Accessor; + /** @internal */ export const Inheritable = ReflectionKind.Accessor | diff --git a/src/test/declarationReference.test.ts b/src/test/declarationReference.test.ts index 8d5afc21a..88501955d 100644 --- a/src/test/declarationReference.test.ts +++ b/src/test/declarationReference.test.ts @@ -156,7 +156,8 @@ describe("Declaration References", () => { }); describe("Full reference parsing", () => { - const parse = (s: string) => parseDeclarationReference(s)?.[0]; + const parse = (s: string) => + parseDeclarationReference(s, 0, s.length)?.[0]; it("Parses module if there is one", () => { equal(parse("abc!"), { From e7afeffa334d673005e51027b10299f345029e82 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 13 Jun 2022 20:33:04 -0600 Subject: [PATCH 133/151] nyc -> c8 -> drop 70 devDeps --- package-lock.json | 2047 ++++++--------------------------------------- package.json | 8 +- 2 files changed, 240 insertions(+), 1815 deletions(-) diff --git a/package-lock.json b/package-lock.json index 925bf82a1..db4915e45 100644 --- a/package-lock.json +++ b/package-lock.json @@ -27,10 +27,10 @@ "@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", @@ -47,256 +47,12 @@ "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 +194,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 +305,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 +325,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", @@ -1065,18 +805,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", @@ -1090,39 +818,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", @@ -1414,6 +1115,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", @@ -1443,21 +1240,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", @@ -1480,15 +1262,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", @@ -1517,32 +1290,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", @@ -1762,21 +1509,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", @@ -1798,12 +1530,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", @@ -2503,18 +2229,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", @@ -2740,12 +2454,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", @@ -3092,19 +2800,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", @@ -3412,23 +3107,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", @@ -3554,26 +3232,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", @@ -3598,15 +3256,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", @@ -3630,15 +3279,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", @@ -3748,15 +3388,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", @@ -3836,15 +3467,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", @@ -3944,19 +3566,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", @@ -4587,15 +4196,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", @@ -4685,81 +4285,27 @@ }, "node_modules/isobject": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "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==", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", "dev": true, "dependencies": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" + "isarray": "1.0.0" }, "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "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/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true }, - "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==", + "node_modules/istanbul-lib-coverage": { + "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" } @@ -4778,24 +4324,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", @@ -4811,43 +4343,12 @@ "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", "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", @@ -4872,21 +4373,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", @@ -4978,12 +4464,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", @@ -5627,18 +5107,6 @@ } } }, - "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", @@ -5669,189 +5137,6 @@ "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==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "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" - } - }, - "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==", - "dev": true, - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -6241,18 +5526,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", @@ -6274,21 +5547,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", @@ -6544,18 +5802,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", @@ -7211,18 +6457,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", @@ -7334,12 +6568,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", @@ -7352,15 +6580,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", @@ -7557,12 +6776,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", @@ -7817,15 +7030,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", @@ -7847,23 +7051,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", @@ -7908,12 +7095,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", @@ -8081,15 +7262,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", @@ -8281,15 +7453,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", @@ -8466,24 +7629,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", @@ -8663,6 +7808,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", @@ -8753,12 +7912,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", @@ -8830,18 +7983,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "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" - } - }, "node_modules/ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", @@ -8983,238 +8124,12 @@ } }, "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==", + "@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 }, - "@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, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@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, - "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" - } - }, - "@babel/types": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", - "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, "@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -9330,23 +8245,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": { @@ -9439,12 +8341,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", @@ -9465,6 +8361,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", @@ -9789,15 +8691,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", @@ -9808,36 +8701,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", @@ -10052,6 +8921,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", @@ -10077,18 +9011,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", @@ -10105,12 +9027,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", @@ -10135,28 +9051,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", @@ -10321,21 +9215,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", @@ -10351,12 +9230,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", @@ -10932,16 +9805,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "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" - } + "dev": true }, "defaults": { "version": "1.0.3", @@ -11124,12 +9988,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", @@ -11380,12 +10238,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", @@ -11629,17 +10481,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", @@ -11738,12 +10579,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", @@ -11768,12 +10603,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", @@ -11791,12 +10620,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", @@ -11881,12 +10704,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", @@ -11944,12 +10761,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", @@ -12025,16 +10836,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", @@ -12487,12 +11288,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", @@ -12572,55 +11367,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", @@ -12632,21 +11383,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", @@ -12659,34 +11399,12 @@ "integrity": "sha512-ru1HWKek8octvUHFHvE5ZzQ1yAsJmIvRdGWvSoKV52XKyuyYA437QWDttXT8eZXDSbuMpHlLzPDZUPd6idIz+Q==", "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", @@ -12711,15 +11429,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", @@ -12795,12 +11504,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", @@ -13273,15 +11976,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", @@ -13308,158 +12002,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", @@ -13745,15 +12287,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", @@ -13769,18 +12302,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", @@ -13965,15 +12486,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", @@ -14490,15 +13002,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", @@ -14581,12 +13084,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", @@ -14596,12 +13093,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", @@ -14737,12 +13228,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", @@ -14951,12 +13436,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", @@ -14976,20 +13455,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", @@ -15031,12 +13496,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", @@ -15167,12 +13626,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", @@ -15334,12 +13787,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", @@ -15468,21 +13915,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", @@ -15627,6 +14059,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", @@ -15705,12 +14148,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", @@ -15766,18 +14203,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "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" - } - }, "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", diff --git a/package.json b/package.json index eb8c7d686..30e0effd8 100644 --- a/package.json +++ b/package.json @@ -42,10 +42,10 @@ "@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", @@ -67,9 +67,9 @@ "/.config/typedoc-default.tsdoc.json" ], "scripts": { - "test": "nyc mocha -r ts-node/register --config .config/mocha.fast.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": "nyc mocha -r ts-node/register --config .config/mocha.full.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", "rebuild_specs": "node scripts/rebuild_specs.js", @@ -88,7 +88,7 @@ "documentation", "generator" ], - "nyc": { + "c8": { "extension": [ ".ts", ".tsx" From 4dfefe89fb81e0d635582d463afa09f5d27cfbbf Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 19 Jun 2022 14:21:31 -0600 Subject: [PATCH 134/151] Finish support for declaration references, still needs tests Resolves #1949 Resolves #1629 Resolves #488 Resolves #262 --- .eslintrc | 3 + CHANGELOG.md | 10 +- .../comments/declarationReference.ts | 7 +- .../converter/plugins/LinkResolverPlugin.ts | 214 ++++++++++++++++-- src/lib/models/reflections/kind.ts | 14 ++ 5 files changed, 215 insertions(+), 33 deletions(-) diff --git a/.eslintrc b/.eslintrc index dcde5f5c2..75004a2a1 100644 --- a/.eslintrc +++ b/.eslintrc @@ -37,6 +37,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, diff --git a/CHANGELOG.md b/CHANGELOG.md index eade31cb3..3a1a07fa6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,17 +1,11 @@ # Unreleased -### Incomplete - -These TODOs will be resolved before a full release. ([GitHub project](https://github.com/TypeStrong/typedoc/projects/11)) - -- Full support for declaration references, #262, #488, #1326, #1845. -- (Maybe) `@copyDoc` tag to copy parts of documentation from other entries. -- (Maybe) `--commentDiscovery` option to delegate discovery to TypeScript. - ### 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. diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts index a21b7516e..9cf7b8fbb 100644 --- a/src/lib/converter/comments/declarationReference.ts +++ b/src/lib/converter/comments/declarationReference.ts @@ -30,9 +30,14 @@ export interface DeclarationReference { symbolReference?: SymbolReference; } +export interface Meaning { + keyword?: MeaningKeyword; + index?: number; +} + export interface SymbolReference { path?: ComponentPath[]; - meaning?: { keyword?: MeaningKeyword; index?: number }; + meaning?: Meaning; } export interface ComponentPath { diff --git a/src/lib/converter/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts index c79f0d7c4..b936a488d 100644 --- a/src/lib/converter/plugins/LinkResolverPlugin.ts +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -5,15 +5,20 @@ import { ConverterEvents } from "../converter-events"; import { CommentDisplayPart, ContainerReflection, + DeclarationReflection, InlineTagDisplayPart, ReflectionKind, } from "../../models"; import { ComponentPath, DeclarationReference, + Meaning, + MeaningKeyword, parseDeclarationReference, } from "../comments/declarationReference"; import ts = require("typescript"); +import { ok } from "assert"; +import { BindOption, filterMap, ValidationOptions } from "../../utils"; const urlPrefix = /^(http|ftp)s?:\/\//; const brackets = /\[\[([^\]]+)\]\]/g; @@ -22,6 +27,9 @@ const brackets = /\[\[([^\]]+)\]\]/g; */ @Component({ name: "link-resolver" }) export class LinkResolverPlugin extends ConverterComponent { + @BindOption("validation") + validation!: ValidationOptions; + /** * Create a new LinkResolverPlugin instance. */ @@ -163,7 +171,11 @@ export class LinkResolverPlugin extends ConverterComponent { part.tag === "@linkcode" || part.tag === "@linkplain" ) { - return resolveLinkTag(reflection, part); + return resolveLinkTag(reflection, part, (msg: string) => { + if (this.validation.invalidLink) { + this.application.logger.warn(msg); + } + }); } } @@ -199,7 +211,11 @@ export class LinkResolverPlugin extends ConverterComponent { } } -function resolveLinkTag(reflection: Reflection, part: InlineTagDisplayPart) { +function resolveLinkTag( + reflection: Reflection, + part: InlineTagDisplayPart, + warn: (message: string) => void +) { let pos = 0; const end = part.text.length; @@ -219,8 +235,15 @@ function resolveLinkTag(reflection: Reflection, part: InlineTagDisplayPart) { } // If resolution via a declaration reference failed, revert to the legacy "split and check" - // method... should probably warn here. - if (!target) return legacyResolveLinkTag(reflection, part); + // method... this should go away in 0.24, once people have had a chance to migrate any failing links. + if (!target) { + warn( + `Failed to resolve {@link ${ + part.text + }} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.` + ); + return legacyResolveLinkTag(reflection, part); + } // Remaining text after an optional pipe is the link text, so advance // until that's consumed. @@ -261,36 +284,160 @@ function resolveDeclarationReference( reflection: Reflection, ref: DeclarationReference ): Reflection | undefined { - let refl: Reflection | undefined = reflection; + let high: Reflection[] = []; + let low: Reflection[] = []; if (ref.moduleSource) { - refl = refl.project.children?.find((c) => c.name === ref.moduleSource); + high = + reflection.project.children?.filter( + (c) => + c.kindOf(ReflectionKind.SomeModule) && + c.name === ref.moduleSource + ) || []; } else if (ref.resolutionStart === "global") { - refl = refl.project; - } + 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 (!refl) return; + 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) { - let targets = [refl]; for (const part of ref.symbolReference.path || []) { - targets = targets.flatMap((refl) => - resolveSymbolReferencePart(refl, part) - ); + 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); + } } - // TODO: meaning - return targets[0]; + if (ref.symbolReference.meaning) { + high = filterMapByMeaning(high, ref.symbolReference.meaning); + low = filterMapByMeaning(low, ref.symbolReference.meaning); + } } - return refl; + return high[0] || low[0]; +} + +function filterMapByMeaning( + reflections: Reflection[], + meaning: Meaning +): Reflection[] { + return filterMap(reflections, (refl): Reflection | undefined => { + const kwResolved = resolveKeyword(refl, meaning.keyword) || []; + return kwResolved[meaning.index || 0]; + }); +} + +function resolveKeyword( + refl: Reflection, + kw: MeaningKeyword | undefined +): Reflection[] | undefined { + switch (kw) { + case undefined: + return [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.Class)) { + const ctor = (refl as ContainerReflection).children?.find((c) => + c.kindOf(ReflectionKind.Constructor) + ); + return (ctor as DeclarationReflection)?.signatures; + } + if (refl.kindOf(ReflectionKind.Constructor)) { + return (refl as DeclarationReflection).signatures; + } + break; + + case "member": + if (refl.kindOf(ReflectionKind.SomeMember)) return [refl]; + break; + case "event": + if (refl.comment?.hasModifier("@event")) return [refl]; + 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 -): Reflection[] { - if (!(refl instanceof ContainerReflection) || !refl.children) return []; +): { 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. @@ -298,21 +445,40 @@ function resolveSymbolReferencePart( // 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 ".": - return []; // TODO: Finish me + 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 "#": - return refl.children.filter((r) => { - return r.kindOf(ReflectionKind.SomeMember) && !r.flags.isStatic; + 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)) { - return refl.children.filter((r) => r.name === path.path) || []; + if ( + refl.kindOf(ReflectionKind.SomeModule | ReflectionKind.Project) + ) { + high = refl.children.filter((r) => r.name === path.path); } - return []; + break; } + + return { high, low }; } diff --git a/src/lib/models/reflections/kind.ts b/src/lib/models/reflections/kind.ts index 3a12c1567..f96043428 100644 --- a/src/lib/models/reflections/kind.ts +++ b/src/lib/models/reflections/kind.ts @@ -66,6 +66,20 @@ export namespace ReflectionKind { 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 | From 5d442750e670bd7caf2621799847629e7bf59066 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 19 Jun 2022 16:01:55 -0600 Subject: [PATCH 135/151] Add tests for declaration reference resolution --- CHANGELOG.md | 2 +- package.json | 2 +- .../comments/declarationReference.ts | 6 +- .../converter/plugins/LinkResolverPlugin.ts | 61 +++++---- src/lib/utils/general.ts | 7 + src/lib/utils/index.ts | 2 +- src/test/behaviorTests.ts | 120 +++++++++++++---- .../converter2/behavior/linkResolution.ts | 123 ++++++++++++++++++ 8 files changed, 261 insertions(+), 62 deletions(-) create mode 100644 src/test/converter2/behavior/linkResolution.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a1a07fa6..4877404cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ - 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 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. diff --git a/package.json b/package.json index 30e0effd8..defc7b4a2 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ ".tsx" ], "reporter": [ - "html", + "html-spa", "text-summary" ], "exclude": [ diff --git a/src/lib/converter/comments/declarationReference.ts b/src/lib/converter/comments/declarationReference.ts index 9cf7b8fbb..a2238b23a 100644 --- a/src/lib/converter/comments/declarationReference.ts +++ b/src/lib/converter/comments/declarationReference.ts @@ -6,6 +6,8 @@ * @module */ +import type { Chars } from "../../utils"; + export const MeaningKeywords = [ "class", // SymbolFlags.Class "interface", // SymbolFlags.Interface @@ -51,10 +53,6 @@ export interface ComponentPath { path: string; } -type Chars = T extends `${infer C}${infer R}` - ? C | Chars - : never; - // const WhiteSpace = /[\t\u2B7F\u240C \u00A0\uFEFF\p{White_Space}]/u; const LineTerminator = "\r\n\u2028\u2029"; diff --git a/src/lib/converter/plugins/LinkResolverPlugin.ts b/src/lib/converter/plugins/LinkResolverPlugin.ts index b936a488d..c96dede84 100644 --- a/src/lib/converter/plugins/LinkResolverPlugin.ts +++ b/src/lib/converter/plugins/LinkResolverPlugin.ts @@ -65,7 +65,14 @@ export class LinkResolverPlugin extends ConverterComponent { const { target, caption } = LinkResolverPlugin.splitLinkText(content); - if (!urlPrefix.test(target)) { + if (urlPrefix.test(target)) { + parts.push({ + kind: "inline-tag", + tag: "@link", + text: caption, + target, + }); + } else { const targetRefl = reflection.findReflectionByName(target); if (targetRefl) { parts.push({ @@ -75,22 +82,17 @@ export class LinkResolverPlugin extends ConverterComponent { target: targetRefl, }); } else { - this.application.logger.warn( - "Failed to find target: " + content - ); + if (this.validation.invalidLink) { + this.application.logger.warn( + "Failed to find target: " + content + ); + } parts.push({ kind: "inline-tag", tag: "@link", text: content, }); } - } else { - parts.push({ - kind: "inline-tag", - tag: "@link", - text: caption, - target, - }); } } parts.push({ @@ -219,11 +221,6 @@ function resolveLinkTag( let pos = 0; const end = part.text.length; - // Skip any leading white space, which isn't allowed in a declaration reference. - while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) { - pos++; - } - // Try to parse one const declRef = parseDeclarationReference(part.text, pos, end); @@ -237,12 +234,15 @@ function resolveLinkTag( // 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) { - warn( - `Failed to resolve {@link ${ - part.text - }} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.` - ); - return legacyResolveLinkTag(reflection, part); + 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 @@ -369,7 +369,9 @@ function resolveKeyword( ): Reflection[] | undefined { switch (kw) { case undefined: - return [refl]; + return refl instanceof DeclarationReflection && refl.signatures + ? refl.signatures + : [refl]; case "class": if (refl.kindOf(ReflectionKind.Class)) return [refl]; break; @@ -396,22 +398,25 @@ function resolveKeyword( case "new": case "constructor": - if (refl.kindOf(ReflectionKind.Class)) { + if ( + refl.kindOf( + ReflectionKind.ClassOrInterface | ReflectionKind.TypeLiteral + ) + ) { const ctor = (refl as ContainerReflection).children?.find((c) => c.kindOf(ReflectionKind.Constructor) ); return (ctor as DeclarationReflection)?.signatures; } - if (refl.kindOf(ReflectionKind.Constructor)) { - return (refl as DeclarationReflection).signatures; - } break; case "member": if (refl.kindOf(ReflectionKind.SomeMember)) return [refl]; break; case "event": - if (refl.comment?.hasModifier("@event")) return [refl]; + // 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; diff --git a/src/lib/utils/general.ts b/src/lib/utils/general.ts index 367b003cb..ed7fef3ec 100644 --- a/src/lib/utils/general.ts +++ b/src/lib/utils/general.ts @@ -35,6 +35,13 @@ 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. */ diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index f7a8e508a..849ee011b 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -17,7 +17,7 @@ export { 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"; diff --git a/src/test/behaviorTests.ts b/src/test/behaviorTests.ts index 7702bc137..95bf54f4a 100644 --- a/src/test/behaviorTests.ts +++ b/src/test/behaviorTests.ts @@ -8,7 +8,10 @@ import { 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"; @@ -18,33 +21,7 @@ function query(project: ProjectReflection, name: string) { return reflection; } -type Letters = - | "a" - | "b" - | "c" - | "d" - | "e" - | "f" - | "g" - | "h" - | "i" - | "j" - | "k" - | "l" - | "m" - | "n" - | "o" - | "p" - | "q" - | "r" - | "s" - | "t" - | "u" - | "v" - | "w" - | "x" - | "y" - | "z"; +type Letters = Chars<"abcdefghijklmnopqrstuvwxyz">; export const behaviorTests: { [issue: `_${string}`]: (app: Application) => void; @@ -364,6 +341,95 @@ export const behaviorTests: { 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], + + ["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( + 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( 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; + } +} From 6039f2295fcecebfc7ad7e4c61714ac2e7276aff Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Sun, 19 Jun 2022 18:25:53 -0600 Subject: [PATCH 136/151] Bump version to 0.23.0-beta.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index db4915e45..a92deaea2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "typedoc", - "version": "0.23.0-beta.4", + "version": "0.23.0-beta.5", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "typedoc", - "version": "0.23.0-beta.4", + "version": "0.23.0-beta.5", "license": "Apache-2.0", "dependencies": { "lunr": "^2.3.9", diff --git a/package.json b/package.json index defc7b4a2..e95e377e9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "typedoc", "description": "Create api documentation for TypeScript projects.", - "version": "0.23.0-beta.4", + "version": "0.23.0-beta.5", "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": { From 1ca876db5ba9b300f30f5eb9c3aee4aa06f02861 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 20 Jun 2022 17:43:35 -0600 Subject: [PATCH 137/151] Allow new file extensions in pacakges mode Also refactor more tests to use fixture builder Resolves #1952. --- CHANGELOG.md | 1 + src/lib/utils/package-manifest.ts | 10 +- src/test/packages.test.ts | 155 ++++++++++++++++-- src/test/packages/README.md | 4 - src/test/packages/multi-package/package.json | 10 -- .../multi-package/packages/bar/index.d.ts | 1 - .../multi-package/packages/bar/package.json | 5 - .../multi-package/packages/bar/tsconfig.json | 6 - .../multi-package/packages/baz/index.ts | 1 - .../multi-package/packages/baz/package.json | 5 - .../multi-package/packages/baz/tsconfig.json | 8 - .../multi-package/packages/foo/dist/index.js | 2 - .../multi-package/packages/foo/index.ts | 1 - .../multi-package/packages/foo/package.json | 6 - .../multi-package/packages/foo/tsconfig.json | 8 - src/test/packages/multi-package/tsconfig.json | 7 - .../packages/single-package/dist/index.js | 8 - .../packages/single-package/dist/index.js.map | 1 - src/test/packages/single-package/package.json | 7 - src/test/packages/single-package/src/index.ts | 3 - .../packages/single-package/tsconfig.json | 8 - 21 files changed, 150 insertions(+), 107 deletions(-) delete mode 100644 src/test/packages/README.md delete mode 100644 src/test/packages/multi-package/package.json delete mode 100644 src/test/packages/multi-package/packages/bar/index.d.ts delete mode 100644 src/test/packages/multi-package/packages/bar/package.json delete mode 100644 src/test/packages/multi-package/packages/bar/tsconfig.json delete mode 100644 src/test/packages/multi-package/packages/baz/index.ts delete mode 100644 src/test/packages/multi-package/packages/baz/package.json delete mode 100644 src/test/packages/multi-package/packages/baz/tsconfig.json delete mode 100644 src/test/packages/multi-package/packages/foo/dist/index.js delete mode 100644 src/test/packages/multi-package/packages/foo/index.ts delete mode 100644 src/test/packages/multi-package/packages/foo/package.json delete mode 100644 src/test/packages/multi-package/packages/foo/tsconfig.json delete mode 100644 src/test/packages/multi-package/tsconfig.json delete mode 100644 src/test/packages/single-package/dist/index.js delete mode 100644 src/test/packages/single-package/dist/index.js.map delete mode 100644 src/test/packages/single-package/package.json delete mode 100644 src/test/packages/single-package/src/index.ts delete mode 100644 src/test/packages/single-package/tsconfig.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 4877404cf..028d7098e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,6 +73,7 @@ - JS exports defined as `exports.foo = ...` will now be converted as variables rather than properties. - 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! diff --git a/src/lib/utils/package-manifest.ts b/src/lib/utils/package-manifest.ts index 7ea47be57..e19d87e47 100644 --- a/src/lib/utils/package-manifest.ts +++ b/src/lib/utils/package-manifest.ts @@ -225,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) { @@ -237,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/test/packages.test.ts b/src/test/packages.test.ts index b1fc784ad..99f644adf 100644 --- a/src/test/packages.test.ts +++ b/src/test/packages.test.ts @@ -7,18 +7,82 @@ import { 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"] -} From 3f23d0c2eca77960d5add01da2fb8d6d79e20107 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Mon, 20 Jun 2022 20:59:54 -0600 Subject: [PATCH 138/151] Fix compiler errors --- .config/typedoc-default.tsdoc.json | 5 +++++ src/lib/utils/options/tsdoc-defaults.ts | 3 +++ src/test/packages.test.ts | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.config/typedoc-default.tsdoc.json b/.config/typedoc-default.tsdoc.json index b7a04591d..27c2f675f 100644 --- a/.config/typedoc-default.tsdoc.json +++ b/.config/typedoc-default.tsdoc.json @@ -33,6 +33,11 @@ { "tagName": "@event", "syntaxKind": "modifier" + }, + { + "tagName": "@template", + "syntaxKind": "block", + "allowMultiple": true } ] } diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts index 80e287867..245a619cd 100644 --- a/src/lib/utils/options/tsdoc-defaults.ts +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -7,6 +7,7 @@ export const tsdocBlockTags = [ "@throws", "@privateRemarks", "@defaultValue", + "@typeParam", ] as const; export const blockTags = [ @@ -15,6 +16,8 @@ export const blockTags = [ "@inheritDoc", "@group", "@category", + // Alias for @typeParam + "@template", ] as const; export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; diff --git a/src/test/packages.test.ts b/src/test/packages.test.ts index 99f644adf..18847691f 100644 --- a/src/test/packages.test.ts +++ b/src/test/packages.test.ts @@ -1,7 +1,7 @@ -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 12721f9db893b98b43cea75c557f4ebba78662d5 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Tue, 21 Jun 2022 19:51:29 -0600 Subject: [PATCH 139/151] Minor changes discovered while updating docs --- package.json | 5 +- src/lib/utils/options/declaration.ts | 8 +- src/lib/utils/options/sources/typedoc.ts | 411 +++++++++--------- src/lib/utils/options/tsdoc-defaults.ts | 8 + .../typedoc-default.tsdoc.json => tsdoc.json | 18 + 5 files changed, 249 insertions(+), 201 deletions(-) rename .config/typedoc-default.tsdoc.json => tsdoc.json (72%) diff --git a/package.json b/package.json index e95e377e9..67a0c46ae 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,7 @@ "homepage": "https://typedoc.org", "main": "./dist/index.js", "exports": { - ".": "./dist/index.js", - "./tsdoc.json": "./.config/typedoc-default.tsdoc.json" + ".": "./dist/index.js" }, "types": "./dist/index.d.ts", "bin": { @@ -64,7 +63,7 @@ "!/dist/test", "/LICENSE", "/static", - "/.config/typedoc-default.tsdoc.json" + "/tsdoc.json" ], "scripts": { "test": "c8 mocha -r ts-node/register --config .config/mocha.fast.json", diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts index 80dd90996..3f04e6a87 100644 --- a/src/lib/utils/options/declaration.ts +++ b/src/lib/utils/options/declaration.ts @@ -19,10 +19,10 @@ export type EmitStrategy = typeof EmitStrategy[keyof typeof EmitStrategy]; * @enum */ export const CommentStyle = { - JSDoc: "JSDoc", - Block: "Block", - Line: "Line", - All: "All", + JSDoc: "jsdoc", + Block: "block", + Line: "line", + All: "all", } as const; export type CommentStyle = typeof CommentStyle[keyof typeof CommentStyle]; diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts index 584efb947..76d6c39d4 100644 --- a/src/lib/utils/options/sources/typedoc.ts +++ b/src/lib/utils/options/sources/typedoc.ts @@ -13,7 +13,12 @@ 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", @@ -28,6 +33,23 @@ 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.", @@ -41,40 +63,6 @@ export function addTypeDocOptions(options: Pick) { defaultValue: EntryPointStrategy.Resolve, }); - options.addDeclaration({ - 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: "exclude", help: "Define patterns to be excluded when expanding a directory that was specified as an entry point.", @@ -112,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", @@ -215,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", }); @@ -264,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.", @@ -275,54 +209,32 @@ export function addTypeDocOptions(options: Pick) { type: ParameterType.Boolean, }); options.addDeclaration({ - name: "readme", - help: "Path to the readme file that should be displayed on the index page. Pass `none` to disable the index page and start the documentation on the globals page.", - type: ParameterType.Path, - }); - options.addDeclaration({ - 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: "categorizeByGroup", - help: "Specify whether categorization will be done at the group level.", + name: "disableSources", + help: "Disable setting the source of a reflection when documenting it.", type: ParameterType.Boolean, - defaultValue: true, }); options.addDeclaration({ - name: "cname", - help: "Set the CNAME file text, it's useful for custom domains on GitHub Pages.", - }); - options.addDeclaration({ - name: "sort", - help: "Specify the sort strategy for documented values.", + name: "excludeTags", + help: "Remove the listed block/modifier tags from doc comments.", type: ParameterType.Array, - defaultValue: ["kind", "instance-first", "alphabetical"], + defaultValue: ["@override", "@virtual", "@privateRemarks"], validate(value) { - const invalid = new Set(value); - for (const v of SORT_STRATEGIES) { - invalid.delete(v); - } - - if (invalid.size !== 0) { + if (!Validation.validate([Array, Validation.isTagString], value)) { throw new Error( - `sort may only specify known values, and invalid values were provided (${Array.from( - invalid - ).join( - ", " - )}). The valid sort strategies are:\n${SORT_STRATEGIES.join( - ", " - )}` + `excludeTags must be an array of valid tag names.` ); } }, }); + options.addDeclaration({ + name: "readme", + help: "Path to the readme file that should be displayed on the index page. Pass `none` to disable the index page and start the documentation on the globals page.", + type: ParameterType.Path, + }); + options.addDeclaration({ + name: "cname", + help: "Set the CNAME file text, it's useful for custom domains on GitHub Pages.", + }); options.addDeclaration({ name: "gitRevision", help: "Use specified revision instead of the last revision for linking to GitHub/Bitbucket source files.", @@ -332,16 +244,16 @@ export function addTypeDocOptions(options: Pick) { 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: "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.", @@ -354,6 +266,10 @@ export function addTypeDocOptions(options: Pick) { defaultValue: true, }); + /////////////////////////// + ///// Comment Options ///// + /////////////////////////// + options.addDeclaration({ name: "commentStyle", help: "Determines how TypeDoc searches for comments.", @@ -362,19 +278,6 @@ export function addTypeDocOptions(options: Pick) { defaultValue: CommentStyle.JSDoc, }); - options.addDeclaration({ - name: "excludeTags", - 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: "blockTags", help: "Block tags which TypeDoc should recognize when parsing comments.", @@ -415,6 +318,150 @@ export function addTypeDocOptions(options: Pick) { }, }); + /////////////////////////// + // Organization Options /// + /////////////////////////// + + options.addDeclaration({ + name: "categorizeByGroup", + help: "Specify whether categorization will be done at the group level.", + type: ParameterType.Boolean, + defaultValue: true, + }); + options.addDeclaration({ + 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", + help: "Specify the sort strategy for documented values.", + type: ParameterType.Array, + defaultValue: ["kind", "instance-first", "alphabetical"], + validate(value) { + const invalid = new Set(value); + for (const v of SORT_STRATEGIES) { + invalid.delete(v); + } + + if (invalid.size !== 0) { + throw new Error( + `sort may only specify known values, and invalid values were provided (${Array.from( + invalid + ).join( + ", " + )}). The valid sort strategies are:\n${SORT_STRATEGIES.join( + ", " + )}` + ); + } + }, + }); + options.addDeclaration({ + 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: "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." + ); + } + }, + }); + + /////////////////////////// + ///// General Options ///// + /////////////////////////// + + 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: "help", help: "Print this message.", @@ -448,30 +495,6 @@ 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 (!Validation.validate({}, 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 (!Validation.validate({}, value)) { - throw new Error( - "The 'compilerOptions' option must be a non-array object." - ); - } - }, - }); options.addDeclaration({ name: "treatWarningsAsErrors", diff --git a/src/lib/utils/options/tsdoc-defaults.ts b/src/lib/utils/options/tsdoc-defaults.ts index 245a619cd..06b13f542 100644 --- a/src/lib/utils/options/tsdoc-defaults.ts +++ b/src/lib/utils/options/tsdoc-defaults.ts @@ -4,6 +4,7 @@ export const tsdocBlockTags = [ "@deprecated", "@param", "@remarks", + "@returns", "@throws", "@privateRemarks", "@defaultValue", @@ -18,6 +19,12 @@ export const blockTags = [ "@category", // Alias for @typeParam "@template", + // Because TypeScript is important! + "@type", + "@typedef", + "@callback", + "@prop", + "@property", ] as const; export const tsdocInlineTags = ["@link", "@inheritDoc", "@label"] as const; @@ -33,6 +40,7 @@ export const tsdocModifierTags = [ "@eventProperty", "@alpha", "@beta", + "@experimental", "@sealed", "@override", "@virtual", diff --git a/.config/typedoc-default.tsdoc.json b/tsdoc.json similarity index 72% rename from .config/typedoc-default.tsdoc.json rename to tsdoc.json index 27c2f675f..7f8c7cc88 100644 --- a/.config/typedoc-default.tsdoc.json +++ b/tsdoc.json @@ -6,6 +6,24 @@ "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. { From 9713c9aea8c5c7f68a3aaba4e85bd24d25b02706 Mon Sep 17 00:00:00 2001 From: Gerrit Birkeland Date: Wed, 22 Jun 2022 17:16:54 -0600 Subject: [PATCH 140/151] Beta feedback from @jlarmstrongiv Also fix a bug, `@deprecated` is a block tag, not a modifier tag. --- src/lib/converter/plugins/PackagePlugin.ts | 8 ++++- .../assets/typedoc/services/Viewport.ts | 16 +++++++++- .../output/themes/default/partials/index.tsx | 2 +- .../output/themes/default/partials/member.tsx | 2 +- .../themes/default/partials/navigation.tsx | 32 ++++++++++++------- static/style.css | 1 + 6 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts index ee26dde85..79e6969c6 100644 --- a/src/lib/converter/plugins/PackagePlugin.ts +++ b/src/lib/converter/plugins/PackagePlugin.ts @@ -112,8 +112,14 @@ export class PackagePlugin extends ConverterComponent { ); 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.` + `Block and modifier tags will be ignored within the readme:\n\t${ignored.join( + "\n\t" + )}` ); } 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 35bf6d167..0360340c3 100644 --- a/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts +++ b/src/lib/output/themes/default/assets/typedoc/services/Viewport.ts @@ -42,6 +42,8 @@ export class Viewport extends EventTarget { */ navigation: HTMLElement; + searchInput: HTMLInputElement | null; + /** * Create new Viewport instance. */ @@ -62,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(); } @@ -118,7 +129,10 @@ 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.navigation?.classList.toggle("col-menu--hide"); diff --git a/src/lib/output/themes/default/partials/index.tsx b/src/lib/output/themes/default/partials/index.tsx index 816791c2a..bab56968f 100644 --- a/src/lib/output/themes/default/partials/index.tsx +++ b/src/lib/output/themes/default/partials/index.tsx @@ -14,7 +14,7 @@ function renderCategory({ urlTo }: DefaultThemeRenderContext, item: ReflectionCa diff --git a/src/lib/output/themes/default/partials/member.tsx b/src/lib/output/themes/default/partials/member.tsx index a6e9c7133..2d66b70ad 100644 --- a/src/lib/output/themes/default/partials/member.tsx +++ b/src/lib/output/themes/default/partials/member.tsx @@ -10,7 +10,7 @@ export const member = (context: DefaultThemeRenderContext, props: DeclarationRef {!!props.name && (