typedoc 0.28.7 → 0.28.9

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 (40) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/lib/application.js +0 -2
  3. package/dist/lib/converter/comments/blockLexer.d.ts +2 -1
  4. package/dist/lib/converter/comments/blockLexer.js +6 -5
  5. package/dist/lib/converter/comments/index.d.ts +20 -5
  6. package/dist/lib/converter/comments/index.js +26 -23
  7. package/dist/lib/converter/comments/lineLexer.js +1 -1
  8. package/dist/lib/converter/comments/parser.d.ts +2 -2
  9. package/dist/lib/converter/comments/parser.js +6 -6
  10. package/dist/lib/converter/comments/rawLexer.js +1 -1
  11. package/dist/lib/converter/comments/textParser.js +93 -19
  12. package/dist/lib/converter/context.d.ts +10 -0
  13. package/dist/lib/converter/context.js +30 -10
  14. package/dist/lib/converter/factories/signature.js +1 -2
  15. package/dist/lib/converter/factories/symbol-id.d.ts +1 -2
  16. package/dist/lib/converter/factories/symbol-id.js +5 -51
  17. package/dist/lib/converter/jsdoc.js +1 -2
  18. package/dist/lib/converter/plugins/GroupPlugin.d.ts +1 -1
  19. package/dist/lib/converter/plugins/ImplementsPlugin.js +52 -11
  20. package/dist/lib/converter/plugins/PackagePlugin.js +2 -2
  21. package/dist/lib/converter/types.js +2 -3
  22. package/dist/lib/internationalization/locales/en.cjs +1 -0
  23. package/dist/lib/internationalization/locales/en.d.cts +1 -0
  24. package/dist/lib/internationalization/locales/zh.cjs +9 -2
  25. package/dist/lib/internationalization/locales/zh.d.cts +9 -2
  26. package/dist/lib/serialization/schema.d.ts +1 -1
  27. package/dist/lib/utils/declaration-maps.d.ts +3 -0
  28. package/dist/lib/utils/declaration-maps.js +51 -0
  29. package/dist/lib/utils/entry-point.js +6 -2
  30. package/dist/lib/utils/index.d.ts +1 -0
  31. package/dist/lib/utils/index.js +1 -0
  32. package/dist/lib/utils/options/declaration.d.ts +17 -9
  33. package/dist/lib/utils/options/declaration.js +38 -9
  34. package/dist/lib/utils/options/readers/arguments.js +2 -0
  35. package/dist/lib/utils/options/sources/typedoc.js +1 -1
  36. package/dist/lib/utils/plugins.d.ts +2 -1
  37. package/dist/lib/utils/plugins.js +26 -17
  38. package/dist/lib/utils-common/path.d.ts +6 -0
  39. package/dist/lib/utils-common/validation.js +1 -1
  40. package/package.json +9 -9
