typedoc 0.26.0-beta.2 → 0.26.0-beta.4

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.
Files changed (94) hide show
  1. package/README.md +0 -2
  2. package/dist/lib/application.d.ts +6 -1
  3. package/dist/lib/application.js +10 -0
  4. package/dist/lib/cli.js +14 -0
  5. package/dist/lib/converter/comments/discovery.js +0 -1
  6. package/dist/lib/converter/comments/index.d.ts +1 -1
  7. package/dist/lib/converter/comments/index.js +5 -2
  8. package/dist/lib/converter/comments/textParser.d.ts +0 -3
  9. package/dist/lib/converter/comments/textParser.js +39 -3
  10. package/dist/lib/converter/context.d.ts +2 -2
  11. package/dist/lib/converter/context.js +2 -4
  12. package/dist/lib/converter/converter.d.ts +1 -0
  13. package/dist/lib/converter/converter.js +58 -9
  14. package/dist/lib/converter/factories/index-signature.js +1 -1
  15. package/dist/lib/converter/plugins/ImplementsPlugin.js +3 -2
  16. package/dist/lib/converter/plugins/LinkResolverPlugin.js +7 -0
  17. package/dist/lib/converter/plugins/SourcePlugin.d.ts +1 -15
  18. package/dist/lib/converter/plugins/SourcePlugin.js +4 -45
  19. package/dist/lib/converter/symbols.js +22 -0
  20. package/dist/lib/converter/types.js +20 -1
  21. package/dist/lib/converter/utils/repository.d.ts +46 -1
  22. package/dist/lib/converter/utils/repository.js +191 -64
  23. package/dist/lib/internationalization/internationalization.d.ts +5 -2
  24. package/dist/lib/internationalization/internationalization.js +42 -1
  25. package/dist/lib/internationalization/locales/jp.cjs +308 -0
  26. package/dist/lib/internationalization/locales/jp.d.cts +307 -0
  27. package/dist/lib/internationalization/locales/zh.cjs +308 -0
  28. package/dist/lib/internationalization/locales/zh.d.cts +307 -0
  29. package/dist/lib/internationalization/translatable.d.ts +187 -164
  30. package/dist/lib/internationalization/translatable.js +185 -163
  31. package/dist/lib/models/comments/comment.d.ts +29 -3
  32. package/dist/lib/models/comments/comment.js +6 -0
  33. package/dist/lib/models/reflections/abstract.d.ts +12 -11
  34. package/dist/lib/models/reflections/abstract.js +46 -49
  35. package/dist/lib/models/reflections/document.d.ts +6 -1
  36. package/dist/lib/models/reflections/document.js +12 -2
  37. package/dist/lib/models/reflections/kind.d.ts +2 -0
  38. package/dist/lib/models/reflections/kind.js +3 -1
  39. package/dist/lib/models/reflections/project.js +1 -0
  40. package/dist/lib/models/reflections/signature.js +7 -2
  41. package/dist/lib/models/types.d.ts +9 -1
  42. package/dist/lib/models/types.js +5 -18
  43. package/dist/lib/output/components.d.ts +2 -0
  44. package/dist/lib/output/components.js +139 -66
  45. package/dist/lib/output/models/UrlMapping.d.ts +4 -0
  46. package/dist/lib/output/plugins/IconsPlugin.js +21 -17
  47. package/dist/lib/output/renderer.d.ts +16 -0
  48. package/dist/lib/output/themes/MarkedPlugin.js +8 -2
  49. package/dist/lib/output/themes/default/DefaultTheme.js +5 -2
  50. package/dist/lib/output/themes/default/DefaultThemeRenderContext.d.ts +4 -3
  51. package/dist/lib/output/themes/default/DefaultThemeRenderContext.js +3 -2
  52. package/dist/lib/output/themes/default/layouts/default.js +10 -10
  53. package/dist/lib/output/themes/default/partials/comment.d.ts +2 -2
  54. package/dist/lib/output/themes/default/partials/comment.js +24 -15
  55. package/dist/lib/output/themes/default/partials/footer.js +2 -2
  56. package/dist/lib/output/themes/default/partials/index.js +1 -1
  57. package/dist/lib/output/themes/default/partials/member.declaration.js +30 -4
  58. package/dist/lib/output/themes/default/partials/member.signature.title.d.ts +2 -1
  59. package/dist/lib/output/themes/default/partials/member.signature.title.js +1 -2
  60. package/dist/lib/output/themes/default/partials/members.group.js +17 -10
  61. package/dist/lib/output/themes/default/partials/members.js +7 -3
  62. package/dist/lib/output/themes/default/partials/navigation.js +10 -4
  63. package/dist/lib/output/themes/default/partials/reflectionPreview.js +3 -2
  64. package/dist/lib/output/themes/default/partials/type.js +26 -2
  65. package/dist/lib/output/themes/default/templates/reflection.js +2 -2
  66. package/dist/lib/output/themes/lib.d.ts +0 -1
  67. package/dist/lib/output/themes/lib.js +0 -4
  68. package/dist/lib/serialization/schema.d.ts +23 -11
  69. package/dist/lib/serialization/serializer.d.ts +1 -1
  70. package/dist/lib/utils/component.js +0 -3
  71. package/dist/lib/utils/events.js +0 -1
  72. package/dist/lib/utils/general.d.ts +1 -0
  73. package/dist/lib/utils/general.js +5 -0
  74. package/dist/lib/utils/html-entities.json +2324 -2231
  75. package/dist/lib/utils/html.d.ts +59 -1
  76. package/dist/lib/utils/html.js +577 -19
  77. package/dist/lib/utils/options/declaration.d.ts +1 -0
  78. package/dist/lib/utils/options/help.js +0 -1
  79. package/dist/lib/utils/options/options.js +0 -1
  80. package/dist/lib/utils/options/sources/typedoc.js +6 -0
  81. package/dist/lib/utils/options/tsdoc-defaults.d.ts +1 -1
  82. package/dist/lib/utils/options/tsdoc-defaults.js +5 -1
  83. package/dist/lib/utils/paths.js +11 -1
  84. package/dist/lib/utils/perf.js +3 -1
  85. package/dist/lib/utils/sort.js +4 -13
  86. package/dist/lib/validation/links.d.ts +1 -1
  87. package/dist/lib/validation/links.js +42 -7
  88. package/package.json +5 -7
  89. package/static/main.js +4 -4
  90. package/static/style.css +11 -2
  91. package/dist/lib/converter/utils/base-path.d.ts +0 -36
  92. package/dist/lib/converter/utils/base-path.js +0 -112
  93. package/dist/lib/internationalization/locales/test.cjs +0 -8
  94. package/dist/lib/internationalization/locales/test.d.cts +0 -5
