typedoc 0.23.11 → 0.23.14

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 (37) hide show
  1. package/dist/index.d.ts +2 -2
  2. package/dist/lib/application-events.d.ts +3 -0
  3. package/dist/lib/application-events.js +6 -0
  4. package/dist/lib/application.d.ts +6 -0
  5. package/dist/lib/application.js +8 -0
  6. package/dist/lib/converter/comments/linkResolver.d.ts +3 -2
  7. package/dist/lib/converter/comments/linkResolver.js +23 -13
  8. package/dist/lib/converter/converter.d.ts +26 -4
  9. package/dist/lib/converter/converter.js +54 -6
  10. package/dist/lib/converter/index.d.ts +1 -0
  11. package/dist/lib/converter/plugins/LinkResolverPlugin.js +6 -0
  12. package/dist/lib/converter/types.js +6 -0
  13. package/dist/lib/converter/utils/nodes.js +1 -3
  14. package/dist/lib/models/types.d.ts +11 -1
  15. package/dist/lib/models/types.js +15 -0
  16. package/dist/lib/output/renderer.d.ts +4 -10
  17. package/dist/lib/output/renderer.js +12 -26
  18. package/dist/lib/output/themes/default/DefaultThemeRenderContext.d.ts +6 -1
  19. package/dist/lib/output/themes/default/DefaultThemeRenderContext.js +6 -1
  20. package/dist/lib/output/themes/default/partials/type.js +4 -7
  21. package/dist/lib/serialization/schema.d.ts +1 -1
  22. package/dist/lib/utils/entry-point.js +12 -1
  23. package/dist/lib/utils/fs.js +1 -5
  24. package/dist/lib/utils/index.d.ts +1 -1
  25. package/dist/lib/utils/options/declaration.d.ts +26 -6
  26. package/dist/lib/utils/options/declaration.js +16 -3
  27. package/dist/lib/utils/options/index.d.ts +1 -1
  28. package/dist/lib/utils/options/options.js +4 -1
  29. package/dist/lib/utils/options/sources/typedoc.js +22 -0
  30. package/dist/lib/utils/package-manifest.d.ts +2 -2
  31. package/dist/lib/utils/paths.d.ts +3 -3
  32. package/dist/lib/utils/reflections.d.ts +5 -0
  33. package/dist/lib/utils/reflections.js +68 -0
  34. package/dist/lib/validation/exports.d.ts +1 -1
  35. package/dist/lib/validation/exports.js +12 -64
  36. package/package.json +7 -7
  37. package/static/style.css +1 -0
package/dist/index.d.ts CHANGED
@@ -3,11 +3,11 @@ export { EventDispatcher, Event } from "./lib/utils/events";
3
3
  export { resetReflectionID } from "./lib/models/reflections/abstract";
4
4
  export { normalizePath } from "./lib/utils/fs";
5
5
  export * from "./lib/models";
6
- export { Converter, Context, type CommentParserConfig } from "./lib/converter";
6
+ export { Converter, Context, type CommentParserConfig, type DeclarationReference, type SymbolReference, type ComponentPath, type Meaning, type MeaningKeyword, } from "./lib/converter";
7
7
  export { Renderer, DefaultTheme, DefaultThemeRenderContext, UrlMapping, Theme, PageEvent, RendererEvent, MarkdownEvent, IndexEvent, } from "./lib/output";
8
8
  export type { RenderTemplate, RendererHooks } from "./lib/output";
9
9
  export { ArgumentsReader, BindOption, CommentStyle, JSX, LogLevel, Logger, Options, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, EntryPointStrategy, EventHooks, MinimalSourceFile, } from "./lib/utils";
10
- export type { OptionsReader, TypeDocOptions, TypeDocOptionMap, ValidationOptions, TypeDocOptionValues, KeyToDeclaration, DeclarationOption, DeclarationOptionBase, StringDeclarationOption, NumberDeclarationOption, BooleanDeclarationOption, ArrayDeclarationOption, MixedDeclarationOption, MapDeclarationOption, FlagsDeclarationOption, DeclarationOptionToOptionType, SortStrategy, ParameterTypeToOptionTypeMap, DocumentationEntryPoint, ManuallyValidatedOption, } from "./lib/utils";
10
+ export type { OptionsReader, TypeDocOptions, TypeDocOptionMap, ValidationOptions, TypeDocOptionValues, KeyToDeclaration, DeclarationOption, DeclarationOptionBase, StringDeclarationOption, NumberDeclarationOption, BooleanDeclarationOption, ArrayDeclarationOption, MixedDeclarationOption, ObjectDeclarationOption, MapDeclarationOption, FlagsDeclarationOption, DeclarationOptionToOptionType, SortStrategy, ParameterTypeToOptionTypeMap, DocumentationEntryPoint, ManuallyValidatedOption, } from "./lib/utils";
11
11
  export type { EventMap, EventCallback } from "./lib/utils/events";
12
12
  export { JSONOutput, Serializer, type SerializerComponent, SerializeEvent, } from "./lib/serialization";
13
13
  export type { SerializeEventData } from "./lib/serialization";
@@ -0,0 +1,3 @@
1
+ export declare const ApplicationEvents: {
2
+ BOOTSTRAP_END: string;
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ApplicationEvents = void 0;
4
+ exports.ApplicationEvents = {
5
+ BOOTSTRAP_END: "bootstrapEnd",
6
+ };
@@ -46,6 +46,12 @@ export declare class Application extends ChildableComponent<Application, Abstrac
46
46
  * The version number of TypeDoc.
47
47
  */
48
48
  static VERSION: string;
49
+ /**
50
+ * Emitted after plugins have been loaded and options have been read, but before they have been frozen.
51
+ * The listener will be given an instance of {@link Application} and the {@link TypeDocOptions | Partial<TypeDocOptions>}
52
+ * passed to `bootstrap`.
53
+ */
54
+ static readonly EVENT_BOOTSTRAP_END: string;
49
55
  /**
50
56
  * Create a new TypeDoc application instance.
51
57
  *
@@ -24,6 +24,7 @@ const general_1 = require("./utils/general");
24
24
  const exports_1 = require("./validation/exports");
25
25
  const documentation_1 = require("./validation/documentation");
26
26
  const links_1 = require("./validation/links");
27
+ const application_events_1 = require("./application-events");
27
28
  // eslint-disable-next-line @typescript-eslint/no-var-requires
28
29
  const packageInfo = require("../../package.json");
29
30
  const supportedVersionMajorMinor = packageInfo.peerDependencies.typescript
@@ -98,6 +99,7 @@ let Application = Application_1 = class Application extends component_1.Childabl
98
99
  if ((0, general_1.hasBeenLoadedMultipleTimes)()) {
99
100
  this.logger.warn(`TypeDoc has been loaded multiple times. This is commonly caused by plugins which have their own installation of TypeDoc. The loaded paths are:\n\t${(0, general_1.getLoadedPaths)().join("\n\t")}`);
100
101
  }
102
+ this.trigger(application_events_1.ApplicationEvents.BOOTSTRAP_END, this, options);
101
103
  }
102
104
  /**
103
105
  * Return the path to the TypeScript compiler.
@@ -304,6 +306,12 @@ let Application = Application_1 = class Application extends component_1.Childabl
304
306
  * The version number of TypeDoc.
305
307
  */
306
308
  Application.VERSION = packageInfo.version;
309
+ /**
310
+ * Emitted after plugins have been loaded and options have been read, but before they have been frozen.
311
+ * The listener will be given an instance of {@link Application} and the {@link TypeDocOptions | Partial<TypeDocOptions>}
312
+ * passed to `bootstrap`.
313
+ */
314
+ Application.EVENT_BOOTSTRAP_END = application_events_1.ApplicationEvents.BOOTSTRAP_END;
307
315
  __decorate([
308
316
  (0, utils_1.BindOption)("logger")
309
317
  ], Application.prototype, "loggerType", void 0);
@@ -1,4 +1,5 @@
1
1
  import { Comment, CommentDisplayPart, Reflection } from "../../models";
2
2
  import type { Logger, ValidationOptions } from "../../utils";
3
- export declare function resolveLinks(comment: Comment, reflection: Reflection, validation: ValidationOptions, logger: Logger): void;
4
- export declare function resolvePartLinks(reflection: Reflection, parts: readonly CommentDisplayPart[], warn: () => void, validation: ValidationOptions, logger: Logger): CommentDisplayPart[];
3
+ import { DeclarationReference } from "./declarationReference";
4
+ export declare function resolveLinks(comment: Comment, reflection: Reflection, validation: ValidationOptions, logger: Logger, attemptExternalResolve: (ref: DeclarationReference) => string | undefined): void;
5
+ export declare function resolvePartLinks(reflection: Reflection, parts: readonly CommentDisplayPart[], warn: () => void, validation: ValidationOptions, logger: Logger, attemptExternalResolve: (ref: DeclarationReference) => string | undefined): CommentDisplayPart[];
@@ -7,7 +7,7 @@ const declarationReference_1 = require("./declarationReference");
7
7
  const declarationReferenceResolver_1 = require("./declarationReferenceResolver");
8
8
  const urlPrefix = /^(http|ftp)s?:\/\//;
9
9
  const brackets = /\[\[(?!include:)([^\]]+)\]\]/g;
