typedoc 0.28.5 → 0.28.7

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 (61) hide show
  1. package/dist/lib/converter/comments/discovery.js +7 -1
  2. package/dist/lib/converter/comments/linkResolver.d.ts +2 -2
  3. package/dist/lib/converter/comments/linkResolver.js +53 -10
  4. package/dist/lib/converter/comments/textParser.d.ts +1 -0
  5. package/dist/lib/converter/comments/textParser.js +76 -34
  6. package/dist/lib/converter/context.js +14 -3
  7. package/dist/lib/converter/converter.d.ts +3 -1
  8. package/dist/lib/converter/converter.js +9 -3
  9. package/dist/lib/converter/plugins/CategoryPlugin.d.ts +3 -2
  10. package/dist/lib/converter/plugins/CategoryPlugin.js +15 -3
  11. package/dist/lib/converter/plugins/GroupPlugin.d.ts +2 -1
  12. package/dist/lib/converter/plugins/GroupPlugin.js +23 -9
  13. package/dist/lib/converter/plugins/LinkResolverPlugin.d.ts +1 -2
  14. package/dist/lib/converter/plugins/LinkResolverPlugin.js +1 -55
  15. package/dist/lib/converter/plugins/PackagePlugin.js +5 -1
  16. package/dist/lib/converter/symbols.js +37 -2
  17. package/dist/lib/converter/utils/repository.js +1 -1
  18. package/dist/lib/internationalization/internationalization.js +1 -1
  19. package/dist/lib/internationalization/locales/de.cjs +1 -1
  20. package/dist/lib/internationalization/locales/de.d.cts +1 -1
  21. package/dist/lib/internationalization/locales/en.cjs +5 -2
  22. package/dist/lib/internationalization/locales/en.d.cts +5 -2
  23. package/dist/lib/internationalization/locales/ja.cjs +1 -1
  24. package/dist/lib/internationalization/locales/zh.cjs +1 -1
  25. package/dist/lib/internationalization/locales/zh.d.cts +1 -1
  26. package/dist/lib/models/Comment.d.ts +2 -1
  27. package/dist/lib/models/Comment.js +1 -1
  28. package/dist/lib/models/ContainerReflection.d.ts +1 -0
  29. package/dist/lib/models/ContainerReflection.js +3 -0
  30. package/dist/lib/models/DocumentReflection.js +1 -1
  31. package/dist/lib/models/FileRegistry.d.ts +20 -8
  32. package/dist/lib/models/FileRegistry.js +19 -6
  33. package/dist/lib/models/ProjectReflection.js +1 -1
  34. package/dist/lib/models/Reflection.d.ts +6 -0
  35. package/dist/lib/models/Reflection.js +3 -0
  36. package/dist/lib/models/types.d.ts +2 -2
  37. package/dist/lib/models/types.js +16 -14
  38. package/dist/lib/output/plugins/AssetsPlugin.js +7 -2
  39. package/dist/lib/output/themes/MarkedPlugin.js +2 -2
  40. package/dist/lib/output/themes/default/partials/moduleReflection.js +1 -1
  41. package/dist/lib/output/themes/default/partials/navigation.js +1 -1
  42. package/dist/lib/output/themes/default/templates/hierarchy.js +1 -1
  43. package/dist/lib/serialization/deserializer.d.ts +3 -3
  44. package/dist/lib/serialization/schema.d.ts +10 -8
  45. package/dist/lib/utils/ValidatingFileRegistry.d.ts +2 -2
  46. package/dist/lib/utils/ValidatingFileRegistry.js +7 -4
  47. package/dist/lib/utils/options/declaration.js +14 -22
  48. package/dist/lib/utils/options/sources/typedoc.js +1 -4
  49. package/dist/lib/utils/options/tsdoc-defaults.d.ts +1 -1
  50. package/dist/lib/utils/options/tsdoc-defaults.js +1 -0
  51. package/dist/lib/utils/sort.d.ts +2 -1
  52. package/dist/lib/utils/sort.js +4 -2
  53. package/dist/lib/utils-common/array.d.ts +1 -2
  54. package/dist/lib/utils-common/array.js +0 -7
  55. package/dist/lib/utils-common/jsx.elements.d.ts +1 -1
  56. package/dist/lib/utils-common/jsx.js +7 -6
  57. package/dist/lib/utils-common/map.d.ts +1 -1
  58. package/dist/lib/validation/links.js +23 -28
  59. package/package.json +12 -12
  60. package/static/style.css +2 -9
  61. package/tsdoc.json +4 -0