package/README.md CHANGED
@@ -2,8 +2,6 @@
2
2
 
3
3
  Documentation generator for TypeScript projects.
4
4
 
5
- Plugins: [plugins](./internal-docs/plugins.md)
6
-
7
5
  [![CI](https://github.com/TypeStrong/typedoc/workflows/CI/badge.svg)](https://github.com/TypeStrong/typedoc/actions)
8
6
  [![NPM Version](https://img.shields.io/npm/v/typedoc?color=33cd56&logo=npm)](https://www.npmjs.com/package/typedoc)
9
7
 
@@ -22,6 +22,11 @@ export declare function createAppForTesting(): Application;
22
22
  *
23
23
  * Both the {@link Converter} and the {@link Renderer} emit a series of events while processing the project.
24
24
  * Subscribe to these Events to control the application flow or alter the output.
25
+ *
26
+ * @remarks
27
+ *
28
+ * Access to an Application instance can be retrieved with {@link Application.bootstrap} or
29
+ * {@link Application.bootstrapWithPlugins}. It can not be constructed manually.
25
30
  */
26
31
  export declare class Application extends ChildableComponent<Application, AbstractComponent<Application>> {
27
32
  /**
@@ -66,7 +71,7 @@ export declare class Application extends ChildableComponent<Application, Abstrac
66
71
  /**
67
72
  * The version number of TypeDoc.
68
73
  */
69
- static VERSION: string;
74
+ static readonly VERSION: string;
70
75
  /**
71
76
  * Emitted after plugins have been loaded and options have been read, but before they have been frozen.
72
77
  * The listener will be given an instance of {@link Application}.
@@ -130,6 +130,11 @@ const DEFAULT_READERS = [
130
130
  *
131
131
  * Both the {@link Converter} and the {@link Renderer} emit a series of events while processing the project.
132
132
  * Subscribe to these Events to control the application flow or alter the output.
133
+ *
134
+ * @remarks
135
+ *
136
+ * Access to an Application instance can be retrieved with {@link Application.bootstrap} or
137
+ * {@link Application.bootstrapWithPlugins}. It can not be constructed manually.
133
138
  */
134
139
  let Application = (() => {
135
140
  var _Application_lang_accessor_storage, _Application_skipErrorChecking_accessor_storage, _Application_entryPointStrategy_accessor_storage, _Application_entryPoints_accessor_storage;
@@ -259,6 +264,11 @@ let Application = (() => {
259
264
  .join("\n\t")));
260
265
  this.logger.info("You can define/override local locales with the `locales` option, or contribute them to TypeDoc!");
261
266
  }
267
+ if (this.options.getValue("useHostedBaseUrlForAbsoluteLinks") &&
268
+ !this.options.getValue("hostedBaseUrl")) {
269
+ this.logger.warn(this.i18n.useHostedBaseUrlForAbsoluteLinks_requires_hostedBaseUrl());
270
+ this.options.setValue("useHostedBaseUrlForAbsoluteLinks", false);
271
+ }
262
272
  }
263
273
  setOptions(options, reportErrors = true) {
264
274
  for (const [key, val] of Object.entries(options)) {
package/dist/lib/cli.js CHANGED
@@ -49,6 +49,7 @@ async function main() {
49
49
  const exitCode = await run(app);
50
50
  if (exitCode !== ExitCodes.Watching) {
51
51
  app.logger.verbose(`Full run took ${Date.now() - start}ms`);
52
+ logRunSummary(app.logger);
52
53
  process.exit(exitCode);
53
54
  }
54
55
  }
@@ -83,6 +84,7 @@ async function run(app) {
83
84
  }
84
85
  if (app.options.getValue("watch")) {
85
86
  app.convertAndWatch(async (project) => {
87
+ app.validate(project);
86
88
  const json = app.options.getValue("json");
87
89
  if (!json || app.options.isSet("out")) {
88
90
  await app.generateDocs(project, app.options.getValue("out"));
@@ -130,3 +132,15 @@ async function run(app) {
130
132
  }
131
133
  return ExitCodes.Ok;
132
134
  }
135
+ /**
136
+ * Generate a string with the number of errors and warnings found.
137
+ */
138
+ function logRunSummary(logger) {
139
+ const { errorCount, warningCount } = logger;
140
+ if (errorCount) {
141
+ logger.error(logger.i18n.found_0_errors_and_1_warnings(errorCount.toString(), warningCount.toString()));
142
+ }
143
+ else if (warningCount) {
144
+ logger.warn(logger.i18n.found_0_errors_and_1_warnings(errorCount.toString(), warningCount.toString()));
145
+ }
146
+ }
@@ -284,7 +284,6 @@ function getRootModuleDeclaration(node) {
284
284
  }
285
285
  function declarationToCommentNode(node) {
286
286
  // ts.SourceFile is a counterexample
287
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
288
287
  if (!node.parent)
289
288
  return node;
290
289
  // const abc = 123
@@ -11,7 +11,7 @@ export interface CommentParserConfig {
11
11
  }
12
12
  export declare function clearCommentCache(): void;
13
13
  export declare function getComment(symbol: ts.Symbol, kind: ReflectionKind, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
14
- export declare function getNodeComment(node: ts.Node, kind: ReflectionKind, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
14
+ export declare function getNodeComment(node: ts.Node, moduleComment: boolean, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
15
15
  export declare function getFileComment(file: ts.SourceFile, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
16
16
  export declare function getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature, config: CommentParserConfig, logger: Logger, commentStyle: CommentStyle, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
17
17
  export declare function getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
@@ -58,6 +58,9 @@ function getCommentWithCache(discovered, config, logger, checker, files) {
58
58
  }
59
59
  function getCommentImpl(commentSource, config, logger, moduleComment, checker, files) {
60
60
  const comment = getCommentWithCache(commentSource, config, logger, checker, files);
61
+ if (comment?.getTag("@import") || comment?.getTag("@license")) {
62
+ return;
63
+ }
61
64
  if (moduleComment && comment) {
62
65
  // Module comment, make sure it is tagged with @packageDocumentation or @module.
63
66
  // If it isn't then the comment applies to the first statement in the file, so throw it away.
@@ -97,8 +100,8 @@ function getComment(symbol, kind, config, logger, commentStyle, checker, files)
97
100
  }
98
101
  return comment;
99
102
  }
100
- function getNodeComment(node, kind, config, logger, commentStyle, checker, files) {
101
- return getCommentImpl((0, discovery_1.discoverNodeComment)(node, commentStyle), config, logger, kind === models_1.ReflectionKind.Module, checker, files);
103
+ function getNodeComment(node, moduleComment, config, logger, commentStyle, checker, files) {
104
+ return getCommentImpl((0, discovery_1.discoverNodeComment)(node, commentStyle), config, logger, moduleComment, checker, files);
102
105
  }
103
106
  function getFileComment(file, config, logger, commentStyle, checker, files) {
104
107
  for (const commentSource of (0, discovery_1.discoverFileComments)(file, commentStyle)) {
@@ -12,8 +12,5 @@ import { type Token } from "./lexer";
12
12
  /**
13
13
  * Look for relative links within a piece of text and add them to the {@link FileRegistry}
14
14
  * so that they can be correctly resolved during rendering.
15
- *
16
- * TODO: We also handle `<a>` and `<img>` tags with relative targets here.
17
- *
18
15
  */
19
16
  export declare function textContent(sourcePath: string, token: Token, i18n: TranslationProxy, warning: (msg: TranslatedString, token: Token) => void, outContent: CommentDisplayPart[], files: FileRegistry, atNewLine: boolean): void;
@@ -4,15 +4,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.textContent = textContent;
7
+ const html_1 = require("../../utils/html");
7
8
  const lexer_1 = require("./lexer");
8
9
  const markdown_it_1 = __importDefault(require("markdown-it"));
9
10
  const MdHelpers = new markdown_it_1.default().helpers;
10
11
  /**
11
12
  * Look for relative links within a piece of text and add them to the {@link FileRegistry}
12
13
  * so that they can be correctly resolved during rendering.
13
- *
14
- * TODO: We also handle `<a>` and `<img>` tags with relative targets here.
15
- *
16
14
  */
17
15
  function textContent(sourcePath, token, i18n, warning, outContent, files, atNewLine) {
18
16
  let lastPartEnd = 0;
@@ -56,6 +54,11 @@ function textContent(sourcePath, token, i18n, warning, outContent, files, atNewL
56
54
  addRef(reference);
57
55
  continue;
58
56
  }
57
+ const tagLink = checkTagLink(data);
58
+ if (tagLink) {
59
+ addRef(tagLink);
60
+ continue;
61
+ }
59
62
  ++data.pos;
60
63
  }
61
64
  if (lastPartEnd !== token.text.length) {
@@ -138,6 +141,39 @@ function checkReference(data) {
138
141
  }
139
142
  }
140
143
  }
144
+ /**
145
+ * Looks for `<a href="./relative">` and `<img src="./relative">`
146
+ */
147
+ function checkTagLink(data) {
148
+ const { pos, token } = data;
149
+ if (token.text.startsWith("<img ", pos)) {
150
+ data.pos += 4;
151
+ return checkAttribute(data, "src");
152
+ }
153
+ if (token.text.startsWith("<a ", pos)) {
154
+ data.pos += 3;
155
+ return checkAttribute(data, "href");
156
+ }
157
+ }
158
+ function checkAttribute(data, attr) {
159
+ const parser = new html_1.HtmlAttributeParser(data.token.text, data.pos);
160
+ while (parser.state !== html_1.ParserState.END) {
161
+ if (parser.state === html_1.ParserState.BeforeAttributeValue &&
162
+ parser.currentAttributeName === attr) {
163
+ parser.step();
164
+ if (isRelativeLink(parser.currentAttributeValue)) {
165
+ data.pos = parser.pos;
166
+ return {
167
+ pos: parser.currentAttributeValueStart,
168
+ end: parser.currentAttributeValueEnd,
169
+ target: data.files.register(data.sourcePath, parser.currentAttributeValue),
170
+ };
171
+ }
172
+ return;
173
+ }
174
+ parser.step();
175
+ }
176
+ }
141
177
  function isRelativeLink(link) {
142
178
  return !/^[a-z]+:\/\/|^\/|^[a-z]:\\/i.test(link);
143
179
  }
@@ -1,5 +1,5 @@
1
1
  import ts from "typescript";
2
- import { type Reflection, type ProjectReflection, DeclarationReflection, ReflectionKind, type DocumentReflection } from "../models/index";
2
+ import { type Reflection, type ProjectReflection, DeclarationReflection, type DocumentReflection, ReflectionKind } from "../models/index";
3
3
  import type { Converter } from "./converter";
4
4
  import type { TranslationProxy } from "../internationalization/internationalization";
5
5
  /**
@@ -84,7 +84,7 @@ export declare class Context {
84
84
  /** @internal */
85
85
  setActiveProgram(program: ts.Program | undefined): void;
86
86
  getComment(symbol: ts.Symbol, kind: ReflectionKind): import("../models/index").Comment | undefined;
87
- getNodeComment(node: ts.Node, kind: ReflectionKind): import("../models/index").Comment | undefined;
87
+ getNodeComment(node: ts.Node, moduleComment: boolean): import("../models/index").Comment | undefined;
88
88
  getFileComment(node: ts.SourceFile): import("../models/index").Comment | undefined;
89
89
  getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag): import("../models/index").Comment | undefined;
90
90
  getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature): import("../models/index").Comment | undefined;
@@ -73,12 +73,10 @@ class Context {
73
73
  if (node.symbol) {
74
74
  nodeType = this.checker.getDeclaredTypeOfSymbol(node.symbol);
75
75
  // The TS types lie due to ts.SourceFile
76
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
77
76
  }
78
77
  else if (node.parent?.symbol) {
79
78
  nodeType = this.checker.getDeclaredTypeOfSymbol(node.parent.symbol);
80
79
  // The TS types lie due to ts.SourceFile
81
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
82
80
  }
83
81
  else if (node.parent?.parent?.symbol) {
84
82
  nodeType = this.checker.getDeclaredTypeOfSymbol(node.parent.parent.symbol);
@@ -190,8 +188,8 @@ class Context {
190
188
  getComment(symbol, kind) {
191
189
  return (0, comments_1.getComment)(symbol, kind, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined, this.project.files);
192
190
  }
193
- getNodeComment(node, kind) {
194
- return (0, comments_1.getNodeComment)(node, kind, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined, this.project.files);
191
+ getNodeComment(node, moduleComment) {
192
+ return (0, comments_1.getNodeComment)(node, moduleComment, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined, this.project.files);
195
193
  }
196
194
  getFileComment(node) {
197
195
  return (0, comments_1.getFileComment)(node, this.converter.config, this.logger, this.converter.commentStyle, this.converter.useTsLinkResolution ? this.checker : undefined, this.project.files);
@@ -177,5 +177,6 @@ export declare class Converter extends ChildableComponent<Application, Converter
177
177
  /** @internal */
178
178
  isExternal(symbol: ts.Symbol): boolean;
179
179
  processDocumentTags(reflection: Reflection, parent: ContainerReflection): void;
180
+ private addDocument;
180
181
  private _buildCommentParserConfig;
181
182
  }
@@ -221,11 +221,15 @@ let Converter = (() => {
221
221
  addProjectDocuments(project) {
222
222
  const projectDocuments = (0, utils_1.getDocumentEntryPoints)(this.application.logger, this.application.options);
223
223
  for (const { displayName, path } of projectDocuments) {
224
- const file = new utils_1.MinimalSourceFile((0, utils_1.readFile)(path), path);
225
- const { content, frontmatter } = this.parseRawComment(file, project.files);
226
- const docRefl = new index_1.DocumentReflection(displayName, project, content, frontmatter);
227
- project.addChild(docRefl);
228
- project.registerReflection(docRefl, undefined, path);
224
+ let file;
225
+ try {
226
+ file = new utils_1.MinimalSourceFile((0, utils_1.readFile)(path), path);
227
+ }
228
+ catch (error) {
229
+ this.application.logger.error(this.application.logger.i18n.failed_to_read_0_when_processing_project_document(path));
230
+ continue;
231
+ }
232
+ this.addDocument(project, file, displayName);
229
233
  }
230
234
  }
231
235
  /** @internal */
@@ -407,11 +411,56 @@ let Converter = (() => {
407
411
  this.application.logger.warn(this.application.logger.i18n.failed_to_read_0_when_processing_document_tag_in_1((0, paths_1.nicePath)(path), (0, paths_1.nicePath)(reflection.comment.sourcePath)));
408
412
  continue;
409
413
  }
410
- const { content, frontmatter } = this.parseRawComment(file, reflection.project.files);
411
- const docRefl = new index_1.DocumentReflection((0, path_1.basename)(file.fileName).replace(/\.[^.]+$/, ""), parent, content, frontmatter);
412
- parent.addChild(docRefl);
413
- parent.project.registerReflection(docRefl, undefined, file.fileName);
414
+ this.addDocument(parent, file, (0, path_1.basename)(file.fileName).replace(/\.[^.]+$/, ""));
415
+ }
416
+ }
417
+ }
418
+ addDocument(parent, file, displayName) {
419
+ const { content, frontmatter } = this.parseRawComment(file, parent.project.files);
420
+ const children = frontmatter["children"];
421
+ delete frontmatter["children"];
422
+ const docRefl = new index_1.DocumentReflection(displayName, parent, content, frontmatter);
423
+ parent.addChild(docRefl);
424
+ parent.project.registerReflection(docRefl, undefined, file.fileName);
425
+ const childrenToAdd = [];
426
+ if (children && typeof children === "object") {
427
+ if (Array.isArray(children)) {
428
+ for (const child of children) {
429
+ if (typeof child === "string") {
430
+ childrenToAdd.push([
431
+ (0, path_1.basename)(child).replace(/\.[^.]+$/, ""),
432
+ child,
433
+ ]);
434
+ }
435
+ else {
436
+ this.application.logger.error(this.application.i18n.frontmatter_children_0_should_be_an_array_of_strings_or_object_with_string_values((0, paths_1.nicePath)(file.fileName)));
437
+ return;
438
+ }
439
+ }
440
+ }
441
+ else {
442
+ for (const [name, path] of Object.entries(children)) {
443
+ if (typeof path === "string") {
444
+ childrenToAdd.push([name, path]);
445
+ }
446
+ else {
447
+ this.application.logger.error(this.application.i18n.frontmatter_children_0_should_be_an_array_of_strings_or_object_with_string_values((0, paths_1.nicePath)(file.fileName)));
448
+ return;
449
+ }
450
+ }
451
+ }
452
+ }
453
+ for (const [displayName, path] of childrenToAdd) {
454
+ const absPath = (0, path_1.resolve)((0, path_1.dirname)(file.fileName), path);
455
+ let childFile;
456
+ try {
457
+ childFile = new utils_1.MinimalSourceFile((0, utils_1.readFile)(absPath), absPath);
458
+ }
459
+ catch (error) {
460
+ this.application.logger.error(this.application.logger.i18n.failed_to_read_0_when_processing_document_child_in_1(path, (0, paths_1.nicePath)(file.fileName)));
461
+ continue;
414
462
  }
463
+ this.addDocument(docRefl, childFile, displayName);
415
464
  }
416
465
  }
417
466
  _buildCommentParserConfig() {
@@ -18,7 +18,7 @@ function convertIndexSignatures(context, symbol) {
18
18
  const param = indexDeclaration.parameters[0];
19
19
  (0, assert_1.default)(param && typescript_1.default.isParameter(param));
20
20
  const index = new models_1.SignatureReflection("__index", models_1.ReflectionKind.IndexSignature, context.scope);
21
- index.comment = context.getNodeComment(indexDeclaration, index.kind);
21
+ index.comment = context.getNodeComment(indexDeclaration, false);
22
22
  index.parameters = [
23
23
  new models_1.ParameterReflection(param.name.getText(), models_1.ReflectionKind.Parameter, index),
24
24
  ];
@@ -292,7 +292,7 @@ function findProperty(reflection, parent) {
292
292
  : prop.name === reflection.name;
293
293
  });
294
294
  }
295
- function createLink(context, reflection, clause, expr, symbol, isOverwrite) {
295
+ function createLink(context, reflection, clause, expr, symbol, isInherit) {
296
296
  const project = context.project;
297
297
  const name = `${expr.expression.getText()}.${(0, utils_1.getHumanName)(symbol.name)}`;
298
298
  link(reflection);
@@ -313,7 +313,8 @@ function createLink(context, reflection, clause, expr, symbol, isOverwrite) {
313
313
  target.implementationOf ??= types_1.ReferenceType.createBrokenReference(name, project);
314
314
  return;
315
315
  }
316
- if (isOverwrite) {
316
+ if (isInherit) {
317
+ target.setFlag(index_1.ReflectionFlag.Inherited);
317
318
  target.inheritedFrom ??= types_1.ReferenceType.createBrokenReference(name, project);
318
319
  }
319
320
  else {
@@ -86,6 +86,13 @@ let LinkResolverPlugin = (() => {
86
86
  if (reflection.comment) {
87
87
  this.owner.resolveLinks(reflection.comment, reflection);
88
88
  }
89
+ if (reflection.isDeclaration()) {
90
+ reflection.type?.visit((0, models_1.makeRecursiveVisitor)({
91
+ union: (type) => {
92
+ type.elementSummaries = type.elementSummaries?.map((parts) => this.owner.resolveLinks(parts, reflection));
93
+ },
94
+ }));
95
+ }
89
96
  if (reflection instanceof models_1.DeclarationReflection &&
90
97
  reflection.readme) {
91
98
  reflection.readme = this.owner.resolveLinks(reflection.readme, reflection);
@@ -13,14 +13,7 @@ export declare class SourcePlugin extends ConverterComponent {
13
13
  * All file names to find the base path from.
14
14
  */
15
15
  private fileNames;
16
- /**
17
- * List of known repositories.
18
- */
19
- private repositories;
20
- /**
21
- * List of paths known to be not under git control.
22
- */
23
- private ignoredPaths;
16
+ private repositories?;
24
17
  /**
25
18
  * Create a new SourceHandler instance.
26
19
  */
@@ -42,11 +35,4 @@ export declare class SourcePlugin extends ConverterComponent {
42
35
  * @param context The context object describing the current state the converter is in.
43
36
  */
44
37
  private onBeginResolve;
45
- /**
46
- * Check whether the given file is placed inside a repository.
47
- *
48
- * @param fileName The name of the file a repository should be looked for.
49
- * @returns The found repository info or undefined.
50
- */
51
- private getRepository;
52
38
  }
@@ -62,7 +62,6 @@ const nodes_1 = require("../utils/nodes");
62
62
  const path_1 = require("path");
63
63
  const models_1 = require("../../models");
64
64
  const repository_1 = require("../utils/repository");
65
- const base_path_1 = require("../utils/base-path");
66
65
  /**
67
66
  * A handler that attaches source file information to reflections.
68
67
  */
@@ -104,14 +103,6 @@ let SourcePlugin = (() => {
104
103
  * All file names to find the base path from.
105
104
  */
106
105
  this.fileNames = (__runInitializers(this, _basePath_extraInitializers), new Set());
107
- /**
108
- * List of known repositories.
109
- */
110
- this.repositories = {};
111
- /**
112
- * List of paths known to be not under git control.
113
- */
114
- this.ignoredPaths = new Set();
115
106
  }
116
107
  get disableSources() { return __classPrivateFieldGet(this, _SourcePlugin_disableSources_accessor_storage, "f"); }
117
108
  set disableSources(value) { __classPrivateFieldSet(this, _SourcePlugin_disableSources_accessor_storage, value, "f"); }
@@ -154,7 +145,7 @@ let SourcePlugin = (() => {
154
145
  const symbol = reflection.project.getSymbolFromReflection(reflection);
155
146
  for (const node of symbol?.declarations || []) {
156
147
  const sourceFile = node.getSourceFile();
157
- const fileName = base_path_1.BasePath.normalize(sourceFile.fileName);
148
+ const fileName = (0, utils_1.normalizePath)(sourceFile.fileName);
158
149
  this.fileNames.add(fileName);
159
150
  let position;
160
151
  if (typescript_1.default.isSourceFile(node)) {
@@ -171,7 +162,7 @@ let SourcePlugin = (() => {
171
162
  if (this.disableSources || !sig)
172
163
  return;
173
164
  const sourceFile = sig.getSourceFile();
174
- const fileName = base_path_1.BasePath.normalize(sourceFile.fileName);
165
+ const fileName = (0, utils_1.normalizePath)(sourceFile.fileName);
175
166
  this.fileNames.add(fileName);
176
167
  const position = typescript_1.default.getLineAndCharacterOfPosition(sourceFile, getLocationNode(sig).getStart());
177
168
  reflection.sources ||= [];
@@ -195,6 +186,7 @@ let SourcePlugin = (() => {
195
186
  this.application.logger.warn(context.i18n.disable_git_set_and_git_revision_used());
196
187
  }
197
188
  const basePath = this.basePath || (0, utils_1.getCommonDirectory)([...this.fileNames]);
189
+ this.repositories ||= new repository_1.RepositoryManager(basePath, this.gitRevision, this.gitRemote, this.sourceLinkTemplate, this.disableGit, this.application.logger);
198
190
  for (const id in context.project.reflections) {
199
191
  const refl = context.project.reflections[id];
200
192
  if (!(refl instanceof index_1.DeclarationReflection ||
@@ -206,46 +198,13 @@ let SourcePlugin = (() => {
206
198
  }
207
199
  for (const source of refl.sources || []) {
208
200
  if (this.disableGit || (0, repository_1.gitIsInstalled)()) {
209
- const repo = this.getRepository(basePath, source.fullFileName);
201
+ const repo = this.repositories.getRepository(source.fullFileName);
210
202
  source.url = repo?.getURL(source.fullFileName, source.line);
211
203
  }
212
204
  source.fileName = (0, utils_1.normalizePath)((0, path_1.relative)(basePath, source.fullFileName));
213
205
  }
214
206
  }
215
207
  }
216
- /**
217
- * Check whether the given file is placed inside a repository.
218
- *
219
- * @param fileName The name of the file a repository should be looked for.
220
- * @returns The found repository info or undefined.
221
- */
222
- getRepository(basePath, fileName) {
223
- if (this.disableGit) {
224
- return new repository_1.AssumedRepository(basePath, this.gitRevision, this.sourceLinkTemplate);
225
- }
226
- // Check for known non-repositories
227
- const dirName = (0, path_1.dirname)(fileName);
228
- const segments = dirName.split("/");
229
- for (let i = segments.length; i > 0; i--) {
230
- if (this.ignoredPaths.has(segments.slice(0, i).join("/"))) {
231
- return;
232
- }
233
- }
234
- // Check for known repositories
235
- for (const path of Object.keys(this.repositories)) {
236
- if (fileName.toLowerCase().startsWith(path)) {
237
- return this.repositories[path];
238
- }
239
- }
240
- // Try to create a new repository
241
- const repository = repository_1.GitRepository.tryCreateRepository(dirName, this.sourceLinkTemplate, this.gitRevision, this.gitRemote, this.application.logger);
242
- if (repository) {
243
- this.repositories[repository.path.toLowerCase()] = repository;
244
- return repository;
245
- }
246
- // No repository found, add path to ignored paths
247
- this.ignoredPaths.add(dirName);
248
- }
249
208
  };
250
209
  _SourcePlugin_disableSources_accessor_storage = new WeakMap();
251
210
  _SourcePlugin_gitRevision_accessor_storage = new WeakMap();
@@ -198,6 +198,9 @@ function convertTypeAlias(context, symbol, exportSymbol) {
198
198
  }
199
199
  const reflection = context.createDeclarationReflection(models_1.ReflectionKind.TypeAlias, symbol, exportSymbol);
200
200
  reflection.type = context.converter.convertType(context.withScope(reflection), declaration.type);
201
+ if (reflection.type.type === "union") {
202
+ attachUnionComments(context, declaration, reflection.type);
203
+ }
201
204
  context.finalizeDeclarationReflection(reflection);
202
205
  // Do this after finalization so that the CommentPlugin can get @typeParam tags
203
206
  // from the parent comment. Ugly, but works for now. Should be cleaned up eventually.
@@ -211,6 +214,25 @@ function convertTypeAlias(context, symbol, exportSymbol) {
211
214
  (0, jsdoc_1.convertJsDocCallback)(context, symbol, declaration, exportSymbol);
212
215
  }
213
216
  }
217
+ function attachUnionComments(context, declaration, union) {
218
+ const list = declaration.type.getChildAt(0);
219
+ if (list.kind !== typescript_1.default.SyntaxKind.SyntaxList)
220
+ return;
221
+ let unionIndex = 0;
222
+ for (const child of list.getChildren()) {
223
+ const comment = context.getNodeComment(child, false);
224
+ if (comment?.modifierTags.size || comment?.blockTags.length) {
225
+ context.logger.warn(context.logger.i18n.comment_for_0_should_not_contain_block_or_modifier_tags(`${context.scope.getFriendlyFullName()}.${unionIndex}`), child);
226
+ }
227
+ if (comment) {
228
+ union.elementSummaries ||= Array.from({ length: union.types.length }, () => []);
229
+ union.elementSummaries[unionIndex] = comment.summary;
230
+ }
231
+ if (child.kind !== typescript_1.default.SyntaxKind.BarToken) {
232
+ ++unionIndex;
233
+ }
234
+ }
235
+ }
214
236
  function convertTypeAliasAsInterface(context, symbol, exportSymbol, declaration) {
215
237
  const reflection = context.createDeclarationReflection(models_1.ReflectionKind.Interface, symbol, exportSymbol);
216
238
  context.finalizeDeclarationReflection(reflection);
@@ -53,7 +53,6 @@ function loadConverters() {
53
53
  jsDocNonNullableTypeConverter,
54
54
  ]) {
55
55
  for (const key of actor.kind) {
56
- // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
57
56
  if (key === undefined) {
58
57
  // Might happen if running on an older TS version.
59
58
  continue;
@@ -672,6 +671,7 @@ const unionConverter = {
672
671
  },
673
672
  convertType(context, type) {
674
673
  const types = type.types.map((type) => convertType(context, type));
674
+ normalizeUnion(types);
675
675
  sortLiteralUnion(types);
676
676
  return new models_1.UnionType(types);
677
677
  },
@@ -735,3 +735,22 @@ function sortLiteralUnion(types) {
735
735
  return aLit.value - bLit.value;
736
736
  });
737
737
  }
738
+ function normalizeUnion(types) {
739
+ let trueIndex = -1;
740
+ let falseIndex = -1;
741
+ for (let i = 0; i < types.length && (trueIndex === -1 || falseIndex === -1); i++) {
742
+ const t = types[i];
743
+ if (t instanceof models_1.LiteralType) {
744
+ if (t.value === true) {
745
+ trueIndex = i;
746
+ }
747
+ if (t.value === false) {
748
+ falseIndex = i;
749
+ }
750
+ }
751
+ }
752
+ if (trueIndex !== -1 && falseIndex !== -1) {
753
+ types.splice(Math.max(trueIndex, falseIndex), 1);
754
+ types.splice(Math.min(trueIndex, falseIndex), 1, new models_1.IntrinsicType("boolean"));
755
+ }
756
+ }
@@ -1,6 +1,7 @@
1
- import type { Logger } from "../../utils";
1
+ import { type Logger } from "../../utils";
2
2
  export declare function gitIsInstalled(): boolean;
3
3
  export interface Repository {
4
+ readonly path: string;
4
5
  getURL(fileName: string, line: number): string | undefined;
5
6
  }
6
7
  export declare class AssumedRepository implements Repository {
@@ -48,4 +49,48 @@ export declare class GitRepository implements Repository {
48
49
  */
49
50
  static tryCreateRepository(path: string, sourceLinkTemplate: string, gitRevision: string, gitRemote: string, logger: Logger): GitRepository | undefined;
50
51
  }
52
+ /**
53
+ * Responsible for keeping track of 0-N repositories which exist on a machine.
54
+ * This used to be inlined in SourcePlugin, moved out for easy unit testing.
55
+ *
56
+ * Git repositories can be nested. Files should be resolved to a repo as shown
57
+ * below:
58
+ * ```text
59
+ * /project
60
+ * /project/.git (A)
61
+ * /project/file.js (A)
62
+ * /project/folder/file.js (A)
63
+ * /project/sub/.git (B)
64
+ * /project/sub/file.js (B)
65
+ * ```
66
+ *
67
+ * In order words, it is not safe to assume that just because a file is within
68
+ * the `/project` directory, that it belongs to repo `A`. As calling git is
69
+ * expensive (~20-300ms depending on the machine, antivirus, etc.) we check for
70
+ * `.git` folders manually, and only call git if one is found.
71
+ *
72
+ * Symlinked files have the potential to further complicate this. If TypeScript's
73
+ * `preserveSymlinks` option is on, then this may be passed the path to a symlinked
74
+ * file. Unlike TypeScript, we will resolve the path, as the repo link should really
75
+ * point to the actual file.
76
+ */
77
+ export declare class RepositoryManager {
78
+ private basePath;
79
+ private gitRevision;
80
+ private gitRemote;
81
+ private sourceLinkTemplate;
82
+ private disableGit;
83
+ private logger;
84
+ private cache;
85
+ private assumedRepo;
86
+ constructor(basePath: string, gitRevision: string, gitRemote: string, sourceLinkTemplate: string, disableGit: boolean, logger: Logger);
87
+ /**
88
+ * Check whether the given file is placed inside a repository.
89
+ *
90
+ * @param fileName The name of the file a repository should be looked for.
91
+ * @returns The found repository info or undefined.
92
+ */
93
+ getRepository(fileName: string): Repository | undefined;
94
+ private getRepositoryFolder;
95
+ }
51
96
  export declare function guessSourceUrlTemplate(remotes: string[]): string | undefined;