typedoc 0.23.9 → 0.23.10

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.
@@ -54,6 +54,8 @@ const wantedKinds = {
54
54
  ts.SyntaxKind.PropertySignature,
55
55
  ts.SyntaxKind.BinaryExpression,
56
56
  ts.SyntaxKind.PropertyAssignment,
57
+ // class X { constructor(/** Comment */ readonly z: any) }
58
+ ts.SyntaxKind.Parameter,
57
59
  ],
58
60
  [models_1.ReflectionKind.Method]: [
59
61
  ts.SyntaxKind.FunctionDeclaration,
@@ -8,6 +8,13 @@ const blockLexer_1 = require("./blockLexer");
8
8
  const discovery_1 = require("./discovery");
9
9
  const lineLexer_1 = require("./lineLexer");
10
10
  const parser_1 = require("./parser");
11
+ const jsDocCommentKinds = [
12
+ ts.SyntaxKind.JSDocPropertyTag,
13
+ ts.SyntaxKind.JSDocCallbackTag,
14
+ ts.SyntaxKind.JSDocTypedefTag,
15
+ ts.SyntaxKind.JSDocTemplateTag,
16
+ ts.SyntaxKind.JSDocEnumTag,
17
+ ];
11
18
  const commentCache = new WeakMap();
12
19
  function getCommentWithCache(discovered, config, logger) {
13
20
  if (!discovered)
@@ -52,6 +59,11 @@ function getCommentImpl(commentSource, config, logger, moduleComment) {
52
59
  return comment;
53
60
  }
54
61
  function getComment(symbol, kind, config, logger, commentStyle) {
62
+ if (symbol
63
+ .getDeclarations()
64
+ ?.every((d) => jsDocCommentKinds.includes(d.kind))) {
65
+ return getJsDocComment(symbol.declarations[0], config, logger);
66
+ }
55
67
  return getCommentImpl((0, discovery_1.discoverComment)(symbol, kind, logger, commentStyle), config, logger, symbol.declarations?.some(ts.isSourceFile) || false);
56
68
  }
57
69
  exports.getComment = getComment;
@@ -106,7 +118,7 @@ function getJsDocComment(declaration, config, logger) {
106
118
  logger.error(`Failed to find JSDoc tag for ${name} after parsing comment, please file a bug report.`, declaration);
107
119
  }
108
120
  else {
109
- return new models_1.Comment(tag.content.slice());
121
+ return new models_1.Comment(models_1.Comment.cloneDisplayParts(tag.content));
110
122
  }
111
123
  }
112
124
  exports.getJsDocComment = getJsDocComment;
@@ -0,0 +1,4 @@
1
+ import { Comment, CommentDisplayPart, Reflection } from "../../models";
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[];
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolvePartLinks = exports.resolveLinks = void 0;
4
+ const ts = require("typescript");
5
+ const models_1 = require("../../models");
6
+ const declarationReference_1 = require("./declarationReference");
7
+ const declarationReferenceResolver_1 = require("./declarationReferenceResolver");
8
+ const urlPrefix = /^(http|ftp)s?:\/\//;
9
+ const brackets = /\[\[(?!include:)([^\]]+)\]\]/g;
10
+ function resolveLinks(comment, reflection, validation, logger) {
11
+ let warned = false;
12
+ const warn = () => {
13
+ if (!warned) {
14
+ warned = true;
15
+ logger.warn(`${reflection.getFriendlyFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24`);
16
+ }
17
+ };
18
+ comment.summary = resolvePartLinks(reflection, comment.summary, warn, validation, logger);
19
+ for (const tag of comment.blockTags) {
20
+ tag.content = resolvePartLinks(reflection, tag.content, warn, validation, logger);
21
+ }
22
+ if (reflection instanceof models_1.DeclarationReflection && reflection.readme) {
23
+ reflection.readme = resolvePartLinks(reflection, reflection.readme, warn, validation, logger);
24
+ }
25
+ }
26
+ exports.resolveLinks = resolveLinks;
27
+ function resolvePartLinks(reflection, parts, warn, validation, logger) {
28
+ return parts.flatMap((part) => processPart(reflection, part, warn, validation, logger));
29
+ }
30
+ exports.resolvePartLinks = resolvePartLinks;
31
+ function processPart(reflection, part, warn, validation, logger) {
32
+ if (part.kind === "text" && brackets.test(part.text)) {
33
+ warn();
34
+ return replaceBrackets(reflection, part.text, validation, logger);
35
+ }
36
+ if (part.kind === "inline-tag") {
37
+ if (part.tag === "@link" ||
38
+ part.tag === "@linkcode" ||
39
+ part.tag === "@linkplain") {
40
+ return resolveLinkTag(reflection, part, (msg) => {
41
+ if (validation.invalidLink) {
42
+ logger.warn(msg);
43
+ }
44
+ });
45
+ }
46
+ }
47
+ return part;
48
+ }
49
+ function resolveLinkTag(reflection, part, warn) {
50
+ let pos = 0;
51
+ const end = part.text.length;
52
+ while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
53
+ pos++;
54
+ }
55
+ const origText = part.text;
56
+ // Try to parse one
57
+ const declRef = (0, declarationReference_1.parseDeclarationReference)(part.text, pos, end);
58
+ let target;
59
+ if (declRef) {
60
+ // Got one, great! Try to resolve the link
61
+ target = (0, declarationReferenceResolver_1.resolveDeclarationReference)(reflection, declRef[0]);
62
+ pos = declRef[1];
63
+ }
64
+ if (!target) {
65
+ if (urlPrefix.test(part.text)) {
66
+ const wsIndex = part.text.search(/\s/);
67
+ target =
68
+ wsIndex === -1 ? part.text : part.text.substring(0, wsIndex);
69
+ pos = target.length;
70
+ }
71
+ }
72
+ // If resolution via a declaration reference failed, revert to the legacy "split and check"
73
+ // method... this should go away in 0.24, once people have had a chance to migrate any failing links.
74
+ if (!target) {
75
+ const resolved = legacyResolveLinkTag(reflection, part);
76
+ if (resolved) {
77
+ warn(`Failed to resolve {@link ${origText}} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.`);
78
+ }
79
+ return resolved;
80
+ }
81
+ // Remaining text after an optional pipe is the link text, so advance
82
+ // until that's consumed.
83
+ while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
84
+ pos++;
85
+ }
86
+ if (pos < end && part.text[pos] === "|") {
87
+ pos++;
88
+ }
89
+ part.target = target;
90
+ part.text =
91
+ part.text.substring(pos).trim() ||
92
+ (typeof target === "string" ? target : target.name);
93
+ return part;
94
+ }
95
+ function legacyResolveLinkTag(reflection, part) {
96
+ const { caption, target } = splitLinkText(part.text);
97
+ if (urlPrefix.test(target)) {
98
+ part.text = caption;
99
+ part.target = target;
100
+ }
101
+ else {
102
+ const targetRefl = reflection.findReflectionByName(target);
103
+ if (targetRefl) {
104
+ part.text = caption;
105
+ part.target = targetRefl;
106
+ }
107
+ }
108
+ return part;
109
+ }
110
+ function replaceBrackets(reflection, text, validation, logger) {
111
+ const parts = [];
112
+ let begin = 0;
113
+ brackets.lastIndex = 0;
114
+ for (const match of text.matchAll(brackets)) {
115
+ if (begin != match.index) {
116
+ parts.push({
117
+ kind: "text",
118
+ text: text.substring(begin, match.index),
119
+ });
120
+ }
121
+ begin = match.index + match[0].length;
122
+ const content = match[1];
123
+ const { target, caption } = splitLinkText(content);
124
+ if (urlPrefix.test(target)) {
125
+ parts.push({
126
+ kind: "inline-tag",
127
+ tag: "@link",
128
+ text: caption,
129
+ target,
130
+ });
131
+ }
132
+ else {
133
+ const targetRefl = reflection.findReflectionByName(target);
134
+ if (targetRefl) {
135
+ parts.push({
136
+ kind: "inline-tag",
137
+ tag: "@link",
138
+ text: caption,
139
+ target: targetRefl,
140
+ });
141
+ }
142
+ else {
143
+ if (validation.invalidLink) {
144
+ logger.warn("Failed to find target: " + content);
145
+ }
146
+ parts.push({
147
+ kind: "inline-tag",
148
+ tag: "@link",
149
+ text: content,
150
+ });
151
+ }
152
+ }
153
+ }
154
+ parts.push({
155
+ kind: "text",
156
+ text: text.substring(begin),
157
+ });
158
+ return parts;
159
+ }
160
+ /**
161
+ * Split the given link into text and target at first pipe or space.
162
+ *
163
+ * @param text The source string that should be checked for a split character.
164
+ * @returns An object containing the link text and target.
165
+ */
166
+ function splitLinkText(text) {
167
+ let splitIndex = text.indexOf("|");
168
+ if (splitIndex === -1) {
169
+ splitIndex = text.search(/\s/);
170
+ }
171
+ if (splitIndex !== -1) {
172
+ return {
173
+ caption: text
174
+ .substring(splitIndex + 1)
175
+ .replace(/\n+/, " ")
176
+ .trim(),
177
+ target: text.substring(0, splitIndex).trim(),
178
+ };
179
+ }
180
+ else {
181
+ return {
182
+ caption: text,
183
+ target: text,
184
+ };
185
+ }
186
+ }
@@ -1,13 +1,13 @@
1
1
  import * as ts from "typescript";
