typedoc 0.28.5 → 0.28.6
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/converter/comments/textParser.d.ts +1 -0
- package/dist/lib/converter/comments/textParser.js +76 -34
- package/dist/lib/converter/context.js +14 -3
- package/dist/lib/converter/converter.js +3 -0
- package/dist/lib/converter/plugins/PackagePlugin.js +5 -1
- package/dist/lib/converter/symbols.js +37 -2
- package/dist/lib/internationalization/locales/de.cjs +1 -1
- package/dist/lib/internationalization/locales/de.d.cts +1 -1
- package/dist/lib/internationalization/locales/en.cjs +2 -1
- package/dist/lib/internationalization/locales/en.d.cts +2 -1
- package/dist/lib/internationalization/locales/ja.cjs +1 -1
- package/dist/lib/internationalization/locales/zh.cjs +1 -1
- package/dist/lib/internationalization/locales/zh.d.cts +1 -1
- package/dist/lib/models/Comment.d.ts +2 -1
- package/dist/lib/models/DocumentReflection.js +1 -1
- package/dist/lib/models/FileRegistry.d.ts +20 -8
- package/dist/lib/models/FileRegistry.js +19 -6
- package/dist/lib/models/ProjectReflection.js +1 -1
- package/dist/lib/models/Reflection.d.ts +4 -0
- package/dist/lib/models/types.d.ts +2 -2
- package/dist/lib/models/types.js +16 -14
- package/dist/lib/output/plugins/AssetsPlugin.js +7 -2
- package/dist/lib/output/themes/MarkedPlugin.js +2 -2
- package/dist/lib/serialization/deserializer.d.ts +3 -3
- package/dist/lib/serialization/schema.d.ts +10 -8
- package/dist/lib/utils/ValidatingFileRegistry.d.ts +2 -2
- package/dist/lib/utils/ValidatingFileRegistry.js +7 -4
- package/dist/lib/validation/links.js +23 -25
- package/package.json +1 -1
|
@@ -10,17 +10,20 @@ const MdHelpers = new MarkdownIt().helpers;
|
|
|
10
10
|
*/
|
|
11
11
|
export class TextParserReentryState {
|
|
12
12
|
withinLinkLabel = false;
|
|
13
|
+
withinLinkDest = false;
|
|
13
14
|
lastPartWasNewline = false;
|
|
14
15
|
checkState(token) {
|
|
15
16
|
switch (token.kind) {
|
|
16
17
|
case TokenSyntaxKind.Code:
|
|
17
18
|
if (/\n\s*\n/.test(token.text)) {
|
|
18
19
|
this.withinLinkLabel = false;
|
|
20
|
+
this.withinLinkDest = false;
|
|
19
21
|
}
|
|
20
22
|
break;
|
|
21
23
|
case TokenSyntaxKind.NewLine:
|
|
22
24
|
if (this.lastPartWasNewline) {
|
|
23
25
|
this.withinLinkLabel = false;
|
|
26
|
+
this.withinLinkDest = false;
|
|
24
27
|
}
|
|
25
28
|
break;
|
|
26
29
|
}
|
|
@@ -33,16 +36,17 @@ export class TextParserReentryState {
|
|
|
33
36
|
*/
|
|
34
37
|
export function textContent(sourcePath, token, i18n, warning, outContent, files, atNewLine, reentry) {
|
|
35
38
|
let lastPartEnd = 0;
|
|
39
|
+
let canEndMarkdownLink = true;
|
|
36
40
|
const data = {
|
|
37
41
|
sourcePath,
|
|
38
42
|
token,
|
|
39
43
|
pos: 0, // relative to the token
|
|
40
|
-
i18n,
|
|
41
44
|
warning,
|
|
42
45
|
files: files,
|
|
43
46
|
atNewLine,
|
|
44
47
|
};
|
|
45
48
|
function addRef(ref) {
|
|
49
|
+
canEndMarkdownLink = true;
|
|
46
50
|
outContent.push({
|
|
47
51
|
kind: "text",
|
|
48
52
|
text: token.text.slice(lastPartEnd, ref.pos),
|
|
@@ -66,10 +70,15 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
|
|
|
66
70
|
}
|
|
67
71
|
}
|
|
68
72
|
while (data.pos < token.text.length) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
+
if (canEndMarkdownLink) {
|
|
74
|
+
const link = checkMarkdownLink(data, reentry);
|
|
75
|
+
if (link) {
|
|
76
|
+
addRef(link);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
// If we're within a Markdown link, then `checkMarkdownLink`
|
|
80
|
+
// already scanned `token` up to a line feed (if any).
|
|
81
|
+
canEndMarkdownLink = !reentry.withinLinkLabel && !reentry.withinLinkDest;
|
|
73
82
|
}
|
|
74
83
|
const reference = checkReference(data);
|
|
75
84
|
if (reference) {
|
|
@@ -81,7 +90,10 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
|
|
|
81
90
|
addRef(tagLink);
|
|
82
91
|
continue;
|
|
83
92
|
}
|
|
84
|
-
|
|
93
|
+
const atNewLine = token.text[data.pos] === "\n";
|
|
94
|
+
data.atNewLine = atNewLine;
|
|
95
|
+
if (atNewLine && !reentry.withinLinkDest)
|
|
96
|
+
canEndMarkdownLink = true;
|
|
85
97
|
++data.pos;
|
|
86
98
|
}
|
|
87
99
|
if (lastPartEnd !== token.text.length) {
|
|
@@ -101,9 +113,8 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
|
|
|
101
113
|
function checkMarkdownLink(data, reentry) {
|
|
102
114
|
const { token, sourcePath, files } = data;
|
|
103
115
|
let searchStart;
|
|
104
|
-
if (reentry.withinLinkLabel) {
|
|
116
|
+
if (reentry.withinLinkLabel || reentry.withinLinkDest) {
|
|
105
117
|
searchStart = data.pos;
|
|
106
|
-
reentry.withinLinkLabel = false;
|
|
107
118
|
}
|
|
108
119
|
else if (token.text[data.pos] === "[") {
|
|
109
120
|
searchStart = data.pos + 1;
|
|
@@ -111,34 +122,60 @@ function checkMarkdownLink(data, reentry) {
|
|
|
111
122
|
else {
|
|
112
123
|
return;
|
|
113
124
|
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
125
|
+
if (!reentry.withinLinkDest) {
|
|
126
|
+
const labelEnd = findLabelEnd(token.text, searchStart);
|
|
127
|
+
if (labelEnd === -1 || token.text[labelEnd] === "\n") {
|
|
128
|
+
// This markdown link might be split across multiple lines or input tokens
|
|
129
|
+
// [prefix `code` suffix](target)
|
|
130
|
+
// ........^^^^^^................
|
|
131
|
+
// Unless we encounter two consecutive line feeds, expect it to keep going.
|
|
132
|
+
reentry.withinLinkLabel = labelEnd !== data.pos || !data.atNewLine;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
reentry.withinLinkLabel = false;
|
|
136
|
+
if (!token.text.startsWith("](", labelEnd))
|
|
137
|
+
return;
|
|
138
|
+
searchStart = labelEnd + 2;
|
|
123
139
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
140
|
+
// Skip whitespace (including line breaks) between "](" and the link destination.
|
|
141
|
+
// https://spec.commonmark.org/0.31.2/#links
|
|
142
|
+
const end = token.text.length;
|
|
143
|
+
let lookahead = searchStart;
|
|
144
|
+
for (let newlines = 0;; ++lookahead) {
|
|
145
|
+
if (lookahead === end) {
|
|
146
|
+
reentry.withinLinkDest = true;
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
switch (token.text[lookahead]) {
|
|
150
|
+
case "\n":
|
|
151
|
+
if (++newlines === 2) {
|
|
152
|
+
reentry.withinLinkDest = false;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
continue;
|
|
156
|
+
case " ":
|
|
157
|
+
case "\t":
|
|
158
|
+
continue;
|
|
141
159
|
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
reentry.withinLinkDest = false;
|
|
163
|
+
const link = MdHelpers.parseLinkDestination(token.text, lookahead, end);
|
|
164
|
+
if (link.ok) {
|
|
165
|
+
// Only make a relative-link display part if it's actually a relative link.
|
|
166
|
+
// Discard protocol:// links, unix style absolute paths, and windows style absolute paths.
|
|
167
|
+
if (isRelativePath(link.str)) {
|
|
168
|
+
const { target, anchor } = files.register(sourcePath, link.str) || { target: undefined, anchor: undefined };
|
|
169
|
+
return {
|
|
170
|
+
pos: lookahead,
|
|
171
|
+
end: link.pos,
|
|
172
|
+
target,
|
|
173
|
+
targetAnchor: anchor,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
// This was a link, skip ahead to ensure we don't happen to parse
|
|
177
|
+
// something else as a link within the link.
|
|
178
|
+
data.pos = link.pos - 1;
|
|
142
179
|
}
|
|
143
180
|
}
|
|
144
181
|
/**
|
|
@@ -230,6 +267,11 @@ function isRelativePath(link) {
|
|
|
230
267
|
function findLabelEnd(text, pos) {
|
|
231
268
|
while (pos < text.length) {
|
|
232
269
|
switch (text[pos]) {
|
|
270
|
+
case "\\":
|
|
271
|
+
++pos;
|
|
272
|
+
if (pos < text.length && text[pos] === "\n")
|
|
273
|
+
return pos;
|
|
274
|
+
break;
|
|
233
275
|
case "\n":
|
|
234
276
|
case "]":
|
|
235
277
|
case "[":
|
|
@@ -130,14 +130,25 @@ export class Context {
|
|
|
130
130
|
return reflection;
|
|
131
131
|
}
|
|
132
132
|
postReflectionCreation(reflection, symbol, exportSymbol) {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
133
|
+
// Allow comments on export declarations to take priority over comments directly
|
|
134
|
+
// on the symbol to enable overriding comments on modules/references, #1504
|
|
135
|
+
if (!reflection.comment &&
|
|
136
|
+
exportSymbol &&
|
|
137
|
+
(reflection.kind &
|
|
138
|
+
(ReflectionKind.SomeModule | ReflectionKind.Reference))) {
|
|
136
139
|
reflection.comment = this.getComment(exportSymbol, reflection.kind);
|
|
137
140
|
}
|
|
141
|
+
// If that didn't get us a comment (the normal case), then get the comment from
|
|
142
|
+
// the source declarations, this is the common case.
|
|
138
143
|
if (symbol && !reflection.comment) {
|
|
139
144
|
reflection.comment = this.getComment(symbol, reflection.kind);
|
|
140
145
|
}
|
|
146
|
+
// If we still don't have a comment, check for any comments on the export declaration,
|
|
147
|
+
// we don't have to worry about functions being weird in this case as the regular declaration
|
|
148
|
+
// doesn't have any comment.
|
|
149
|
+
if (exportSymbol && !reflection.comment) {
|
|
150
|
+
reflection.comment = this.getComment(exportSymbol, ReflectionKind.Reference);
|
|
151
|
+
}
|
|
141
152
|
if (this.shouldBeStatic) {
|
|
142
153
|
reflection.setFlag(ReflectionFlag.Static);
|
|
143
154
|
}
|
|
@@ -305,6 +305,9 @@ let Converter = (() => {
|
|
|
305
305
|
const programs = unique(entryPoints.map((e) => e.program));
|
|
306
306
|
this.externalPatternCache = void 0;
|
|
307
307
|
const project = new ProjectReflection(this.application.options.getValue("name"), this.application.files);
|
|
308
|
+
if (this.owner.options.packageDir) {
|
|
309
|
+
project.files.registerReflectionPath(normalizePath(this.owner.options.packageDir), project);
|
|
310
|
+
}
|
|
308
311
|
const context = new Context(this, programs, project);
|
|
309
312
|
this.trigger(Converter.EVENT_BEGIN, context);
|
|
310
313
|
this.addProjectDocuments(project);
|
|
@@ -36,7 +36,7 @@ import * as Path from "path";
|
|
|
36
36
|
import { ConverterComponent } from "../components.js";
|
|
37
37
|
import { ApplicationEvents } from "../../application-events.js";
|
|
38
38
|
import { ConverterEvents } from "../converter-events.js";
|
|
39
|
-
import { i18n, MinimalSourceFile } from "#utils";
|
|
39
|
+
import { i18n, MinimalSourceFile, NormalizedPathUtils } from "#utils";
|
|
40
40
|
import { discoverPackageJson, getCommonDirectory, nicePath, normalizePath, Option, readFile, } from "#node-utils";
|
|
41
41
|
import { existsSync } from "fs";
|
|
42
42
|
/**
|
|
@@ -161,6 +161,10 @@ let PackagePlugin = (() => {
|
|
|
161
161
|
if (this.readmeFile && this.readmeContents) {
|
|
162
162
|
const { content } = this.application.converter.parseRawComment(new MinimalSourceFile(this.readmeContents, this.readmeFile), project.files);
|
|
163
163
|
project.readme = content;
|
|
164
|
+
project.files.registerReflectionPath(this.readmeFile, project);
|
|
165
|
+
// In packages mode, this probably won't do anything unless someone uses the readme
|
|
166
|
+
// option to select a different file.
|
|
167
|
+
project.files.registerReflectionPath(NormalizedPathUtils.dirname(this.readmeFile), project);
|
|
164
168
|
// This isn't ideal, but seems better than figuring out the readme
|
|
165
169
|
// path over in the include plugin...
|
|
166
170
|
this.owner.includePlugin.checkIncludeTagsParts(project, Path.dirname(this.readmeFile), content);
|
|
@@ -238,6 +238,25 @@ function convertTypeAlias(context, symbol, exportSymbol) {
|
|
|
238
238
|
convertJsDocCallback(context, symbol, declaration, exportSymbol);
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
+
function convertTypeAliasFromValueDeclaration(context, symbol, exportSymbol, valueKind) {
|
|
242
|
+
const comment = context.getComment(symbol, valueKind);
|
|
243
|
+
const reflection = new DeclarationReflection(exportSymbol?.name || symbol.name, ReflectionKind.TypeAlias, context.scope);
|
|
244
|
+
reflection.comment = comment;
|
|
245
|
+
context.postReflectionCreation(reflection, symbol, exportSymbol);
|
|
246
|
+
context.finalizeDeclarationReflection(reflection);
|
|
247
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), context.checker.getTypeOfSymbol(symbol));
|
|
248
|
+
if (reflection.type.type === "reflection" && reflection.type.declaration.children) {
|
|
249
|
+
// #2817 lift properties of object literal types up to the reflection level.
|
|
250
|
+
const typeDecl = reflection.type.declaration;
|
|
251
|
+
reflection.project.mergeReflections(typeDecl, reflection);
|
|
252
|
+
delete reflection.type;
|
|
253
|
+
// When created any signatures will be created with __type as their
|
|
254
|
+
// name, rename them so that they have the alias's name as their name
|
|
255
|
+
for (const sig of reflection.signatures || []) {
|
|
256
|
+
sig.name = reflection.name;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
241
260
|
function attachUnionComments(context, declaration, union) {
|
|
242
261
|
const list = declaration.type.getChildAt(0);
|
|
243
262
|
if (list.kind !== ts.SyntaxKind.SyntaxList)
|
|
@@ -285,6 +304,9 @@ function convertTypeAliasAsInterface(context, symbol, exportSymbol, declaration)
|
|
|
285
304
|
convertIndexSignatures(rc, type);
|
|
286
305
|
}
|
|
287
306
|
function convertFunctionOrMethod(context, symbol, exportSymbol) {
|
|
307
|
+
if (isTypeOnlyExport(exportSymbol)) {
|
|
308
|
+
return convertTypeAliasFromValueDeclaration(context, symbol, exportSymbol, ReflectionKind.Function);
|
|
309
|
+
}
|
|
288
310
|
// Can't just check method flag because this might be called for properties as well
|
|
289
311
|
// This will *NOT* be called for variables that look like functions, they need a special case.
|
|
290
312
|
const isMethod = !!(symbol.flags &
|
|
@@ -330,7 +352,7 @@ function convertFunctionOrMethod(context, symbol, exportSymbol) {
|
|
|
330
352
|
// getDeclaredTypeOfSymbol gets the INSTANCE type
|
|
331
353
|
// getTypeOfSymbolAtLocation gets the STATIC type
|
|
332
354
|
function convertClassOrInterface(context, symbol, exportSymbol) {
|
|
333
|
-
const reflection = context.createDeclarationReflection(ts.SymbolFlags.Class & symbol.flags
|
|
355
|
+
const reflection = context.createDeclarationReflection((ts.SymbolFlags.Class & symbol.flags) && !isTypeOnlyExport(exportSymbol)
|
|
334
356
|
? ReflectionKind.Class
|
|
335
357
|
: ReflectionKind.Interface, symbol, exportSymbol, void 0);
|
|
336
358
|
const classDeclaration = symbol
|
|
@@ -355,7 +377,7 @@ function convertClassOrInterface(context, symbol, exportSymbol) {
|
|
|
355
377
|
reflection.implementedTypes = implementedTypes;
|
|
356
378
|
}
|
|
357
379
|
context.finalizeDeclarationReflection(reflection);
|
|
358
|
-
if (classDeclaration) {
|
|
380
|
+
if (classDeclaration && reflection.kind === ReflectionKind.Class) {
|
|
359
381
|
// Classes can have static props
|
|
360
382
|
const staticType = context.checker.getTypeOfSymbolAtLocation(symbol, classDeclaration);
|
|
361
383
|
reflectionContext.shouldBeStatic = true;
|
|
@@ -548,6 +570,9 @@ function createAlias(target, context, symbol, exportSymbol) {
|
|
|
548
570
|
context.finalizeDeclarationReflection(ref);
|
|
549
571
|
}
|
|
550
572
|
function convertVariable(context, symbol, exportSymbol) {
|
|
573
|
+
if (isTypeOnlyExport(exportSymbol)) {
|
|
574
|
+
return convertTypeAliasFromValueDeclaration(context, symbol, exportSymbol, ReflectionKind.Variable);
|
|
575
|
+
}
|
|
551
576
|
const declaration = symbol.getDeclarations()?.[0];
|
|
552
577
|
const comment = context.getComment(symbol, ReflectionKind.Variable);
|
|
553
578
|
const type = declaration
|
|
@@ -826,3 +851,13 @@ function isFunctionLikeInitializer(node) {
|
|
|
826
851
|
}
|
|
827
852
|
return false;
|
|
828
853
|
}
|
|
854
|
+
function isTypeOnlyExport(symbol) {
|
|
855
|
+
if (!symbol)
|
|
856
|
+
return false;
|
|
857
|
+
const declaration = symbol.declarations?.[0];
|
|
858
|
+
if (!declaration)
|
|
859
|
+
return false;
|
|
860
|
+
if (!ts.isExportSpecifier(declaration))
|
|
861
|
+
return false;
|
|
862
|
+
return declaration.isTypeOnly || declaration.parent.parent.isTypeOnly;
|
|
863
|
+
}
|
|
@@ -126,7 +126,7 @@ module.exports = localeUtils.buildIncompleteTranslation({
|
|
|
126
126
|
file_0_not_an_object: "Die Datei {0} ist kein Objekt",
|
|
127
127
|
// deserialization
|
|
128
128
|
serialized_project_referenced_0_not_part_of_project: "Serialisiertes Projekt referenziert Reflection {0}, welche kein Teil des Projekts ist",
|
|
129
|
-
|
|
129
|
+
saved_relative_path_0_resolved_from_1_does_not_exist: "Serialisiertes Projekt referenziert {0}, was relativ zu {1} nicht existiert",
|
|
130
130
|
// options
|
|
131
131
|
circular_reference_extends_0: `Zyklische Referenz im "extends"-Feld von {0} gefunden`,
|
|
132
132
|
failed_resolve_0_to_file_in_1: "Konnte {0} in {1} nicht zu einer Datei auflösen",
|
|
@@ -114,7 +114,7 @@ declare const _default: {
|
|
|
114
114
|
entry_point_0_did_not_match_any_packages: "Der Einstiegspunkt-Glob {0} passte auf keine Verzeichnisse mit einer package.json-Datei";
|
|
115
115
|
file_0_not_an_object: "Die Datei {0} ist kein Objekt";
|
|
116
116
|
serialized_project_referenced_0_not_part_of_project: "Serialisiertes Projekt referenziert Reflection {0}, welche kein Teil des Projekts ist";
|
|
117
|
-
|
|
117
|
+
saved_relative_path_0_resolved_from_1_does_not_exist: "Serialisiertes Projekt referenziert {0}, was relativ zu {1} nicht existiert";
|
|
118
118
|
circular_reference_extends_0: "Zyklische Referenz im \"extends\"-Feld von {0} gefunden";
|
|
119
119
|
failed_resolve_0_to_file_in_1: "Konnte {0} in {1} nicht zu einer Datei auflösen";
|
|
120
120
|
glob_0_should_use_posix_slash: "Der Glob \"{0}\" maskiert nichtspezielle Zeichen. Glob-Eingaben für TypeDoc dürfen keine Windows-Pfadtrennzeichen (\\) verwenden, nutzen Sie stattdessen Posix-Pfadtrennzeichen (/)";
|
|
@@ -54,6 +54,7 @@ module.exports = {
|
|
|
54
54
|
open_brace_within_inline_tag: `Encountered an open brace within an inline tag, this is likely a mistake`,
|
|
55
55
|
inline_tag_not_closed: `Inline tag is not closed`,
|
|
56
56
|
// validation
|
|
57
|
+
comment_for_0_links_to_1_not_included_in_docs_use_external_link_2: `The comment for {0} links to "{1}" which was resolved but is not included in the documentation. To fix this warning export it or add {2} to the externalSymbolLinkMappings option`,
|
|
57
58
|
failed_to_resolve_link_to_0_in_comment_for_1: `Failed to resolve link to "{0}" in comment for {1}`,
|
|
58
59
|
failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2: `Failed to resolve link to "{0}" in comment for {1}. You may have wanted "{2}"`,
|
|
59
60
|
failed_to_resolve_link_to_0_in_readme_for_1: `Failed to resolve link to "{0}" in readme for {1}`,
|
|
@@ -124,7 +125,7 @@ module.exports = {
|
|
|
124
125
|
file_0_not_an_object: `The file {0} is not an object`,
|
|
125
126
|
// deserialization
|
|
126
127
|
serialized_project_referenced_0_not_part_of_project: `Serialized project referenced reflection {0}, which was not a part of the project`,
|
|
127
|
-
|
|
128
|
+
saved_relative_path_0_resolved_from_1_does_not_exist: `Serialized project referenced {0}, which does not exist relative to {1}`,
|
|
128
129
|
// options
|
|
129
130
|
circular_reference_extends_0: `Circular reference encountered for "extends" field of {0}`,
|
|
130
131
|
failed_resolve_0_to_file_in_1: `Failed to resolve {0} to a file in {1}`,
|
|
@@ -49,6 +49,7 @@ declare const _default: {
|
|
|
49
49
|
readonly unknown_inline_tag_0: "Encountered an unknown inline tag {0}";
|
|
50
50
|
readonly open_brace_within_inline_tag: "Encountered an open brace within an inline tag, this is likely a mistake";
|
|
51
51
|
readonly inline_tag_not_closed: "Inline tag is not closed";
|
|
52
|
+
readonly comment_for_0_links_to_1_not_included_in_docs_use_external_link_2: "The comment for {0} links to \"{1}\" which was resolved but is not included in the documentation. To fix this warning export it or add {2} to the externalSymbolLinkMappings option";
|
|
52
53
|
readonly failed_to_resolve_link_to_0_in_comment_for_1: "Failed to resolve link to \"{0}\" in comment for {1}";
|
|
53
54
|
readonly failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2: "Failed to resolve link to \"{0}\" in comment for {1}. You may have wanted \"{2}\"";
|
|
54
55
|
readonly failed_to_resolve_link_to_0_in_readme_for_1: "Failed to resolve link to \"{0}\" in readme for {1}";
|
|
@@ -114,7 +115,7 @@ declare const _default: {
|
|
|
114
115
|
readonly entry_point_0_did_not_match_any_packages: "The entry point glob {0} did not match any directories containing package.json";
|
|
115
116
|
readonly file_0_not_an_object: "The file {0} is not an object";
|
|
116
117
|
readonly serialized_project_referenced_0_not_part_of_project: "Serialized project referenced reflection {0}, which was not a part of the project";
|
|
117
|
-
readonly
|
|
118
|
+
readonly saved_relative_path_0_resolved_from_1_does_not_exist: "Serialized project referenced {0}, which does not exist relative to {1}";
|
|
118
119
|
readonly circular_reference_extends_0: "Circular reference encountered for \"extends\" field of {0}";
|
|
119
120
|
readonly failed_resolve_0_to_file_in_1: "Failed to resolve {0} to a file in {1}";
|
|
120
121
|
readonly glob_0_should_use_posix_slash: "The glob \"{0}\" escapes a non-special character. Glob inputs to TypeDoc may not use Windows path separators (\\), try replacing with posix path separators (/)";
|
|
@@ -94,7 +94,7 @@ module.exports = localeUtils.buildIncompleteTranslation({
|
|
|
94
94
|
entry_point_0_did_not_match_any_packages: "エントリ ポイント glob {0} は、package.json を含むディレクトリと一致しませんでした。",
|
|
95
95
|
file_0_not_an_object: "ファイル {0} はオブジェクトではありません",
|
|
96
96
|
serialized_project_referenced_0_not_part_of_project: "シリアル化されたプロジェクトは、プロジェクトの一部ではないリフレクション {0} を参照しました",
|
|
97
|
-
//
|
|
97
|
+
// saved_relative_path_0_resolved_from_1_does_not_exist
|
|
98
98
|
circular_reference_extends_0: '{0} の "extends" フィールドで循環参照が検出されました',
|
|
99
99
|
failed_resolve_0_to_file_in_1: "{0} を {1} 内のファイルに解決できませんでした",
|
|
100
100
|
option_0_can_only_be_specified_by_config_file: "'{0}' オプションは設定ファイル経由でのみ指定できます",
|
|
@@ -126,7 +126,7 @@ module.exports = localeUtils.buildIncompleteTranslation({
|
|
|
126
126
|
file_0_not_an_object: "文件 {0} 不是对象",
|
|
127
127
|
// deserialization
|
|
128
128
|
serialized_project_referenced_0_not_part_of_project: "序列化项目引用了反射 {0},但它不是项目的一部分",
|
|
129
|
-
|
|
129
|
+
saved_relative_path_0_resolved_from_1_does_not_exist: "序列化项目引用的 {0} 不存在或无法在 {1} 下找到",
|
|
130
130
|
// options
|
|
131
131
|
circular_reference_extends_0: "{0} 的“extends”字段出现循环引用",
|
|
132
132
|
failed_resolve_0_to_file_in_1: "无法将 {0} 解析为 {1} 中的文件",
|
|
@@ -114,7 +114,7 @@ declare const _default: {
|
|
|
114
114
|
entry_point_0_did_not_match_any_packages: "入口点 glob {0} 与任何包含 package.json 的目录不匹配";
|
|
115
115
|
file_0_not_an_object: "文件 {0} 不是对象";
|
|
116
116
|
serialized_project_referenced_0_not_part_of_project: "序列化项目引用了反射 {0},但它不是项目的一部分";
|
|
117
|
-
|
|
117
|
+
saved_relative_path_0_resolved_from_1_does_not_exist: "序列化项目引用的 {0} 不存在或无法在 {1} 下找到";
|
|
118
118
|
circular_reference_extends_0: "{0} 的“extends”字段出现循环引用";
|
|
119
119
|
failed_resolve_0_to_file_in_1: "无法将 {0} 解析为 {1} 中的文件";
|
|
120
120
|
option_0_can_only_be_specified_by_config_file: "“{0}”选项只能通过配置文件指定";
|
|
@@ -2,6 +2,7 @@ import { type NormalizedPath } from "#utils";
|
|
|
2
2
|
import type { Reflection } from "./Reflection.js";
|
|
3
3
|
import { ReflectionSymbolId } from "./ReflectionSymbolId.js";
|
|
4
4
|
import type { Deserializer, JSONOutput, Serializer } from "#serialization";
|
|
5
|
+
import type { FileId } from "./FileRegistry.js";
|
|
5
6
|
/**
|
|
6
7
|
* Represents a parsed piece of a comment.
|
|
7
8
|
* @category Comments
|
|
@@ -62,7 +63,7 @@ export interface RelativeLinkDisplayPart {
|
|
|
62
63
|
* A link to either some document outside of the project or a reflection.
|
|
63
64
|
* This may be `undefined` if the relative path does not exist.
|
|
64
65
|
*/
|
|
65
|
-
target:
|
|
66
|
+
target: FileId | undefined;
|
|
66
67
|
/**
|
|
67
68
|
* Anchor within the target page, validated after rendering if possible
|
|
68
69
|
*/
|
|
@@ -61,6 +61,6 @@ export class DocumentReflection extends Reflection {
|
|
|
61
61
|
this.content = Comment.deserializeDisplayParts(de, obj.content);
|
|
62
62
|
this.frontmatter = obj.frontmatter;
|
|
63
63
|
this.relevanceBoost = obj.relevanceBoost;
|
|
64
|
-
this.children = de.reviveMany(obj.children, (obj) => de.
|
|
64
|
+
this.children = de.reviveMany(obj.children, (obj) => de.constructReflection(obj));
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -2,27 +2,39 @@ import type { Deserializer, JSONOutput, Serializer } from "#serialization";
|
|
|
2
2
|
import type { ProjectReflection, Reflection } from "./index.js";
|
|
3
3
|
import type { ReflectionId } from "./Reflection.js";
|
|
4
4
|
import { type NormalizedPath } from "#utils";
|
|
5
|
+
export type FileId = number & {
|
|
6
|
+
__mediaIdBrand: never;
|
|
7
|
+
};
|
|
5
8
|
export declare class FileRegistry {
|
|
6
9
|
protected nextId: number;
|
|
7
|
-
protected mediaToReflection: Map<
|
|
8
|
-
protected mediaToPath: Map<
|
|
10
|
+
protected mediaToReflection: Map<FileId, ReflectionId>;
|
|
11
|
+
protected mediaToPath: Map<FileId, NormalizedPath>;
|
|
9
12
|
protected reflectionToPath: Map<ReflectionId, NormalizedPath>;
|
|
10
|
-
protected pathToMedia: Map<NormalizedPath,
|
|
11
|
-
protected names: Map<
|
|
13
|
+
protected pathToMedia: Map<NormalizedPath, FileId>;
|
|
14
|
+
protected names: Map<FileId, string>;
|
|
12
15
|
protected nameUsage: Map<string, number>;
|
|
13
16
|
registerAbsolute(absolute: NormalizedPath): {
|
|
14
|
-
target:
|
|
17
|
+
target: FileId;
|
|
15
18
|
anchor: string | undefined;
|
|
16
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Registers the specified path as the canonical file for this reflection
|
|
22
|
+
*/
|
|
17
23
|
registerReflection(absolute: NormalizedPath, reflection: Reflection): void;
|
|
24
|
+
/**
|
|
25
|
+
* Registers the specified path as a path which should be resolved to the specified
|
|
26
|
+
* reflection. A reflection *may* be associated with multiple paths.
|
|
27
|
+
*/
|
|
28
|
+
registerReflectionPath(absolute: NormalizedPath, reflection: Reflection): void;
|
|
18
29
|
getReflectionPath(reflection: Reflection): string | undefined;
|
|
19
30
|
register(sourcePath: NormalizedPath, relativePath: NormalizedPath): {
|
|
20
|
-
target:
|
|
31
|
+
target: FileId;
|
|
21
32
|
anchor: string | undefined;
|
|
22
33
|
} | undefined;
|
|
23
34
|
removeReflection(reflection: Reflection): void;
|
|
24
|
-
resolve(id:
|
|
25
|
-
|
|
35
|
+
resolve(id: FileId, project: ProjectReflection): string | Reflection | undefined;
|
|
36
|
+
resolvePath(id: FileId): string | undefined;
|
|
37
|
+
getName(id: FileId): string | undefined;
|
|
26
38
|
getNameToAbsoluteMap(): ReadonlyMap<string, string>;
|
|
27
39
|
toObject(ser: Serializer): JSONOutput.FileRegistry;
|
|
28
40
|
/**
|
|
@@ -16,7 +16,6 @@ export class FileRegistry {
|
|
|
16
16
|
anchor = absolute.substring(anchorIndex + 1);
|
|
17
17
|
absolute = absolute.substring(0, anchorIndex);
|
|
18
18
|
}
|
|
19
|
-
absolute = absolute.replace(/#.*/, "");
|
|
20
19
|
const existing = this.pathToMedia.get(absolute);
|
|
21
20
|
if (existing) {
|
|
22
21
|
return { target: existing, anchor };
|
|
@@ -25,11 +24,22 @@ export class FileRegistry {
|
|
|
25
24
|
this.pathToMedia.set(absolute, this.nextId);
|
|
26
25
|
return { target: this.nextId++, anchor };
|
|
27
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Registers the specified path as the canonical file for this reflection
|
|
29
|
+
*/
|
|
28
30
|
registerReflection(absolute, reflection) {
|
|
29
31
|
const { target } = this.registerAbsolute(absolute);
|
|
30
32
|
this.reflectionToPath.set(reflection.id, absolute);
|
|
31
33
|
this.mediaToReflection.set(target, reflection.id);
|
|
32
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Registers the specified path as a path which should be resolved to the specified
|
|
37
|
+
* reflection. A reflection *may* be associated with multiple paths.
|
|
38
|
+
*/
|
|
39
|
+
registerReflectionPath(absolute, reflection) {
|
|
40
|
+
const { target } = this.registerAbsolute(absolute);
|
|
41
|
+
this.mediaToReflection.set(target, reflection.id);
|
|
42
|
+
}
|
|
33
43
|
getReflectionPath(reflection) {
|
|
34
44
|
return this.reflectionToPath.get(reflection.id);
|
|
35
45
|
}
|
|
@@ -50,6 +60,9 @@ export class FileRegistry {
|
|
|
50
60
|
}
|
|
51
61
|
return this.mediaToPath.get(id);
|
|
52
62
|
}
|
|
63
|
+
resolvePath(id) {
|
|
64
|
+
return this.mediaToPath.get(id);
|
|
65
|
+
}
|
|
53
66
|
getName(id) {
|
|
54
67
|
const absolute = this.mediaToPath.get(id);
|
|
55
68
|
if (!absolute)
|
|
@@ -104,15 +117,15 @@ export class FileRegistry {
|
|
|
104
117
|
* a single object, and should merge in files from the other registries.
|
|
105
118
|
*/
|
|
106
119
|
fromObject(de, obj) {
|
|
107
|
-
for (const [
|
|
108
|
-
const absolute = NormalizedPathUtils.resolve(de.projectRoot,
|
|
109
|
-
de.oldFileIdToNewFileId[+
|
|
120
|
+
for (const [fileId, path] of Object.entries(obj.entries)) {
|
|
121
|
+
const absolute = NormalizedPathUtils.resolve(de.projectRoot, path);
|
|
122
|
+
de.oldFileIdToNewFileId[+fileId] = this.registerAbsolute(absolute).target;
|
|
110
123
|
}
|
|
111
124
|
de.defer((project) => {
|
|
112
|
-
for (const [
|
|
125
|
+
for (const [fileId, reflId] of Object.entries(obj.reflections)) {
|
|
113
126
|
const refl = project.getReflectionById(de.oldIdToNewId[reflId]);
|
|
114
127
|
if (refl) {
|
|
115
|
-
this.mediaToReflection.set(de.oldFileIdToNewFileId[+
|
|
128
|
+
this.mediaToReflection.set(de.oldFileIdToNewFileId[+fileId], refl.id);
|
|
116
129
|
}
|
|
117
130
|
}
|
|
118
131
|
});
|
|
@@ -32,7 +32,7 @@ export class ProjectReflection extends ContainerReflection {
|
|
|
32
32
|
*
|
|
33
33
|
* This may be replaced with a `Map<number, Reflection>` someday.
|
|
34
34
|
*/
|
|
35
|
-
reflections = {
|
|
35
|
+
reflections = {};
|
|
36
36
|
/**
|
|
37
37
|
* The name of the package that this reflection documents according to package.json.
|
|
38
38
|
*/
|
|
@@ -99,6 +99,10 @@ export interface TraverseCallback {
|
|
|
99
99
|
export type ReflectionVisitor = {
|
|
100
100
|
[K in keyof ReflectionVariant]?: (refl: ReflectionVariant[K]) => void;
|
|
101
101
|
};
|
|
102
|
+
/**
|
|
103
|
+
* Alias for a `number` which references a reflection.
|
|
104
|
+
* `-1` may be used for an invalid reflection ID.
|
|
105
|
+
*/
|
|
102
106
|
export type ReflectionId = number & {
|
|
103
107
|
__reflectionIdBrand: never;
|
|
104
108
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Reflection } from "./Reflection.js";
|
|
1
|
+
import type { Reflection, ReflectionId } from "./Reflection.js";
|
|
2
2
|
import type { DeclarationReflection } from "./DeclarationReflection.js";
|
|
3
3
|
import type { ProjectReflection } from "./ProjectReflection.js";
|
|
4
4
|
import type { Deserializer, JSONOutput, Serializer } from "#serialization";
|
|
@@ -386,7 +386,7 @@ export declare class ReferenceType extends Type {
|
|
|
386
386
|
private _project;
|
|
387
387
|
private constructor();
|
|
388
388
|
static createUnresolvedReference(name: string, target: ReflectionSymbolId, project: ProjectReflection, qualifiedName: string): ReferenceType;
|
|
389
|
-
static createResolvedReference(name: string, target: Reflection |
|
|
389
|
+
static createResolvedReference(name: string, target: Reflection | ReflectionId, project: ProjectReflection | null): ReferenceType;
|
|
390
390
|
/**
|
|
391
391
|
* This is used for type parameters, which don't actually point to something,
|
|
392
392
|
* and also for temporary references which will be cleaned up with real references
|
package/dist/lib/models/types.js
CHANGED
|
@@ -894,20 +894,22 @@ let ReferenceType = (() => {
|
|
|
894
894
|
}
|
|
895
895
|
fromObject(de, obj) {
|
|
896
896
|
this.typeArguments = de.reviveMany(obj.typeArguments, (t) => de.constructType(t));
|
|
897
|
-
if (typeof obj.target === "number"
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
897
|
+
if (typeof obj.target === "number") {
|
|
898
|
+
if (obj.target === -1) {
|
|
899
|
+
this._target = -1;
|
|
900
|
+
}
|
|
901
|
+
else {
|
|
902
|
+
de.defer((project) => {
|
|
903
|
+
const target = project.getReflectionById(de.oldIdToNewId[obj.target] ?? -1);
|
|
904
|
+
if (target) {
|
|
905
|
+
this._project = project;
|
|
906
|
+
this._target = target.id;
|
|
907
|
+
}
|
|
908
|
+
else {
|
|
909
|
+
de.logger.warn(i18n.serialized_project_referenced_0_not_part_of_project(JSON.stringify(obj.target)));
|
|
910
|
+
}
|
|
911
|
+
});
|
|
912
|
+
}
|
|
911
913
|
}
|
|
912
914
|
else {
|
|
913
915
|
this._project = de.project;
|
|
@@ -34,7 +34,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
34
34
|
};
|
|
35
35
|
import { RendererComponent } from "../components.js";
|
|
36
36
|
import { RendererEvent } from "../events.js";
|
|
37
|
-
import { copySync, readFile, writeFileSync } from "../../utils/fs.js";
|
|
37
|
+
import { copySync, isFile, readFile, writeFileSync } from "../../utils/fs.js";
|
|
38
38
|
import { DefaultTheme } from "../themes/default/DefaultTheme.js";
|
|
39
39
|
import { getStyles } from "../../utils/highlighter.js";
|
|
40
40
|
import { getEnumKeys, i18n } from "#utils";
|
|
@@ -146,7 +146,12 @@ let AssetsPlugin = (() => {
|
|
|
146
146
|
const media = join(event.outputDirectory, "media");
|
|
147
147
|
const toCopy = event.project.files.getNameToAbsoluteMap();
|
|
148
148
|
for (const [fileName, absolute] of toCopy.entries()) {
|
|
149
|
-
|
|
149
|
+
if (isFile(absolute)) {
|
|
150
|
+
copySync(absolute, join(media, fileName));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
this.application.logger.warn(i18n.relative_path_0_is_not_a_file_and_will_not_be_copied_to_output(absolute));
|
|
154
|
+
}
|
|
150
155
|
}
|
|
151
156
|
}
|
|
152
157
|
}
|
|
@@ -129,8 +129,8 @@ let MarkedPlugin = (() => {
|
|
|
129
129
|
getHighlighted(text, lang) {
|
|
130
130
|
lang = lang || "typescript";
|
|
131
131
|
lang = lang.toLowerCase();
|
|
132
|
-
if (!
|
|
133
|
-
if (
|
|
132
|
+
if (!isLoadedLanguage(lang)) {
|
|
133
|
+
if (isSupportedLanguage(lang)) {
|
|
134
134
|
this.application.logger.warn(i18n.unloaded_language_0_not_highlighted_in_comment_for_1(lang, getFriendlyFullName(this.page?.model || { name: "(unknown)" })));
|
|
135
135
|
}
|
|
136
136
|
else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FileRegistry, ProjectReflection, type ReflectionVariant, type TypeKindMap } from "#models";
|
|
1
|
+
import { type FileId, type FileRegistry, ProjectReflection, type ReflectionId, type ReflectionVariant, type TypeKindMap } from "#models";
|
|
2
2
|
import { type Logger, type NormalizedPath } from "#utils";
|
|
3
3
|
import * as JSONOutput from "./schema.js";
|
|
4
4
|
export interface DeserializerComponent {
|
|
@@ -30,8 +30,8 @@ export declare class Deserializer {
|
|
|
30
30
|
* Only set when deserializing.
|
|
31
31
|
*/
|
|
32
32
|
projectRoot: NormalizedPath;
|
|
33
|
-
oldIdToNewId: Record<
|
|
34
|
-
oldFileIdToNewFileId: Record<
|
|
33
|
+
oldIdToNewId: Record<ReflectionId, ReflectionId | undefined>;
|
|
34
|
+
oldFileIdToNewFileId: Record<FileId, FileId | undefined>;
|
|
35
35
|
project: ProjectReflection | undefined;
|
|
36
36
|
constructor(logger: Logger);
|
|
37
37
|
addDeserializer(de: DeserializerComponent): void;
|
|
@@ -52,6 +52,8 @@ type ToSerialized<T> = T extends Primitive ? T : T extends bigint ? {
|
|
|
52
52
|
type S<T, K extends keyof T> = {
|
|
53
53
|
-readonly [K2 in K]: ToSerialized<T[K2]>;
|
|
54
54
|
};
|
|
55
|
+
export type ReflectionId = M.ReflectionId;
|
|
56
|
+
export type FileId = M.FileId;
|
|
55
57
|
export interface ReflectionSymbolId {
|
|
56
58
|
packageName: string;
|
|
57
59
|
packagePath: NormalizedPath;
|
|
@@ -85,7 +87,7 @@ export interface ReferenceReflection extends Omit<DeclarationReflection, "varian
|
|
|
85
87
|
* -1 if the reference refers to a symbol that does not exist in the documentation.
|
|
86
88
|
* Otherwise, the reflection ID.
|
|
87
89
|
*/
|
|
88
|
-
target:
|
|
90
|
+
target: ReflectionId;
|
|
89
91
|
}
|
|
90
92
|
/** @category Reflections */
|
|
91
93
|
export interface SignatureReflection extends Omit<Reflection, "variant">, S<M.SignatureReflection, "variant" | "sources" | "parameters" | "typeParameters" | "type" | "overwrites" | "inheritedFrom" | "implementationOf"> {
|
|
@@ -107,12 +109,12 @@ export interface ProjectReflection extends Omit<ContainerReflection, "variant">,
|
|
|
107
109
|
* See {@link SCHEMA_VERSION} for the current version.
|
|
108
110
|
*/
|
|
109
111
|
schemaVersion: string;
|
|
110
|
-
symbolIdMap: Record<
|
|
112
|
+
symbolIdMap: Record<ReflectionId, ReflectionSymbolId> | IfInternal<undefined, never>;
|
|
111
113
|
files: FileRegistry;
|
|
112
114
|
}
|
|
113
115
|
/** @category Reflections */
|
|
114
116
|
export interface ContainerReflection extends Reflection, S<M.ContainerReflection, "children" | "documents" | "groups" | "categories"> {
|
|
115
|
-
childrenIncludingDocuments?:
|
|
117
|
+
childrenIncludingDocuments?: ReflectionId[];
|
|
116
118
|
}
|
|
117
119
|
/** @category Reflections */
|
|
118
120
|
export interface Reflection extends S<M.Reflection, "id" | "variant" | "name" | "kind" | "comment"> {
|
|
@@ -172,7 +174,7 @@ export interface QueryType extends Type, S<M.QueryType, "type" | "queryType"> {
|
|
|
172
174
|
}
|
|
173
175
|
/** @category Types */
|
|
174
176
|
export interface ReferenceType extends Type, S<M.ReferenceType, "type" | "name" | "typeArguments" | "package" | "externalUrl"> {
|
|
175
|
-
target:
|
|
177
|
+
target: ReflectionId | ReflectionSymbolId;
|
|
176
178
|
qualifiedName?: string;
|
|
177
179
|
refersToTypeParameter?: boolean;
|
|
178
180
|
preferValues?: boolean;
|
|
@@ -247,7 +249,7 @@ export interface InlineTagDisplayPart {
|
|
|
247
249
|
kind: "inline-tag";
|
|
248
250
|
tag: `@${string}`;
|
|
249
251
|
text: string;
|
|
250
|
-
target?: string |
|
|
252
|
+
target?: string | ReflectionId | ReflectionSymbolId;
|
|
251
253
|
tsLinkText?: string;
|
|
252
254
|
}
|
|
253
255
|
/**
|
|
@@ -264,7 +266,7 @@ export interface RelativeLinkDisplayPart {
|
|
|
264
266
|
/**
|
|
265
267
|
* File ID, if present
|
|
266
268
|
*/
|
|
267
|
-
target?:
|
|
269
|
+
target?: FileId;
|
|
268
270
|
/**
|
|
269
271
|
* Anchor within the target file, if present
|
|
270
272
|
*/
|
|
@@ -274,8 +276,8 @@ export interface SourceReference extends S<M.SourceReference, "fileName" | "line
|
|
|
274
276
|
}
|
|
275
277
|
export interface FileRegistry {
|
|
276
278
|
/** Relative path according to the serialization root */
|
|
277
|
-
entries: Record<
|
|
279
|
+
entries: Record<FileId, NormalizedPath>;
|
|
278
280
|
/** File ID to reflection ID */
|
|
279
|
-
reflections: Record<
|
|
281
|
+
reflections: Record<FileId, ReflectionId>;
|
|
280
282
|
}
|
|
281
283
|
export {};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { FileRegistry } from "../models/FileRegistry.js";
|
|
1
|
+
import { type FileId, FileRegistry } from "../models/FileRegistry.js";
|
|
2
2
|
import type { Deserializer, JSONOutput } from "#serialization";
|
|
3
3
|
import { type NormalizedPath } from "#utils";
|
|
4
4
|
export declare class ValidatingFileRegistry extends FileRegistry {
|
|
5
5
|
register(sourcePath: NormalizedPath, relativePath: NormalizedPath): {
|
|
6
|
-
target:
|
|
6
|
+
target: FileId;
|
|
7
7
|
anchor: string | undefined;
|
|
8
8
|
} | undefined;
|
|
9
9
|
fromObject(de: Deserializer, obj: JSONOutput.FileRegistry): void;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { FileRegistry } from "../models/FileRegistry.js";
|
|
2
|
-
import { isFile } from "./fs.js";
|
|
3
2
|
import { i18n, NormalizedPathUtils } from "#utils";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
4
|
export class ValidatingFileRegistry extends FileRegistry {
|
|
5
5
|
register(sourcePath, relativePath) {
|
|
6
6
|
const absolute = NormalizedPathUtils.resolve(NormalizedPathUtils.dirname(sourcePath), relativePath);
|
|
7
7
|
const absoluteWithoutAnchor = absolute.replace(/#.*/, "");
|
|
8
|
-
|
|
8
|
+
// Note: We allow paths to directories to be registered here, but the AssetsPlugin will not
|
|
9
|
+
// copy them to the output path. This is so that we can link to directories and associate them
|
|
10
|
+
// with reflections in packages mode.
|
|
11
|
+
if (!existsSync(absoluteWithoutAnchor)) {
|
|
9
12
|
return;
|
|
10
13
|
}
|
|
11
14
|
return this.registerAbsolute(absolute);
|
|
@@ -13,8 +16,8 @@ export class ValidatingFileRegistry extends FileRegistry {
|
|
|
13
16
|
fromObject(de, obj) {
|
|
14
17
|
for (const [key, val] of Object.entries(obj.entries)) {
|
|
15
18
|
const absolute = NormalizedPathUtils.resolve(de.projectRoot, val);
|
|
16
|
-
if (!
|
|
17
|
-
de.logger.warn(i18n.
|
|
19
|
+
if (!existsSync(absolute)) {
|
|
20
|
+
de.logger.warn(i18n.saved_relative_path_0_resolved_from_1_does_not_exist(val, de.projectRoot));
|
|
18
21
|
continue;
|
|
19
22
|
}
|
|
20
23
|
de.oldFileIdToNewFileId[+key] = this.registerAbsolute(absolute).target;
|
|
@@ -7,7 +7,7 @@ function getBrokenPartLinks(parts) {
|
|
|
7
7
|
if (part.kind === "inline-tag" &&
|
|
8
8
|
linkTags.includes(part.tag) &&
|
|
9
9
|
(!part.target || part.target instanceof ReflectionSymbolId)) {
|
|
10
|
-
links.push(part
|
|
10
|
+
links.push(part);
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
return links;
|
|
@@ -32,52 +32,50 @@ export function validateLinks(project, logger) {
|
|
|
32
32
|
function checkReflection(reflection, logger) {
|
|
33
33
|
if (reflection.isProject() || reflection.isDeclaration()) {
|
|
34
34
|
for (const broken of getBrokenPartLinks(reflection.readme || [])) {
|
|
35
|
+
const linkText = broken.text.trim();
|
|
35
36
|
// #2360, "@" is a future reserved character in TSDoc component paths
|
|
36
37
|
// If a link starts with it, and doesn't include a module source indicator "!"
|
|
37
38
|
// then the user probably is trying to link to a package containing "@" with an absolute link.
|
|
38
|
-
if (
|
|
39
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1_may_have_meant_2(
|
|
39
|
+
if (linkText.startsWith("@") && !linkText.includes("!")) {
|
|
40
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1_may_have_meant_2(linkText, reflection.getFriendlyFullName(), linkText.replace(/[.#~]/, "!")));
|
|
40
41
|
}
|
|
41
42
|
else {
|
|
42
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1(
|
|
43
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_readme_for_1(linkText, reflection.getFriendlyFullName()));
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
46
|
}
|
|
46
47
|
if (reflection.isDocument()) {
|
|
47
48
|
for (const broken of getBrokenPartLinks(reflection.content)) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (broken.startsWith("@") && !broken.includes("!")) {
|
|
52
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
|
|
49
|
+
const linkText = broken.text.trim();
|
|
50
|
+
if (linkText.startsWith("@") && !linkText.includes("!")) {
|
|
51
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1_may_have_meant_2(linkText, reflection.getFriendlyFullName(), linkText.replace(/[.#~]/, "!")));
|
|
53
52
|
}
|
|
54
53
|
else {
|
|
55
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1(
|
|
54
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_document_1(linkText, reflection.getFriendlyFullName()));
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
}
|
|
59
58
|
for (const broken of getBrokenLinks(reflection.comment)) {
|
|
60
|
-
|
|
61
|
-
// If a link starts with it, and doesn't include a module source indicator "!"
|
|
62
|
-
// then the user probably is trying to link to a package containing "@" with an absolute link.
|
|
63
|
-
if (broken.startsWith("@") && !broken.includes("!")) {
|
|
64
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1(broken, reflection.getFriendlyFullName()));
|
|
68
|
-
}
|
|
59
|
+
reportBrokenCommentLink(broken, reflection, logger);
|
|
69
60
|
}
|
|
70
61
|
if (reflection.isDeclaration() &&
|
|
71
62
|
reflection.kindOf(ReflectionKind.TypeAlias) &&
|
|
72
63
|
reflection.type?.type === "union" &&
|
|
73
64
|
reflection.type.elementSummaries) {
|
|
74
65
|
for (const broken of reflection.type.elementSummaries.flatMap(getBrokenPartLinks)) {
|
|
75
|
-
|
|
76
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2(broken, reflection.getFriendlyFullName(), broken.replace(/[.#~]/, "!")));
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1(broken, reflection.getFriendlyFullName()));
|
|
80
|
-
}
|
|
66
|
+
reportBrokenCommentLink(broken, reflection, logger);
|
|
81
67
|
}
|
|
82
68
|
}
|
|
83
69
|
}
|
|
70
|
+
function reportBrokenCommentLink(broken, reflection, logger) {
|
|
71
|
+
const linkText = broken.text.trim();
|
|
72
|
+
if (broken.target instanceof ReflectionSymbolId) {
|
|
73
|
+
logger.warn(i18n.comment_for_0_links_to_1_not_included_in_docs_use_external_link_2(reflection.getFriendlyFullName(), linkText, `{ "${broken.target.packageName}": { "${broken.target.qualifiedName}": "#" }}`));
|
|
74
|
+
}
|
|
75
|
+
else if (linkText.startsWith("@") && !linkText.includes("!")) {
|
|
76
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2(linkText, reflection.getFriendlyFullName(), linkText.replace(/[.#~]/, "!")));
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
logger.warn(i18n.failed_to_resolve_link_to_0_in_comment_for_1(linkText, reflection.getFriendlyFullName()));
|
|
80
|
+
}
|
|
81
|
+
}
|