10
- function resolveLinks(comment, reflection, validation, logger) {
10
+ function resolveLinks(comment, reflection, validation, logger, attemptExternalResolve) {
11
11
  let warned = false;
12
12
  const warn = () => {
13
13
  if (!warned) {
@@ -15,20 +15,20 @@ function resolveLinks(comment, reflection, validation, logger) {
15
15
  logger.warn(`${reflection.getFriendlyFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24`);
16
16
  }
17
17
  };
18
- comment.summary = resolvePartLinks(reflection, comment.summary, warn, validation, logger);
18
+ comment.summary = resolvePartLinks(reflection, comment.summary, warn, validation, logger, attemptExternalResolve);
19
19
  for (const tag of comment.blockTags) {
20
- tag.content = resolvePartLinks(reflection, tag.content, warn, validation, logger);
20
+ tag.content = resolvePartLinks(reflection, tag.content, warn, validation, logger, attemptExternalResolve);
21
21
  }
22
22
  if (reflection instanceof models_1.DeclarationReflection && reflection.readme) {
23
- reflection.readme = resolvePartLinks(reflection, reflection.readme, warn, validation, logger);
23
+ reflection.readme = resolvePartLinks(reflection, reflection.readme, warn, validation, logger, attemptExternalResolve);
24
24
  }
25
25
  }
26
26
  exports.resolveLinks = resolveLinks;
27
- function resolvePartLinks(reflection, parts, warn, validation, logger) {
28
- return parts.flatMap((part) => processPart(reflection, part, warn, validation, logger));
27
+ function resolvePartLinks(reflection, parts, warn, validation, logger, attemptExternalResolve) {
28
+ return parts.flatMap((part) => processPart(reflection, part, warn, validation, logger, attemptExternalResolve));
29
29
  }
30
30
  exports.resolvePartLinks = resolvePartLinks;
31
- function processPart(reflection, part, warn, validation, logger) {
31
+ function processPart(reflection, part, warn, validation, logger, attemptExternalResolve) {
32
32
  if (part.kind === "text" && brackets.test(part.text)) {
33
33
  warn();
34
34
  return replaceBrackets(reflection, part.text, validation, logger);
@@ -37,7 +37,7 @@ function processPart(reflection, part, warn, validation, logger) {
37
37
  if (part.tag === "@link" ||
38
38
  part.tag === "@linkcode" ||
39
39
  part.tag === "@linkplain") {
40
- return resolveLinkTag(reflection, part, (msg) => {
40
+ return resolveLinkTag(reflection, part, attemptExternalResolve, (msg) => {
41
41
  if (validation.invalidLink) {
42
42
  logger.warn(msg);
43
43
  }
@@ -46,7 +46,7 @@ function processPart(reflection, part, warn, validation, logger) {
46
46
  }
47
47
  return part;
48
48
  }
49
- function resolveLinkTag(reflection, part, warn) {
49
+ function resolveLinkTag(reflection, part, attemptExternalResolve, warn) {
50
50
  let pos = 0;
51
51
  const end = part.text.length;
52
52
  while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
@@ -56,10 +56,21 @@ function resolveLinkTag(reflection, part, warn) {
56
56
  // Try to parse one
57
57
  const declRef = (0, declarationReference_1.parseDeclarationReference)(part.text, pos, end);
58
58
  let target;
59
+ let defaultDisplayText;
59
60
  if (declRef) {
60
61
  // Got one, great! Try to resolve the link
61
62
  target = (0, declarationReferenceResolver_1.resolveDeclarationReference)(reflection, declRef[0]);
62
63
  pos = declRef[1];
64
+ if (target) {
65
+ defaultDisplayText = target.name;
66
+ }
67
+ else {
68
+ // If we didn't find a link, it might be a @link tag to an external symbol, check that next.
69
+ target = attemptExternalResolve(declRef[0]);
70
+ if (target) {
71
+ defaultDisplayText = part.text.substring(0, pos);
72
+ }
73
+ }
63
74
  }
64
75
  if (!target) {
65
76
  if (urlPrefix.test(part.text)) {
@@ -67,13 +78,14 @@ function resolveLinkTag(reflection, part, warn) {
67
78
  target =
68
79
  wsIndex === -1 ? part.text : part.text.substring(0, wsIndex);
69
80
  pos = target.length;
81
+ defaultDisplayText = target;
70
82
  }
71
83
  }
72
84
  // If resolution via a declaration reference failed, revert to the legacy "split and check"
73
85
  // method... this should go away in 0.24, once people have had a chance to migrate any failing links.
74
86
  if (!target) {
75
87
  const resolved = legacyResolveLinkTag(reflection, part);
76
- if (resolved) {
88
+ if (resolved.target) {
77
89
  warn(`Failed to resolve {@link ${origText}} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.`);
78
90
  }
79
91
  return resolved;
@@ -87,9 +99,7 @@ function resolveLinkTag(reflection, part, warn) {
87
99
  pos++;
88
100
  }
89
101
  part.target = target;
90
- part.text =
91
- part.text.substring(pos).trim() ||
92
- (typeof target === "string" ? target : target.name);
102
+ part.text = part.text.substring(pos).trim() || defaultDisplayText;
93
103
  return part;
94
104
  }
95
105
  function legacyResolveLinkTag(reflection, part) {
@@ -8,25 +8,31 @@ import { MinimalSourceFile } from "../utils";
8
8
  import type { DocumentationEntryPoint } from "../utils/entry-point";
9
9
  import { CommentParserConfig } from "./comments";
10
10
  import type { CommentStyle, ValidationOptions } from "../utils/options/declaration";
11
+ import type { DeclarationReference } from "./comments/declarationReference";
11
12
  /**
12
13
  * Compiles source files using TypeScript and converts compiler symbols to reflections.
13
14
  */
14
15
  export declare class Converter extends ChildableComponent<Application, ConverterComponent> {
15
- /**
16
- * The human readable name of the project. Used within the templates to set the title of the document.
17
- */
18
- name: string;
16
+ /** @internal */
19
17
  externalPattern: string[];
20
18
  private externalPatternCache?;
21
19
  private excludeCache?;
20
+ /** @internal */
22
21
  excludeExternals: boolean;
22
+ /** @internal */
23
23
  excludeNotDocumented: boolean;
24
+ /** @internal */
24
25
  excludePrivate: boolean;
26
+ /** @internal */
25
27
  excludeProtected: boolean;
28
+ /** @internal */
26
29
  commentStyle: CommentStyle;
27
30
  /** @internal */
28
31
  validation: ValidationOptions;
32
+ /** @internal */
33
+ externalSymbolLinkMappings: Record<string, Record<string, string>>;
29
34
  private _config?;
35
+ private _externalSymbolResolvers;
30
36
  get config(): CommentParserConfig;
31
37
  /**
32
38
  * General events
@@ -92,6 +98,7 @@ export declare class Converter extends ChildableComponent<Application, Converter
92
98
  * @event
93
99
  */
94
100
  static readonly EVENT_RESOLVE_END: "resolveEnd";
101
+ constructor(owner: Application);
95
102
  /**
96
103
  * Compile the given source files and create a project reflection for them.
97
104
  */
@@ -111,6 +118,21 @@ export declare class Converter extends ChildableComponent<Application, Converter
111
118
  * Parse the given file into a comment. Intended to be used with markdown files.
112
119
  */
113
120
  parseRawComment(file: MinimalSourceFile): Comment;
121
+ /**
122
+ * Adds a new resolver that the theme can use to try to figure out how to link to a symbol declared
123
+ * by a third-party library which is not included in the documentation.
124
+ *
125
+ * The resolver function will be passed a declaration reference which it can attempt to resolve. If
126
+ * resolution fails, the function should return undefined.
127
+ *
128
+ * Note: This will be used for both references to types declared in node_modules (in which case the
129
+ * reference passed will have the `moduleSource` set and the `symbolReference` will navigate via `.`)
130
+ * and user defined \{\@link\} tags which cannot be resolved.
131
+ * @since 0.22.14
132
+ */
133
+ addUnknownSymbolResolver(resolver: (ref: DeclarationReference) => string | undefined): void;
134
+ /** @internal */
135
+ resolveExternalLink(ref: DeclarationReference): string | undefined;
114
136
  resolveLinks(comment: Comment, owner: Reflection): void;
115
137
  resolveLinks(parts: readonly CommentDisplayPart[], owner: Reflection): CommentDisplayPart[];
116
138
  /**
@@ -27,6 +27,31 @@ const linkResolver_1 = require("./comments/linkResolver");
27
27
  * Compiles source files using TypeScript and converts compiler symbols to reflections.
28
28
  */
29
29
  let Converter = Converter_1 = class Converter extends component_1.ChildableComponent {
30
+ constructor(owner) {
31
+ super(owner);
32
+ this._externalSymbolResolvers = [];
33
+ this.addUnknownSymbolResolver((ref) => {
34
+ // Require global links, matching local ones will likely hide mistakes where the
35
+ // user meant to link to a local type.
36
+ if (ref.resolutionStart !== "global" || !ref.symbolReference) {
37
+ return;
38
+ }
39
+ const modLinks = this.externalSymbolLinkMappings[ref.moduleSource ?? "global"];
40
+ if (typeof modLinks !== "object") {
41
+ return;
42
+ }
43
+ let name = "";
44
+ if (ref.symbolReference.path) {
45
+ name += ref.symbolReference.path.map((p) => p.path).join(".");
46
+ }
47
+ if (ref.symbolReference.meaning) {
48
+ name += ":" + ref.symbolReference.meaning;
49
+ }
50
+ if (typeof modLinks[name] === "string") {
51
+ return modLinks[name];
52
+ }
53
+ });
54
+ }
30
55
  get config() {
31
56
  return this._config || this._buildCommentParserConfig();
32
57
  }
@@ -36,7 +61,7 @@ let Converter = Converter_1 = class Converter extends component_1.ChildableCompo
36
61
  convert(entryPoints) {
37
62
  const programs = entryPoints.map((e) => e.program);
38
63
  this.externalPatternCache = void 0;
39
- const project = new index_1.ProjectReflection(this.name);
64
+ const project = new index_1.ProjectReflection(this.application.options.getValue("name"));
40
65
  const context = new context_1.Context(this, programs, project);
41
66
  this.trigger(Converter_1.EVENT_BEGIN, context);
42
67
  this.compile(entryPoints, context);
@@ -67,9 +92,32 @@ let Converter = Converter_1 = class Converter extends component_1.ChildableCompo
67
92
  parseRawComment(file) {
68
93
  return (0, parser_1.parseComment)((0, rawLexer_1.lexCommentString)(file.text), this.config, file, this.application.logger);
69
94
  }
95
+ /**
96
+ * Adds a new resolver that the theme can use to try to figure out how to link to a symbol declared
97
+ * by a third-party library which is not included in the documentation.
98
+ *
99
+ * The resolver function will be passed a declaration reference which it can attempt to resolve. If
100
+ * resolution fails, the function should return undefined.
101
+ *
102
+ * Note: This will be used for both references to types declared in node_modules (in which case the
103
+ * reference passed will have the `moduleSource` set and the `symbolReference` will navigate via `.`)
104
+ * and user defined \{\@link\} tags which cannot be resolved.
105
+ * @since 0.22.14
106
+ */
107
+ addUnknownSymbolResolver(resolver) {
108
+ this._externalSymbolResolvers.push(resolver);
109
+ }
110
+ /** @internal */
111
+ resolveExternalLink(ref) {
112
+ for (const resolver of this._externalSymbolResolvers) {
113
+ const resolved = resolver(ref);
114
+ if (resolved)
115
+ return resolved;
116
+ }
117
+ }
70
118
  resolveLinks(comment, owner) {
71
119
  if (comment instanceof index_1.Comment) {
72
- (0, linkResolver_1.resolveLinks)(comment, owner, this.validation, this.owner.logger);
120
+ (0, linkResolver_1.resolveLinks)(comment, owner, this.validation, this.owner.logger, (ref) => this.resolveExternalLink(ref));
73
121
  }
74
122
  else {
75
123
  let warned = false;
@@ -79,7 +127,7 @@ let Converter = Converter_1 = class Converter extends component_1.ChildableCompo
79
127
  this.application.logger.warn(`${owner.name}: Comment [[target]] style links are deprecated and will be removed in 0.24`);
80
128
  }
81
129
  };
82
- return (0, linkResolver_1.resolvePartLinks)(owner, comment, warn, this.validation, this.owner.logger);
130
+ return (0, linkResolver_1.resolvePartLinks)(owner, comment, warn, this.validation, this.owner.logger, (ref) => this.resolveExternalLink(ref));
83
131
  }
84
132
  }
85
133
  /**
@@ -262,9 +310,6 @@ Converter.EVENT_RESOLVE = converter_events_1.ConverterEvents.RESOLVE;
262
310
  * @event
263
311
  */
264
312
  Converter.EVENT_RESOLVE_END = converter_events_1.ConverterEvents.RESOLVE_END;
265
- __decorate([
266
- (0, utils_1.BindOption)("name")
267
- ], Converter.prototype, "name", void 0);
268
313
  __decorate([
269
314
  (0, utils_1.BindOption)("externalPattern")
270
315
  ], Converter.prototype, "externalPattern", void 0);
@@ -286,6 +331,9 @@ __decorate([
286
331
  __decorate([
287
332
  (0, utils_1.BindOption)("validation")
288
333
  ], Converter.prototype, "validation", void 0);
334
+ __decorate([
335
+ (0, utils_1.BindOption)("externalSymbolLinkMappings")
336
+ ], Converter.prototype, "externalSymbolLinkMappings", void 0);
289
337
  Converter = Converter_1 = __decorate([
290
338
  (0, component_1.Component)({
291
339
  name: "converter",
@@ -2,4 +2,5 @@ export { Context } from "./context";
2
2
  export { Converter } from "./converter";
3
3
  export type { CommentParserConfig } from "./comments/index";
4
4
  export { convertDefaultValue, convertExpression } from "./convert-expression";
5
+ export type { DeclarationReference, SymbolReference, ComponentPath, Meaning, MeaningKeyword, } from "./comments/declarationReference";
5
6
  import "./plugins/index";
@@ -11,6 +11,7 @@ const components_1 = require("../components");
11
11
  const converter_events_1 = require("../converter-events");
12
12
  const utils_1 = require("../../utils");
13
13
  const models_1 = require("../../models");
14
+ const reflections_1 = require("../../utils/reflections");
14
15
  /**
15
16
  * A plugin that resolves `{@link Foo}` tags.
16
17
  */
@@ -35,6 +36,11 @@ let LinkResolverPlugin = class LinkResolverPlugin extends components_1.Converter
35
36
  if (context.project.readme) {
36
37
  context.project.readme = context.converter.resolveLinks(context.project.readme, context.project);
37
38
  }
39
+ for (const { type } of (0, reflections_1.discoverAllReferenceTypes)(context.project, false)) {
40
+ if (!type.reflection) {
41
+ type.externalUrl = context.converter.resolveExternalLink(type.toDeclarationReference());
42
+ }
43
+ }
38
44
  }
39
45
  };
40
46
  __decorate([
@@ -348,6 +348,9 @@ const typeLiteralConverter = {
348
348
  for (const signature of type.getCallSignatures()) {
349
349
  (0, signature_1.createSignature)(rc, models_1.ReflectionKind.CallSignature, signature);
350
350
  }
351
+ for (const signature of type.getConstructSignatures()) {
352
+ (0, signature_1.createSignature)(rc, models_1.ReflectionKind.ConstructorSignature, signature);
353
+ }
351
354
  (0, index_signature_1.convertIndexSignature)(rc, symbol);
352
355
  return new models_1.ReflectionType(reflection);
353
356
  },
@@ -364,6 +367,9 @@ const typeLiteralConverter = {
364
367
  for (const signature of type.getCallSignatures()) {
365
368
  (0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.CallSignature, signature);
366
369
  }
370
+ for (const signature of type.getConstructSignatures()) {
371
+ (0, signature_1.createSignature)(context.withScope(reflection), models_1.ReflectionKind.ConstructorSignature, signature);
372
+ }
367
373
  (0, index_signature_1.convertIndexSignature)(context.withScope(reflection), type.symbol);
368
374
  return new models_1.ReflectionType(reflection);
369
375
  },
@@ -4,9 +4,7 @@ exports.getHeritageTypes = exports.isNamedNode = void 0;
4
4
  const ts = require("typescript");
5
5
  function isNamedNode(node) {
6
6
  const name = node.name;
7
- return (!!name &&
8
- (ts.isIdentifierOrPrivateIdentifier(name) ||
9
- ts.isComputedPropertyName(name)));
7
+ return !!name && (ts.isMemberName(name) || ts.isComputedPropertyName(name));
10
8
  }
11
9
  exports.isNamedNode = isNamedNode;
12
10
  function getHeritageTypes(declarations, kind) {
@@ -4,6 +4,7 @@ import { Reflection } from "./reflections/abstract";
4
4
  import type { DeclarationReflection } from "./reflections/declaration";
5
5
  import type { ProjectReflection } from "./reflections/project";
6
6
  import type { Serializer, JSONOutput } from "../serialization";
7
+ import type { DeclarationReference } from "../converter/comments/declarationReference";
7
8
  /**
8
9
  * Base class of all type definitions.
9
10
  */
@@ -320,6 +321,10 @@ export declare class ReferenceType extends Type {
320
321
  * @internal
321
322
  */
322
323
  getSymbol(): ts.Symbol | undefined;
324
+ /**
325
+ * Convert this reference type to a declaration reference used for resolution of external types.
326
+ */
327
+ toDeclarationReference(): DeclarationReference;
323
328
  /**
324
329
  * The fully qualified name of the referenced type, relative to the file it is defined in.
325
330
  * This will usually be the same as `name`, unless namespaces are used.
@@ -330,10 +335,15 @@ export declare class ReferenceType extends Type {
330
335
  * Will only be set for `ReferenceType`s pointing to a symbol within `node_modules`.
331
336
  */
332
337
  package?: string;
338
+ /**
339
+ * If this reference type refers to a reflection defined by a project not being rendered,
340
+ * points to the url that this type should be linked to.
341
+ */
342
+ externalUrl?: string;
333
343
  private _target;
334
344
  private _project;
335
345
  private constructor();
336
- static createResolvedReference(name: string, target: Reflection | number, project: ProjectReflection | null): ReferenceType;
346
+ static createResolvedReference(name: string, target: Reflection | number, project: ProjectReflection): ReferenceType;
337
347
  static createSymbolReference(symbol: ts.Symbol, context: Context, name?: string): ReferenceType;
338
348
  /** @internal this is used for type parameters, which don't actually point to something */
339
349
  static createBrokenReference(name: string, project: ProjectReflection): ReferenceType;
@@ -661,6 +661,20 @@ class ReferenceType extends Type {
661
661
  }
662
662
  return this._target;
663
663
  }
664
+ /**
665
+ * Convert this reference type to a declaration reference used for resolution of external types.
666
+ */
667
+ toDeclarationReference() {
668
+ return {
669
+ resolutionStart: "global",
670
+ moduleSource: this.package,
671
+ symbolReference: {
672
+ path: this.qualifiedName
673
+ .split(".")
674
+ .map((p) => ({ path: p, navigation: "." })),
675
+ },
676
+ };
677
+ }
664
678
  static createResolvedReference(name, target, project) {
665
679
  return new ReferenceType(name, target, project, name);
666
680
  }
@@ -709,6 +723,7 @@ class ReferenceType extends Type {
709
723
  id: this.reflection?.id,
710
724
  typeArguments: serializer.toObjectsOptional(this.typeArguments),
711
725
  name: this.name,
726
+ externalUrl: this.externalUrl,
712
727
  };
713
728
  if (this.package) {
714
729
  result.qualifiedName = this.qualifiedName;
@@ -5,7 +5,6 @@ import { RendererComponent } from "./components";
5
5
  import { ChildableComponent } from "../utils/component";
6
6
  import { EventHooks } from "../utils";
7
7
  import type { Theme as ShikiTheme } from "shiki";
8
- import { ReferenceType } from "../models";
9
8
  import type { JsxElement } from "../utils/jsx.elements";
10
9
  import type { DefaultThemeRenderContext } from "./themes/default/DefaultThemeRenderContext";
11
10
  /**
@@ -80,7 +79,6 @@ export interface RendererHooks {
80
79
  */
81
80
  export declare class Renderer extends ChildableComponent<Application, RendererComponent> {
82
81
  private themes;
83
- private unknownSymbolResolvers;
84
82
  /** @event */
85
83
  static readonly EVENT_BEGIN_PAGE = "beginPage";
86
84
  /** @event */
@@ -125,7 +123,7 @@ export declare class Renderer extends ChildableComponent<Application, RendererCo
125
123
  */
126
124
  defineTheme(name: string, theme: new (renderer: Renderer) => Theme): void;
127
125
  /**
128
- * Adds a new resolver that the theme can used to try to figure out how to link to a symbol
126
+ * Adds a new resolver that the theme can use to try to figure out how to link to a symbol
129
127
  * declared by a third-party library which is not included in the documentation.
130
128
  * @param packageName the npm package name that this resolver can handle to limit which files it will be tried on.
131
129
  * If the resolver will create links for Node builtin types, it should be set to `@types/node`.
@@ -133,15 +131,11 @@ export declare class Renderer extends ChildableComponent<Application, RendererCo
133
131
  * @param resolver a function that will be called to create links for a given symbol name in the registered path.
134
132
  * If the provided name is not contained within the docs, should return `undefined`.
135
133
  * @since 0.22.0
134
+ * @deprecated
135
+ * Deprecated since v0.23.14, use {@link Converter.addUnknownSymbolResolver | Converter.addUnknownSymbolResolver} instead.
136
+ * This signature will be removed in 0.24 or possibly 0.25.
136
137
  */
137
138
  addUnknownSymbolResolver(packageName: string, resolver: (name: string) => string | undefined): void;
138
- /**
139
- * Marked as internal for now. Using this requires the internal `getSymbol()` method on ReferenceType.
140
- * Someday that needs to be fixed so that this can be made public. ReferenceTypes really shouldn't store
141
- * symbols so that we don't need to keep the program around forever.
142
- * @internal
143
- */
144
- attemptExternalResolution(type: ReferenceType): string | undefined;
145
139
  /**
146
140
  * Render the given project reflection to the specified output directory.
147
141
  *
@@ -64,7 +64,6 @@ let Renderer = class Renderer extends component_1.ChildableComponent {
64
64
  this.themes = new Map([
65
65
  ["default", DefaultTheme_1.DefaultTheme],
66
66
  ]);
67
- this.unknownSymbolResolvers = new Map();
68
67
  /**
69
68
  * Hooks which will be called when rendering pages.
70
69
  * Note:
@@ -89,7 +88,7 @@ let Renderer = class Renderer extends component_1.ChildableComponent {
89
88
  this.themes.set(name, theme);
90
89
  }
91
90
  /**
92
- * Adds a new resolver that the theme can used to try to figure out how to link to a symbol
91
+ * Adds a new resolver that the theme can use to try to figure out how to link to a symbol
93
92
  * declared by a third-party library which is not included in the documentation.
94
93
  * @param packageName the npm package name that this resolver can handle to limit which files it will be tried on.
95
94
  * If the resolver will create links for Node builtin types, it should be set to `@types/node`.
@@ -97,32 +96,19 @@ let Renderer = class Renderer extends component_1.ChildableComponent {
97
96
  * @param resolver a function that will be called to create links for a given symbol name in the registered path.
98
97
  * If the provided name is not contained within the docs, should return `undefined`.
99
98
  * @since 0.22.0
99
+ * @deprecated
100
+ * Deprecated since v0.23.14, use {@link Converter.addUnknownSymbolResolver | Converter.addUnknownSymbolResolver} instead.
101
+ * This signature will be removed in 0.24 or possibly 0.25.
100
102
  */
101
103
  addUnknownSymbolResolver(packageName, resolver) {
102
- const existing = this.unknownSymbolResolvers.get(packageName);
103
- if (existing) {
104
- existing.push(resolver);
105
- }
106
- else {
107
- this.unknownSymbolResolvers.set(packageName, [resolver]);
108
- }
109
- }
110
- /**
111
- * Marked as internal for now. Using this requires the internal `getSymbol()` method on ReferenceType.
112
- * Someday that needs to be fixed so that this can be made public. ReferenceTypes really shouldn't store
113
- * symbols so that we don't need to keep the program around forever.
114
- * @internal
115
- */
116
- attemptExternalResolution(type) {
117
- if (!type.qualifiedName || !type.package) {
118
- return;
119
- }
120
- const resolvers = this.unknownSymbolResolvers.get(type.package);
121
- for (const resolver of resolvers || []) {
122
- const resolved = resolver(type.qualifiedName);
123
- if (resolved)
124
- return resolved;
125
- }
104
+ this.owner.converter.addUnknownSymbolResolver((ref) => {
105
+ const path = ref.symbolReference?.path
106
+ ?.map((path) => path.path)
107
+ .join(".");
108
+ if (ref.moduleSource === packageName && path) {
109
+ return resolver(path);
110
+ }
111
+ });
126
112
  }
127
113
  /**
128
114
  * Render the given project reflection to the specified output directory.
@@ -12,7 +12,12 @@ export declare class DefaultThemeRenderContext {
12
12
  relativeURL: (url: string | undefined) => string | undefined;
13
13
  urlTo: (reflection: Reflection) => string | undefined;
14
14
  markdown: (md: readonly CommentDisplayPart[] | NeverIfInternal<string | undefined>) => string;
15
- attemptExternalResolution: (type: ReferenceType) => string | undefined;
15
+ /**
16
+ * Using this method will repeat work already done, instead of calling it, use `type.externalUrl`.
17
+ * @deprecated
18
+ * Will be removed in 0.24.
19
+ */
20
+ attemptExternalResolution: (type: NeverIfInternal<ReferenceType>) => string | undefined;
16
21
  reflectionTemplate: (props: import("../..").PageEvent<import("../../../models").ContainerReflection>) => import("../../../utils/jsx.elements").JsxElement;
17
22
  indexTemplate: (props: import("../..").PageEvent<import("../../../models").ProjectReflection>) => import("../../../utils/jsx.elements").JsxElement;
18
23
  defaultLayout: (props: import("../..").PageEvent<Reflection>) => import("../../../utils/jsx.elements").JsxElement;
@@ -48,8 +48,13 @@ class DefaultThemeRenderContext {
48
48
  }
49
49
  return md ? this.theme.markedPlugin.parseMarkdown(md) : "";
50
50
  };
51
+ /**
52
+ * Using this method will repeat work already done, instead of calling it, use `type.externalUrl`.
53
+ * @deprecated
54
+ * Will be removed in 0.24.
55
+ */
51
56
  this.attemptExternalResolution = (type) => {
52
- return this.theme.owner.attemptExternalResolution(type);
57
+ return type.externalUrl;
53
58
  };
54
59
  this.reflectionTemplate = bind(reflection_1.reflectionTemplate, this);
55
60
  this.indexTemplate = bind(templates_1.indexTemplate, this);
@@ -175,14 +175,11 @@ const typeRenderers = {
175
175
  name = renderUniquePath(context, reflection);
176
176
  }
177
177
  }
178
+ else if (type.externalUrl) {
179
+ name = (utils_1.JSX.createElement("a", { href: type.externalUrl, class: "tsd-signature-type external", target: "_blank" }, type.name));
180
+ }
178
181
  else {
179
- const externalUrl = context.attemptExternalResolution(type);
180
- if (externalUrl) {
181
- name = (utils_1.JSX.createElement("a", { href: externalUrl, class: "tsd-signature-type external", target: "_blank" }, type.name));
182
- }
183
- else {
184
- name = utils_1.JSX.createElement("span", { class: "tsd-signature-type" }, type.name);
185
- }
182
+ name = utils_1.JSX.createElement("span", { class: "tsd-signature-type" }, type.name);
186
183
  }
187
184
  if (type.typeArguments?.length) {
188
185
  return (utils_1.JSX.createElement(utils_1.JSX.Fragment, null,
@@ -119,7 +119,7 @@ export interface PredicateType extends Type, S<M.PredicateType, "type" | "name"
119
119
  }
120
120
  export interface QueryType extends Type, S<M.QueryType, "type" | "queryType"> {
121
121
  }
122
- export interface ReferenceType extends Type, S<M.ReferenceType, "type" | "name" | "typeArguments" | "package"> {
122
+ export interface ReferenceType extends Type, S<M.ReferenceType, "type" | "name" | "typeArguments" | "package" | "externalUrl"> {
123
123
  id?: number;
124
124
  qualifiedName?: string;
125
125
  }
@@ -9,6 +9,7 @@ const package_manifest_1 = require("./package-manifest");
9
9
  const paths_1 = require("./paths");
10
10
  const fs_1 = require("./fs");
11
11
  const validation_1 = require("./validation");
12
+ const array_1 = require("./array");
12
13
  /**
13
14
  * Defines how entry points are interpreted.
14
15
  * @enum
@@ -191,6 +192,15 @@ function expandInputFiles(logger, entryPoints, options) {
191
192
  });
192
193
  return files;
193
194
  }
195
+ function deriveRootDir(packageGlobPaths) {
196
+ const globs = (0, paths_1.createMinimatch)(packageGlobPaths);
197
+ const rootPaths = globs.flatMap((glob) => (0, array_1.filterMap)(glob.set, (set) => {
198
+ const stop = set.findIndex((part) => typeof part !== "string");
199
+ const path = stop === -1 ? set : set.slice(0, stop);
200
+ return `/${path.join("/")}`;
201
+ }));
202
+ return (0, fs_1.getCommonDirectory)(rootPaths);
203
+ }
194
204
  /**
195
205
  * Expand the provided packages configuration paths, determining the entry points
196
206
  * and creating the ts.Programs for any which are found.
@@ -201,9 +211,10 @@ function expandInputFiles(logger, entryPoints, options) {
201
211
  function getEntryPointsForPackages(logger, packageGlobPaths, options) {
202
212
  const results = [];
203
213
  const exclude = (0, paths_1.createMinimatch)(options.getValue("exclude"));
214
+ const rootDir = deriveRootDir(packageGlobPaths);
204
215
  // packages arguments are workspace tree roots, or glob patterns
205
216
  // This expands them to leave only leaf packages
206
- const expandedPackages = (0, package_manifest_1.expandPackages)(logger, ".", packageGlobPaths, exclude);
217
+ const expandedPackages = (0, package_manifest_1.expandPackages)(logger, rootDir, packageGlobPaths, exclude);
207
218
  for (const packagePath of expandedPackages) {
208
219
  const packageJsonPath = (0, path_1.resolve)(packagePath, "package.json");
209
220
  const packageJson = (0, package_manifest_1.loadPackageManifest)(logger, packageJsonPath);
@@ -149,11 +149,7 @@ function glob(pattern, root, options) {
149
149
  }
150
150
  if (child.isDirectory() && child.name !== "node_modules") {
151
151
  const childPath = dir.concat(child.name);
152
- if (mini.set.some((row) => mini.matchOne(
153
- // @ts-expect-error childPath really should be an array of strings, not a string.
154
- // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/61956
155
- childPath, row,
156
- /* partial */ true))) {
152
+ if (mini.set.some((row) => mini.matchOne(childPath, row, /* partial */ true))) {
157
153
  dirs.push(childPath);
158
154
  }
159
155
  }
@@ -7,7 +7,7 @@ export { assertNever } from "./general";
7
7
  export { CallbackLogger, ConsoleLogger, Logger, LogLevel } from "./loggers";
8
8
  export { DefaultMap } from "./map";
9
9
  export { ArgumentsReader, BindOption, CommentStyle, Options, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, } from "./options";
10
- export type { ArrayDeclarationOption, BooleanDeclarationOption, DeclarationOption, DeclarationOptionBase, DeclarationOptionToOptionType, KeyToDeclaration, MapDeclarationOption, MixedDeclarationOption, NumberDeclarationOption, FlagsDeclarationOption, OptionsReader, StringDeclarationOption, TypeDocOptionMap, TypeDocOptions, ValidationOptions, TypeDocOptionValues, ParameterTypeToOptionTypeMap, ManuallyValidatedOption, } from "./options";
10
+ export type { ArrayDeclarationOption, BooleanDeclarationOption, DeclarationOption, DeclarationOptionBase, DeclarationOptionToOptionType, KeyToDeclaration, MapDeclarationOption, MixedDeclarationOption, NumberDeclarationOption, FlagsDeclarationOption, ObjectDeclarationOption, OptionsReader, StringDeclarationOption, TypeDocOptionMap, TypeDocOptions, ValidationOptions, TypeDocOptionValues, ParameterTypeToOptionTypeMap, ManuallyValidatedOption, } from "./options";
11
11
  export { discoverPlugins, loadPlugins } from "./plugins";
12
12
  export { sortReflections } from "./sort";
13
13
  export type { SortStrategy } from "./sort";
@@ -55,6 +55,7 @@ export interface TypeDocOptionMap {
55
55
  excludeInternal: boolean;
56
56
  excludePrivate: boolean;
57
57
  excludeProtected: boolean;
58
+ externalSymbolLinkMappings: ManuallyValidatedOption<Record<string, Record<string, string>>>;
58
59
  media: string;
59
60
  includes: string;
60
61
  out: string;
@@ -126,7 +127,7 @@ export declare type ValidationOptions = {
126
127
  */
127
128
  notExported: boolean;
128
129
  /**
129
- * If set, TypeDoc will produce warnings about \{&amp;link\} tags which will produce broken links.
130
+ * If set, TypeDoc will produce warnings about \{\@link\} tags which will produce broken links.
130
131
  */
131
132
  invalidLink: boolean;
132
133
  /**
@@ -137,9 +138,11 @@ export declare type ValidationOptions = {
137
138
  /**
138
139
  * Converts a given TypeDoc option key to the type of the declaration expected.
139
140
  */
140
- export declare type KeyToDeclaration<K extends keyof TypeDocOptionMap> = TypeDocOptionMap[K] extends boolean ? BooleanDeclarationOption : TypeDocOptionMap[K] extends string ? StringDeclarationOption : TypeDocOptionMap[K] extends number ? NumberDeclarationOption : TypeDocOptionMap[K] extends string[] ? ArrayDeclarationOption : unknown extends TypeDocOptionMap[K] ? MixedDeclarationOption : TypeDocOptionMap[K] extends ManuallyValidatedOption<unknown> ? MixedDeclarationOption & {
141
+ export declare type KeyToDeclaration<K extends keyof TypeDocOptionMap> = TypeDocOptionMap[K] extends boolean ? BooleanDeclarationOption : TypeDocOptionMap[K] extends string ? StringDeclarationOption : TypeDocOptionMap[K] extends number ? NumberDeclarationOption : TypeDocOptionMap[K] extends string[] ? ArrayDeclarationOption : unknown extends TypeDocOptionMap[K] ? MixedDeclarationOption | ObjectDeclarationOption : TypeDocOptionMap[K] extends ManuallyValidatedOption<unknown> ? (MixedDeclarationOption & {
141
142
  validate(value: unknown): void;
142
- } : TypeDocOptionMap[K] extends Record<string, boolean> ? FlagsDeclarationOption<TypeDocOptionMap[K]> : TypeDocOptionMap[K] extends Record<string | number, infer U> ? MapDeclarationOption<U> : never;
143
+ }) | (ObjectDeclarationOption & {
144
+ validate(value: unknown): void;
145
+ }) : TypeDocOptionMap[K] extends Record<string, boolean> ? FlagsDeclarationOption<TypeDocOptionMap[K]> : TypeDocOptionMap[K] extends Record<string | number, infer U> ? MapDeclarationOption<U> : never;
143
146
  export declare enum ParameterHint {
144
147
  File = 0,
145
148
  Directory = 1
@@ -167,10 +170,14 @@ export declare enum ParameterType {
167
170
  * Resolved according to the config directory unless it starts with `**`, after skipping any leading `!` and `#` characters.
168
171
  */
169
172
  GlobArray = 9,
173
+ /**
174
+ * An unopinionated object that preserves default settings unless explicitly overridden
175
+ */
176
+ Object = 10,
170
177
  /**
171
178
  * An object with true/false flags
172
179
  */
173
- Flags = 10
180
+ Flags = 11
174
181
  }
175
182
  export interface DeclarationOptionBase {
176
183
  /**
@@ -258,6 +265,18 @@ export interface MixedDeclarationOption extends DeclarationOptionBase {
258
265
  */
259
266
  validate?: (value: unknown) => void;
260
267
  }
268
+ export interface ObjectDeclarationOption extends DeclarationOptionBase {
269
+ type: ParameterType.Object;
270
+ /**
271
+ * If not specified defaults to undefined.
272
+ */
273
+ defaultValue?: unknown;
274
+ /**
275
+ * An optional validation function that validates a potential value of this option.
276
+ * The function must throw an Error if the validation fails and should do nothing otherwise.
277
+ */
278
+ validate?: (value: unknown) => void;
279
+ }
261
280
  export interface MapDeclarationOption<T> extends DeclarationOptionBase {
262
281
  type: ParameterType.Map;
263
282
  /**
@@ -283,13 +302,14 @@ export interface FlagsDeclarationOption<T extends Record<string, boolean>> exten
283
302
  */
284
303
  defaults: T;
285
304
  }
286
- export declare type DeclarationOption = StringDeclarationOption | NumberDeclarationOption | BooleanDeclarationOption | MixedDeclarationOption | MapDeclarationOption<unknown> | ArrayDeclarationOption | FlagsDeclarationOption<Record<string, boolean>>;
305
+ export declare type DeclarationOption = StringDeclarationOption | NumberDeclarationOption | BooleanDeclarationOption | MixedDeclarationOption | ObjectDeclarationOption | MapDeclarationOption<unknown> | ArrayDeclarationOption | FlagsDeclarationOption<Record<string, boolean>>;
287
306
  export interface ParameterTypeToOptionTypeMap {
288
307
  [ParameterType.String]: string;
289
308
  [ParameterType.Path]: string;
290
309
  [ParameterType.Number]: number;
291
310
  [ParameterType.Boolean]: boolean;
292
311
  [ParameterType.Mixed]: unknown;
312
+ [ParameterType.Object]: unknown;
293
313
  [ParameterType.Array]: string[];
294
314
  [ParameterType.PathArray]: string[];
295
315
  [ParameterType.ModuleArray]: string[];
@@ -306,5 +326,5 @@ export declare type DeclarationOptionToOptionType<T extends DeclarationOption> =
306
326
  * @param option The option for which the value should be converted.
307
327
  * @returns The result of the conversion. Might be the value or an error.
308
328
  */
309
- export declare function convert(value: unknown, option: DeclarationOption, configPath: string): unknown;
329
+ export declare function convert(value: unknown, option: DeclarationOption, configPath: string, oldValue?: unknown): unknown;
310
330
  export declare function getDefaultValue(option: DeclarationOption): unknown;
@@ -47,10 +47,14 @@ var ParameterType;
47
47
  * Resolved according to the config directory unless it starts with `**`, after skipping any leading `!` and `#` characters.
48
48
  */
49
49
  ParameterType[ParameterType["GlobArray"] = 9] = "GlobArray";
50
+ /**
51
+ * An unopinionated object that preserves default settings unless explicitly overridden
52
+ */
53
+ ParameterType[ParameterType["Object"] = 10] = "Object";
50
54
  /**
51
55
  * An object with true/false flags
52
56
  */
53
- ParameterType[ParameterType["Flags"] = 10] = "Flags";
57
+ ParameterType[ParameterType["Flags"] = 11] = "Flags";
54
58
  })(ParameterType = exports.ParameterType || (exports.ParameterType = {}));
55
59
  const converters = {
56
60
  [ParameterType.String](value, option) {
@@ -146,6 +150,12 @@ const converters = {
146
150
  option.validate?.(value);
147
151
  return value;
148
152
  },
153
+ [ParameterType.Object](value, option, _configPath, oldValue) {
154
+ option.validate?.(value);
155
+ if (typeof oldValue !== "undefined")
156
+ value = { ...oldValue, ...value };
157
+ return value;
158
+ },
149
159
  [ParameterType.Flags](value, option) {
150
160
  if (typeof value === "boolean") {
151
161
  value = Object.fromEntries(Object.keys(option.defaults).map((key) => [key, value]));
@@ -179,9 +189,9 @@ const converters = {
179
189
  * @param option The option for which the value should be converted.
180
190
  * @returns The result of the conversion. Might be the value or an error.
181
191
  */
182
- function convert(value, option, configPath) {
192
+ function convert(value, option, configPath, oldValue) {
183
193
  const _converters = converters;
184
- return _converters[option.type ?? ParameterType.String](value, option, configPath);
194
+ return _converters[option.type ?? ParameterType.String](value, option, configPath, oldValue);
185
195
  }
186
196
  exports.convert = convert;
187
197
  const defaultGetters = {
@@ -209,6 +219,9 @@ const defaultGetters = {
209
219
  [ParameterType.Mixed](option) {
210
220
  return option.defaultValue;
211
221
  },
222
+ [ParameterType.Object](option) {
223
+ return option.defaultValue;
224
+ },
212
225
  [ParameterType.Array](option) {
213
226
  return option.defaultValue?.slice() ?? [];
214
227
  },
@@ -2,4 +2,4 @@ export { Options, BindOption } from "./options";
2
2
  export type { OptionsReader } from "./options";
3
3
  export { ArgumentsReader, TypeDocReader, TSConfigReader } from "./readers";
4
4
  export { CommentStyle, EmitStrategy, ParameterType, ParameterHint, } from "./declaration";
5
- export type { TypeDocOptions, TypeDocOptionMap, ValidationOptions, KeyToDeclaration, DeclarationOption, DeclarationOptionBase, StringDeclarationOption, NumberDeclarationOption, BooleanDeclarationOption, ArrayDeclarationOption, MixedDeclarationOption, MapDeclarationOption, FlagsDeclarationOption, DeclarationOptionToOptionType, TypeDocOptionValues, ParameterTypeToOptionTypeMap, ManuallyValidatedOption, } from "./declaration";
5
+ export type { TypeDocOptions, TypeDocOptionMap, ValidationOptions, KeyToDeclaration, DeclarationOption, DeclarationOptionBase, StringDeclarationOption, NumberDeclarationOption, BooleanDeclarationOption, ArrayDeclarationOption, MixedDeclarationOption, ObjectDeclarationOption, MapDeclarationOption, FlagsDeclarationOption, DeclarationOptionToOptionType, TypeDocOptionValues, ParameterTypeToOptionTypeMap, ManuallyValidatedOption, } from "./declaration";
@@ -164,7 +164,10 @@ class Options {
164
164
  if (!declaration) {
165
165
  throw new Error(`Tried to set an option (${name}) that was not declared.`);
166
166
  }
167
- const converted = (0, declaration_2.convert)(value, declaration, configPath ?? process.cwd());
167
+ let oldValue = this._values[declaration.name];
168
+ if (typeof oldValue === "undefined")
169
+ oldValue = (0, declaration_2.getDefaultValue)(declaration);
170
+ const converted = (0, declaration_2.convert)(value, declaration, configPath ?? process.cwd(), oldValue);
168
171
  if (declaration.type === declaration_1.ParameterType.Flags) {
169
172
  Object.assign(this._values[declaration.name], converted);
170
173
  }
@@ -89,6 +89,28 @@ function addTypeDocOptions(options) {
89
89
  help: "Ignore protected variables and methods.",
90
90
  type: declaration_1.ParameterType.Boolean,
91
91
  });
92
+ options.addDeclaration({
93
+ name: "externalSymbolLinkMappings",
94
+ help: "Define custom links for symbols not included in the documentation.",
95
+ type: declaration_1.ParameterType.Mixed,
96
+ defaultValue: {},
97
+ validate(value) {
98
+ const error = "externalSymbolLinkMappings must be a Record<package name, Record<symbol name, link>>";
99
+ if (!Validation.validate({}, value)) {
100
+ throw new Error(error);
101
+ }
102
+ for (const mappings of Object.values(value)) {
103
+ if (!Validation.validate({}, mappings)) {
104
+ throw new Error(error);
105
+ }
106
+ for (const link of Object.values(mappings)) {
107
+ if (typeof link !== "string") {
108
+ throw new Error(error);
109
+ }
110
+ }
111
+ }
112
+ },
113
+ });
92
114
  options.addDeclaration({
93
115
  name: "media",
94
116
  help: "Specify the location with media files that should be copied to the output directory.",
@@ -1,5 +1,5 @@
1
1
  import type { Logger } from "./loggers";
2
- import type { IMinimatch } from "minimatch";
2
+ import type { Minimatch } from "minimatch";
3
3
  import { additionalProperties, Infer } from "./validation";
4
4
  /**
5
5
  * Loads a package.json and validates that it is a JSON Object
@@ -20,7 +20,7 @@ export declare function extractTypedocConfigFromPackageManifest(logger: Logger,
20
20
  * Given a list of (potentially wildcarded) package paths,
21
21
  * return all the actual package folders found.
22
22
  */
23
- export declare function expandPackages(logger: Logger, packageJsonDir: string, workspaces: string[], exclude: IMinimatch[]): string[];
23
+ export declare function expandPackages(logger: Logger, packageJsonDir: string, workspaces: string[], exclude: Minimatch[]): string[];
24
24
  export declare const ignorePackage: unique symbol;
25
25
  /**
26
26
  * Given a package.json, attempt to find the TS file that defines its entry point
@@ -1,9 +1,9 @@
1
- import { IMinimatch } from "minimatch";
1
+ import { Minimatch } from "minimatch";
2
2
  /**
3
3
  * Convert array of glob patterns to array of minimatch instances.
4
4
  *
5
5
  * Handle a few Windows-Unix path gotchas.
6
6
  */
7
- export declare function createMinimatch(patterns: string[]): IMinimatch[];
8
- export declare function matchesAny(patterns: readonly IMinimatch[], path: string): boolean;
7
+ export declare function createMinimatch(patterns: string[]): Minimatch[];
8
+ export declare function matchesAny(patterns: readonly Minimatch[], path: string): boolean;
9
9
  export declare function nicePath(absPath: string): string;
@@ -0,0 +1,5 @@
1
+ import { ProjectReflection, ReferenceType, Reflection } from "../models";
2
+ export declare function discoverAllReferenceTypes(project: ProjectReflection, forExportValidation: boolean): {
3
+ type: ReferenceType;
4
+ owner: Reflection;
5
+ }[];
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.discoverAllReferenceTypes = void 0;
4
+ const models_1 = require("../models");
5
+ function discoverAllReferenceTypes(project, forExportValidation) {
6
+ let current = project;
7
+ const queue = [];
8
+ const result = [];
9
+ const visitor = (0, models_1.makeRecursiveVisitor)({
10
+ reference(type) {
11
+ result.push({ type, owner: current });
12
+ },
13
+ reflection(type) {
14
+ queue.push(type.declaration);
15
+ },
16
+ });
17
+ const add = (item) => {
18
+ if (!item)
19
+ return;
20
+ if (item instanceof models_1.Reflection) {
21
+ queue.push(item);
22
+ }
23
+ else {
24
+ queue.push(...item);
25
+ }
26
+ };
27
+ do {
28
+ if (current instanceof models_1.ContainerReflection) {
29
+ add(current.children);
30
+ }
31
+ if (current instanceof models_1.DeclarationReflection) {
32
+ current.type?.visit(visitor);
33
+ add(current.typeParameters);
34
+ add(current.signatures);
35
+ add(current.indexSignature);
36
+ add(current.getSignature);
37
+ add(current.setSignature);
38
+ current.overwrites?.visit(visitor);
39
+ current.implementedTypes?.forEach((type) => type.visit(visitor));
40
+ if (!forExportValidation) {
41
+ current.inheritedFrom?.visit(visitor);
42
+ current.implementationOf?.visit(visitor);
43
+ current.extendedTypes?.forEach((t) => t.visit(visitor));
44
+ current.extendedBy?.forEach((t) => t.visit(visitor));
45
+ current.implementedBy?.forEach((t) => t.visit(visitor));
46
+ }
47
+ }
48
+ if (current instanceof models_1.SignatureReflection) {
49
+ add(current.parameters);
50
+ add(current.typeParameters);
51
+ current.type?.visit(visitor);
52
+ current.overwrites?.visit(visitor);
53
+ if (!forExportValidation) {
54
+ current.inheritedFrom?.visit(visitor);
55
+ current.implementationOf?.visit(visitor);
56
+ }
57
+ }
58
+ if (current instanceof models_1.ParameterReflection) {
59
+ current.type?.visit(visitor);
60
+ }
61
+ if (current instanceof models_1.TypeParameterReflection) {
62
+ current.type?.visit(visitor);
63
+ current.default?.visit(visitor);
64
+ }
65
+ } while ((current = queue.shift()));
66
+ return result;
67
+ }
68
+ exports.discoverAllReferenceTypes = discoverAllReferenceTypes;
@@ -1,3 +1,3 @@
1
- import { ProjectReflection } from "../models";
1
+ import type { ProjectReflection } from "../models";
2
2
  import type { Logger } from "../utils";
3
3
  export declare function validateExports(project: ProjectReflection, logger: Logger, intentionallyNotExported: readonly string[]): void;
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.validateExports = void 0;
4
4
  const ts = require("typescript");
5
- const models_1 = require("../models");
5
+ const reflections_1 = require("../utils/reflections");
6
6
  function makeIntentionallyExportedHelper(intentional, logger) {
7
7
  const used = new Set();
8
8
  const processed = intentional.map((v) => {
@@ -45,73 +45,21 @@ function makeIntentionallyExportedHelper(intentional, logger) {
45
45
  };
46
46
  }
47
47
  function validateExports(project, logger, intentionallyNotExported) {
48
- let current = project;
49
- const queue = [];
50
48
  const intentional = makeIntentionallyExportedHelper(intentionallyNotExported, logger);
51
49
  const warned = new Set();
52
- const visitor = (0, models_1.makeRecursiveVisitor)({
53
- reference(type) {
54
- // If we don't have a symbol, then this was an intentionally broken reference.
55
- const symbol = type.getSymbol();
56
- if (!type.reflection && symbol) {
57
- if ((symbol.flags & ts.SymbolFlags.TypeParameter) === 0 &&
58
- !intentional.has(symbol, type.qualifiedName) &&
59
- !warned.has(symbol)) {
60
- warned.add(symbol);
61
- const decl = symbol.declarations[0];
62
- logger.warn(`${type.qualifiedName} is referenced by ${current.getFullName()} but not included in the documentation.`, decl);
63
- }
50
+ for (const { type, owner } of (0, reflections_1.discoverAllReferenceTypes)(project, true)) {
51
+ // If we don't have a symbol, then this was an intentionally broken reference.
52
+ const symbol = type.getSymbol();
53
+ if (!type.reflection && !type.externalUrl && symbol) {
54
+ if ((symbol.flags & ts.SymbolFlags.TypeParameter) === 0 &&
55
+ !intentional.has(symbol, type.qualifiedName) &&
56
+ !warned.has(symbol)) {
57
+ warned.add(symbol);
58
+ const decl = symbol.declarations[0];
59
+ logger.warn(`${type.qualifiedName} is referenced by ${owner.getFullName()} but not included in the documentation.`, decl);
64
60
  }
65
- },
66
- reflection(type) {
67
- queue.push(type.declaration);
68
- },
69
- });
70
- const add = (item) => {
71
- if (!item)
72
- return;
73
- if (item instanceof models_1.Reflection) {
74
- queue.push(item);
75
- }
76
- else {
77
- queue.push(...item);
78
- }
79
- };
80
- do {
81
- if (current instanceof models_1.ContainerReflection) {
82
- add(current.children);
83
- }
84
- if (current instanceof models_1.DeclarationReflection) {
85
- current.type?.visit(visitor);
86
- add(current.typeParameters);
87
- add(current.signatures);
88
- add(current.indexSignature);
89
- add(current.getSignature);
90
- add(current.setSignature);
91
- current.overwrites?.visit(visitor);
92
- // Do not check inheritedFrom, it doesn't always make sense to export a base type.
93
- // Do not validate implementationOf will always be defined or intentionally broken.
94
- // Do not check extendedTypes, it doesn't always make sense to export a base type.
95
- // Do not validate extendedBy, guaranteed to all be in the documentation.
96
- current.implementedTypes?.forEach((type) => type.visit(visitor));
97
- // Do not validate implementedBy, guaranteed to all be in the documentation.
98
- }
99
- if (current instanceof models_1.SignatureReflection) {
100
- add(current.parameters);
101
- add(current.typeParameters);
102
- current.type?.visit(visitor);
103
- current.overwrites?.visit(visitor);
104
- // Do not check inheritedFrom, it doesn't always make sense to export a base type.
105
- // Do not validate implementationOf will always be defined or intentionally broken.
106
61
  }
107
- if (current instanceof models_1.ParameterReflection) {
108
- current.type?.visit(visitor);
109
- }
110
- if (current instanceof models_1.TypeParameterReflection) {
111
- current.type?.visit(visitor);
112
- current.default?.visit(visitor);
113
- }
114
- } while ((current = queue.shift()));
62
+ }
115
63
  const unusedIntentional = intentional.getUnused();
116
64
  if (unusedIntentional.length) {
117
65
  logger.warn("The following symbols were marked as intentionally not exported, but were either not referenced in the documentation, or were exported:\n\t" +
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typedoc",
3
3
  "description": "Create api documentation for TypeScript projects.",
4
- "version": "0.23.11",
4
+ "version": "0.23.14",
5
5
  "homepage": "https://typedoc.org",
6
6
  "main": "./dist/index.js",
7
7
  "exports": {
@@ -35,15 +35,15 @@
35
35
  "devDependencies": {
36
36
  "@types/lunr": "^2.3.4",
37
37
  "@types/marked": "^4.0.6",
38
- "@types/minimatch": "5.1.0",
38
+ "@types/minimatch": "5.1.2",
39
39
  "@types/mocha": "^9.1.1",
40
40
  "@types/node": "14",
41
- "@typescript-eslint/eslint-plugin": "^5.35.1",
42
- "@typescript-eslint/parser": "^5.35.1",
43
- "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de",
41
+ "@typescript-eslint/eslint-plugin": "^5.36.1",
42
+ "@typescript-eslint/parser": "^5.36.1",
43
+ "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#5a9486bc66f6e36988106685768396281f6cbc10",
44
44
  "c8": "^7.12.0",
45
- "esbuild": "^0.15.5",
46
- "eslint": "^8.22.0",
45
+ "esbuild": "^0.15.6",
46
+ "eslint": "^8.23.0",
47
47
  "mocha": "^10.0.0",
48
48
  "prettier": "2.7.1",
49
49
  "puppeteer": "^13.5.2",
package/static/style.css CHANGED
@@ -1124,6 +1124,7 @@ ul.tsd-type-parameter-list h5 {
1124
1124
  display: flex;
1125
1125
  justify-content: space-between;
1126
1126
  height: 2.5rem;
1127
+ margin: 0 auto;
1127
1128
  }
1128
1129
  .tsd-page-toolbar .table-cell {
1129
1130
  position: relative;