2
2
  import type { Application } from "../application";
3
- import { ProjectReflection, SomeType } from "../models/index";
3
+ import { Comment, CommentDisplayPart, ProjectReflection, Reflection, SomeType } from "../models/index";
4
4
  import { Context } from "./context";
5
5
  import { ConverterComponent } from "./components";
6
6
  import { ChildableComponent } from "../utils/component";
7
7
  import { MinimalSourceFile } from "../utils";
8
8
  import type { DocumentationEntryPoint } from "../utils/entry-point";
9
9
  import { CommentParserConfig } from "./comments";
10
- import type { CommentStyle } from "../utils/options/declaration";
10
+ import type { CommentStyle, ValidationOptions } from "../utils/options/declaration";
11
11
  /**
12
12
  * Compiles source files using TypeScript and converts compiler symbols to reflections.
13
13
  */
@@ -24,6 +24,8 @@ export declare class Converter extends ChildableComponent<Application, Converter
24
24
  excludePrivate: boolean;
25
25
  excludeProtected: boolean;
26
26
  commentStyle: CommentStyle;
27
+ /** @internal */
28
+ validation: ValidationOptions;
27
29
  private _config?;
28
30
  get config(): CommentParserConfig;
29
31
  /**
@@ -108,7 +110,9 @@ export declare class Converter extends ChildableComponent<Application, Converter
108
110
  /**
109
111
  * Parse the given file into a comment. Intended to be used with markdown files.
110
112
  */