@@ -78,6 +78,7 @@ const wantedKinds = {
78
78
  [ReflectionKind.Interface]: [
79
79
  ts.SyntaxKind.InterfaceDeclaration,
80
80
  ts.SyntaxKind.TypeAliasDeclaration,
81
+ ts.SyntaxKind.ClassDeclaration, // type only exports
81
82
  ],
82
83
  [ReflectionKind.Constructor]: [ts.SyntaxKind.Constructor],
83
84
  [ReflectionKind.Property]: variablePropertyKinds,
@@ -102,7 +103,12 @@ const wantedKinds = {
102
103
  [ReflectionKind.Accessor]: [ts.SyntaxKind.PropertyDeclaration],
103
104
  [ReflectionKind.GetSignature]: [ts.SyntaxKind.GetAccessor],
104
105
  [ReflectionKind.SetSignature]: [ts.SyntaxKind.SetAccessor],
105
- [ReflectionKind.TypeAlias]: [ts.SyntaxKind.TypeAliasDeclaration],
106
+ [ReflectionKind.TypeAlias]: [
107
+ ts.SyntaxKind.TypeAliasDeclaration,
108
+ ts.SyntaxKind.FunctionDeclaration, // type only exports
109
+ // Intentionally not included to avoid comments being copied for variable/alias combos
110
+ // ts.SyntaxKind.VariableDeclaration,
111
+ ],
106
112
  [ReflectionKind.Reference]: [
107
113
  ts.SyntaxKind.NamespaceExport,
108
114
  ts.SyntaxKind.ExportSpecifier,
@@ -1,4 +1,4 @@
1
- import { type Comment, type CommentDisplayPart, Reflection, ReflectionSymbolId } from "../../models/index.js";
1
+ import { type CommentDisplayPart, Reflection, ReflectionSymbolId } from "../../models/index.js";
2
2
  import { type DeclarationReference } from "#utils";
3
3
  export type ExternalResolveResult = {
4
4
  target: string;
@@ -16,5 +16,5 @@ export type ExternalSymbolResolver = (ref: DeclarationReference, refl: Reflectio
16
16
  export type LinkResolverOptions = {
17
17
  preserveLinkText: boolean;
18
18
  };
19
- export declare function resolveLinks(comment: Comment, reflection: Reflection, externalResolver: ExternalSymbolResolver, options: LinkResolverOptions): void;
19
+ export declare function resolveLinks(reflection: Reflection, externalResolver: ExternalSymbolResolver, options: LinkResolverOptions): void;
20
20
  export declare function resolvePartLinks(reflection: Reflection, parts: readonly CommentDisplayPart[], externalResolver: ExternalSymbolResolver, options: LinkResolverOptions): CommentDisplayPart[];
@@ -1,19 +1,62 @@
1
1
  import ts from "typescript";
2
- import { DeclarationReflection, Reflection, ReflectionKind, ReflectionSymbolId, } from "../../models/index.js";
2
+ import { makeRecursiveVisitor, Reflection, ReflectionKind, ReflectionSymbolId, } from "../../models/index.js";
3
3
  import { resolveDeclarationReference } from "./declarationReferenceResolver.js";
4
4
  import { maxElementByScore, parseDeclarationReference } from "#utils";
5
5
  const urlPrefix = /^(http|ftp)s?:\/\//;
6
- export function resolveLinks(comment, reflection, externalResolver, options) {
7
- comment.summary = resolvePartLinks(reflection, comment.summary, externalResolver, options);
8
- for (const tag of comment.blockTags) {
9
- tag.content = resolvePartLinks(reflection, tag.content, externalResolver, options);
6
+ export function resolveLinks(reflection, externalResolver, options) {
7
+ if (reflection.comment) {
8
+ reflection.comment.summary = resolvePartLinks(reflection, reflection.comment.summary, externalResolver, options);
9
+ for (const tag of reflection.comment.blockTags) {
10
+ tag.content = resolvePartLinks(reflection, tag.content, externalResolver, options);
11
+ }
10
12
  }
11
- if (reflection instanceof DeclarationReflection && reflection.readme) {
13
+ if ((reflection.isDeclaration() || reflection.isProject()) && reflection.readme) {
12
14
  reflection.readme = resolvePartLinks(reflection, reflection.readme, externalResolver, options);
13
15
  }
16
+ if (reflection.isDeclaration()) {
17
+ reflection.type?.visit(makeRecursiveVisitor({
18
+ union: (type) => {
19
+ type.elementSummaries = type.elementSummaries?.map((parts) => resolvePartLinks(reflection, parts, externalResolver, options));
20
+ },
21
+ }));
22
+ }
14
23
  if (reflection.isDocument()) {
15
24
  reflection.content = resolvePartLinks(reflection, reflection.content, externalResolver, options);
16
25
  }
26
+ if (reflection.isParameter() &&
27
+ reflection.type?.type === "reference" &&
28
+ reflection.type.highlightedProperties) {
29
+ const resolved = new Map(Array.from(reflection.type.highlightedProperties, ([name, parts]) => {
30
+ return [
31
+ name,
32
+ resolvePartLinks(reflection, parts, externalResolver, options),
33
+ ];
34
+ }));
35
+ reflection.type.highlightedProperties = resolved;
36
+ }
37
+ if (reflection.isContainer()) {
38
+ if (reflection.groups) {
39
+ for (const group of reflection.groups) {
40
+ if (group.description) {
41
+ group.description = resolvePartLinks(reflection, group.description, externalResolver, options);
42
+ }
43
+ if (group.categories) {
44
+ for (const cat of group.categories) {
45
+ if (cat.description) {
46
+ cat.description = resolvePartLinks(reflection, cat.description, externalResolver, options);
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ if (reflection.categories) {
53
+ for (const cat of reflection.categories) {
54
+ if (cat.description) {
55
+ cat.description = resolvePartLinks(reflection, cat.description, externalResolver, options);
56
+ }
57
+ }
58
+ }
59
+ }
17
60
  }
18
61
  export function resolvePartLinks(reflection, parts, externalResolver, options) {
19
62
  return parts.flatMap((part) => processPart(reflection, part, externalResolver, options));
@@ -48,10 +91,10 @@ function resolveLinkTag(reflection, part, externalResolver, options) {
48
91
  const tsTargets = reflection.project.getReflectionsFromSymbolId(part.target);
49
92
  if (tsTargets.length) {
50
93
  // Find the target most likely to have a real url in the generated documentation
51
- // 1. A direct export (class, interface, variable)
52
- // 2. A property of a direct export (class/interface property)
53
- // 3. A property of a type of an export (property on type alias)
54
- // 4. Whatever the first symbol found was
94
+ // 4. A direct export (class, interface, variable)
95
+ // 3. A property of a direct export (class/interface property)
96
+ // 2. A property of a type of an export (property on type alias)
97
+ // 1. Whatever the first symbol found was
55
98
  target = maxElementByScore(tsTargets, (r) => {
56
99
  if (r.kindOf(ReflectionKind.SomeExport)) {
57
100
  return 4;
@@ -18,6 +18,7 @@ import type { NormalizedPath, TranslatedString } from "#utils";
18
18
  */
19
19
  export declare class TextParserReentryState {
20
20
  withinLinkLabel: boolean;
21
+ withinLinkDest: boolean;
21
22
  private lastPartWasNewline;
22
23
  checkState(token: Token): void;
23
24
  }
@@ -10,17 +10,20 @@ const MdHelpers = new MarkdownIt().helpers;
10
10
  */
11
11
  export class TextParserReentryState {
12
12
  withinLinkLabel = false;
13
+ withinLinkDest = false;
13
14
  lastPartWasNewline = false;
14
15
  checkState(token) {
15
16
  switch (token.kind) {
16
17
  case TokenSyntaxKind.Code:
17
18
  if (/\n\s*\n/.test(token.text)) {
18
19
  this.withinLinkLabel = false;
20
+ this.withinLinkDest = false;
19
21
  }
20
22
  break;
21
23
  case TokenSyntaxKind.NewLine:
22
24
  if (this.lastPartWasNewline) {
23
25
  this.withinLinkLabel = false;
26
+ this.withinLinkDest = false;
24
27
  }
25
28
  break;
26
29
  }
@@ -33,16 +36,17 @@ export class TextParserReentryState {
33
36
  */
34
37
  export function textContent(sourcePath, token, i18n, warning, outContent, files, atNewLine, reentry) {
35
38
  let lastPartEnd = 0;
39
+ let canEndMarkdownLink = true;
36
40
  const data = {
37
41
  sourcePath,
38
42
  token,
39
43
  pos: 0, // relative to the token
40
- i18n,
41
44
  warning,
42
45
  files: files,
43
46
  atNewLine,
44
47
  };
45
48
  function addRef(ref) {
49
+ canEndMarkdownLink = true;
46
50
  outContent.push({
47
51
  kind: "text",
48
52
  text: token.text.slice(lastPartEnd, ref.pos),
@@ -66,10 +70,15 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
66
70
  }
67
71
  }
68
72
  while (data.pos < token.text.length) {
69
- const link = checkMarkdownLink(data, reentry);
70
- if (link) {
71
- addRef(link);
72
- continue;
73
+ if (canEndMarkdownLink) {
74
+ const link = checkMarkdownLink(data, reentry);
75
+ if (link) {
76
+ addRef(link);
77
+ continue;
78
+ }
79
+ // If we're within a Markdown link, then `checkMarkdownLink`
80
+ // already scanned `token` up to a line feed (if any).
81
+ canEndMarkdownLink = !reentry.withinLinkLabel && !reentry.withinLinkDest;
73
82
  }
74
83
  const reference = checkReference(data);
75
84
  if (reference) {
@@ -81,7 +90,10 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
81
90
  addRef(tagLink);
82
91
  continue;
83
92
  }
84
- data.atNewLine = token.text[data.pos] === "\n";
93
+ const atNewLine = token.text[data.pos] === "\n";
94
+ data.atNewLine = atNewLine;
95
+ if (atNewLine && !reentry.withinLinkDest)
96
+ canEndMarkdownLink = true;
85
97
  ++data.pos;
86
98
  }
87
99
  if (lastPartEnd !== token.text.length) {
@@ -101,9 +113,8 @@ export function textContent(sourcePath, token, i18n, warning, outContent, files,
101
113
  function checkMarkdownLink(data, reentry) {
102
114
  const { token, sourcePath, files } = data;
103
115
  let searchStart;
104
- if (reentry.withinLinkLabel) {
116
+ if (reentry.withinLinkLabel || reentry.withinLinkDest) {
105
117
  searchStart = data.pos;
106
- reentry.withinLinkLabel = false;
107
118
  }
108
119
  else if (token.text[data.pos] === "[") {
109
120
  searchStart = data.pos + 1;
@@ -111,34 +122,60 @@ function checkMarkdownLink(data, reentry) {
111
122
  else {
112
123
  return;
113
124
  }
114
- const labelEnd = findLabelEnd(token.text, searchStart);
115
- if (labelEnd === -1) {
116
- // This markdown link might be split across multiple display parts
117
- // [ `text` ](link)
118
- // ^^ text
119
- // ^^^^^^ code
120
- // ^^^^^^^^ text
121
- reentry.withinLinkLabel = true;
122
- return;
125
+ if (!reentry.withinLinkDest) {
126
+ const labelEnd = findLabelEnd(token.text, searchStart);
127
+ if (labelEnd === -1 || token.text[labelEnd] === "\n") {
128
+ // This markdown link might be split across multiple lines or input tokens
129
+ // [prefix `code` suffix](target)
130
+ // ........^^^^^^................
131
+ // Unless we encounter two consecutive line feeds, expect it to keep going.
132
+ reentry.withinLinkLabel = labelEnd !== data.pos || !data.atNewLine;
133
+ return;
134
+ }
135
+ reentry.withinLinkLabel = false;
136
+ if (!token.text.startsWith("](", labelEnd))
137
+ return;
138
+ searchStart = labelEnd + 2;
123
139
  }
124
- if (token.text[labelEnd] === "]" && token.text[labelEnd + 1] === "(") {
125
- const link = MdHelpers.parseLinkDestination(token.text, labelEnd + 2, token.text.length);
126
- if (link.ok) {
127
- // Only make a relative-link display part if it's actually a relative link.
128
- // Discard protocol:// links, unix style absolute paths, and windows style absolute paths.
129
- if (isRelativePath(link.str)) {
130
- const { target, anchor } = files.register(sourcePath, link.str) || { target: undefined, anchor: undefined };
131
- return {
132
- pos: labelEnd + 2,
133
- end: link.pos,
134
- target,
135
- targetAnchor: anchor,
136
- };
137
- }
138
- // This was a link, skip ahead to ensure we don't happen to parse
139
- // something else as a link within the link.
140
- data.pos = link.pos - 1;
140
+ // Skip whitespace (including line breaks) between "](" and the link destination.
141
+ // https://spec.commonmark.org/0.31.2/#links
142
+ const end = token.text.length;
143
+ let lookahead = searchStart;
144
+ for (let newlines = 0;; ++lookahead) {
145
+ if (lookahead === end) {
146
+ reentry.withinLinkDest = true;
147
+ return;
148
+ }
149
+ switch (token.text[lookahead]) {
150
+ case "\n":
151
+ if (++newlines === 2) {
152
+ reentry.withinLinkDest = false;
153
+ return;
154
+ }
155
+ continue;
156
+ case " ":
157
+ case "\t":
158
+ continue;
141
159
  }
160
+ break;
161
+ }
162
+ reentry.withinLinkDest = false;
163
+ const link = MdHelpers.parseLinkDestination(token.text, lookahead, end);
164
+ if (link.ok) {
165
+ // Only make a relative-link display part if it's actually a relative link.
166
+ // Discard protocol:// links, unix style absolute paths, and windows style absolute paths.
167
+ if (isRelativePath(link.str)) {
168
+ const { target, anchor } = files.register(sourcePath, link.str) || { target: undefined, anchor: undefined };
169
+ return {
170
+ pos: lookahead,
171
+ end: link.pos,
172
+ target,
173
+ targetAnchor: anchor,
174
+ };
175
+ }
176
+ // This was a link, skip ahead to ensure we don't happen to parse
177
+ // something else as a link within the link.
178
+ data.pos = link.pos - 1;
142
179
  }
143
180
  }
144
181
  /**
@@ -230,6 +267,11 @@ function isRelativePath(link) {
230
267
  function findLabelEnd(text, pos) {
231
268
  while (pos < text.length) {
232
269
  switch (text[pos]) {
270
+ case "\\":
271
+ ++pos;
272
+ if (pos < text.length && text[pos] === "\n")
273
+ return pos;
274
+ break;
233
275
  case "\n":
234
276
  case "]":
235
277
  case "[":
@@ -130,14 +130,25 @@ export class Context {
130
130
  return reflection;
131
131
  }
132
132
  postReflectionCreation(reflection, symbol, exportSymbol) {
133
- if (exportSymbol &&
134
- reflection.kind &
135
- (ReflectionKind.SomeModule | ReflectionKind.Reference)) {
133
+ // Allow comments on export declarations to take priority over comments directly
134
+ // on the symbol to enable overriding comments on modules/references, #1504
135
+ if (!reflection.comment &&
136
+ exportSymbol &&
137
+ (reflection.kind &
138
+ (ReflectionKind.SomeModule | ReflectionKind.Reference))) {
136
139
  reflection.comment = this.getComment(exportSymbol, reflection.kind);
137
140
  }
141
+ // If that didn't get us a comment (the normal case), then get the comment from
142
+ // the source declarations, this is the common case.
138
143
  if (symbol && !reflection.comment) {
139
144
  reflection.comment = this.getComment(symbol, reflection.kind);
140
145
  }
146
+ // If we still don't have a comment, check for any comments on the export declaration,
147
+ // we don't have to worry about functions being weird in this case as the regular declaration
148
+ // doesn't have any comment.
149
+ if (exportSymbol && !reflection.comment) {
150
+ reflection.comment = this.getComment(exportSymbol, ReflectionKind.Reference);
151
+ }
141
152
  if (this.shouldBeStatic) {
142
153
  reflection.setFlag(ReflectionFlag.Static);
143
154
  }
@@ -1,6 +1,6 @@
1
1
  import ts from "typescript";
2
2
  import type { Application } from "../application.js";
3
- import { Comment, type CommentDisplayPart, type ContainerReflection, type DeclarationReflection, DocumentReflection, type ParameterReflection, ProjectReflection, type Reflection, type ReflectionSymbolId, type SignatureReflection, type SomeType, type TypeParameterReflection } from "../models/index.js";
3
+ import { Comment, type CommentDisplayPart, type ContainerReflection, type DeclarationReflection, DocumentReflection, type ParameterReflection, ProjectReflection, Reflection, type ReflectionSymbolId, type SignatureReflection, type SomeType, type TypeParameterReflection } from "../models/index.js";
4
4
  import { Context } from "./context.js";
5
5
  import { AbstractComponent } from "../utils/component.js";
6
6
  import { type GlobString, MinimalSourceFile } from "#utils";
@@ -187,6 +187,8 @@ export declare class Converter extends AbstractComponent<Application, ConverterE
187
187
  addUnknownSymbolResolver(resolver: ExternalSymbolResolver): void;
188
188
  /** @internal */
189
189
  resolveExternalLink(ref: DeclarationReference, refl: Reflection, part: CommentDisplayPart | undefined, symbolId: ReflectionSymbolId | undefined): ExternalResolveResult | string | undefined;
190
+ resolveLinks(reflection: Reflection): void;
191
+ /** @deprecated just pass the reflection */
190
192
  resolveLinks(comment: Comment, owner: Reflection): void;
191
193
  resolveLinks(parts: readonly CommentDisplayPart[], owner: Reflection): CommentDisplayPart[];
192
194
  /**
@@ -34,7 +34,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
34
34
  };
35
35
  import ts from "typescript";
36
36
  import { ok } from "assert";
37
- import { Comment, DocumentReflection, ProjectReflection, ReflectionKind, } from "../models/index.js";
37
+ import { Comment, DocumentReflection, ProjectReflection, Reflection, ReflectionKind, } from "../models/index.js";
38
38
  import { Context } from "./context.js";
39
39
  import { AbstractComponent } from "../utils/component.js";
40
40
  import { getDocumentEntryPoints, Option, readFile } from "../utils/index.js";
@@ -305,6 +305,9 @@ let Converter = (() => {
305
305
  const programs = unique(entryPoints.map((e) => e.program));
306
306
  this.externalPatternCache = void 0;
307
307
  const project = new ProjectReflection(this.application.options.getValue("name"), this.application.files);
308
+ if (this.owner.options.packageDir) {
309
+ project.files.registerReflectionPath(normalizePath(this.owner.options.packageDir), project);
310
+ }
308
311
  const context = new Context(this, programs, project);
309
312
  this.trigger(Converter.EVENT_BEGIN, context);
310
313
  this.addProjectDocuments(project);
@@ -371,8 +374,11 @@ let Converter = (() => {
371
374
  }
372
375
  }
373
376
  resolveLinks(comment, owner) {
374
- if (comment instanceof Comment) {
375
- resolveLinks(comment, owner, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
377
+ if (comment instanceof Reflection) {
378
+ resolveLinks(comment, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
379
+ }
380
+ else if (comment instanceof Comment) {
381
+ resolveLinks(owner, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
376
382
  }
377
383
  else {
378
384
  return resolvePartLinks(owner, comment, (ref, part, refl, id) => this.resolveExternalLink(ref, part, refl, id), { preserveLinkText: this.preserveLinkText });
@@ -1,4 +1,4 @@
1
- import { type DeclarationReflection, type DocumentReflection } from "../../models/index.js";
1
+ import { ContainerReflection, type DeclarationReflection, type DocumentReflection } from "../../models/index.js";
2
2
  import { ConverterComponent } from "../components.js";
3
3
  import type { Converter } from "../converter.js";
4
4
  /**
@@ -7,7 +7,7 @@ import type { Converter } from "../converter.js";
7
7
  * The handler sets the ´category´ property of all reflections.
8
8
  */
9
9
  export declare class CategoryPlugin extends ConverterComponent {
10
- sortFunction: (reflections: Array<DeclarationReflection | DocumentReflection>) => void;
10
+ defaultSortFunction: (reflections: Array<DeclarationReflection | DocumentReflection>) => void;
11
11
  accessor defaultCategory: string;
12
12
  accessor categoryOrder: string[];
13
13
  accessor categorizeByGroup: boolean;
@@ -35,6 +35,7 @@ export declare class CategoryPlugin extends ConverterComponent {
35
35
  * @returns An array containing all children of the given reflection categorized
36
36
  */
37
37
  private getReflectionCategories;
38
+ getSortFunction(reflection: ContainerReflection): (reflections: (DeclarationReflection | DocumentReflection)[]) => void;
38
39
  /**
39
40
  * Callback used to sort categories by name.
40
41
  *
@@ -39,6 +39,7 @@ import { getSortFunction, Option } from "../../utils/index.js";
39
39
  import { ConverterComponent } from "../components.js";
40
40
  import { ConverterEvents } from "../converter-events.js";
41
41
  import { i18n } from "#utils";
42
+ import { isValidSortStrategy } from "../../utils/sort.js";
42
43
  /**
43
44
  * A handler that sorts and categorizes the found reflections in the resolving phase.
44
45
  *
@@ -66,7 +67,7 @@ let CategoryPlugin = (() => {
66
67
  __esDecorate(this, null, _categorizeByGroup_decorators, { kind: "accessor", name: "categorizeByGroup", static: false, private: false, access: { has: obj => "categorizeByGroup" in obj, get: obj => obj.categorizeByGroup, set: (obj, value) => { obj.categorizeByGroup = value; } }, metadata: _metadata }, _categorizeByGroup_initializers, _categorizeByGroup_extraInitializers);
67
68
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
68
69
  }
69
- sortFunction;
70
+ defaultSortFunction;
70
71
  #defaultCategory_accessor_storage = __runInitializers(this, _defaultCategory_initializers, void 0);
71
72
  get defaultCategory() { return this.#defaultCategory_accessor_storage; }
72
73
  set defaultCategory(value) { this.#defaultCategory_accessor_storage = value; }
@@ -97,7 +98,7 @@ let CategoryPlugin = (() => {
97
98
  * Triggered when the converter begins converting a project.
98
99
  */
99
100
  setup() {
100
- this.sortFunction = getSortFunction(this.application.options);
101
+ this.defaultSortFunction = getSortFunction(this.application.options);
101
102
  // Set up static properties
102
103
  if (this.defaultCategory) {
103
104
  CategoryPlugin.defaultCategory = this.defaultCategory;
@@ -201,10 +202,21 @@ let CategoryPlugin = (() => {
201
202
  }
202
203
  }
203
204
  for (const cat of categories.values()) {
204
- this.sortFunction(cat.children);
205
+ this.getSortFunction(parent)(cat.children);
205
206
  }
206
207
  return Array.from(categories.values());
207
208
  }
209
+ getSortFunction(reflection) {
210
+ const tag = reflection.comment?.getTag("@sortStrategy");
211
+ if (tag) {
212
+ const text = Comment.combineDisplayParts(tag.content);
213
+ // We don't need to warn about invalid strategies here because the group plugin
214
+ // runs first and will have already warned.
215
+ const strategies = text.split(/[,\s]+/).filter(isValidSortStrategy);
216
+ return getSortFunction(this.application.options, strategies);
217
+ }
218
+ return this.defaultSortFunction;
219
+ }
208
220
  /**
209
221
  * Callback used to sort categories by name.
210
222
  *
@@ -8,7 +8,7 @@ import type { Converter } from "../converter.js";
8
8
  * The handler sets the `groups` property of all container reflections.
9
9
  */
10
10
  export declare class GroupPlugin extends ConverterComponent {
11
- sortFunction: (reflections: Array<DeclarationReflection | DocumentReflection>) => void;
11
+ defaultSortFunction: (reflections: Array<DeclarationReflection | DocumentReflection>) => void;
12
12
  accessor groupOrder: string[];
13
13
  accessor sortEntryPoints: boolean;
14
14
  accessor groupReferencesByType: boolean;
@@ -40,6 +40,7 @@ export declare class GroupPlugin extends ConverterComponent {
40
40
  * @returns An array containing all children of the given reflection grouped by their kind.
41
41
  */
42
42
  getReflectionGroups(parent: ContainerReflection, reflections: Array<DeclarationReflection | DocumentReflection>): ReflectionGroup[];
43
+ getSortFunction(reflection: ContainerReflection): (reflections: (DeclarationReflection | DocumentReflection)[]) => void;
43
44
  /**
44
45
  * Callback used to sort groups by name.
45
46
  */
@@ -35,13 +35,13 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
35
35
  import { ContainerReflection, ReferenceReflection, ReflectionKind, } from "../../models/index.js";
36
36
  import { ReflectionGroup } from "../../models/ReflectionGroup.js";
37
37
  import { ConverterComponent } from "../components.js";
38
- import { getSortFunction } from "../../utils/sort.js";
38
+ import { getSortFunction, isValidSortStrategy, SORT_STRATEGIES } from "../../utils/sort.js";
39
39
  import { Option } from "../../utils/index.js";
40
40
  import { Comment } from "../../models/index.js";
41
41
  import { ConverterEvents } from "../converter-events.js";
42
42
  import { ApplicationEvents } from "../../application-events.js";
43
43
  import assert from "assert";
44
- import { i18n } from "#utils";
44
+ import { i18n, partition } from "#utils";
45
45
  // Same as the defaultKindSortOrder in sort.ts
46
46
  const defaultGroupOrder = [
47
47
  ReflectionKind.Document,
@@ -89,7 +89,7 @@ let GroupPlugin = (() => {
89
89
  __esDecorate(this, null, _groupReferencesByType_decorators, { kind: "accessor", name: "groupReferencesByType", static: false, private: false, access: { has: obj => "groupReferencesByType" in obj, get: obj => obj.groupReferencesByType, set: (obj, value) => { obj.groupReferencesByType = value; } }, metadata: _metadata }, _groupReferencesByType_initializers, _groupReferencesByType_extraInitializers);
90
90
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
91
91
  }
92
- sortFunction;
92
+ defaultSortFunction;
93
93
  #groupOrder_accessor_storage = __runInitializers(this, _groupOrder_initializers, void 0);
94
94
  get groupOrder() { return this.#groupOrder_accessor_storage; }
95
95
  set groupOrder(value) { this.#groupOrder_accessor_storage = value; }
@@ -130,25 +130,26 @@ let GroupPlugin = (() => {
130
130
  }
131
131
  }
132
132
  setup() {
133
- this.sortFunction = getSortFunction(this.application.options);
133
+ this.defaultSortFunction = getSortFunction(this.application.options);
134
134
  GroupPlugin.WEIGHTS = this.groupOrder;
135
135
  if (GroupPlugin.WEIGHTS.length === 0) {
136
136
  GroupPlugin.WEIGHTS = defaultGroupOrder.map((kind) => ReflectionKind.pluralString(kind));
137
137
  }
138
138
  }
139
139
  group(reflection) {
140
+ const sortFunction = this.getSortFunction(reflection);
140
141
  if (reflection.childrenIncludingDocuments && !reflection.groups) {
141
142
  if (reflection.children) {
142
143
  if (this.sortEntryPoints ||
143
144
  !reflection.children.some((c) => c.kindOf(ReflectionKind.Module))) {
144
- this.sortFunction(reflection.children);
145
- this.sortFunction(reflection.documents || []);
146
- this.sortFunction(reflection.childrenIncludingDocuments);
145
+ sortFunction(reflection.children);
146
+ sortFunction(reflection.documents || []);
147
+ sortFunction(reflection.childrenIncludingDocuments);
147
148
  }
148
149
  }
149
150
  else if (reflection.documents) {
150
- this.sortFunction(reflection.documents);
151
- this.sortFunction(reflection.childrenIncludingDocuments);
151
+ sortFunction(reflection.documents);
152
+ sortFunction(reflection.childrenIncludingDocuments);
152
153
  }
153
154
  if (reflection.comment?.hasModifier("@disableGroups")) {
154
155
  return;
@@ -239,6 +240,19 @@ let GroupPlugin = (() => {
239
240
  }
240
241
  return Array.from(groups.values()).sort(GroupPlugin.sortGroupCallback);
241
242
  }
243
+ getSortFunction(reflection) {
244
+ const tag = reflection.comment?.getTag("@sortStrategy");
245
+ if (tag) {
246
+ const text = Comment.combineDisplayParts(tag.content);
247
+ const strategies = text.split(/[,\s]+/);
248
+ const [valid, invalid] = partition(strategies, isValidSortStrategy);
249
+ for (const inv of invalid) {
250
+ this.application.logger.warn(i18n.comment_for_0_specifies_1_as_sort_strategy_but_only_2_is_valid(reflection.getFriendlyFullName(), inv, SORT_STRATEGIES.join("\n\t")));
251
+ }
252
+ return getSortFunction(this.application.options, valid);
253
+ }
254
+ return this.defaultSortFunction;
255
+ }
242
256
  /**
243
257
  * Callback used to sort groups by name.
244
258
  */
@@ -1,7 +1,7 @@
1
1
  import { ConverterComponent } from "../components.js";
2
2
  import type { Context, Converter } from "../../converter/index.js";
3
3
  import { type ValidationOptions } from "../../utils/index.js";
4
- import { type ProjectReflection } from "../../models/index.js";
4
+ import type { ProjectReflection } from "../../models/index.js";
5
5
  /**
6
6
  * A plugin that resolves `{@link Foo}` tags.
7
7
  */
@@ -10,5 +10,4 @@ export declare class LinkResolverPlugin extends ConverterComponent {
10
10
  constructor(owner: Converter);
11
11
  onResolve(context: Context): void;
12
12
  resolveLinks(project: ProjectReflection): void;
13
- private resolveCategoryLinks;
14
13
  }