typedoc 0.28.13 → 0.28.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/cli.js +2 -1
- package/dist/lib/converter/comments/index.d.ts +3 -1
- package/dist/lib/converter/comments/parser.js +61 -23
- package/dist/lib/converter/comments/textParser.d.ts +13 -9
- package/dist/lib/converter/comments/textParser.js +21 -16
- package/dist/lib/converter/converter.js +2 -0
- package/dist/lib/converter/factories/signature.js +5 -4
- package/dist/lib/converter/plugins/CommentPlugin.d.ts +1 -0
- package/dist/lib/converter/plugins/CommentPlugin.js +48 -11
- package/dist/lib/converter/symbols.js +15 -8
- package/dist/lib/converter/types.js +18 -6
- package/dist/lib/converter/utils/repository.js +3 -0
- package/dist/lib/internationalization/locales/de.cjs +0 -1
- package/dist/lib/internationalization/locales/de.d.cts +0 -1
- package/dist/lib/internationalization/locales/en.cjs +3 -1
- package/dist/lib/internationalization/locales/en.d.cts +3 -1
- package/dist/lib/internationalization/locales/ja.cjs +0 -1
- package/dist/lib/internationalization/locales/ja.d.cts +0 -1
- package/dist/lib/internationalization/locales/ko.cjs +0 -1
- package/dist/lib/internationalization/locales/ko.d.cts +0 -1
- package/dist/lib/internationalization/locales/zh.cjs +0 -1
- package/dist/lib/internationalization/locales/zh.d.cts +0 -1
- package/dist/lib/models/Comment.d.ts +5 -0
- package/dist/lib/models/Comment.js +10 -0
- package/dist/lib/models/DeclarationReflection.d.ts +7 -0
- package/dist/lib/models/DeclarationReflection.js +9 -0
- package/dist/lib/output/events.d.ts +2 -0
- package/dist/lib/output/events.js +1 -0
- package/dist/lib/output/plugins/JavascriptIndexPlugin.js +1 -1
- package/dist/lib/output/themes/MarkedPlugin.js +8 -1
- package/dist/lib/output/themes/default/Slugger.d.ts +1 -1
- package/dist/lib/output/themes/default/Slugger.js +13 -5
- package/dist/lib/output/themes/default/partials/comment.js +1 -0
- package/dist/lib/output/themes/default/partials/member.js +1 -0
- package/dist/lib/output/themes/default/partials/moduleReflection.js +1 -0
- package/dist/lib/output/themes/default/partials/navigation.js +1 -1
- package/dist/lib/serialization/schema.d.ts +2 -2
- package/dist/lib/utils/options/declaration.d.ts +6 -0
- package/dist/lib/utils/options/defaults.d.ts +1 -0
- package/dist/lib/utils/options/defaults.js +1 -0
- package/dist/lib/utils/options/sources/typedoc.js +14 -0
- package/dist/lib/utils/options/tsdoc-defaults.d.ts +2 -2
- package/dist/lib/utils/options/tsdoc-defaults.js +2 -1
- package/dist/lib/utils-common/general.js +2 -0
- package/dist/lib/utils-common/logger.d.ts +12 -1
- package/dist/lib/utils-common/logger.js +9 -0
- package/dist/lib/validation/documentation.js +2 -2
- package/dist/lib/validation/exports.js +2 -2
- package/dist/lib/validation/links.js +7 -7
- package/package.json +14 -14
- package/static/style.css +3 -3
- package/tsdoc.json +5 -4
package/dist/lib/cli.js
CHANGED
|
@@ -75,7 +75,8 @@ async function run(app) {
|
|
|
75
75
|
}
|
|
76
76
|
const preValidationWarnCount = app.logger.warningCount;
|
|
77
77
|
app.validate(project);
|
|
78
|
-
const hadValidationWarnings = app.logger.warningCount !== preValidationWarnCount
|
|
78
|
+
const hadValidationWarnings = app.logger.warningCount !== preValidationWarnCount ||
|
|
79
|
+
app.logger.validationWarningCount != 0;
|
|
79
80
|
if (app.logger.hasErrors()) {
|
|
80
81
|
return ExitCodes.ValidationError;
|
|
81
82
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { Comment, ReflectionKind } from "../../models/index.js";
|
|
3
|
-
import type { CommentStyle, JsDocCompatibility } from "../../utils/options/declaration.js";
|
|
3
|
+
import type { CommentStyle, JsDocCompatibility, ValidationOptions } from "../../utils/options/declaration.js";
|
|
4
4
|
import type { FileRegistry } from "../../models/FileRegistry.js";
|
|
5
5
|
import { type Logger } from "#utils";
|
|
6
6
|
import type { Context } from "../context.js";
|
|
@@ -8,10 +8,12 @@ export interface CommentParserConfig {
|
|
|
8
8
|
blockTags: Set<string>;
|
|
9
9
|
inlineTags: Set<string>;
|
|
10
10
|
modifierTags: Set<string>;
|
|
11
|
+
preservedTypeAnnotationTags: Set<string>;
|
|
11
12
|
jsDocCompatibility: JsDocCompatibility;
|
|
12
13
|
suppressCommentWarningsInDeclarationFiles: boolean;
|
|
13
14
|
useTsLinkResolution: boolean;
|
|
14
15
|
commentStyle: CommentStyle;
|
|
16
|
+
validationOptions: ValidationOptions;
|
|
15
17
|
}
|
|
16
18
|
export interface CommentContext {
|
|
17
19
|
config: CommentParserConfig;
|
|
@@ -45,12 +45,12 @@ export function parseComment(tokens, file, context) {
|
|
|
45
45
|
const tok = lexer.done() || lexer.peek();
|
|
46
46
|
const comment = new Comment();
|
|
47
47
|
comment.sourcePath = file.fileName;
|
|
48
|
-
comment.summary = blockContent(comment, lexer, context.config,
|
|
48
|
+
comment.summary = blockContent(comment, lexer, context.config, warningImpl, validationWarningImpl, context.files);
|
|
49
49
|
while (!lexer.done()) {
|
|
50
|
-
comment.blockTags.push(blockTag(comment, lexer, context.config,
|
|
50
|
+
comment.blockTags.push(blockTag(comment, lexer, context.config, warningImpl, validationWarningImpl, context.files));
|
|
51
51
|
}
|
|
52
52
|
const tok2 = tok;
|
|
53
|
-
postProcessComment(comment,
|
|
53
|
+
postProcessComment(comment, () => `${nicePath(file.fileName)}:${file.getLineAndCharacterOfPosition(tok2.pos).line + 1}`, (message) => context.logger.warn(message));
|
|
54
54
|
return comment;
|
|
55
55
|
function warningImpl(message, token) {
|
|
56
56
|
if (context.config.suppressCommentWarningsInDeclarationFiles &&
|
|
@@ -59,6 +59,13 @@ export function parseComment(tokens, file, context) {
|
|
|
59
59
|
}
|
|
60
60
|
context.logger.warn(message, token.pos, file);
|
|
61
61
|
}
|
|
62
|
+
function validationWarningImpl(message, token) {
|
|
63
|
+
if (context.config.suppressCommentWarningsInDeclarationFiles &&
|
|
64
|
+
hasDeclarationFileExtension(file.fileName)) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
context.logger.validationWarning(message, token.pos, file);
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* Intended for parsing markdown documents. This only parses code blocks and
|
|
@@ -95,13 +102,22 @@ export function parseCommentString(tokens, config, file, logger, files) {
|
|
|
95
102
|
case TokenSyntaxKind.Text:
|
|
96
103
|
case TokenSyntaxKind.Tag:
|
|
97
104
|
case TokenSyntaxKind.CloseBrace:
|
|
98
|
-
textContent(
|
|
105
|
+
textContent({
|
|
106
|
+
sourcePath: file.fileName,
|
|
107
|
+
token: next,
|
|
108
|
+
warning: (msg, token) => logger.warn(msg, token.pos, file),
|
|
109
|
+
validationWarning: (msg, token) => logger.validationWarning(msg, token.pos, file),
|
|
110
|
+
files,
|
|
111
|
+
atNewLine,
|
|
112
|
+
validationOptions: config.validationOptions,
|
|
113
|
+
},
|
|
114
|
+
/* out */ content, reentry);
|
|
99
115
|
break;
|
|
100
116
|
case TokenSyntaxKind.Code:
|
|
101
117
|
content.push({ kind: "code", text: next.text });
|
|
102
118
|
break;
|
|
103
119
|
case TokenSyntaxKind.OpenBrace:
|
|
104
|
-
inlineTag(lexer, content, suppressWarningsConfig,
|
|
120
|
+
inlineTag(lexer, content, suppressWarningsConfig, (message, token) => logger.warn(message, token.pos, file));
|
|
105
121
|
consume = false;
|
|
106
122
|
break;
|
|
107
123
|
default:
|
|
@@ -161,7 +177,7 @@ function makeCodeBlock(text) {
|
|
|
161
177
|
* Loop over comment, produce lint warnings, and set tag names for tags
|
|
162
178
|
* which have them.
|
|
163
179
|
*/
|
|
164
|
-
function postProcessComment(comment,
|
|
180
|
+
function postProcessComment(comment, getPosition, warning) {
|
|
165
181
|
for (const tag of comment.blockTags) {
|
|
166
182
|
if (HAS_USER_IDENTIFIER.includes(tag.tag) && tag.content.length) {
|
|
167
183
|
const first = tag.content[0];
|
|
@@ -211,7 +227,7 @@ function postProcessComment(comment, i18n, getPosition, warning) {
|
|
|
211
227
|
}
|
|
212
228
|
}
|
|
213
229
|
const aliasedTags = new Map([["@return", "@returns"]]);
|
|
214
|
-
function blockTag(comment, lexer, config,
|
|
230
|
+
function blockTag(comment, lexer, config, warning, validationWarning, files) {
|
|
215
231
|
const blockTag = lexer.take();
|
|
216
232
|
ok(blockTag.kind === TokenSyntaxKind.Tag, "blockTag called not at the start of a block tag."); // blockContent is broken if this fails.
|
|
217
233
|
if (!config.blockTags.has(blockTag.text)) {
|
|
@@ -220,29 +236,43 @@ function blockTag(comment, lexer, config, i18n, warning, files) {
|
|
|
220
236
|
const tagName = aliasedTags.get(blockTag.text) || blockTag.text;
|
|
221
237
|
let content;
|
|
222
238
|
if (tagName === "@example") {
|
|
223
|
-
return exampleBlock(comment, lexer, config,
|
|
239
|
+
return exampleBlock(comment, lexer, config, warning, validationWarning, files);
|
|
224
240
|
}
|
|
225
|
-
|
|
241
|
+
let typeAnnotation;
|
|
242
|
+
if (!lexer.done() &&
|
|
243
|
+
config.preservedTypeAnnotationTags.has(tagName)) {
|
|
244
|
+
if (lexer.peek().kind === TokenSyntaxKind.Text && /^\s+$/.test(lexer.peek().text)) {
|
|
245
|
+
lexer.take();
|
|
246
|
+
}
|
|
247
|
+
if (lexer.peek().kind === TokenSyntaxKind.TypeAnnotation) {
|
|
248
|
+
typeAnnotation = lexer.take().text;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (["@default", "@defaultValue"].includes(tagName) &&
|
|
226
252
|
config.jsDocCompatibility.defaultTag) {
|
|
227
|
-
content = defaultBlockContent(comment, lexer, config,
|
|
253
|
+
content = defaultBlockContent(comment, lexer, config, warning, validationWarning, files);
|
|
228
254
|
}
|
|
229
255
|
else {
|
|
230
|
-
content = blockContent(comment, lexer, config,
|
|
256
|
+
content = blockContent(comment, lexer, config, warning, validationWarning, files);
|
|
257
|
+
}
|
|
258
|
+
const tag = new CommentTag(tagName, content);
|
|
259
|
+
if (typeAnnotation) {
|
|
260
|
+
tag.typeAnnotation = typeAnnotation;
|
|
231
261
|
}
|
|
232
|
-
return
|
|
262
|
+
return tag;
|
|
233
263
|
}
|
|
234
264
|
/**
|
|
235
265
|
* The `@default` tag gets a special case because otherwise we will produce many warnings
|
|
236
266
|
* about unescaped/mismatched/missing braces in legacy JSDoc comments
|
|
237
267
|
*/
|
|
238
|
-
function defaultBlockContent(comment, lexer, config,
|
|
268
|
+
function defaultBlockContent(comment, lexer, config, warning, validationWarning, files) {
|
|
239
269
|
lexer.mark();
|
|
240
270
|
const tempRegistry = new FileRegistry();
|
|
241
|
-
const content = blockContent(comment, lexer, config,
|
|
271
|
+
const content = blockContent(comment, lexer, config, () => { }, () => { }, tempRegistry);
|
|
242
272
|
const end = lexer.done() || lexer.peek();
|
|
243
273
|
lexer.release();
|
|
244
274
|
if (content.some((part) => part.kind === "code" || part.kind === "inline-tag")) {
|
|
245
|
-
return blockContent(comment, lexer, config,
|
|
275
|
+
return blockContent(comment, lexer, config, warning, validationWarning, files);
|
|
246
276
|
}
|
|
247
277
|
const tokens = [];
|
|
248
278
|
while ((lexer.done() || lexer.peek()) !== end) {
|
|
@@ -265,10 +295,10 @@ function defaultBlockContent(comment, lexer, config, i18n, warning, files) {
|
|
|
265
295
|
*
|
|
266
296
|
* In TSDoc, we also want to treat the first line of the block as the example name.
|
|
267
297
|
*/
|
|
268
|
-
function exampleBlock(comment, lexer, config,
|
|
298
|
+
function exampleBlock(comment, lexer, config, warning, validationWarning, files) {
|
|
269
299
|
lexer.mark();
|
|
270
300
|
const tempRegistry = new FileRegistry();
|
|
271
|
-
const content = blockContent(comment, lexer, config,
|
|
301
|
+
const content = blockContent(comment, lexer, config, () => { }, () => { }, tempRegistry);
|
|
272
302
|
const end = lexer.done() || lexer.peek();
|
|
273
303
|
lexer.release();
|
|
274
304
|
if (!config.jsDocCompatibility.exampleTag ||
|
|
@@ -309,7 +339,7 @@ function exampleBlock(comment, lexer, config, i18n, warning, files) {
|
|
|
309
339
|
assertNever(next.kind);
|
|
310
340
|
}
|
|
311
341
|
}
|
|
312
|
-
const content = blockContent(comment, lexer, config,
|
|
342
|
+
const content = blockContent(comment, lexer, config, warning, validationWarning, files);
|
|
313
343
|
const tag = new CommentTag("@example", content);
|
|
314
344
|
if (exampleName.trim()) {
|
|
315
345
|
tag.name = exampleName.trim();
|
|
@@ -348,7 +378,7 @@ function exampleBlock(comment, lexer, config, i18n, warning, files) {
|
|
|
348
378
|
* If you change this, also look at parseCommentString as it
|
|
349
379
|
* likely needs similar modifications to ensure parsing is consistent.
|
|
350
380
|
*/
|
|
351
|
-
function blockContent(comment, lexer, config,
|
|
381
|
+
function blockContent(comment, lexer, config, warning, validationWarning, files) {
|
|
352
382
|
const content = [];
|
|
353
383
|
let atNewLine = true;
|
|
354
384
|
const reentry = new TextParserReentryState();
|
|
@@ -361,8 +391,16 @@ function blockContent(comment, lexer, config, i18n, warning, files) {
|
|
|
361
391
|
content.push({ kind: "text", text: next.text });
|
|
362
392
|
break;
|
|
363
393
|
case TokenSyntaxKind.Text:
|
|
364
|
-
textContent(
|
|
365
|
-
|
|
394
|
+
textContent({
|
|
395
|
+
sourcePath: comment.sourcePath,
|
|
396
|
+
token: next,
|
|
397
|
+
files,
|
|
398
|
+
atNewLine,
|
|
399
|
+
warning,
|
|
400
|
+
validationWarning,
|
|
401
|
+
validationOptions: config.validationOptions,
|
|
402
|
+
},
|
|
403
|
+
/*out*/ content, reentry);
|
|
366
404
|
break;
|
|
367
405
|
case TokenSyntaxKind.Code:
|
|
368
406
|
content.push({ kind: "code", text: next.text });
|
|
@@ -400,7 +438,7 @@ function blockContent(comment, lexer, config, i18n, warning, files) {
|
|
|
400
438
|
content.push({ kind: "text", text: next.text });
|
|
401
439
|
break;
|
|
402
440
|
case TokenSyntaxKind.OpenBrace:
|
|
403
|
-
inlineTag(lexer, content, config,
|
|
441
|
+
inlineTag(lexer, content, config, warning);
|
|
404
442
|
consume = false;
|
|
405
443
|
break;
|
|
406
444
|
default:
|
|
@@ -437,7 +475,7 @@ function blockContent(comment, lexer, config, i18n, warning, files) {
|
|
|
437
475
|
}
|
|
438
476
|
return content;
|
|
439
477
|
}
|
|
440
|
-
function inlineTag(lexer, block, config,
|
|
478
|
+
function inlineTag(lexer, block, config, warning) {
|
|
441
479
|
const openBrace = lexer.take();
|
|
442
480
|
// Now skip whitespace to grab the tag name.
|
|
443
481
|
// If the first non-whitespace text after the brace isn't a tag,
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parser to handle plain text markdown.
|
|
3
|
-
*
|
|
4
|
-
* Responsible for recognizing relative paths within the text and turning
|
|
5
|
-
* them into references.
|
|
6
|
-
* @module
|
|
7
|
-
*/
|
|
8
|
-
import type { TranslationProxy } from "../../internationalization/index.js";
|
|
9
1
|
import type { CommentDisplayPart } from "../../models/index.js";
|
|
10
2
|
import type { FileRegistry } from "../../models/FileRegistry.js";
|
|
3
|
+
import { type ValidationOptions } from "#node-utils";
|
|
11
4
|
import { type Token } from "./lexer.js";
|
|
12
5
|
import type { NormalizedPath, TranslatedString } from "#utils";
|
|
6
|
+
interface TextParserData {
|
|
7
|
+
sourcePath: NormalizedPath;
|
|
8
|
+
token: Token;
|
|
9
|
+
pos: number;
|
|
10
|
+
warning: (msg: TranslatedString, token: Token) => void;
|
|
11
|
+
validationWarning: (msg: TranslatedString, token: Token) => void;
|
|
12
|
+
files: FileRegistry;
|
|
13
|
+
atNewLine: boolean;
|
|
14
|
+
validationOptions: ValidationOptions;
|
|
15
|
+
}
|
|
13
16
|
/**
|
|
14
17
|
* This is incredibly unfortunate. The comment lexer owns the responsibility
|
|
15
18
|
* for splitting up text into text/code, this is totally fine for HTML links
|
|
@@ -26,4 +29,5 @@ export declare class TextParserReentryState {
|
|
|
26
29
|
* Look for relative links within a piece of text and add them to the {@link FileRegistry}
|
|
27
30
|
* so that they can be correctly resolved during rendering.
|
|
28
31
|
*/
|
|
29
|
-
export declare function textContent(
|
|
32
|
+
export declare function textContent(parserData: Omit<TextParserData, "pos">, outContent: CommentDisplayPart[], reentry: TextParserReentryState): void;
|
|
33
|
+
export {};
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parser to handle plain text markdown.
|
|
3
|
+
*
|
|
4
|
+
* Responsible for recognizing relative paths within the text and turning
|
|
5
|
+
* them into references.
|
|
6
|
+
* @module
|
|
7
|
+
*/
|
|
8
|
+
import { i18n } from "#utils";
|
|
1
9
|
import { HtmlAttributeParser, ParserState } from "#node-utils";
|
|
2
10
|
import { TokenSyntaxKind } from "./lexer.js";
|
|
3
11
|
import MarkdownIt from "markdown-it";
|
|
@@ -34,42 +42,38 @@ export class TextParserReentryState {
|
|
|
34
42
|
* Look for relative links within a piece of text and add them to the {@link FileRegistry}
|
|
35
43
|
* so that they can be correctly resolved during rendering.
|
|
36
44
|
*/
|
|
37
|
-
export function textContent(
|
|
45
|
+
export function textContent(parserData, outContent, reentry) {
|
|
38
46
|
let lastPartEnd = 0;
|
|
39
47
|
let canEndMarkdownLink = true;
|
|
40
48
|
const data = {
|
|
41
|
-
|
|
42
|
-
token,
|
|
49
|
+
...parserData,
|
|
43
50
|
pos: 0, // relative to the token
|
|
44
|
-
warning,
|
|
45
|
-
files: files,
|
|
46
|
-
atNewLine,
|
|
47
51
|
};
|
|
48
52
|
function addRef(ref) {
|
|
49
53
|
canEndMarkdownLink = true;
|
|
50
54
|
outContent.push({
|
|
51
55
|
kind: "text",
|
|
52
|
-
text: token.text.slice(lastPartEnd, ref.pos),
|
|
56
|
+
text: data.token.text.slice(lastPartEnd, ref.pos),
|
|
53
57
|
});
|
|
54
58
|
const link = {
|
|
55
59
|
kind: "relative-link",
|
|
56
|
-
text: token.text.slice(ref.pos, ref.end),
|
|
60
|
+
text: data.token.text.slice(ref.pos, ref.end),
|
|
57
61
|
target: ref.target,
|
|
58
62
|
targetAnchor: ref.targetAnchor,
|
|
59
63
|
};
|
|
60
64
|
outContent.push(link);
|
|
61
65
|
lastPartEnd = ref.end;
|
|
62
66
|
data.pos = ref.end;
|
|
63
|
-
if (!ref.target) {
|
|
64
|
-
|
|
67
|
+
if (!ref.target && data.validationOptions.invalidPath) {
|
|
68
|
+
data.validationWarning(i18n.relative_path_0_is_not_a_file_and_will_not_be_copied_to_output(data.token.text.slice(ref.pos, ref.end)), {
|
|
65
69
|
kind: TokenSyntaxKind.Text,
|
|
66
70
|
// ref.pos is relative to the token, but this pos is relative to the file.
|
|
67
|
-
pos: token.pos + ref.pos,
|
|
68
|
-
text: token.text.slice(ref.pos, ref.end),
|
|
71
|
+
pos: data.token.pos + ref.pos,
|
|
72
|
+
text: data.token.text.slice(ref.pos, ref.end),
|
|
69
73
|
});
|
|
70
74
|
}
|
|
71
75
|
}
|
|
72
|
-
while (data.pos < token.text.length) {
|
|
76
|
+
while (data.pos < data.token.text.length) {
|
|
73
77
|
if (canEndMarkdownLink) {
|
|
74
78
|
const link = checkMarkdownLink(data, reentry);
|
|
75
79
|
if (link) {
|
|
@@ -92,14 +96,14 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
|
|
|
92
96
|
}
|
|
93
97
|
continue;
|
|
94
98
|
}
|
|
95
|
-
const atNewLine = token.text[data.pos] === "\n";
|
|
99
|
+
const atNewLine = data.token.text[data.pos] === "\n";
|
|
96
100
|
data.atNewLine = atNewLine;
|
|
97
101
|
if (atNewLine && !reentry.withinLinkDest)
|
|
98
102
|
canEndMarkdownLink = true;
|
|
99
103
|
++data.pos;
|
|
100
104
|
}
|
|
101
|
-
if (lastPartEnd !== token.text.length) {
|
|
102
|
-
outContent.push({ kind: "text", text: token.text.slice(lastPartEnd) });
|
|
105
|
+
if (lastPartEnd !== data.token.text.length) {
|
|
106
|
+
outContent.push({ kind: "text", text: data.token.text.slice(lastPartEnd) });
|
|
103
107
|
}
|
|
104
108
|
}
|
|
105
109
|
/**
|
|
@@ -245,6 +249,7 @@ function checkTagLink(data) {
|
|
|
245
249
|
if (token.text.startsWith("<link ", pos)) {
|
|
246
250
|
data.pos += 4;
|
|
247
251
|
return checkAttributes(data, {
|
|
252
|
+
// cspell:words imagesrcset
|
|
248
253
|
imagesrcset: checkAttributeSrcSet,
|
|
249
254
|
});
|
|
250
255
|
}
|
|
@@ -609,10 +609,12 @@ let Converter = (() => {
|
|
|
609
609
|
blockTags: new Set(this.application.options.getValue("blockTags")),
|
|
610
610
|
inlineTags: new Set(this.application.options.getValue("inlineTags")),
|
|
611
611
|
modifierTags: new Set(this.application.options.getValue("modifierTags")),
|
|
612
|
+
preservedTypeAnnotationTags: new Set(this.application.options.getValue("preservedTypeAnnotationTags")),
|
|
612
613
|
jsDocCompatibility: this.application.options.getValue("jsDocCompatibility"),
|
|
613
614
|
suppressCommentWarningsInDeclarationFiles: this.application.options.getValue("suppressCommentWarningsInDeclarationFiles"),
|
|
614
615
|
useTsLinkResolution: this.application.options.getValue("useTsLinkResolution"),
|
|
615
616
|
commentStyle: this.application.options.getValue("commentStyle"),
|
|
617
|
+
validationOptions: this.application.options.getValue("validation"),
|
|
616
618
|
};
|
|
617
619
|
// Can't be included in options because the TSDoc parser blows up if we do.
|
|
618
620
|
// TypeDoc supports it as one, so it should always be included here.
|
|
@@ -113,7 +113,7 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
|
|
|
113
113
|
assert(!declaration ||
|
|
114
114
|
ts.isParameter(declaration) ||
|
|
115
115
|
ts.isJSDocParameterTag(declaration));
|
|
116
|
-
const paramRefl = new ParameterReflection(
|
|
116
|
+
const paramRefl = new ParameterReflection(/^__\d+$/.test(param.name) ? "__namedParameters" : param.name, ReflectionKind.Parameter, sigRef);
|
|
117
117
|
if (declaration && ts.isJSDocParameterTag(declaration)) {
|
|
118
118
|
paramRefl.comment = context.getJsDocComment(declaration);
|
|
119
119
|
}
|
|
@@ -132,7 +132,7 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
|
|
|
132
132
|
}
|
|
133
133
|
}
|
|
134
134
|
else {
|
|
135
|
-
type = param
|
|
135
|
+
type = context.checker.getTypeOfSymbol(param);
|
|
136
136
|
}
|
|
137
137
|
if (declaration &&
|
|
138
138
|
ts.isParameter(declaration) &&
|
|
@@ -160,8 +160,9 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
|
|
|
160
160
|
paramRefl.defaultValue = convertDefaultValue(parameterNodes?.[i + parameterNodeOffset]);
|
|
161
161
|
paramRefl.setFlag(ReflectionFlag.Optional, isOptional);
|
|
162
162
|
// If we have no declaration, then this is an implicitly defined parameter in JS land
|
|
163
|
-
// because the method body uses `arguments`... which is always a rest argument
|
|
164
|
-
|
|
163
|
+
// because the method body uses `arguments`... which is always a rest argument,
|
|
164
|
+
// unless it is a this parameter defined with @this in JSDoc.
|
|
165
|
+
let isRest = param.name !== "this";
|
|
165
166
|
if (declaration) {
|
|
166
167
|
isRest = ts.isParameter(declaration)
|
|
167
168
|
? !!declaration.dotDotDotToken
|
|
@@ -61,6 +61,7 @@ export declare class CommentPlugin extends ConverterComponent {
|
|
|
61
61
|
accessor cascadedModifierTags: TagString[];
|
|
62
62
|
accessor excludeInternal: boolean;
|
|
63
63
|
accessor excludePrivate: boolean;
|
|
64
|
+
accessor excludePrivateClassFields: boolean;
|
|
64
65
|
accessor excludeProtected: boolean;
|
|
65
66
|
accessor excludeNotDocumented: boolean;
|
|
66
67
|
accessor excludeCategories: string[];
|
|
@@ -44,9 +44,9 @@ import { CategoryPlugin } from "./CategoryPlugin.js";
|
|
|
44
44
|
* (for JS users) will be consumed by TypeScript and need not be preserved
|
|
45
45
|
* in the comment.
|
|
46
46
|
*
|
|
47
|
-
* Note that param/arg/argument/return/returns are not present.
|
|
47
|
+
* Note that param/arg/argument/return/returns/this are not present.
|
|
48
48
|
* These tags will have their type information stripped when parsing, but still
|
|
49
|
-
* provide useful information for documentation.
|
|
49
|
+
* may provide useful information for documentation.
|
|
50
50
|
*/
|
|
51
51
|
const NEVER_RENDERED = [
|
|
52
52
|
"@augments",
|
|
@@ -55,7 +55,6 @@ const NEVER_RENDERED = [
|
|
|
55
55
|
"@constructor",
|
|
56
56
|
"@enum",
|
|
57
57
|
"@extends",
|
|
58
|
-
"@this",
|
|
59
58
|
"@type",
|
|
60
59
|
"@typedef",
|
|
61
60
|
"@jsx",
|
|
@@ -140,6 +139,9 @@ let CommentPlugin = (() => {
|
|
|
140
139
|
let _excludePrivate_decorators;
|
|
141
140
|
let _excludePrivate_initializers = [];
|
|
142
141
|
let _excludePrivate_extraInitializers = [];
|
|
142
|
+
let _excludePrivateClassFields_decorators;
|
|
143
|
+
let _excludePrivateClassFields_initializers = [];
|
|
144
|
+
let _excludePrivateClassFields_extraInitializers = [];
|
|
143
145
|
let _excludeProtected_decorators;
|
|
144
146
|
let _excludeProtected_initializers = [];
|
|
145
147
|
let _excludeProtected_extraInitializers = [];
|
|
@@ -159,6 +161,7 @@ let CommentPlugin = (() => {
|
|
|
159
161
|
_cascadedModifierTags_decorators = [Option("cascadedModifierTags")];
|
|
160
162
|
_excludeInternal_decorators = [Option("excludeInternal")];
|
|
161
163
|
_excludePrivate_decorators = [Option("excludePrivate")];
|
|
164
|
+
_excludePrivateClassFields_decorators = [Option("excludePrivateClassFields")];
|
|
162
165
|
_excludeProtected_decorators = [Option("excludeProtected")];
|
|
163
166
|
_excludeNotDocumented_decorators = [Option("excludeNotDocumented")];
|
|
164
167
|
_excludeCategories_decorators = [Option("excludeCategories")];
|
|
@@ -167,6 +170,7 @@ let CommentPlugin = (() => {
|
|
|
167
170
|
__esDecorate(this, null, _cascadedModifierTags_decorators, { kind: "accessor", name: "cascadedModifierTags", static: false, private: false, access: { has: obj => "cascadedModifierTags" in obj, get: obj => obj.cascadedModifierTags, set: (obj, value) => { obj.cascadedModifierTags = value; } }, metadata: _metadata }, _cascadedModifierTags_initializers, _cascadedModifierTags_extraInitializers);
|
|
168
171
|
__esDecorate(this, null, _excludeInternal_decorators, { kind: "accessor", name: "excludeInternal", static: false, private: false, access: { has: obj => "excludeInternal" in obj, get: obj => obj.excludeInternal, set: (obj, value) => { obj.excludeInternal = value; } }, metadata: _metadata }, _excludeInternal_initializers, _excludeInternal_extraInitializers);
|
|
169
172
|
__esDecorate(this, null, _excludePrivate_decorators, { kind: "accessor", name: "excludePrivate", static: false, private: false, access: { has: obj => "excludePrivate" in obj, get: obj => obj.excludePrivate, set: (obj, value) => { obj.excludePrivate = value; } }, metadata: _metadata }, _excludePrivate_initializers, _excludePrivate_extraInitializers);
|
|
173
|
+
__esDecorate(this, null, _excludePrivateClassFields_decorators, { kind: "accessor", name: "excludePrivateClassFields", static: false, private: false, access: { has: obj => "excludePrivateClassFields" in obj, get: obj => obj.excludePrivateClassFields, set: (obj, value) => { obj.excludePrivateClassFields = value; } }, metadata: _metadata }, _excludePrivateClassFields_initializers, _excludePrivateClassFields_extraInitializers);
|
|
170
174
|
__esDecorate(this, null, _excludeProtected_decorators, { kind: "accessor", name: "excludeProtected", static: false, private: false, access: { has: obj => "excludeProtected" in obj, get: obj => obj.excludeProtected, set: (obj, value) => { obj.excludeProtected = value; } }, metadata: _metadata }, _excludeProtected_initializers, _excludeProtected_extraInitializers);
|
|
171
175
|
__esDecorate(this, null, _excludeNotDocumented_decorators, { kind: "accessor", name: "excludeNotDocumented", static: false, private: false, access: { has: obj => "excludeNotDocumented" in obj, get: obj => obj.excludeNotDocumented, set: (obj, value) => { obj.excludeNotDocumented = value; } }, metadata: _metadata }, _excludeNotDocumented_initializers, _excludeNotDocumented_extraInitializers);
|
|
172
176
|
__esDecorate(this, null, _excludeCategories_decorators, { kind: "accessor", name: "excludeCategories", static: false, private: false, access: { has: obj => "excludeCategories" in obj, get: obj => obj.excludeCategories, set: (obj, value) => { obj.excludeCategories = value; } }, metadata: _metadata }, _excludeCategories_initializers, _excludeCategories_extraInitializers);
|
|
@@ -185,7 +189,10 @@ let CommentPlugin = (() => {
|
|
|
185
189
|
#excludePrivate_accessor_storage = (__runInitializers(this, _excludeInternal_extraInitializers), __runInitializers(this, _excludePrivate_initializers, void 0));
|
|
186
190
|
get excludePrivate() { return this.#excludePrivate_accessor_storage; }
|
|
187
191
|
set excludePrivate(value) { this.#excludePrivate_accessor_storage = value; }
|
|
188
|
-
#
|
|
192
|
+
#excludePrivateClassFields_accessor_storage = (__runInitializers(this, _excludePrivate_extraInitializers), __runInitializers(this, _excludePrivateClassFields_initializers, void 0));
|
|
193
|
+
get excludePrivateClassFields() { return this.#excludePrivateClassFields_accessor_storage; }
|
|
194
|
+
set excludePrivateClassFields(value) { this.#excludePrivateClassFields_accessor_storage = value; }
|
|
195
|
+
#excludeProtected_accessor_storage = (__runInitializers(this, _excludePrivateClassFields_extraInitializers), __runInitializers(this, _excludeProtected_initializers, void 0));
|
|
189
196
|
get excludeProtected() { return this.#excludeProtected_accessor_storage; }
|
|
190
197
|
set excludeProtected(value) { this.#excludeProtected_accessor_storage = value; }
|
|
191
198
|
#excludeNotDocumented_accessor_storage = (__runInitializers(this, _excludeProtected_extraInitializers), __runInitializers(this, _excludeNotDocumented_initializers, void 0));
|
|
@@ -283,6 +290,8 @@ let CommentPlugin = (() => {
|
|
|
283
290
|
* @param reflection The reflection that is currently processed.
|
|
284
291
|
*/
|
|
285
292
|
onCreateTypeParameter(_context, reflection) {
|
|
293
|
+
if (reflection.comment)
|
|
294
|
+
return;
|
|
286
295
|
const comment = reflection.parent?.comment;
|
|
287
296
|
if (comment) {
|
|
288
297
|
let tag = comment.getIdentifiedTag(reflection.name, "@typeParam");
|
|
@@ -299,6 +308,17 @@ let CommentPlugin = (() => {
|
|
|
299
308
|
reflection.comment = new Comment(tag.content);
|
|
300
309
|
reflection.comment.sourcePath = comment.sourcePath;
|
|
301
310
|
removeIfPresent(comment.blockTags, tag);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
// #3031 if this is a class constructor, also check for type parameters
|
|
315
|
+
// that live on the class itself and potentially copy their comment.
|
|
316
|
+
if (reflection.parent?.kindOf(ReflectionKind.ConstructorSignature) &&
|
|
317
|
+
reflection.parent.parent?.kindOf(ReflectionKind.Constructor)) {
|
|
318
|
+
const cls = reflection.parent.parent.parent;
|
|
319
|
+
const typeParam = cls.typeParameters?.find(param => param.name === reflection.name);
|
|
320
|
+
if (typeParam?.comment) {
|
|
321
|
+
reflection.comment = typeParam.comment.clone();
|
|
302
322
|
}
|
|
303
323
|
}
|
|
304
324
|
}
|
|
@@ -447,19 +467,25 @@ let CommentPlugin = (() => {
|
|
|
447
467
|
moveSignatureParamComments(signature, comment = signature.comment) {
|
|
448
468
|
if (!comment)
|
|
449
469
|
return;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
470
|
+
const unusedCommentParams = comment.blockTags.filter((tag) => tag.tag === "@param" && tag.name && !tag.name.includes(".") &&
|
|
471
|
+
!signature.parameters?.some(p => p.name === tag.name));
|
|
472
|
+
signature.parameters?.forEach((parameter) => {
|
|
473
|
+
if (parameter.name === "__namedParameters" && unusedCommentParams.length) {
|
|
474
|
+
parameter.name = unusedCommentParams[0].name;
|
|
475
|
+
unusedCommentParams.splice(0, 1);
|
|
457
476
|
}
|
|
458
477
|
const tag = comment.getIdentifiedTag(parameter.name, "@param");
|
|
459
478
|
if (tag) {
|
|
460
479
|
parameter.comment = new Comment(Comment.cloneDisplayParts(tag.content));
|
|
461
480
|
parameter.comment.sourcePath = comment.sourcePath;
|
|
462
481
|
}
|
|
482
|
+
else if (parameter.name === "this") {
|
|
483
|
+
const thisTag = comment.getTag("@this");
|
|
484
|
+
if (thisTag) {
|
|
485
|
+
parameter.comment = new Comment(Comment.cloneDisplayParts(thisTag.content));
|
|
486
|
+
parameter.comment.sourcePath = comment.sourcePath;
|
|
487
|
+
}
|
|
488
|
+
}
|
|
463
489
|
});
|
|
464
490
|
for (const parameter of signature.typeParameters || []) {
|
|
465
491
|
const tag = comment.getIdentifiedTag(parameter.name, "@typeParam") ||
|
|
@@ -471,6 +497,7 @@ let CommentPlugin = (() => {
|
|
|
471
497
|
}
|
|
472
498
|
}
|
|
473
499
|
this.validateParamTags(signature, comment, signature.parameters || []);
|
|
500
|
+
comment.removeTags("@this");
|
|
474
501
|
comment.removeTags("@param");
|
|
475
502
|
comment.removeTags("@typeParam");
|
|
476
503
|
comment.removeTags("@template");
|
|
@@ -513,6 +540,16 @@ let CommentPlugin = (() => {
|
|
|
513
540
|
this.excludePrivate) {
|
|
514
541
|
return true;
|
|
515
542
|
}
|
|
543
|
+
// #3017 this isn't quite right as it may incorrectly detect
|
|
544
|
+
// private members named with a hash which aren't actually private
|
|
545
|
+
// class fields (e.g. class Foo { "#hash" = 1 })
|
|
546
|
+
// We can't fix this without storing more information about the name,
|
|
547
|
+
// which I'm going to put off until #3015 is done.
|
|
548
|
+
if (reflection.flags.hasFlag(ReflectionFlag.Private) &&
|
|
549
|
+
reflection.name.startsWith("#") &&
|
|
550
|
+
this.excludePrivateClassFields) {
|
|
551
|
+
return true;
|
|
552
|
+
}
|
|
516
553
|
if (reflection.flags.hasFlag(ReflectionFlag.Protected) &&
|
|
517
554
|
this.excludeProtected) {
|
|
518
555
|
return true;
|
|
@@ -377,6 +377,14 @@ function convertClassOrInterface(context, symbol, exportSymbol) {
|
|
|
377
377
|
reflection.implementedTypes = implementedTypes;
|
|
378
378
|
}
|
|
379
379
|
context.finalizeDeclarationReflection(reflection);
|
|
380
|
+
// Convert type parameters early so that we get access them when converting the constructors if any
|
|
381
|
+
if (instanceType.typeParameters) {
|
|
382
|
+
reflection.typeParameters = instanceType.typeParameters.map((param) => {
|
|
383
|
+
const declaration = param.symbol.declarations?.[0];
|
|
384
|
+
assert(declaration && ts.isTypeParameterDeclaration(declaration));
|
|
385
|
+
return createTypeParamReflection(declaration, reflectionContext);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
380
388
|
if (classDeclaration && reflection.kind === ReflectionKind.Class) {
|
|
381
389
|
// Classes can have static props
|
|
382
390
|
const staticType = context.checker.getTypeOfSymbolAtLocation(symbol, classDeclaration);
|
|
@@ -404,14 +412,6 @@ function convertClassOrInterface(context, symbol, exportSymbol) {
|
|
|
404
412
|
}
|
|
405
413
|
// Classes/interfaces usually just have properties...
|
|
406
414
|
convertSymbols(reflectionContext, context.checker.getPropertiesOfType(instanceType));
|
|
407
|
-
// And type arguments
|
|
408
|
-
if (instanceType.typeParameters) {
|
|
409
|
-
reflection.typeParameters = instanceType.typeParameters.map((param) => {
|
|
410
|
-
const declaration = param.symbol.declarations?.[0];
|
|
411
|
-
assert(declaration && ts.isTypeParameterDeclaration(declaration));
|
|
412
|
-
return createTypeParamReflection(declaration, reflectionContext);
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
415
|
// Interfaces might also have call signatures
|
|
416
416
|
// Classes might too, because of declaration merging
|
|
417
417
|
context.checker
|
|
@@ -754,6 +754,13 @@ function convertAccessor(context, symbol, exportSymbol) {
|
|
|
754
754
|
const declaration = symbol.getDeclarations()?.[0];
|
|
755
755
|
if (declaration) {
|
|
756
756
|
setModifiers(symbol, declaration, reflection);
|
|
757
|
+
// #3019, auto accessors `accessor x: string` get the symbol flag for
|
|
758
|
+
// an accessor, but they don't have get/set accessors, so the need a type
|
|
759
|
+
// set on the accessor reflection structure.
|
|
760
|
+
if (ts.isPropertyDeclaration(declaration) &&
|
|
761
|
+
declaration.modifiers?.some(n => n.kind === ts.SyntaxKind.AccessorKeyword)) {
|
|
762
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), context.checker.getTypeOfSymbol(symbol), declaration.type);
|
|
763
|
+
}
|
|
757
764
|
}
|
|
758
765
|
context.finalizeDeclarationReflection(reflection);
|
|
759
766
|
const getDeclaration = symbol.getDeclarations()?.find(ts.isGetAccessor);
|
|
@@ -696,7 +696,7 @@ const unionConverter = {
|
|
|
696
696
|
convertType(context, type) {
|
|
697
697
|
const types = type.types.map((type) => convertType(context, type));
|
|
698
698
|
normalizeUnion(types);
|
|
699
|
-
|
|
699
|
+
sortUnion(types);
|
|
700
700
|
return new UnionType(types);
|
|
701
701
|
},
|
|
702
702
|
};
|
|
@@ -764,14 +764,26 @@ function kindToModifier(kind) {
|
|
|
764
764
|
return undefined;
|
|
765
765
|
}
|
|
766
766
|
}
|
|
767
|
-
function
|
|
768
|
-
|
|
767
|
+
function sortUnion(types) {
|
|
768
|
+
// If every member of the union is a literal numeric type, sort in ascending order
|
|
769
|
+
if (types.every(t => t.type === "literal" && typeof t.value === "number")) {
|
|
770
|
+
types.sort((a, b) => {
|
|
771
|
+
const aLit = a;
|
|
772
|
+
const bLit = b;
|
|
773
|
+
return aLit.value - bLit.value;
|
|
774
|
+
});
|
|
769
775
|
return;
|
|
770
776
|
}
|
|
777
|
+
// #3024 Otherwise, leave the union in the converted order with the exception of null
|
|
778
|
+
// and undefined, which should be sorted last, with null before undefined.
|
|
771
779
|
types.sort((a, b) => {
|
|
772
|
-
const
|
|
773
|
-
const
|
|
774
|
-
|
|
780
|
+
const aIsNull = a.type === "literal" && a.value === null;
|
|
781
|
+
const aIsUndef = a.type === "intrinsic" && a.name === "undefined";
|
|
782
|
+
const bIsNull = b.type === "literal" && b.value === null;
|
|
783
|
+
const bIsUndef = b.type === "intrinsic" && b.name === "undefined";
|
|
784
|
+
const aWeight = aIsNull ? 1 : aIsUndef ? 2 : 0;
|
|
785
|
+
const bWeight = bIsNull ? 1 : bIsUndef ? 2 : 0;
|
|
786
|
+
return aWeight - bWeight;
|
|
775
787
|
});
|
|
776
788
|
}
|
|
777
789
|
function normalizeUnion(types) {
|
|
@@ -139,6 +139,9 @@ let GitRepository = (() => {
|
|
|
139
139
|
* @returns A new instance of {@link GitRepository} or undefined.
|
|
140
140
|
*/
|
|
141
141
|
static tryCreateRepository(path, sourceLinkTemplate, gitRevision, gitRemote, logger) {
|
|
142
|
+
if (gitRevision === "{branch}") {
|
|
143
|
+
gitRevision = git("-C", path, "branch", "--show-current").stdout.trim();
|
|
144
|
+
}
|
|
142
145
|
gitRevision ||= git("-C", path, "rev-parse", "HEAD").stdout.trim();
|
|
143
146
|
if (gitRevision == "HEAD")
|
|
144
147
|
return; // Will only happen in a repo with no commits.
|
|
@@ -165,7 +165,6 @@ module.exports = localeUtils.buildIncompleteTranslation({
|
|
|
165
165
|
help_excludeNotDocumentedKinds: "Arten von Reflections, die von excludeNotDocumented entfernt werden können",
|
|
166
166
|
help_excludeInternal: "Verhindert, dass Symbole in der Dokumentation erscheinen, die mit @internal markiert sind",
|
|
167
167
|
help_excludeCategories: "Schließt Symbole aus dieser Kategorie von der Dokumentation aus",
|
|
168
|
-
help_excludePrivate: "Ignoriert private Variablen und Methoden, Standardwert ist true.",
|
|
169
168
|
help_excludeProtected: "Ignoriert geschützte Variablen und Methoden",
|
|
170
169
|
help_excludeReferences: "Wird ein Symbol mehrfach exportiert, ignoriere alle außer dem ersten Export",
|
|
171
170
|
help_externalSymbolLinkMappings: "Definiert eigene Links für Symbole, die nicht in der Dokumentation enthalten sind",
|