111
- parseRawComment(file: MinimalSourceFile): import("../models/index").Comment;
113
+ parseRawComment(file: MinimalSourceFile): Comment;
114
+ resolveLinks(comment: Comment, owner: Reflection): void;
115
+ resolveLinks(parts: readonly CommentDisplayPart[], owner: Reflection): CommentDisplayPart[];
112
116
  /**
113
117
  * Compile the files within the given context and convert the compiler symbols to reflections.
114
118
  *
@@ -22,6 +22,7 @@ const enum_1 = require("../utils/enum");
22
22
  const comments_1 = require("./comments");
23
23
  const parser_1 = require("./comments/parser");
24
24
  const rawLexer_1 = require("./comments/rawLexer");
25
+ const linkResolver_1 = require("./comments/linkResolver");
25
26
  /**
26
27
  * Compiles source files using TypeScript and converts compiler symbols to reflections.
27
28
  */
@@ -66,6 +67,21 @@ let Converter = Converter_1 = class Converter extends component_1.ChildableCompo
66
67
  parseRawComment(file) {
67
68
  return (0, parser_1.parseComment)((0, rawLexer_1.lexCommentString)(file.text), this.config, file, this.application.logger);
68
69
  }
70
+ resolveLinks(comment, owner) {
71
+ if (comment instanceof index_1.Comment) {
72
+ (0, linkResolver_1.resolveLinks)(comment, owner, this.validation, this.owner.logger);
73
+ }
74
+ else {
75
+ let warned = false;
76
+ const warn = () => {
77
+ if (!warned) {
78
+ warned = true;
79
+ this.application.logger.warn(`${owner.name}: Comment [[target]] style links are deprecated and will be removed in 0.24`);
80
+ }
81
+ };
82
+ return (0, linkResolver_1.resolvePartLinks)(owner, comment, warn, this.validation, this.owner.logger);
83
+ }
84
+ }
69
85
  /**
70
86
  * Compile the files within the given context and convert the compiler symbols to reflections.
71
87
  *
@@ -267,6 +283,9 @@ __decorate([
267
283
  __decorate([
268
284
  (0, utils_1.BindOption)("commentStyle")
269
285
  ], Converter.prototype, "commentStyle", void 0);
286
+ __decorate([
287
+ (0, utils_1.BindOption)("validation")
288
+ ], Converter.prototype, "validation", void 0);
270
289
  Converter = Converter_1 = __decorate([
271
290
  (0, component_1.Component)({
272
291
  name: "converter",
@@ -62,6 +62,7 @@ function convertParameters(context, sigRef, parameters, parameterNodes) {
62
62
  if (declaration && ts.isJSDocParameterTag(declaration)) {
63
63
  paramRefl.comment = (0, comments_1.getJsDocComment)(declaration, context.converter.config, context.logger);
64
64
  }
65
+ paramRefl.comment || (paramRefl.comment = (0, comments_1.getComment)(param, paramRefl.kind, context.converter.config, context.logger, context.converter.commentStyle));
65
66
  context.registerReflection(paramRefl, param);
66
67
  context.trigger(converter_events_1.ConverterEvents.CREATE_PARAMETER, paramRefl);
67
68
  let type;
@@ -1,4 +1,3 @@
1
- import type { Reflection } from "../../models/reflections/abstract";
2
1
  import { ConverterComponent } from "../components";
3
2
  import type { Context } from "../../converter";
4
3
  import { ValidationOptions } from "../../utils";
@@ -11,25 +10,5 @@ export declare class LinkResolverPlugin extends ConverterComponent {
11
10
  * Create a new LinkResolverPlugin instance.
12
11
  */
