typedoc 0.23.13 → 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.
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ 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";
@@ -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,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
  }
@@ -149,10 +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(childPath,
153
- // @ts-expect-error https://github.com/DefinitelyTyped/DefinitelyTyped/pull/62049
154
- row,
155
- /* partial */ true))) {
152
+ if (mini.set.some((row) => mini.matchOne(childPath, row, /* partial */ true))) {
156
153
  dirs.push(childPath);
157
154
  }
158
155
  }
@@ -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
  /**
@@ -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.",
@@ -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.13",
4
+ "version": "0.23.14",
5
5
  "homepage": "https://typedoc.org",
6
6
  "main": "./dist/index.js",
7
7
  "exports": {
@@ -35,7 +35,7 @@
35
35
  "devDependencies": {
36
36
  "@types/lunr": "^2.3.4",
37
37
  "@types/marked": "^4.0.6",
38
- "@types/minimatch": "5.1.1",
38
+ "@types/minimatch": "5.1.2",
39
39
  "@types/mocha": "^9.1.1",
40
40
  "@types/node": "14",
41
41
  "@typescript-eslint/eslint-plugin": "^5.36.1",
package/static/style.css CHANGED
@@ -1109,7 +1109,6 @@ ul.tsd-type-parameter-list h5 {
1109
1109
  background: var(--color-background-secondary);
1110
1110
  border-bottom: 1px var(--color-accent) solid;
1111
1111
  transition: transform 0.3s ease-in-out;
1112
- margin: 0 auto;
1113
1112
  }
1114
1113
  .tsd-page-toolbar a {
1115
1114
  color: var(--color-text);
@@ -1125,6 +1124,7 @@ ul.tsd-type-parameter-list h5 {
1125
1124
  display: flex;
1126
1125
  justify-content: space-between;
1127
1126
  height: 2.5rem;
1127
+ margin: 0 auto;
1128
1128
  }
1129
1129
  .tsd-page-toolbar .table-cell {
1130
1130
  position: relative;