package/dist/index.d.ts CHANGED
@@ -41,7 +41,7 @@ export type { Icons, NavigationElement, PageDefinition, PageHeading, RendererEve
41
41
  export { Outputs } from "./lib/output/output.js";
42
42
  export { ArgumentsReader, CommentStyle, EntryPointStrategy, normalizePath, Option, OptionDefaults, Options, PackageJsonReader, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, ValidatingFileRegistry, } from "./lib/utils/index.js";
43
43
  export type { ArrayDeclarationOption, BooleanDeclarationOption, DeclarationOption, DeclarationOptionBase, DeclarationOptionToOptionType, DocumentationEntryPoint, FancyConsoleLogger, FlagsDeclarationOption, JsDocCompatibility, KeyToDeclaration, ManuallyValidatedOption, MapDeclarationOption, MixedDeclarationOption, NumberDeclarationOption, ObjectDeclarationOption, OptionsReader, OutputSpecification, ParameterTypeToOptionTypeMap, SortStrategy, StringDeclarationOption, TypeDocOptionMap, TypeDocOptions, TypeDocOptionValues, ValidationOptions, } from "./lib/utils/index.js";
44
- export { type ComponentPath, ConsoleLogger, type DeclarationReference, type EnumKeys, EventDispatcher, EventHooks, type GlobString, i18n, JSX, Logger, LogLevel, type Meaning, type MeaningKeyword, type MinimalNode, MinimalSourceFile, type NormalizedPath, type NormalizedPathOrModule, type SymbolReference, type TranslatedString, translateTagName, } from "#utils";
44
+ export { type ComponentPath, ConsoleLogger, type DeclarationReference, type EnumKeys, EventDispatcher, EventHooks, type GlobString, i18n, JSX, Logger, LogLevel, type Meaning, type MeaningKeyword, type MinimalNode, MinimalSourceFile, type NormalizedPath, type NormalizedPathOrModule, type NormalizedPathOrModuleOrFunction, type SymbolReference, type TranslatedString, translateTagName, } from "#utils";
45
45
  export { type Deserializable, Deserializer, type DeserializerComponent, JSONOutput, SerializeEvent, Serializer, type SerializerComponent, type SerializerEvents, } from "./lib/serialization/index.js";
46
46
  export * as Internationalization from "./lib/internationalization/index.js";
47
47
  export type { TranslatableStrings } from "./lib/internationalization/internationalization.js";
@@ -59,7 +59,6 @@ import { Outputs } from "./output/output.js";
59
59
  import { validateMergeModuleWith } from "./validation/unusedMergeModuleWith.js";
60
60
  import { diagnostic, diagnostics } from "./utils/loggers.js";
61
61
  import { ValidatingFileRegistry } from "./utils/ValidatingFileRegistry.js";
62
- import { addInferredDeclarationMapPaths } from "./converter/factories/symbol-id.js";
63
62
  import { Internationalization } from "./internationalization/internationalization.js";
64
63
  const packageInfo = JSON.parse(readFileSync(Path.join(fileURLToPath(import.meta.url), "../../../package.json"), "utf8"));
65
64
  const supportedVersionMajorMinor = packageInfo.peerDependencies.typescript
@@ -626,7 +625,6 @@ let Application = (() => {
626
625
  this.logger.error(i18n.nested_packages_unsupported_0(nicePath(dir)));
627
626
  continue;
628
627
  }
629
- addInferredDeclarationMapPaths(opts.getCompilerOptions(), opts.getFileNames());
630
628
  projectsToConvert.push({ dir, options: opts });
631
629
  }
632
630
  for (const { dir, options } of projectsToConvert) {
@@ -1,3 +1,4 @@
1
1
  import ts from "typescript";
2
2
  import { type Token } from "./lexer.js";
3
- export declare function lexBlockComment(file: string, pos?: number, end?: number, jsDoc?: ts.JSDoc | undefined, checker?: ts.TypeChecker | undefined): Generator<Token, undefined, undefined>;
3
+ import type { Context } from "../context.js";
4
+ export declare function lexBlockComment(file: string, pos?: number, end?: number, createSymbolId?: Context["createSymbolId"], jsDoc?: ts.JSDoc | undefined, checker?: ts.TypeChecker | undefined): Generator<Token, undefined, undefined>;
@@ -1,11 +1,12 @@
1
1
  import ts from "typescript";
2
2
  import { TokenSyntaxKind } from "./lexer.js";
3
3
  import { resolveAliasedSymbol } from "../utils/symbols.js";
4
- import { createSymbolId } from "../factories/symbol-id.js";
5
- export function* lexBlockComment(file, pos = 0, end = file.length, jsDoc = undefined, checker = undefined) {
4
+ export function* lexBlockComment(file, pos = 0, end = file.length, createSymbolId = () => {
5
+ throw new Error("unreachable");
6
+ }, jsDoc = undefined, checker = undefined) {
6
7
  // Wrapper around our real lex function to collapse adjacent text tokens.
7
8
  let textToken;
8
- for (const token of lexBlockComment2(file, pos, end, getLinkTags(jsDoc), checker)) {
9
+ for (const token of lexBlockComment2(file, pos, end, getLinkTags(jsDoc), checker, createSymbolId)) {
9
10
  if (token.kind === TokenSyntaxKind.Text) {
10
11
  if (textToken) {
11
12
  textToken.text += token.text;
@@ -53,7 +54,7 @@ function getLinkTags(jsDoc) {
53
54
  }
54
55
  return result;
55
56
  }
56
- function* lexBlockComment2(file, pos, end, linkTags, checker) {
57
+ function* lexBlockComment2(file, pos, end, linkTags, checker, createSymbolId) {
57
58
  pos += 2; // Leading '/*'
58
59
  end -= 2; // Trailing '*/'
59
60
  if (pos < end && file[pos] === "*") {
@@ -208,7 +209,7 @@ function* lexBlockComment2(file, pos, end, linkTags, checker) {
208
209
  }
209
210
  if (lookahead !== pos + 1) {
210
211
  while (lookahead < end &&
211
- /[a-z0-9]/i.test(file[lookahead])) {
212
+ /[a-z0-9-]/i.test(file[lookahead])) {
212
213
  lookahead++;
213
214
  }
214
215
  }
@@ -3,6 +3,7 @@ import { Comment, ReflectionKind } from "../../models/index.js";
3
3
  import type { CommentStyle, JsDocCompatibility } from "../../utils/options/declaration.js";
4
4
  import type { FileRegistry } from "../../models/FileRegistry.js";
5
5
  import { type Logger } from "#utils";
6
+ import type { Context } from "../context.js";
6
7
  export interface CommentParserConfig {
7
8
  blockTags: Set<string>;
8
9
  inlineTags: Set<string>;
@@ -12,9 +13,23 @@ export interface CommentParserConfig {
12
13
  useTsLinkResolution: boolean;
13
14
  commentStyle: CommentStyle;
14
15
  }
16
+ export interface CommentContext {
17
+ config: CommentParserConfig;
18
+ logger: Logger;
19
+ checker: ts.TypeChecker;
20
+ files: FileRegistry;
21
+ createSymbolId: Context["createSymbolId"];
22
+ }
23
+ export interface CommentContextOptionalChecker {
24
+ config: CommentParserConfig;
25
+ logger: Logger;
26
+ checker?: ts.TypeChecker | undefined;
27
+ files: FileRegistry;
28
+ createSymbolId: Context["createSymbolId"];
29
+ }
15
30
  export declare function clearCommentCache(): void;
16
- export declare function getComment(symbol: ts.Symbol, kind: ReflectionKind, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker, files: FileRegistry): Comment | undefined;
17
- export declare function getNodeComment(node: ts.Node, moduleComment: boolean, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
18
- export declare function getFileComment(file: ts.SourceFile, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
19
- export declare function getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker, files: FileRegistry): Comment | undefined;
20
- export declare function getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag, config: CommentParserConfig, logger: Logger, checker: ts.TypeChecker | undefined, files: FileRegistry): Comment | undefined;
31
+ export declare function getComment(symbol: ts.Symbol, kind: ReflectionKind, context: CommentContext): Comment | undefined;
32
+ export declare function getNodeComment(node: ts.Node, moduleComment: boolean, context: CommentContext): Comment | undefined;
33
+ export declare function getFileComment(file: ts.SourceFile, context: CommentContext): Comment | undefined;
34
+ export declare function getSignatureComment(declaration: ts.SignatureDeclaration | ts.JSDocSignature, context: CommentContext): Comment | undefined;
35
+ export declare function getJsDocComment(declaration: ts.JSDocPropertyLikeTag | ts.JSDocCallbackTag | ts.JSDocTypedefTag | ts.JSDocTemplateTag | ts.JSDocEnumTag, context: CommentContext): Comment | undefined;
@@ -21,7 +21,7 @@ export function clearCommentCache() {
21
21
  commentCache = new WeakMap();
22
22
  commentDiscoveryId = 0;
23
23
  }
24
- function getCommentWithCache(discovered, config, logger, checker, files) {
24
+ function getCommentWithCache(discovered, context) {
25
25
  if (!discovered)
26
26
  return;
27
27
  const { file, ranges, jsDoc } = discovered;
@@ -34,10 +34,10 @@ function getCommentWithCache(discovered, config, logger, checker, files) {
34
34
  let comment;
35
35
  switch (ranges[0].kind) {
36
36
  case ts.SyntaxKind.MultiLineCommentTrivia:
37
- comment = parseComment(lexBlockComment(file.text, ranges[0].pos, ranges[0].end, jsDoc, checker), config, file, logger, files);
37
+ comment = parseComment(lexBlockComment(file.text, ranges[0].pos, ranges[0].end, context.createSymbolId, jsDoc, context.checker), file, context);
38
38
  break;
39
39
  case ts.SyntaxKind.SingleLineCommentTrivia:
40
- comment = parseComment(lexLineComments(file.text, ranges), config, file, logger, files);
40
+ comment = parseComment(lexLineComments(file.text, ranges), file, context);
41
41
  break;
42
42
  default:
43
43
  assertNever(ranges[0].kind);
@@ -48,8 +48,11 @@ function getCommentWithCache(discovered, config, logger, checker, files) {
48
48
  commentCache.set(file, cache);
49
49
  return comment.clone();
50
50
  }
51
- function getCommentImpl(commentSource, config, logger, moduleComment, checker, files) {
52
- const comment = getCommentWithCache(commentSource, config, logger, config.useTsLinkResolution ? checker : undefined, files);
51
+ function getCommentImpl(commentSource, moduleComment, context) {
52
+ const comment = getCommentWithCache(commentSource, {
53
+ ...context,
54
+ checker: context.config.useTsLinkResolution ? context.checker : undefined,
55
+ });
53
56
  if (comment?.getTag("@import") || comment?.getTag("@license")) {
54
57
  return;
55
58
  }
@@ -70,15 +73,15 @@ function getCommentImpl(commentSource, config, logger, moduleComment, checker, f
70
73
  }
71
74
  return comment;
72
75
  }
73
- export function getComment(symbol, kind, config, logger, checker, files) {
76
+ export function getComment(symbol, kind, context) {
74
77
  const declarations = symbol.declarations || [];
75
78
  if (declarations.length &&
76
79
  declarations.every((d) => jsDocCommentKinds.includes(d.kind))) {
77
- return getJsDocComment(declarations[0], config, logger, checker, files);
80
+ return getJsDocComment(declarations[0], context);
78
81
  }
79
82
  const sf = declarations.find(ts.isSourceFile);
80
83
  if (sf) {
81
- return getFileComment(sf, config, logger, checker, files);
84
+ return getFileComment(sf, context);
82
85
  }
83
86
  const isModule = declarations.some((decl) => {
84
87
  if (ts.isModuleDeclaration(decl) && ts.isStringLiteral(decl.name)) {
@@ -86,18 +89,18 @@ export function getComment(symbol, kind, config, logger, checker, files) {
86
89
  }
87
90
  return false;
88
91
  });
89
- const comment = getCommentImpl(discoverComment(symbol, kind, logger, config.commentStyle, checker, !config.suppressCommentWarningsInDeclarationFiles), config, logger, isModule, checker, files);
92
+ const comment = getCommentImpl(discoverComment(symbol, kind, context.logger, context.config.commentStyle, context.checker, !context.config.suppressCommentWarningsInDeclarationFiles), isModule, context);
90
93
  if (!comment && kind === ReflectionKind.Property) {
91
- return getConstructorParamPropertyComment(symbol, config, logger, checker, files);
94
+ return getConstructorParamPropertyComment(symbol, context);
92
95
  }
93
96
  return comment;
94
97
  }
95
- export function getNodeComment(node, moduleComment, config, logger, checker, files) {
96
- return getCommentImpl(discoverNodeComment(node, config.commentStyle), config, logger, moduleComment, checker, files);
98
+ export function getNodeComment(node, moduleComment, context) {
99
+ return getCommentImpl(discoverNodeComment(node, context.config.commentStyle), moduleComment, context);
97
100
  }
98
- export function getFileComment(file, config, logger, checker, files) {
99
- for (const commentSource of discoverFileComments(file, config.commentStyle)) {
100
- const comment = getCommentWithCache(commentSource, config, logger, config.useTsLinkResolution ? checker : undefined, files);
101
+ export function getFileComment(file, context) {
102
+ for (const commentSource of discoverFileComments(file, context.config.commentStyle)) {
103
+ const comment = getCommentWithCache(commentSource, context);
101
104
  if (comment?.getTag("@license") || comment?.getTag("@import")) {
102
105
  continue;
103
106
  }
@@ -108,12 +111,12 @@ export function getFileComment(file, config, logger, checker, files) {
108
111
  return;
109
112
  }
110
113
  }
111
- function getConstructorParamPropertyComment(symbol, config, logger, checker, files) {
114
+ function getConstructorParamPropertyComment(symbol, context) {
112
115
  const decl = symbol.declarations?.find(ts.isParameter);
113
116
  if (!decl)
114
117
  return;
115
118
  const ctor = decl.parent;
116
- const comment = getSignatureComment(ctor, config, logger, checker, files);
119
+ const comment = getSignatureComment(ctor, context);
117
120
  const paramTag = comment?.getIdentifiedTag(symbol.name, "@param");
118
121
  if (paramTag) {
119
122
  const result = new Comment(paramTag.content);
@@ -121,10 +124,10 @@ function getConstructorParamPropertyComment(symbol, config, logger, checker, fil
121
124
  return result;
122
125
  }
123
126
  }
124
- export function getSignatureComment(declaration, config, logger, checker, files) {
125
- return getCommentImpl(discoverSignatureComment(declaration, checker, config.commentStyle), config, logger, false, checker, files);
127
+ export function getSignatureComment(declaration, context) {
128
+ return getCommentImpl(discoverSignatureComment(declaration, context.checker, context.config.commentStyle), false, context);
126
129
  }
127
- export function getJsDocComment(declaration, config, logger, checker, files) {
130
+ export function getJsDocComment(declaration, context) {
128
131
  const file = declaration.getSourceFile();
129
132
  // First, get the whole comment. We know we'll need all of it.
130
133
  let parent = declaration.parent;
@@ -143,7 +146,7 @@ export function getJsDocComment(declaration, config, logger, checker, files) {
143
146
  ],
144
147
  jsDoc: parent,
145
148
  inheritedFromParentDeclaration: false,
146
- }, config, logger, config.useTsLinkResolution ? checker : undefined, files);
149
+ }, context);
147
150
  // And pull out the tag we actually care about.
148
151
  if (ts.isJSDocEnumTag(declaration)) {
149
152
  const result = new Comment(comment.getTag("@enum")?.content);
@@ -156,7 +159,7 @@ export function getJsDocComment(declaration, config, logger, checker, files) {
156
159
  // We could just put the same comment on everything, but due to how comment parsing works,
157
160
  // we'd have to search for any @template with a name starting with the first type parameter's name
158
161
  // which feels horribly hacky.
159
- logger.warn(i18n.multiple_type_parameters_on_template_tag_unsupported(), declaration);
162
+ context.logger.warn(i18n.multiple_type_parameters_on_template_tag_unsupported(), declaration);
160
163
  return;
161
164
  }
162
165
  let name;
@@ -176,7 +179,7 @@ export function getJsDocComment(declaration, config, logger, checker, files) {
176
179
  // was a comment attached. If there wasn't, then don't error about failing to find
177
180
  // a tag because this is unsupported.
178
181
  if (!ts.isJSDocTemplateTag(declaration)) {
179
- logger.error(i18n.failed_to_find_jsdoc_tag_for_name_0(name), declaration);
182
+ context.logger.error(i18n.failed_to_find_jsdoc_tag_for_name_0(name), declaration);
180
183
  }
181
184
  }
182
185
  else {
@@ -145,7 +145,7 @@ function* lexLineComments2(file, pos, end) {
145
145
  }
146
146
  if (lookahead !== pos + 1) {
147
147
  while (lookahead < end &&
148
- /[a-z0-9]/i.test(file[lookahead])) {
148
+ /[a-z0-9-]/i.test(file[lookahead])) {
149
149
  lookahead++;
150
150
  }
151
151
  }
@@ -1,10 +1,10 @@
1
- import type { CommentParserConfig } from "./index.js";
1
+ import type { CommentContextOptionalChecker, CommentParserConfig } from "./index.js";
2
2
  import { Comment, type CommentDisplayPart } from "../../models/index.js";
3
3
  import type { MinimalSourceFile } from "#utils";
4
4
  import { type Token } from "./lexer.js";
5
5
  import { FileRegistry } from "../../models/FileRegistry.js";
6
6
  import { type Logger } from "#utils";
7
- export declare function parseComment(tokens: Generator<Token, undefined, undefined>, config: CommentParserConfig, file: MinimalSourceFile, logger: Logger, files: FileRegistry): Comment;
7
+ export declare function parseComment(tokens: Generator<Token, undefined, undefined>, file: MinimalSourceFile, context: CommentContextOptionalChecker): Comment;
8
8
  /**
9
9
  * Intended for parsing markdown documents. This only parses code blocks and
10
10
  * inline tags outside of code blocks, everything else is text.
@@ -40,24 +40,24 @@ function makeLookaheadGenerator(gen) {
40
40
  },
41
41
  };
42
42
  }
43
- export function parseComment(tokens, config, file, logger, files) {
43
+ export function parseComment(tokens, file, context) {
44
44
  const lexer = makeLookaheadGenerator(tokens);
45
45
  const tok = lexer.done() || lexer.peek();
46
46
  const comment = new Comment();
47
47
  comment.sourcePath = file.fileName;
48
- comment.summary = blockContent(comment, lexer, config, i18n, warningImpl, files);
48
+ comment.summary = blockContent(comment, lexer, context.config, i18n, warningImpl, context.files);
49
49
  while (!lexer.done()) {
50
- comment.blockTags.push(blockTag(comment, lexer, config, i18n, warningImpl, files));
50
+ comment.blockTags.push(blockTag(comment, lexer, context.config, i18n, warningImpl, context.files));
51
51
  }
52
52
  const tok2 = tok;
53
- postProcessComment(comment, i18n, () => `${nicePath(file.fileName)}:${file.getLineAndCharacterOfPosition(tok2.pos).line + 1}`, (message) => logger.warn(message));
53
+ postProcessComment(comment, i18n, () => `${nicePath(file.fileName)}:${file.getLineAndCharacterOfPosition(tok2.pos).line + 1}`, (message) => context.logger.warn(message));
54
54
  return comment;
55
55
  function warningImpl(message, token) {
56
- if (config.suppressCommentWarningsInDeclarationFiles &&
56
+ if (context.config.suppressCommentWarningsInDeclarationFiles &&
57
57
  hasDeclarationFileExtension(file.fileName)) {
58
58
  return;
59
59
  }
60
- logger.warn(message, token.pos, file);
60
+ context.logger.warn(message, token.pos, file);
61
61
  }
62
62
  }
63
63
  /**
@@ -151,7 +151,7 @@ function* lexCommentString2(file) {
151
151
  }
152
152
  if (lookahead !== pos + 1) {
153
153
  while (lookahead < end &&
154
- /[a-z0-9]/i.test(file[lookahead])) {
154
+ /[a-z0-9-]/i.test(file[lookahead])) {
155
155
  lookahead++;
156
156
  }
157
157
  }
@@ -85,9 +85,11 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
85
85
  addRef(reference);
86
86
  continue;
87
87
  }
88
- const tagLink = checkTagLink(data);
89
- if (tagLink) {
90
- addRef(tagLink);
88
+ const tagLinks = checkTagLink(data);
89
+ if (tagLinks.length) {
90
+ for (const tagLink of tagLinks) {
91
+ addRef(tagLink);
92
+ }
91
93
  continue;
92
94
  }
93
95
  const atNewLine = token.text[data.pos] === "\n";
@@ -221,39 +223,111 @@ function checkReference(data) {
221
223
  }
222
224
  }
223
225
  /**
224
- * Looks for `<a href="./relative">` and `<img src="./relative">`
226
+ * Looks for `<a href="./relative">`, `<img src="./relative">`, and `<source srcset="./relative">`
225
227
  */
226
228
  function checkTagLink(data) {
227
229
  const { pos, token } = data;
228
230
  if (token.text.startsWith("<img ", pos)) {
229
231
  data.pos += 4;
230
- return checkAttribute(data, "src");
232
+ return checkAttributes(data, {
233
+ src: checkAttributeDirectPath,
234
+ srcset: checkAttributeSrcSet,
235
+ });
236
+ }
237
+ if (token.text.startsWith("<link ", pos)) {
238
+ data.pos += 4;
239
+ return checkAttributes(data, {
240
+ imagesrcset: checkAttributeSrcSet,
241
+ });
231
242
  }
232
243
  if (token.text.startsWith("<a ", pos)) {
233
244
  data.pos += 3;
234
- return checkAttribute(data, "href");
245
+ return checkAttributes(data, { href: checkAttributeDirectPath });
235
246
  }
247
+ if (token.text.startsWith("<source ", pos)) {
248
+ data.pos += 8;
249
+ return checkAttributes(data, {
250
+ src: checkAttributeDirectPath,
251
+ srcset: checkAttributeSrcSet,
252
+ });
253
+ }
254
+ return [];
236
255
  }
237
- function checkAttribute(data, attr) {
256
+ function checkAttributes(data, attributes) {
257
+ const links = [];
238
258
  const parser = new HtmlAttributeParser(data.token.text, data.pos);
239
259
  while (parser.state !== ParserState.END) {
240
260
  if (parser.state === ParserState.BeforeAttributeValue &&
241
- parser.currentAttributeName === attr) {
261
+ Object.prototype.hasOwnProperty.call(attributes, parser.currentAttributeName)) {
242
262
  parser.step();
243
- if (isRelativePath(parser.currentAttributeValue)) {
244
- data.pos = parser.pos;
245
- const { target, anchor } = data.files.register(data.sourcePath, parser.currentAttributeValue) || { target: undefined, anchor: undefined };
246
- return {
247
- pos: parser.currentAttributeValueStart,
248
- end: parser.currentAttributeValueEnd,
249
- target,
250
- targetAnchor: anchor,
251
- };
252
- }
253
- return;
263
+ links.push(...attributes[parser.currentAttributeName](data, parser.currentAttributeValue, parser.currentAttributeValueStart, parser.currentAttributeValueEnd));
254
264
  }
255
265
  parser.step();
256
266
  }
267
+ return links;
268
+ }
269
+ function checkAttributeDirectPath(data, text, pos, end) {
270
+ if (isRelativePath(text.trim())) {
271
+ const { target, anchor } = data.files.register(data.sourcePath, text.trim()) || { target: undefined, anchor: undefined };
272
+ return [{
273
+ pos,
274
+ end,
275
+ target,
276
+ targetAnchor: anchor,
277
+ }];
278
+ }
279
+ return [];
280
+ }
281
+ // See https://html.spec.whatwg.org/multipage/images.html#srcset-attribute
282
+ function checkAttributeSrcSet(data, text, pos, _end) {
283
+ const result = [];
284
+ let textPos = 0;
285
+ parseImageCandidate();
286
+ while (textPos < text.length && text[textPos] == ",") {
287
+ ++textPos;
288
+ parseImageCandidate();
289
+ }
290
+ return result;
291
+ function parseImageCandidate() {
292
+ // 1. Zero or more ASCII whitespace
293
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos]))
294
+ ++textPos;
295
+ // 2. A valid non-empty URL that does not start or end with a comma
296
+ // TypeDoc: We don't exactly match this, PR welcome! For now, just permit anything
297
+ // that's not whitespace or a comma
298
+ const url = text.slice(textPos).match(/^[^\t\r\f\n ,]+/);
299
+ if (url && isRelativePath(url[0])) {
300
+ const { target, anchor } = data.files.register(data.sourcePath, url[0]) || { target: undefined, anchor: undefined };
301
+ result.push({
302
+ pos: pos + textPos,
303
+ end: pos + textPos + url[0].length,
304
+ target,
305
+ targetAnchor: anchor,
306
+ });
307
+ }
308
+ textPos += url ? url[0].length : 0;
309
+ // 3. Zero or more ASCII whitespace
310
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos]))
311
+ ++textPos;
312
+ // 4. Zero or one of the following:
313
+ {
314
+ // A width descriptor, consisting of: ASCII whitespace, a valid non-negative integer giving
315
+ // a number greater than zero representing the width descriptor value, and a U+0077 LATIN
316
+ // SMALL LETTER W character.
317
+ const w = text.slice(textPos).match(/^\+?\d+\s*w/);
318
+ textPos += w ? w[0].length : 0;
319
+ // A pixel density descriptor, consisting of: ASCII whitespace, a valid floating-point number
320
+ // giving a number greater than zero representing the pixel density descriptor value, and a
321
+ // U+0078 LATIN SMALL LETTER X character.
322
+ if (!w) {
323
+ const x = text.slice(textPos).match(/^\+?\d+(\.\d+)?([eE][+-]\d+)?\s*x/);
324
+ textPos += x ? x[0].length : 0;
325
+ }
326
+ }
327
+ // 5. Zero or more ASCII whitespace
328
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos]))
329
+ ++textPos;
330
+ }
257
331
  }
258
332
  function isRelativePath(link) {
259
333
  // Lots of edge cases encoded right here!
@@ -67,6 +67,15 @@ export declare class Context {
67
67
  * This is available on Context so that it can be monkey-patched by typedoc-plugin-missing-exports
68
68
  */
69
69
  createSymbolReference(symbol: ts.Symbol, context: Context, name?: string): ReferenceType;
70
+ /**
71
+ * Create a stable {@link ReflectionSymbolId} for the provided symbol,
72
+ * optionally targeting a specific declaration.
73
+ *
74
+ * @privateRemarks
75
+ * This is available on Context so that it can be monkey-patched by typedoc-plugin-missing-exports
76
+ * It might also turn out to be generally useful for other plugin users.
77
+ */
78
+ createSymbolId(symbol: ts.Symbol, declaration?: ts.Declaration): import("../models/ReflectionSymbolId.js").ReflectionSymbolId;
70
79
  addChild(reflection: DeclarationReflection | DocumentReflection): void;
71
80
  shouldIgnore(symbol: ts.Symbol): boolean;
72
81
  /**
@@ -81,6 +90,7 @@ export declare class Context {
81
90
  getSymbolFromReflection(reflection: Reflection): ts.Symbol | undefined;
82
91
  /** @internal */
83
92
  setActiveProgram(program: ts.Program | undefined): void;
93
+ private createCommentContext;
84
94
  getComment(symbol: ts.Symbol, kind: ReflectionKind): Comment | undefined;
85
95
  getNodeComment(node: ts.Node, moduleComment: boolean): Comment | undefined;
86
96
  getFileComment(node: ts.SourceFile): Comment | undefined;
@@ -4,10 +4,10 @@ import { Comment, ContainerReflection, DeclarationReflection, ReferenceType, Ref
4
4
  import { isNamedNode } from "./utils/nodes.js";
5
5
  import { ConverterEvents } from "./converter-events.js";
6
6
  import { resolveAliasedSymbol } from "./utils/symbols.js";
7
- import { getComment, getFileComment, getJsDocComment, getNodeComment, getSignatureComment } from "./comments/index.js";
7
+ import { getComment, getFileComment, getJsDocComment, getNodeComment, getSignatureComment, } from "./comments/index.js";
8
8
  import { getHumanName, getQualifiedName } from "../utils/tsutils.js";
9
9
  import { findPackageForPath, normalizePath } from "#node-utils";
10
- import { createSymbolId } from "./factories/symbol-id.js";
10
+ import { createSymbolIdImpl } from "./factories/symbol-id.js";
11
11
  import { removeIf } from "#utils";
12
12
  /**
13
13
  * The context describes the current state the converter is in.
@@ -185,7 +185,7 @@ export class Context {
185
185
  * This is available on Context so that it can be monkey-patched by typedoc-plugin-missing-exports
186
186
  */
187
187
  createSymbolReference(symbol, context, name) {
188
- const ref = ReferenceType.createUnresolvedReference(name ?? symbol.name, createSymbolId(symbol), context.project, getQualifiedName(symbol, name ?? symbol.name));
188
+ const ref = ReferenceType.createUnresolvedReference(name ?? symbol.name, this.createSymbolId(symbol), context.project, getQualifiedName(symbol, name ?? symbol.name));
189
189
  ref.refersToTypeParameter = !!(symbol.flags & ts.SymbolFlags.TypeParameter);
190
190
  const symbolPath = symbol.declarations?.[0]?.getSourceFile().fileName;
191
191
  if (!symbolPath)
@@ -193,6 +193,17 @@ export class Context {
193
193
  ref.package = findPackageForPath(symbolPath)?.[0];
194
194
  return ref;
195
195
  }
196
+ /**
197
+ * Create a stable {@link ReflectionSymbolId} for the provided symbol,
198
+ * optionally targeting a specific declaration.
199
+ *
200
+ * @privateRemarks
201
+ * This is available on Context so that it can be monkey-patched by typedoc-plugin-missing-exports
202
+ * It might also turn out to be generally useful for other plugin users.
203
+ */
204
+ createSymbolId(symbol, declaration) {
205
+ return createSymbolIdImpl(symbol, declaration);
206
+ }
196
207
  addChild(reflection) {
197
208
  if (this.scope instanceof ContainerReflection) {
198
209
  this.scope.addChild(reflection);
@@ -211,7 +222,7 @@ export class Context {
211
222
  registerReflection(reflection, symbol, filePath) {
212
223
  if (symbol) {
213
224
  this.reflectionIdToSymbolMap.set(reflection.id, symbol);
214
- const id = createSymbolId(symbol);
225
+ const id = this.createSymbolId(symbol);
215
226
  // #2466
216
227
  // If we just registered a member of a class or interface, then we need to check if
217
228
  // we've registered this symbol before under the wrong parent reflection.
@@ -237,7 +248,7 @@ export class Context {
237
248
  }
238
249
  }
239
250
  getReflectionFromSymbol(symbol) {
240
- return this.project.getReflectionFromSymbolId(createSymbolId(symbol));
251
+ return this.project.getReflectionFromSymbolId(this.createSymbolId(symbol));
241
252
  }
242
253
  getSymbolFromReflection(reflection) {
243
254
  return this.reflectionIdToSymbolMap.get(reflection.id);
@@ -246,20 +257,29 @@ export class Context {
246
257
  setActiveProgram(program) {
247
258
  this._program = program;
248
259
  }
260
+ createCommentContext() {
261
+ return {
262
+ config: this.converter.config,
263
+ logger: this.logger,
264
+ checker: this.checker,
265
+ files: this.project.files,
266
+ createSymbolId: (s, d) => this.createSymbolId(s, d),
267
+ };
268
+ }
249
269
  getComment(symbol, kind) {
250
- return getComment(symbol, kind, this.converter.config, this.logger, this.checker, this.project.files);
270
+ return getComment(symbol, kind, this.createCommentContext());
251
271
  }
252
272
  getNodeComment(node, moduleComment) {
253
- return getNodeComment(node, moduleComment, this.converter.config, this.logger, this.checker, this.project.files);
273
+ return getNodeComment(node, moduleComment, this.createCommentContext());
254
274
  }
255
275
  getFileComment(node) {
256
- return getFileComment(node, this.converter.config, this.logger, this.checker, this.project.files);
276
+ return getFileComment(node, this.createCommentContext());
257
277
  }
258
278
  getJsDocComment(declaration) {
259
- return getJsDocComment(declaration, this.converter.config, this.logger, this.checker, this.project.files);
279
+ return getJsDocComment(declaration, this.createCommentContext());
260
280
  }
261
281
  getSignatureComment(declaration) {
262
- return getSignatureComment(declaration, this.converter.config, this.logger, this.checker, this.project.files);
282
+ return getSignatureComment(declaration, this.createCommentContext());
263
283
  }
264
284
  shouldInline(symbol, name) {
265
285
  if (this.preventInline.has(name))
@@ -4,7 +4,6 @@ import { DeclarationReflection, IntrinsicType, ParameterReflection, PredicateTyp
4
4
  import { ConverterEvents } from "../converter-events.js";
5
5
  import { convertDefaultValue } from "../convert-expression.js";
6
6
  import { removeUndefined } from "../utils/reflections.js";
7
- import { createSymbolId } from "./symbol-id.js";
8
7
  export function createSignature(context, kind, signature, symbol, declaration) {
9
8
  assert(context.scope instanceof DeclarationReflection);
10
9
  declaration ||= signature.getDeclaration();
@@ -17,7 +16,7 @@ export function createSignature(context, kind, signature, symbol, declaration) {
17
16
  sigRef.setFlag(ReflectionFlag.Static);
18
17
  }
19
18
  if (symbol && declaration) {
20
- context.project.registerSymbolId(sigRef, createSymbolId(symbol, declaration));
19
+ context.project.registerSymbolId(sigRef, context.createSymbolId(symbol, declaration));
21
20
  }
22
21
  let parentReflection = context.scope;
23
22
  if (parentReflection.kindOf(ReflectionKind.TypeLiteral) &&
@@ -1,4 +1,3 @@
1
1
  import { ReflectionSymbolId } from "#models";
2
2
  import ts from "typescript";
3
- export declare function createSymbolId(symbol: ts.Symbol, declaration?: ts.Declaration): ReflectionSymbolId;
4
- export declare function addInferredDeclarationMapPaths(opts: ts.CompilerOptions, files: readonly string[]): void;
3
+ export declare function createSymbolIdImpl(symbol: ts.Symbol, declaration?: ts.Declaration): ReflectionSymbolId;