13
12
  initialize(): void;
14
- /**
15
- * Find all old style double bracket references to symbols within the given text and transform them into a link.
16
- *
17
- * @param text The text that should be parsed.
18
- * @returns The text with symbol references replaced by links.
19
- */
20
- private replaceBrackets;
21
13
  onResolve(context: Context): void;
22
- processReflection(reflection: Reflection): void;
23
- private processParts;
24
- private processPart;
25
- /**
26
- * Split the given link into text and target at first pipe or space.
27
- *
28
- * @param text The source string that should be checked for a split character.
29
- * @returns An object containing the link text and target.
30
- */
31
- static splitLinkText(text: string): {
32
- caption: string;
33
- target: string;
34
- };
35
14
  }
@@ -5,22 +5,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
7
7
  };
8
- var LinkResolverPlugin_1;
9
8
  Object.defineProperty(exports, "__esModule", { value: true });
10
9
  exports.LinkResolverPlugin = void 0;
11
10
  const components_1 = require("../components");
12
11
  const converter_events_1 = require("../converter-events");
13
- const declarationReference_1 = require("../comments/declarationReference");
14
- const ts = require("typescript");
15
12
  const utils_1 = require("../../utils");
16
- const declarationReferenceResolver_1 = require("../comments/declarationReferenceResolver");
17
- const models_1 = require("../../models");
18
- const urlPrefix = /^(http|ftp)s?:\/\//;
19
- const brackets = /\[\[(?!include:)([^\]]+)\]\]/g;
20
13
  /**
21
14
  * A plugin that resolves `{@link Foo}` tags.
22
15
  */
23
- let LinkResolverPlugin = LinkResolverPlugin_1 = class LinkResolverPlugin extends components_1.ConverterComponent {
16
+ let LinkResolverPlugin = class LinkResolverPlugin extends components_1.ConverterComponent {
24
17
  /**
25
18
  * Create a new LinkResolverPlugin instance.
26
19
  */
@@ -28,210 +21,21 @@ let LinkResolverPlugin = LinkResolverPlugin_1 = class LinkResolverPlugin extends
28
21
  super.initialize();
29
22
  this.owner.on(converter_events_1.ConverterEvents.RESOLVE_END, this.onResolve, this, -300);
30
23
  }
31
- /**
32
- * Find all old style double bracket references to symbols within the given text and transform them into a link.
33
- *
34
- * @param text The text that should be parsed.
35
- * @returns The text with symbol references replaced by links.
36
- */
37
- replaceBrackets(reflection, text) {
38
- const parts = [];
39
- let begin = 0;
40
- brackets.lastIndex = 0;
41
- for (const match of text.matchAll(brackets)) {
42
- if (begin != match.index) {
43
- parts.push({
44
- kind: "text",
45
- text: text.substring(begin, match.index),
46
- });
47
- }
48
- begin = match.index + match[0].length;
49
- const content = match[1];
50
- const { target, caption } = LinkResolverPlugin_1.splitLinkText(content);
51
- if (urlPrefix.test(target)) {
52
- parts.push({
53
- kind: "inline-tag",
54
- tag: "@link",
55
- text: caption,
56
- target,
57
- });
58
- }
59
- else {
60
- const targetRefl = reflection.findReflectionByName(target);
61
- if (targetRefl) {
62
- parts.push({
63
- kind: "inline-tag",
64
- tag: "@link",
65
- text: caption,
66
- target: targetRefl,
67
- });
68
- }
69
- else {
70
- if (this.validation.invalidLink) {
71
- this.application.logger.warn("Failed to find target: " + content);
72
- }
73
- parts.push({
74
- kind: "inline-tag",
75
- tag: "@link",
76
- text: content,
77
- });
78
- }
79
- }
80
- }
81
- parts.push({
82
- kind: "text",
83
- text: text.substring(begin),
84
- });
85
- return parts;
86
- }
87
24
  onResolve(context) {
88
25
  for (const reflection of Object.values(context.project.reflections)) {
89
- this.processReflection(reflection);
90
- }
91
- let warned = false;
92
- const warn = () => {
93
- if (!warned) {
94
- warned = true;
95
- this.application.logger.warn(`README: Comment [[target]] style links are deprecated and will be removed in 0.24`);
96
- }
97
- };
98
- if (context.project.readme) {
99
- context.project.readme = this.processParts(context.project, context.project.readme, warn);
100
- }
101
- }
102
- processReflection(reflection) {
103
- const comment = reflection.comment;
104
- if (!comment)
105
- return;
106
- let warned = false;
107
- const warn = () => {
108
- if (!warned) {
109
- warned = true;
110
- this.application.logger.warn(`${reflection.getFriendlyFullName()}: Comment [[target]] style links are deprecated and will be removed in 0.24`);
111
- }
112
- };
113
- comment.summary = this.processParts(reflection, comment.summary, warn);
114
- for (const tag of comment.blockTags) {
115
- tag.content = this.processParts(reflection, tag.content, warn);
116
- }
117
- if (reflection instanceof models_1.DeclarationReflection && reflection.readme) {
118
- reflection.readme = this.processParts(reflection, reflection.readme, warn);
119
- }
120
- }
121
- processParts(reflection, parts, warn) {
122
- return parts.flatMap((part) => this.processPart(reflection, part, warn));
123
- }
124
- processPart(reflection, part, warn) {
125
- if (part.kind === "text" && brackets.test(part.text)) {
126
- warn();
127
- return this.replaceBrackets(reflection, part.text);
128
- }
129
- if (part.kind === "inline-tag") {
130
- if (part.tag === "@link" ||
131
- part.tag === "@linkcode" ||
132
- part.tag === "@linkplain") {
133
- return resolveLinkTag(reflection, part, (msg) => {
134
- if (this.validation.invalidLink) {
135
- this.application.logger.warn(msg);
136
- }
137
- });
26
+ if (reflection.comment) {
27
+ context.converter.resolveLinks(reflection.comment, reflection);
138
28
  }
139
29
  }
140
- return part;
141
- }
142
- /**
143
- * Split the given link into text and target at first pipe or space.
144
- *
145
- * @param text The source string that should be checked for a split character.
146
- * @returns An object containing the link text and target.
147
- */
148
- static splitLinkText(text) {
149
- let splitIndex = text.indexOf("|");
150
- if (splitIndex === -1) {
151
- splitIndex = text.search(/\s/);
152
- }
153
- if (splitIndex !== -1) {
154
- return {
155
- caption: text
156
- .substring(splitIndex + 1)
157
- .replace(/\n+/, " ")
158
- .trim(),
159
- target: text.substring(0, splitIndex).trim(),
160
- };
161
- }
162
- else {
163
- return {
164
- caption: text,
165
- target: text,
166
- };
30
+ if (context.project.readme) {
31
+ context.project.readme = context.converter.resolveLinks(context.project.readme, context.project);
167
32
  }
168
33
  }
169
34
  };
170
35
  __decorate([
171
36
  (0, utils_1.BindOption)("validation")
172
37
  ], LinkResolverPlugin.prototype, "validation", void 0);
173
- LinkResolverPlugin = LinkResolverPlugin_1 = __decorate([
38
+ LinkResolverPlugin = __decorate([
174
39
  (0, components_1.Component)({ name: "link-resolver" })
175
40
  ], LinkResolverPlugin);
176
41
  exports.LinkResolverPlugin = LinkResolverPlugin;
177
- function resolveLinkTag(reflection, part, warn) {
178
- let pos = 0;
179
- const end = part.text.length;
180
- while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
181
- pos++;
182
- }
183
- const origText = part.text;
184
- // Try to parse one
185
- const declRef = (0, declarationReference_1.parseDeclarationReference)(part.text, pos, end);
186
- let target;
187
- if (declRef) {
188
- // Got one, great! Try to resolve the link
189
- target = (0, declarationReferenceResolver_1.resolveDeclarationReference)(reflection, declRef[0]);
190
- pos = declRef[1];
191
- }
192
- if (!target) {
193
- if (urlPrefix.test(part.text)) {
194
- const wsIndex = part.text.search(/\s/);
195
- target =
196
- wsIndex === -1 ? part.text : part.text.substring(0, wsIndex);
197
- pos = target.length;
198
- }
199
- }
200
- // If resolution via a declaration reference failed, revert to the legacy "split and check"
201
- // method... this should go away in 0.24, once people have had a chance to migrate any failing links.
202
- if (!target) {
203
- const resolved = legacyResolveLinkTag(reflection, part);
204
- if (resolved) {
205
- warn(`Failed to resolve {@link ${origText}} in ${reflection.getFriendlyFullName()} with declaration references. This link will break in v0.24.`);
206
- }
207
- return resolved;
208
- }
209
- // Remaining text after an optional pipe is the link text, so advance
210
- // until that's consumed.
211
- while (pos < end && ts.isWhiteSpaceLike(part.text.charCodeAt(pos))) {
212
- pos++;
213
- }
214
- if (pos < end && part.text[pos] === "|") {
215
- pos++;
216
- }
217
- part.target = target;
218
- part.text =
219
- part.text.substring(pos).trim() ||
220
- (typeof target === "string" ? target : target.name);
221
- return part;
222
- }
223
- function legacyResolveLinkTag(reflection, part) {
224
- const { caption, target } = LinkResolverPlugin.splitLinkText(part.text);
225
- if (urlPrefix.test(target)) {
226
- part.text = caption;
227
- part.target = target;
228
- }
229
- else {
230
- const targetRefl = reflection.findReflectionByName(target);
231
- if (targetRefl) {
232
- part.text = caption;
233
- part.target = targetRefl;
234
- }
235
- }
236
- return part;
237
- }
@@ -671,7 +671,7 @@ class ReferenceType extends Type {
671
671
  .fileName.replace(/\\/g, "/");
672
672
  if (!symbolPath)
673
673
  return ref;
674
- let startIndex = symbolPath.indexOf("node_modules/");
674
+ let startIndex = symbolPath.lastIndexOf("node_modules/");
675
675
  if (startIndex === -1)
676
676
  return ref;
677
677
  startIndex += "node_modules/".length;
@@ -1,6 +1,6 @@
1
1
  import type { RendererHooks } from "../..";
2
- import type { ReferenceType, Reflection } from "../../../models";
3
- import type { Options } from "../../../utils";
2
+ import type { CommentDisplayPart, ReferenceType, Reflection } from "../../../models";
3
+ import type { NeverIfInternal, Options } from "../../../utils";
4
4
  import type { DefaultTheme } from "./DefaultTheme";
5
5
  export declare class DefaultThemeRenderContext {
6
6
  private theme;
@@ -11,7 +11,7 @@ export declare class DefaultThemeRenderContext {
11
11
  /** Avoid this in favor of urlTo if possible */
12
12
  relativeURL: (url: string | undefined) => string | undefined;
13
13
  urlTo: (reflection: Reflection) => string | undefined;
14
- markdown: (md: string | undefined) => string;
14
+ markdown: (md: readonly CommentDisplayPart[] | NeverIfInternal<string | undefined>) => string;
15
15
  attemptExternalResolution: (type: ReferenceType) => string | undefined;
16
16
  reflectionTemplate: (props: import("../..").PageEvent<import("../../../models").ContainerReflection>) => import("../../../utils/jsx.elements").JsxElement;
17
17
  indexTemplate: (props: import("../..").PageEvent<import("../../../models").ProjectReflection>) => import("../../../utils/jsx.elements").JsxElement;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DefaultThemeRenderContext = void 0;
4
+ const lib_1 = require("../lib");
4
5
  const default_1 = require("./layouts/default");
5
6
  const partials_1 = require("./partials");
6
7
  const analytics_1 = require("./partials/analytics");
@@ -42,6 +43,9 @@ class DefaultThemeRenderContext {
42
43
  };
43
44
  this.urlTo = (reflection) => this.relativeURL(reflection.url);
44
45
  this.markdown = (md) => {
46
+ if (md instanceof Array) {
47
+ return this.theme.markedPlugin.parseMarkdown((0, lib_1.displayPartsToMarkdown)(md, this.urlTo));
48
+ }
45
49
  return md ? this.theme.markedPlugin.parseMarkdown(md) : "";
46
50
  };
47
51
  this.attemptExternalResolution = (type) => {
@@ -1,4 +1,4 @@
1
1
  import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext";
2
2
  import { JSX } from "../../../../utils";
3
3
  import type { Reflection } from "../../../../models";
4
- export declare function comment({ markdown, urlTo }: DefaultThemeRenderContext, props: Reflection): JSX.Element | undefined;
4
+ export declare function comment({ markdown }: DefaultThemeRenderContext, props: Reflection): JSX.Element | undefined;
@@ -3,14 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.comment = void 0;
4
4
  const utils_1 = require("../../../../utils");
5
5
  const lib_1 = require("../../lib");
6
- function comment({ markdown, urlTo }, props) {
6
+ function comment({ markdown }, props) {
7
7
  if (!props.comment?.hasVisibleComponent())
8
8
  return;
9
9
  // Note: Comment modifiers are handled in `renderFlags`
10
10
  return (utils_1.JSX.createElement("div", { class: "tsd-comment tsd-typography" },
11
- utils_1.JSX.createElement(utils_1.Raw, { html: markdown((0, lib_1.displayPartsToMarkdown)(props.comment.summary, urlTo)) }),
11
+ utils_1.JSX.createElement(utils_1.Raw, { html: markdown(props.comment.summary) }),
12
12
  props.comment.blockTags.map((item) => (utils_1.JSX.createElement(utils_1.JSX.Fragment, null,
13
13
  utils_1.JSX.createElement("h3", null, (0, lib_1.camelToTitleCase)(item.tag.substring(1))),
14
- utils_1.JSX.createElement(utils_1.Raw, { html: markdown((0, lib_1.displayPartsToMarkdown)(item.content, urlTo)) }))))));
14
+ utils_1.JSX.createElement(utils_1.Raw, { html: markdown(item.content) }))))));
15
15
  }
16
16
  exports.comment = comment;
@@ -10,7 +10,7 @@ function renderCategory({ urlTo, icons }, item, prependName = "") {
10
10
  utils_1.JSX.createElement("div", { class: "tsd-index-list" }, item.children.map((item) => (utils_1.JSX.createElement(utils_1.JSX.Fragment, null,
11
11
  utils_1.JSX.createElement("a", { href: urlTo(item), class: (0, lib_1.classNames)({ "tsd-index-link": true, deprecated: item.isDeprecated() }, item.cssClasses) },
12
12
  icons[item.kind](),
13
- utils_1.JSX.createElement("span", null, item.name ? (0, lib_1.wbr)(item.name) : utils_1.JSX.createElement("em", null, (0, lib_1.wbr)(item.kindString)))),
13
+ utils_1.JSX.createElement("span", null, (0, lib_1.renderName)(item))),
14
14
  "\n"))))));
15
15
  }
16
16
  function index(context, props) {
@@ -42,7 +42,7 @@ function index(context, props) {
42
42
  props.kind === models_1.ReflectionKind.Module &&
43
43
  props.readme?.length !== 0 && (utils_1.JSX.createElement("section", { class: "tsd-panel-group" },
44
44
  utils_1.JSX.createElement("section", { class: "tsd-panel tsd-typography" },
45
- utils_1.JSX.createElement(utils_1.Raw, { html: context.markdown((0, lib_1.displayPartsToMarkdown)(props.readme || [], context.urlTo)) })))),
45
+ utils_1.JSX.createElement(utils_1.Raw, { html: context.markdown(props.readme || []) })))),
46
46
  utils_1.JSX.createElement("section", { class: "tsd-panel-group tsd-index-group" },
47
47
  utils_1.JSX.createElement("section", { class: "tsd-panel tsd-index-panel" }, content))));
48
48
  }
@@ -103,7 +103,7 @@ function secondaryNavigation(context, props) {
103
103
  return (utils_1.JSX.createElement("li", { class: (0, lib_1.classNames)({ deprecated: child.isDeprecated(), current: props.model === child }, child.cssClasses) },
104
104
  utils_1.JSX.createElement("a", { href: context.urlTo(child), class: "tsd-index-link" },
105
105
  context.icons[child.kind](),
106
- (0, lib_1.wbr)(child.name))));
106
+ (0, lib_1.renderName)(child))));
107
107
  });
108
108
  if (effectivePageParent.kindOf(models_1.ReflectionKind.SomeModule | models_1.ReflectionKind.Project)) {
109
109
  return (utils_1.JSX.createElement("nav", { class: "tsd-navigation secondary menu-sticky" }, !!pageNavigation.length && utils_1.JSX.createElement("ul", null, pageNavigation)));
@@ -116,7 +116,7 @@ function secondaryNavigation(context, props) {
116
116
  }, effectivePageParent.cssClasses) },
117
117
  utils_1.JSX.createElement("a", { href: context.urlTo(effectivePageParent), class: "tsd-index-link" },
118
118
  context.icons[effectivePageParent.kind](),
119
- utils_1.JSX.createElement("span", null, (0, lib_1.wbr)(effectivePageParent.name))),
119
+ utils_1.JSX.createElement("span", null, (0, lib_1.renderName)(effectivePageParent))),
120
120
  !!pageNavigation.length && utils_1.JSX.createElement("ul", null, pageNavigation)))));
121
121
  }
122
122
  exports.secondaryNavigation = secondaryNavigation;
@@ -2,4 +2,4 @@ import type { DefaultThemeRenderContext } from "../DefaultThemeRenderContext";
2
2
  import type { ProjectReflection } from "../../../../models";
3
3
  import type { PageEvent } from "../../../events";
4
4
  import { JSX } from "../../../../utils";
5
- export declare const indexTemplate: ({ markdown, urlTo }: DefaultThemeRenderContext, props: PageEvent<ProjectReflection>) => JSX.Element;
5
+ export declare const indexTemplate: ({ markdown }: DefaultThemeRenderContext, props: PageEvent<ProjectReflection>) => JSX.Element;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.indexTemplate = void 0;
4
4
  const utils_1 = require("../../../../utils");
5
- const lib_1 = require("../../lib");
6
- const indexTemplate = ({ markdown, urlTo }, props) => (utils_1.JSX.createElement("div", { class: "tsd-panel tsd-typography" },
7
- utils_1.JSX.createElement(utils_1.Raw, { html: markdown((0, lib_1.displayPartsToMarkdown)(props.model.readme || [], urlTo)) })));
5
+ const indexTemplate = ({ markdown }, props) => (utils_1.JSX.createElement("div", { class: "tsd-panel tsd-typography" },
6
+ utils_1.JSX.createElement(utils_1.Raw, { html: markdown(props.model.readme || []) })));
8
7
  exports.indexTemplate = indexTemplate;
@@ -19,4 +19,8 @@ export declare function hasTypeParameters(reflection: Reflection): reflection is
19
19
  };
20
20
  export declare function renderTypeParametersSignature(typeParameters: readonly TypeParameterReflection[] | undefined): JSX.Element;
21
21
  export declare function camelToTitleCase(text: string): string;
22
- export declare function displayPartsToMarkdown(parts: CommentDisplayPart[], urlTo: DefaultThemeRenderContext["urlTo"]): string;
22
+ export declare function displayPartsToMarkdown(parts: readonly CommentDisplayPart[], urlTo: DefaultThemeRenderContext["urlTo"]): string;
23
+ /**
24
+ * Renders the reflection name with an additional `?` if optional.
25
+ */
26
+ export declare function renderName(refl: Reflection): JSX.Element | (string | JSX.Element)[];
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.displayPartsToMarkdown = exports.camelToTitleCase = exports.renderTypeParametersSignature = exports.hasTypeParameters = exports.classNames = exports.renderFlags = exports.join = exports.wbr = exports.stringify = void 0;
3
+ exports.renderName = exports.displayPartsToMarkdown = exports.camelToTitleCase = exports.renderTypeParametersSignature = exports.hasTypeParameters = exports.classNames = exports.renderFlags = exports.join = exports.wbr = exports.stringify = void 0;
4
4
  const models_1 = require("../../models");
5
5
  const utils_1 = require("../../utils");
6
6
  function stringify(data) {
@@ -122,3 +122,18 @@ function displayPartsToMarkdown(parts, urlTo) {
122
122
  return result.join("");
123
123
  }
124
124
  exports.displayPartsToMarkdown = displayPartsToMarkdown;
125
+ /**
126
+ * Renders the reflection name with an additional `?` if optional.
127
+ */
128
+ function renderName(refl) {
129
+ if (!refl.name) {
130
+ return utils_1.JSX.createElement("em", null, wbr(refl.kindString));
131
+ }
132
+ if (refl.flags.isOptional) {
133
+ return utils_1.JSX.createElement(utils_1.JSX.Fragment, null,
134
+ wbr(refl.name),
135
+ "?");
136
+ }
137
+ return wbr(refl.name);
138
+ }
139
+ exports.renderName = renderName;
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.9",
4
+ "version": "0.23.10",
5
5
  "homepage": "https://typedoc.org",
6
6
  "main": "./dist/index.js",
7
7
  "exports": {
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "lunr": "^2.3.9",
28
- "marked": "^4.0.16",
28
+ "marked": "^4.0.18",
29
29
  "minimatch": "^5.1.0",
30
30
  "shiki": "^0.10.1"
31
31
  },
@@ -37,22 +37,21 @@
37
37
  "@types/marked": "^4.0.3",
38
38
  "@types/minimatch": "3.0.5",
39
39
  "@types/mocha": "^9.1.1",
40
- "@types/node": "^17.0.35",
41
- "@typescript-eslint/eslint-plugin": "^5.26.0",
42
- "@typescript-eslint/parser": "^5.26.0",
40
+ "@types/node": "^18.6.3",
41
+ "@typescript-eslint/eslint-plugin": "^5.31.0",
42
+ "@typescript-eslint/parser": "^5.31.0",
43
43
  "@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#b88cd06fe814614a0d924af9d10d04ff95a551de",
44
- "c8": "^7.11.3",
44
+ "c8": "^7.12.0",
45
45
  "esbuild": "^0.14.39",
46
- "eslint": "^8.16.0",
47
- "mocha": "^9.2.1",
48
- "prettier": "2.6.2",
46
+ "eslint": "^8.20.0",
47
+ "mocha": "^10.0.0",
48
+ "prettier": "2.7.1",
49
49
  "puppeteer": "^13.5.2",
50
- "reg-notify-github-plugin": "^0.11.1",
51
- "reg-suit": "^0.11.1",
52
- "reg-suit-core": "^0.11.1",
53
- "reg-suit-interface": "^0.11.0",
54
- "ts-node": "^10.8.0",
55
- "typescript": "^4.7.2"
50
+ "reg-suit": "^0.12.1",
51
+ "reg-suit-core": "^0.12.1",
52
+ "reg-suit-interface": "^0.12.0",
53
+ "ts-node": "^10.9.1",
54
+ "typescript": "^4.7.4"
56
55
  },
57
56
  "files": [
58
57
  "/bin",
package/tsdoc.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://developer.microsoft.com/en-us/json-schemas/tsdoc/v0/tsdoc.schema.json",
2
+ "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
3
3
  "noStandardTags": false,
4
4
  "tagDefinitions": [
5
5
  {