typedoc 0.27.6 → 0.27.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/typedoc +21 -2
- package/dist/index.d.ts +1 -1
- package/dist/lib/application.d.ts +30 -1
- package/dist/lib/application.js +97 -21
- package/dist/lib/cli.js +4 -4
- package/dist/lib/converter/converter.d.ts +2 -3
- package/dist/lib/converter/converter.js +15 -20
- package/dist/lib/converter/factories/signature.js +16 -4
- package/dist/lib/converter/plugins/IncludePlugin.d.ts +2 -0
- package/dist/lib/converter/plugins/IncludePlugin.js +177 -4
- package/dist/lib/converter/plugins/PackagePlugin.js +2 -0
- package/dist/lib/converter/symbols.js +21 -7
- package/dist/lib/converter/types.d.ts +2 -2
- package/dist/lib/converter/types.js +21 -18
- package/dist/lib/internationalization/internationalization.js +6 -2
- package/dist/lib/internationalization/locales/en.cjs +18 -1
- package/dist/lib/internationalization/locales/en.d.cts +17 -1
- package/dist/lib/internationalization/locales/ja.cjs +321 -0
- package/dist/lib/internationalization/locales/ja.d.cts +308 -0
- package/dist/lib/internationalization/locales/jp.cjs +2 -320
- package/dist/lib/internationalization/locales/jp.d.cts +2 -308
- package/dist/lib/internationalization/locales/zh.cjs +6 -3
- package/dist/lib/internationalization/locales/zh.d.cts +5 -2
- package/dist/lib/internationalization/translatable.d.ts +2 -1
- package/dist/lib/output/formatter.js +6 -1
- package/dist/lib/output/index.d.ts +1 -0
- package/dist/lib/output/plugins/AssetsPlugin.d.ts +1 -7
- package/dist/lib/output/plugins/AssetsPlugin.js +20 -8
- package/dist/lib/output/themes/MarkedPlugin.js +5 -3
- package/dist/lib/output/themes/default/DefaultTheme.d.ts +3 -39
- package/dist/lib/output/themes/default/DefaultTheme.js +19 -10
- package/dist/lib/output/themes/default/DefaultThemeRenderContext.d.ts +12 -12
- package/dist/lib/output/themes/default/layouts/default.js +3 -0
- package/dist/lib/output/themes/default/partials/icon.d.ts +17 -2
- package/dist/lib/output/themes/default/partials/icon.js +77 -79
- package/dist/lib/output/themes/default/partials/member.getterSetter.js +6 -6
- package/dist/lib/output/themes/default/partials/member.signatures.js +3 -3
- package/dist/lib/output/themes/default/templates/reflection.js +2 -2
- package/dist/lib/utils/fs.d.ts +2 -2
- package/dist/lib/utils/fs.js +4 -3
- package/dist/lib/utils/general.d.ts +1 -0
- package/dist/lib/utils/general.js +11 -0
- package/dist/lib/utils/options/declaration.d.ts +18 -12
- package/dist/lib/utils/options/declaration.js +37 -10
- package/dist/lib/utils/options/options.d.ts +3 -2
- package/dist/lib/utils/options/options.js +2 -2
- package/dist/lib/utils/options/readers/package-json.d.ts +1 -1
- package/dist/lib/utils/options/readers/package-json.js +2 -2
- package/dist/lib/utils/options/readers/tsconfig.d.ts +1 -1
- package/dist/lib/utils/options/readers/tsconfig.js +2 -2
- package/dist/lib/utils/options/readers/typedoc.d.ts +1 -1
- package/dist/lib/utils/options/readers/typedoc.js +4 -4
- package/dist/lib/utils/options/sources/typedoc.js +11 -4
- package/dist/lib/utils/tsconfig.d.ts +1 -1
- package/dist/lib/utils/tsconfig.js +2 -2
- package/dist/lib/validation/documentation.d.ts +1 -1
- package/dist/lib/validation/documentation.js +11 -1
- package/package.json +1 -1
- package/static/main.js +3 -3
- package/static/style.css +5 -4
|
@@ -4,6 +4,7 @@ import { ConverterComponent } from "../components.js";
|
|
|
4
4
|
import { ConverterEvents } from "../converter-events.js";
|
|
5
5
|
import { MinimalSourceFile } from "../../utils/minimalSourceFile.js";
|
|
6
6
|
import { isFile } from "../../utils/fs.js";
|
|
7
|
+
import { dedent, escapeRegExp } from "../../utils/general.js";
|
|
7
8
|
/**
|
|
8
9
|
* Handles `@include` and `@includeCode` within comments/documents.
|
|
9
10
|
*/
|
|
@@ -42,14 +43,22 @@ export class IncludePlugin extends ConverterComponent {
|
|
|
42
43
|
!["@include", "@includeCode"].includes(part.tag)) {
|
|
43
44
|
continue;
|
|
44
45
|
}
|
|
45
|
-
const
|
|
46
|
+
const { filename, regionTarget, requestedLines } = parseIncludeCodeTextPart(part.text);
|
|
47
|
+
const file = path.resolve(relative, filename);
|
|
48
|
+
this.application.watchFile(file);
|
|
46
49
|
if (included.includes(file) && part.tag === "@include") {
|
|
47
50
|
this.logger.error(this.logger.i18n.include_0_in_1_specified_2_circular_include_3(part.tag, refl.getFriendlyFullName(), part.text, included.join("\n\t")));
|
|
48
51
|
}
|
|
49
52
|
else if (isFile(file)) {
|
|
50
53
|
const text = fs.readFileSync(file, "utf-8");
|
|
54
|
+
const ext = path.extname(file).substring(1);
|
|
55
|
+
const includedText = regionTarget
|
|
56
|
+
? this.getRegions(refl, file, ext, part.text, text, regionTarget, part.tag, part.tag === "@includeCode")
|
|
57
|
+
: requestedLines
|
|
58
|
+
? this.getLines(refl, file, part.text, text, requestedLines, part.tag)
|
|
59
|
+
: text;
|
|
51
60
|
if (part.tag === "@include") {
|
|
52
|
-
const sf = new MinimalSourceFile(
|
|
61
|
+
const sf = new MinimalSourceFile(includedText, file);
|
|
53
62
|
const { content } = this.owner.parseRawComment(sf, refl.project.files);
|
|
54
63
|
this.checkIncludeTagsParts(refl, path.dirname(file), content, [...included, file]);
|
|
55
64
|
parts.splice(i, 1, ...content);
|
|
@@ -57,17 +66,181 @@ export class IncludePlugin extends ConverterComponent {
|
|
|
57
66
|
else {
|
|
58
67
|
parts[i] = {
|
|
59
68
|
kind: "code",
|
|
60
|
-
text: makeCodeBlock(
|
|
69
|
+
text: makeCodeBlock(ext, includedText),
|
|
61
70
|
};
|
|
62
71
|
}
|
|
63
72
|
}
|
|
64
73
|
else {
|
|
65
|
-
this.logger.
|
|
74
|
+
this.logger.error(this.logger.i18n.include_0_in_1_specified_2_resolved_to_3_does_not_exist(part.tag, refl.getFriendlyFullName(), part.text, file));
|
|
66
75
|
}
|
|
67
76
|
}
|
|
68
77
|
}
|
|
78
|
+
getRegions(refl, file, ext, textPart, text, regionTargets, tag, ignoreIndent) {
|
|
79
|
+
const regionTagsList = regionTagREsByExt[ext];
|
|
80
|
+
if (!regionTagsList) {
|
|
81
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_region_2_region_not_supported(tag, refl.getFriendlyFullName(), textPart));
|
|
82
|
+
return "";
|
|
83
|
+
}
|
|
84
|
+
const targets = regionTargets.split(",").map((s) => s.trim());
|
|
85
|
+
let content = "";
|
|
86
|
+
for (const target of targets) {
|
|
87
|
+
let found = false;
|
|
88
|
+
for (const [startTag, endTag] of regionTagsList) {
|
|
89
|
+
const safeTarget = escapeRegExp(target);
|
|
90
|
+
const start = text.match(startTag(safeTarget));
|
|
91
|
+
const end = text.match(endTag(safeTarget));
|
|
92
|
+
const foundStart = start && start.length > 0;
|
|
93
|
+
const foundEnd = end && end.length > 0;
|
|
94
|
+
if (foundStart && !foundEnd) {
|
|
95
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_close_not_found(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
96
|
+
return "";
|
|
97
|
+
}
|
|
98
|
+
if (!foundStart && foundEnd) {
|
|
99
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_open_not_found(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
100
|
+
return "";
|
|
101
|
+
}
|
|
102
|
+
if (foundStart && foundEnd) {
|
|
103
|
+
if (start.length > 1) {
|
|
104
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_open_found_multiple_times(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
107
|
+
if (end.length > 1) {
|
|
108
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_close_found_multiple_times(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
109
|
+
return "";
|
|
110
|
+
}
|
|
111
|
+
if (found) {
|
|
112
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_found_multiple_times(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
113
|
+
return "";
|
|
114
|
+
}
|
|
115
|
+
found = text.substring(text.indexOf(start[0]) + start[0].length, text.indexOf(end[0]));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (found === false) {
|
|
119
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_not_found(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
120
|
+
return "";
|
|
121
|
+
}
|
|
122
|
+
if (found.trim() === "") {
|
|
123
|
+
this.logger.warn(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_region_4_region_empty(tag, refl.getFriendlyFullName(), textPart, file, target));
|
|
124
|
+
}
|
|
125
|
+
content += ignoreIndent ? dedent(found) + "\n" : found;
|
|
126
|
+
}
|
|
127
|
+
return content;
|
|
128
|
+
}
|
|
129
|
+
getLines(refl, file, textPart, text, requestedLines, tag) {
|
|
130
|
+
let output = "";
|
|
131
|
+
const lines = text.split(/\r\n|\r|\n/);
|
|
132
|
+
requestedLines.split(",").forEach((requestedLineString) => {
|
|
133
|
+
if (requestedLineString.includes("-")) {
|
|
134
|
+
const [start, end] = requestedLineString.split("-").map(Number);
|
|
135
|
+
if (start > end) {
|
|
136
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_invalid_range(tag, refl.getFriendlyFullName(), textPart, file, requestedLines));
|
|
137
|
+
return "";
|
|
138
|
+
}
|
|
139
|
+
if (start > lines.length || end > lines.length) {
|
|
140
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines(tag, refl.getFriendlyFullName(), textPart, file, requestedLines, lines.length.toString()));
|
|
141
|
+
return "";
|
|
142
|
+
}
|
|
143
|
+
output += lines.slice(start - 1, end).join("\n") + "\n";
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
const requestedLine = Number(requestedLineString);
|
|
147
|
+
if (requestedLine > lines.length) {
|
|
148
|
+
this.logger.error(this.logger.i18n.include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines(tag, refl.getFriendlyFullName(), textPart, file, requestedLines, lines.length.toString()));
|
|
149
|
+
return "";
|
|
150
|
+
}
|
|
151
|
+
output += lines[requestedLine - 1] + "\n";
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
return output;
|
|
155
|
+
}
|
|
69
156
|
}
|
|
70
157
|
function makeCodeBlock(lang, code) {
|
|
71
158
|
const escaped = code.replace(/`(?=`)/g, "`\u200B");
|
|
72
159
|
return "\n\n```" + lang + "\n" + escaped.trimEnd() + "\n```";
|
|
73
160
|
}
|
|
161
|
+
function parseIncludeCodeTextPart(text) {
|
|
162
|
+
let filename = text.trim();
|
|
163
|
+
let regionTarget;
|
|
164
|
+
let requestedLines;
|
|
165
|
+
if (filename.includes("#")) {
|
|
166
|
+
const parsed = filename.split("#");
|
|
167
|
+
filename = parsed[0];
|
|
168
|
+
regionTarget = parsed[1];
|
|
169
|
+
}
|
|
170
|
+
else if (filename.includes(":")) {
|
|
171
|
+
const parsed = filename.split(":");
|
|
172
|
+
filename = parsed[0];
|
|
173
|
+
requestedLines = parsed[1];
|
|
174
|
+
}
|
|
175
|
+
return { filename, regionTarget, requestedLines };
|
|
176
|
+
}
|
|
177
|
+
const regionTagREsByExt = {
|
|
178
|
+
bat: [
|
|
179
|
+
[
|
|
180
|
+
(regionName) => new RegExp(`:: *#region *${regionName} *\n`, "g"),
|
|
181
|
+
(regionName) => new RegExp(`:: *#endregion *${regionName} *\n`, "g"),
|
|
182
|
+
],
|
|
183
|
+
[
|
|
184
|
+
(regionName) => new RegExp(`REM *#region *${regionName} *\n`, "g"),
|
|
185
|
+
(regionName) => new RegExp(`REM *#endregion *${regionName} *\n`, "g"),
|
|
186
|
+
],
|
|
187
|
+
],
|
|
188
|
+
cs: [
|
|
189
|
+
[
|
|
190
|
+
(regionName) => new RegExp(`#region *${regionName} *\n`, "g"),
|
|
191
|
+
(regionName) => new RegExp(`#endregion *${regionName} *\n`, "g"),
|
|
192
|
+
],
|
|
193
|
+
],
|
|
194
|
+
c: [
|
|
195
|
+
[
|
|
196
|
+
(regionName) => new RegExp(`#pragma *region *${regionName} *\n`, "g"),
|
|
197
|
+
(regionName) => new RegExp(`#pragma *endregion *${regionName} *\n`, "g"),
|
|
198
|
+
],
|
|
199
|
+
],
|
|
200
|
+
css: [
|
|
201
|
+
[
|
|
202
|
+
(regionName) => new RegExp(`/\\* *#region *\\*/ *${regionName} *\n`, "g"),
|
|
203
|
+
(regionName) => new RegExp(`/\\* *#endregion *\\*/ *${regionName} *\n`, "g"),
|
|
204
|
+
],
|
|
205
|
+
],
|
|
206
|
+
md: [
|
|
207
|
+
[
|
|
208
|
+
(regionName) => new RegExp(`<!-- *#region *${regionName} *--> *\n`, "g"),
|
|
209
|
+
(regionName) => new RegExp(`<!-- *#endregion *${regionName} *--> *\n`, "g"),
|
|
210
|
+
],
|
|
211
|
+
],
|
|
212
|
+
ts: [
|
|
213
|
+
[
|
|
214
|
+
(regionName) => new RegExp(`// *#region *${regionName} *\n`, "g"),
|
|
215
|
+
(regionName) => new RegExp(`// *#endregion *${regionName} *\n`, "g"),
|
|
216
|
+
],
|
|
217
|
+
],
|
|
218
|
+
vb: [
|
|
219
|
+
[
|
|
220
|
+
(regionName) => new RegExp(`#Region *${regionName} *\n`, "g"),
|
|
221
|
+
(regionName) => new RegExp(`#End Region *${regionName} *\n`, "g"),
|
|
222
|
+
],
|
|
223
|
+
],
|
|
224
|
+
};
|
|
225
|
+
regionTagREsByExt["fs"] = [
|
|
226
|
+
...regionTagREsByExt["ts"],
|
|
227
|
+
[
|
|
228
|
+
(regionName) => new RegExp(`(#_region) *${regionName} *\n`, "g"),
|
|
229
|
+
(regionName) => new RegExp(`(#_endregion) *${regionName} *\n`, "g"),
|
|
230
|
+
],
|
|
231
|
+
];
|
|
232
|
+
regionTagREsByExt["java"] = [
|
|
233
|
+
...regionTagREsByExt["ts"],
|
|
234
|
+
[
|
|
235
|
+
(regionName) => new RegExp(`// *<editor-fold> *${regionName} *\n`, "g"),
|
|
236
|
+
(regionName) => new RegExp(`// *</editor-fold> *${regionName} *\n`, "g"),
|
|
237
|
+
],
|
|
238
|
+
];
|
|
239
|
+
regionTagREsByExt["cpp"] = regionTagREsByExt["c"];
|
|
240
|
+
regionTagREsByExt["less"] = regionTagREsByExt["css"];
|
|
241
|
+
regionTagREsByExt["scss"] = regionTagREsByExt["css"];
|
|
242
|
+
regionTagREsByExt["coffee"] = regionTagREsByExt["cs"];
|
|
243
|
+
regionTagREsByExt["php"] = regionTagREsByExt["cs"];
|
|
244
|
+
regionTagREsByExt["ps1"] = regionTagREsByExt["cs"];
|
|
245
|
+
regionTagREsByExt["py"] = regionTagREsByExt["cs"];
|
|
246
|
+
regionTagREsByExt["js"] = regionTagREsByExt["ts"];
|
|
@@ -131,6 +131,7 @@ let PackagePlugin = (() => {
|
|
|
131
131
|
}
|
|
132
132
|
if (this.readme) {
|
|
133
133
|
// Readme path provided, read only that file.
|
|
134
|
+
this.application.watchFile(this.readme);
|
|
134
135
|
try {
|
|
135
136
|
this.readmeContents = readFile(this.readme);
|
|
136
137
|
this.readmeFile = this.readme;
|
|
@@ -145,6 +146,7 @@ let PackagePlugin = (() => {
|
|
|
145
146
|
if (result) {
|
|
146
147
|
this.readmeFile = result.file;
|
|
147
148
|
this.readmeContents = result.content;
|
|
149
|
+
this.application.watchFile(this.readmeFile);
|
|
148
150
|
}
|
|
149
151
|
}
|
|
150
152
|
}
|
|
@@ -401,8 +401,13 @@ function convertProperty(context, symbol, exportSymbol) {
|
|
|
401
401
|
return;
|
|
402
402
|
}
|
|
403
403
|
// Special case: We pretend properties are methods if they look like methods.
|
|
404
|
-
// This happens with mixins / weird inheritance.
|
|
405
|
-
|
|
404
|
+
// This happens with mixins / weird inheritance. Don't do this if the type
|
|
405
|
+
// doesn't have call signatures to avoid converting non-functions. This can
|
|
406
|
+
// happen if @class is used and functions are converted to their return type
|
|
407
|
+
// with a mapped type (e.g. with Vue's `computed` properties)
|
|
408
|
+
const type = context.checker.getTypeOfSymbol(symbol);
|
|
409
|
+
if (type.getCallSignatures().length &&
|
|
410
|
+
declarations.length &&
|
|
406
411
|
declarations.every((decl) => ts.isMethodSignature(decl) || ts.isMethodDeclaration(decl))) {
|
|
407
412
|
return convertFunctionOrMethod(context, symbol, exportSymbol);
|
|
408
413
|
}
|
|
@@ -420,7 +425,7 @@ function convertProperty(context, symbol, exportSymbol) {
|
|
|
420
425
|
? ReflectionKind.Variable
|
|
421
426
|
: ReflectionKind.Property, symbol, exportSymbol);
|
|
422
427
|
const declaration = symbol.getDeclarations()?.[0];
|
|
423
|
-
let
|
|
428
|
+
let parameterTypeNode;
|
|
424
429
|
if (declaration &&
|
|
425
430
|
(ts.isPropertyDeclaration(declaration) ||
|
|
426
431
|
ts.isPropertySignature(declaration) ||
|
|
@@ -429,7 +434,7 @@ function convertProperty(context, symbol, exportSymbol) {
|
|
|
429
434
|
ts.isPropertyAssignment(declaration))) {
|
|
430
435
|
if (!ts.isPropertyAccessExpression(declaration) &&
|
|
431
436
|
!ts.isPropertyAssignment(declaration)) {
|
|
432
|
-
|
|
437
|
+
parameterTypeNode = declaration.type;
|
|
433
438
|
}
|
|
434
439
|
setModifiers(symbol, declaration, reflection);
|
|
435
440
|
}
|
|
@@ -437,8 +442,12 @@ function convertProperty(context, symbol, exportSymbol) {
|
|
|
437
442
|
setSymbolModifiers(symbol, reflection);
|
|
438
443
|
}
|
|
439
444
|
reflection.defaultValue = declaration && convertDefaultValue(declaration);
|
|
440
|
-
|
|
441
|
-
context.
|
|
445
|
+
if (context.convertingTypeNode && parameterTypeNode) {
|
|
446
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), parameterTypeNode);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), context.checker.getTypeOfSymbol(symbol), parameterTypeNode);
|
|
450
|
+
}
|
|
442
451
|
if (reflection.flags.isOptional) {
|
|
443
452
|
reflection.type = removeUndefined(reflection.type);
|
|
444
453
|
}
|
|
@@ -533,7 +542,12 @@ function convertVariable(context, symbol, exportSymbol) {
|
|
|
533
542
|
// Otherwise we might have destructuring
|
|
534
543
|
typeNode = declaration.type;
|
|
535
544
|
}
|
|
536
|
-
|
|
545
|
+
if (typeNode) {
|
|
546
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), typeNode);
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
reflection.type = context.converter.convertType(context.withScope(reflection), type, typeNode);
|
|
550
|
+
}
|
|
537
551
|
setModifiers(symbol, declaration, reflection);
|
|
538
552
|
reflection.defaultValue = convertDefaultValue(declaration);
|
|
539
553
|
context.finalizeDeclarationReflection(reflection);
|
|
@@ -4,7 +4,7 @@ import type { Context } from "./context.js";
|
|
|
4
4
|
export interface TypeConverter<TNode extends ts.TypeNode = ts.TypeNode, TType extends ts.Type = ts.Type> {
|
|
5
5
|
kind: TNode["kind"][];
|
|
6
6
|
convert(context: Context, node: TNode): SomeType;
|
|
7
|
-
convertType(context: Context, type: TType,
|
|
7
|
+
convertType(context: Context, type: TType, serializedNode: TNode, originalNode: ts.TypeNode | undefined): SomeType;
|
|
8
8
|
}
|
|
9
9
|
export declare function loadConverters(): void;
|
|
10
|
-
export declare function convertType(context: Context, typeOrNode: ts.Type | ts.TypeNode | undefined): SomeType;
|
|
10
|
+
export declare function convertType(context: Context, typeOrNode: ts.Type | ts.TypeNode | undefined, maybeNode?: ts.TypeNode): SomeType;
|
|
@@ -41,6 +41,7 @@ export function loadConverters() {
|
|
|
41
41
|
tupleConverter,
|
|
42
42
|
typeOperatorConverter,
|
|
43
43
|
unionConverter,
|
|
44
|
+
jSDocTypeExpressionConverter,
|
|
44
45
|
// Only used if skipLibCheck: true
|
|
45
46
|
jsDocNullableTypeConverter,
|
|
46
47
|
jsDocNonNullableTypeConverter,
|
|
@@ -65,7 +66,7 @@ function maybeConvertType(context, typeOrNode) {
|
|
|
65
66
|
return convertType(context, typeOrNode);
|
|
66
67
|
}
|
|
67
68
|
let typeConversionDepth = 0;
|
|
68
|
-
export function convertType(context, typeOrNode) {
|
|
69
|
+
export function convertType(context, typeOrNode, maybeNode) {
|
|
69
70
|
if (!typeOrNode) {
|
|
70
71
|
return new IntrinsicType("any");
|
|
71
72
|
}
|
|
@@ -108,7 +109,7 @@ export function convertType(context, typeOrNode) {
|
|
|
108
109
|
}
|
|
109
110
|
seenTypes.add(typeOrNode.id);
|
|
110
111
|
++typeConversionDepth;
|
|
111
|
-
const result = converter.convertType(context, typeOrNode, node);
|
|
112
|
+
const result = converter.convertType(context, typeOrNode, node, maybeNode);
|
|
112
113
|
--typeConversionDepth;
|
|
113
114
|
seenTypes.delete(typeOrNode.id);
|
|
114
115
|
return result;
|
|
@@ -286,8 +287,10 @@ const jsDocVariadicTypeConverter = {
|
|
|
286
287
|
convert(context, node) {
|
|
287
288
|
return new ArrayType(convertType(context, node.type));
|
|
288
289
|
},
|
|
289
|
-
|
|
290
|
-
|
|
290
|
+
convertType(context, type, _node, origNode) {
|
|
291
|
+
assert(isTypeReference(type));
|
|
292
|
+
return arrayConverter.convertType(context, type, null, origNode);
|
|
293
|
+
},
|
|
291
294
|
};
|
|
292
295
|
const keywordNames = {
|
|
293
296
|
[ts.SyntaxKind.AnyKeyword]: "any",
|
|
@@ -442,14 +445,14 @@ const referenceConverter = {
|
|
|
442
445
|
// This might not actually be safe, it appears that it is in the relatively small
|
|
443
446
|
// amount of testing I've done with it, but I wouldn't be surprised if someone manages
|
|
444
447
|
// to find a crash.
|
|
445
|
-
return typeLiteralConverter.convertType(context, type, null);
|
|
448
|
+
return typeLiteralConverter.convertType(context, type, null, undefined);
|
|
446
449
|
}
|
|
447
450
|
const name = node.typeName.getText();
|
|
448
451
|
const ref = ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context, name);
|
|
449
452
|
ref.typeArguments = node.typeArguments?.map((type) => convertType(context, type));
|
|
450
453
|
return ref;
|
|
451
454
|
},
|
|
452
|
-
convertType(context, type, node) {
|
|
455
|
+
convertType(context, type, node, originalNode) {
|
|
453
456
|
// typeName.symbol handles the case where this is a union which happens to refer
|
|
454
457
|
// to an enumeration. TS doesn't put the symbol on the type for some reason, but
|
|
455
458
|
// does add it to the constructed type node.
|
|
@@ -468,7 +471,7 @@ const referenceConverter = {
|
|
|
468
471
|
// This might not actually be safe, it appears that it is in the relatively small
|
|
469
472
|
// amount of testing I've done with it, but I wouldn't be surprised if someone manages
|
|
470
473
|
// to find a crash.
|
|
471
|
-
return typeLiteralConverter.convertType(context, type, null);
|
|
474
|
+
return typeLiteralConverter.convertType(context, type, null, undefined);
|
|
472
475
|
}
|
|
473
476
|
let name;
|
|
474
477
|
if (ts.isIdentifier(node.typeName)) {
|
|
@@ -490,21 +493,14 @@ const referenceConverter = {
|
|
|
490
493
|
];
|
|
491
494
|
}
|
|
492
495
|
else {
|
|
493
|
-
// Default type arguments are filled with a reference to the default
|
|
494
|
-
// type. As TS doesn't support specifying earlier defaults, we know
|
|
495
|
-
// that this will only filter out type arguments which aren't specified
|
|
496
|
-
// by the user.
|
|
497
|
-
let ignoredArgs;
|
|
498
|
-
if (isTypeReference(type)) {
|
|
499
|
-
ignoredArgs = type.target.typeParameters
|
|
500
|
-
?.map((p) => p.getDefault())
|
|
501
|
-
.filter((x) => !!x);
|
|
502
|
-
}
|
|
503
496
|
const args = type.aliasSymbol
|
|
504
497
|
? type.aliasTypeArguments
|
|
505
498
|
: type.typeArguments;
|
|
499
|
+
const maxArgLength = originalNode && ts.isTypeReferenceNode(originalNode)
|
|
500
|
+
? (originalNode.typeArguments?.length ?? 0)
|
|
501
|
+
: args?.length;
|
|
506
502
|
ref.typeArguments = args
|
|
507
|
-
?.
|
|
503
|
+
?.slice(0, maxArgLength)
|
|
508
504
|
.map((ref) => convertType(context, ref));
|
|
509
505
|
}
|
|
510
506
|
return ref;
|
|
@@ -708,6 +704,13 @@ const unionConverter = {
|
|
|
708
704
|
return new UnionType(types);
|
|
709
705
|
},
|
|
710
706
|
};
|
|
707
|
+
const jSDocTypeExpressionConverter = {
|
|
708
|
+
kind: [ts.SyntaxKind.JSDocTypeExpression],
|
|
709
|
+
convert(context, node) {
|
|
710
|
+
return convertType(context, node.type);
|
|
711
|
+
},
|
|
712
|
+
convertType: requestBugReport,
|
|
713
|
+
};
|
|
711
714
|
const jsDocNullableTypeConverter = {
|
|
712
715
|
kind: [ts.SyntaxKind.JSDocNullableType],
|
|
713
716
|
convert(context, node) {
|
|
@@ -222,8 +222,12 @@ export class Internationalization {
|
|
|
222
222
|
*/
|
|
223
223
|
getSupportedLanguages() {
|
|
224
224
|
return unique([
|
|
225
|
-
...readdirSync(join(fileURLToPath(import.meta.url), "../locales"))
|
|
225
|
+
...readdirSync(join(fileURLToPath(import.meta.url), "../locales"))
|
|
226
|
+
.map((x) => x.substring(0, x.indexOf(".")))
|
|
227
|
+
.filter((x) => x !== "jp"),
|
|
226
228
|
...this.allTranslations.keys(),
|
|
227
|
-
])
|
|
229
|
+
])
|
|
230
|
+
.filter((lang) => this.hasTranslations(lang))
|
|
231
|
+
.sort();
|
|
228
232
|
}
|
|
229
233
|
}
|
|
@@ -8,6 +8,8 @@ module.exports = {
|
|
|
8
8
|
loaded_plugin_0: `Loaded plugin {0}`,
|
|
9
9
|
solution_not_supported_in_watch_mode: "The provided tsconfig file looks like a solution style tsconfig, which is not supported in watch mode",
|
|
10
10
|
strategy_not_supported_in_watch_mode: "entryPointStrategy must be set to either resolve or expand for watch mode",
|
|
11
|
+
file_0_changed_restarting: "Configuration file {0} changed: full restart required...",
|
|
12
|
+
file_0_changed_rebuilding: "File {0} changed: rebuilding output...",
|
|
11
13
|
found_0_errors_and_1_warnings: "Found {0} errors and {1} warnings",
|
|
12
14
|
output_0_could_not_be_generated: "{0} output could not be generated due to the errors above",
|
|
13
15
|
output_0_generated_at_1: "{0} generated at {1}",
|
|
@@ -59,6 +61,7 @@ module.exports = {
|
|
|
59
61
|
failed_to_resolve_link_to_0_in_document_1_may_have_meant_2: `Failed to resolve link to "{0}" in document {1}. You may have wanted "{2}"`,
|
|
60
62
|
type_0_defined_in_1_is_referenced_by_2_but_not_included_in_docs: `{0}, defined in {1}, is referenced by {2} but not included in the documentation`,
|
|
61
63
|
reflection_0_kind_1_defined_in_2_does_not_have_any_documentation: `{0} ({1}), defined in {2}, does not have any documentation`,
|
|
64
|
+
invalid_intentionally_not_documented_names_0: "The following qualified reflection names were marked as intentionally not documented, but were either not referenced in the documentation, or were documented:\n\t{0}",
|
|
62
65
|
invalid_intentionally_not_exported_symbols_0: "The following symbols were marked as intentionally not exported, but were either not referenced in the documentation, or were exported:\n\t{0}",
|
|
63
66
|
reflection_0_has_unused_mergeModuleWith_tag: "{0} has a @mergeModuleWith tag which could not be resolved",
|
|
64
67
|
reflection_0_links_to_1_with_text_2_but_resolved_to_3: `"{0}" links to "{1}" with text "{2}" which exists but does not have a link in the documentation, will link to "{3}" instead.`,
|
|
@@ -82,6 +85,16 @@ module.exports = {
|
|
|
82
85
|
reflection_0_tried_to_merge_into_child_1: `The reflection {0} tried to use @mergeModuleWith to merge into one of its children: {1}`,
|
|
83
86
|
include_0_in_1_specified_2_resolved_to_3_does_not_exist: `{0} tag in comment for {1} specified "{2}" to include, which was resolved to "{3}" and does not exist or is not a file.`,
|
|
84
87
|
include_0_in_1_specified_2_circular_include_3: `{0} tag in comment for {1} specified "{2}" to include, which resulted in a circular include:\n\t{3}`,
|
|
88
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region was not found in the file.`,
|
|
89
|
+
include_0_tag_in_1_region_2_region_not_supported: `{0} tag in {1} specified "{2}", but regions are not supported for this file extension.`,
|
|
90
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_close_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region closing comment was not found in the file.`,
|
|
91
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_open_not_found: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled "{4}", but the region opening comment was not found in the file.`,
|
|
92
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_close_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region closing comment was found multiple times in the file.`,
|
|
93
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_open_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region opening comment was found multiple times in the file.`,
|
|
94
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_found_multiple_times: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}, but the region was found multiple times in the file.`,
|
|
95
|
+
include_0_tag_in_1_specified_2_file_3_region_4_region_empty: `{0} tag in {1} specified "{2}" to include from file "{3}" the region labeled {4}. The region was found but it is empty or contains only whitespace.`,
|
|
96
|
+
include_0_tag_in_1_specified_2_file_3_lines_4_invalid_range: `{0} tag in {1} specified "{2}" to include from file "{3}" the lines {4}, but an invalid range was specified.`,
|
|
97
|
+
include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines: `{0} tag in {1} specified "{2}" to include from file "{3}" the lines {4}, but the file only has {5} lines.`,
|
|
85
98
|
// output plugins
|
|
86
99
|
custom_css_file_0_does_not_exist: `Custom CSS file at {0} does not exist`,
|
|
87
100
|
custom_js_file_0_does_not_exist: `Custom JavaScript file at {0} does not exist`,
|
|
@@ -205,6 +218,7 @@ module.exports = {
|
|
|
205
218
|
help_searchGroupBoosts: 'Configure search to give a relevance boost to selected kinds (eg "class")',
|
|
206
219
|
help_useFirstParagraphOfCommentAsSummary: "If set and no @summary tag is specified, TypeDoc will use the first paragraph of comments as the short summary in the module/namespace view",
|
|
207
220
|
help_jsDocCompatibility: "Sets compatibility options for comment parsing that increase similarity with JSDoc comments",
|
|
221
|
+
help_suppressCommentWarningsInDeclarationFiles: "Prevents warnings due to unspecified tags from being reported in comments within .d.ts files.",
|
|
208
222
|
help_commentStyle: "Determines how TypeDoc searches for comments",
|
|
209
223
|
help_useTsLinkResolution: "Use TypeScript's link resolution when determining where @link tags point. This only applies to JSDoc style comments",
|
|
210
224
|
help_preserveLinkText: "If set, @link tags without link text will use the text content as the link. If not set, will use the target reflection name",
|
|
@@ -231,6 +245,7 @@ module.exports = {
|
|
|
231
245
|
help_treatValidationWarningsAsErrors: "If set, warnings emitted during validation will be treated as errors. This option cannot be used to disable treatWarningsAsErrors for validation warnings",
|
|
232
246
|
help_intentionallyNotExported: "A list of types which should not produce 'referenced but not documented' warnings",
|
|
233
247
|
help_requiredToBeDocumented: "A list of reflection kinds that must be documented",
|
|
248
|
+
help_intentionallyNotDocumented: "A list of full reflection names which should not produce warnings about not being documented",
|
|
234
249
|
help_validation: "Specify which validation steps TypeDoc should perform on your generated documentation",
|
|
235
250
|
// ==================================================================
|
|
236
251
|
// Option validation
|
|
@@ -250,7 +265,7 @@ module.exports = {
|
|
|
250
265
|
highlightLanguages_contains_invalid_languages_0: "highlightLanguages contains invalid languages: {0}, run typedoc --help for a list of supported languages",
|
|
251
266
|
hostedBaseUrl_must_start_with_http: "hostedBaseUrl must start with http:// or https://",
|
|
252
267
|
useHostedBaseUrlForAbsoluteLinks_requires_hostedBaseUrl: "The useHostedBaseUrlForAbsoluteLinks option requires that hostedBaseUrl be set",
|
|
253
|
-
favicon_must_have_one_of_the_following_extensions_0: "Favicon must have
|
|
268
|
+
favicon_must_have_one_of_the_following_extensions_0: "Favicon must have one of the following extensions: {0}",
|
|
254
269
|
option_0_must_be_an_object: "The '{0}' option must be a non-array object",
|
|
255
270
|
option_0_must_be_a_function: "The '{0}' option must be a function",
|
|
256
271
|
option_0_must_be_object_with_urls: `{0} must be an object with string labels as keys and URL values`,
|
|
@@ -364,9 +379,11 @@ module.exports = {
|
|
|
364
379
|
theme_search: "Search",
|
|
365
380
|
theme_menu: "Menu",
|
|
366
381
|
theme_permalink: "Permalink",
|
|
382
|
+
theme_folder: "Folder",
|
|
367
383
|
// Used by the frontend JS
|
|
368
384
|
// For the English translations only, these should also be added to
|
|
369
385
|
// src/lib/output/themes/default/assets/typedoc/Application.ts
|
|
386
|
+
// Also uses theme_folder and singular kinds
|
|
370
387
|
theme_copy: "Copy",
|
|
371
388
|
theme_copied: "Copied!",
|
|
372
389
|
theme_normally_hidden: "This member is normally hidden due to your filter settings.",
|
|
@@ -5,6 +5,8 @@ declare const _default: {
|
|
|
5
5
|
readonly loaded_plugin_0: "Loaded plugin {0}";
|
|
6
6
|
readonly solution_not_supported_in_watch_mode: "The provided tsconfig file looks like a solution style tsconfig, which is not supported in watch mode";
|
|
7
7
|
readonly strategy_not_supported_in_watch_mode: "entryPointStrategy must be set to either resolve or expand for watch mode";
|
|
8
|
+
readonly file_0_changed_restarting: "Configuration file {0} changed: full restart required...";
|
|
9
|
+
readonly file_0_changed_rebuilding: "File {0} changed: rebuilding output...";
|
|
8
10
|
readonly found_0_errors_and_1_warnings: "Found {0} errors and {1} warnings";
|
|
9
11
|
readonly output_0_could_not_be_generated: "{0} output could not be generated due to the errors above";
|
|
10
12
|
readonly output_0_generated_at_1: "{0} generated at {1}";
|
|
@@ -54,6 +56,7 @@ declare const _default: {
|
|
|
54
56
|
readonly failed_to_resolve_link_to_0_in_document_1_may_have_meant_2: "Failed to resolve link to \"{0}\" in document {1}. You may have wanted \"{2}\"";
|
|
55
57
|
readonly type_0_defined_in_1_is_referenced_by_2_but_not_included_in_docs: "{0}, defined in {1}, is referenced by {2} but not included in the documentation";
|
|
56
58
|
readonly reflection_0_kind_1_defined_in_2_does_not_have_any_documentation: "{0} ({1}), defined in {2}, does not have any documentation";
|
|
59
|
+
readonly invalid_intentionally_not_documented_names_0: "The following qualified reflection names were marked as intentionally not documented, but were either not referenced in the documentation, or were documented:\n\t{0}";
|
|
57
60
|
readonly invalid_intentionally_not_exported_symbols_0: "The following symbols were marked as intentionally not exported, but were either not referenced in the documentation, or were exported:\n\t{0}";
|
|
58
61
|
readonly reflection_0_has_unused_mergeModuleWith_tag: "{0} has a @mergeModuleWith tag which could not be resolved";
|
|
59
62
|
readonly reflection_0_links_to_1_with_text_2_but_resolved_to_3: "\"{0}\" links to \"{1}\" with text \"{2}\" which exists but does not have a link in the documentation, will link to \"{3}\" instead.";
|
|
@@ -76,6 +79,16 @@ declare const _default: {
|
|
|
76
79
|
readonly reflection_0_tried_to_merge_into_child_1: "The reflection {0} tried to use @mergeModuleWith to merge into one of its children: {1}";
|
|
77
80
|
readonly include_0_in_1_specified_2_resolved_to_3_does_not_exist: "{0} tag in comment for {1} specified \"{2}\" to include, which was resolved to \"{3}\" and does not exist or is not a file.";
|
|
78
81
|
readonly include_0_in_1_specified_2_circular_include_3: "{0} tag in comment for {1} specified \"{2}\" to include, which resulted in a circular include:\n\t{3}";
|
|
82
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_not_found: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled \"{4}\", but the region was not found in the file.";
|
|
83
|
+
readonly include_0_tag_in_1_region_2_region_not_supported: "{0} tag in {1} specified \"{2}\", but regions are not supported for this file extension.";
|
|
84
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_close_not_found: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled \"{4}\", but the region closing comment was not found in the file.";
|
|
85
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_open_not_found: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled \"{4}\", but the region opening comment was not found in the file.";
|
|
86
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_close_found_multiple_times: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled {4}, but the region closing comment was found multiple times in the file.";
|
|
87
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_open_found_multiple_times: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled {4}, but the region opening comment was found multiple times in the file.";
|
|
88
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_found_multiple_times: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled {4}, but the region was found multiple times in the file.";
|
|
89
|
+
readonly include_0_tag_in_1_specified_2_file_3_region_4_region_empty: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the region labeled {4}. The region was found but it is empty or contains only whitespace.";
|
|
90
|
+
readonly include_0_tag_in_1_specified_2_file_3_lines_4_invalid_range: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the lines {4}, but an invalid range was specified.";
|
|
91
|
+
readonly include_0_tag_in_1_specified_2_file_3_lines_4_but_only_5_lines: "{0} tag in {1} specified \"{2}\" to include from file \"{3}\" the lines {4}, but the file only has {5} lines.";
|
|
79
92
|
readonly custom_css_file_0_does_not_exist: "Custom CSS file at {0} does not exist";
|
|
80
93
|
readonly custom_js_file_0_does_not_exist: "Custom JavaScript file at {0} does not exist";
|
|
81
94
|
readonly unsupported_highlight_language_0_not_highlighted_in_comment_for_1: "Unsupported highlight language {0} will not be highlighted in comment for {1}";
|
|
@@ -192,6 +205,7 @@ declare const _default: {
|
|
|
192
205
|
readonly help_searchGroupBoosts: "Configure search to give a relevance boost to selected kinds (eg \"class\")";
|
|
193
206
|
readonly help_useFirstParagraphOfCommentAsSummary: "If set and no @summary tag is specified, TypeDoc will use the first paragraph of comments as the short summary in the module/namespace view";
|
|
194
207
|
readonly help_jsDocCompatibility: "Sets compatibility options for comment parsing that increase similarity with JSDoc comments";
|
|
208
|
+
readonly help_suppressCommentWarningsInDeclarationFiles: "Prevents warnings due to unspecified tags from being reported in comments within .d.ts files.";
|
|
195
209
|
readonly help_commentStyle: "Determines how TypeDoc searches for comments";
|
|
196
210
|
readonly help_useTsLinkResolution: "Use TypeScript's link resolution when determining where @link tags point. This only applies to JSDoc style comments";
|
|
197
211
|
readonly help_preserveLinkText: "If set, @link tags without link text will use the text content as the link. If not set, will use the target reflection name";
|
|
@@ -218,6 +232,7 @@ declare const _default: {
|
|
|
218
232
|
readonly help_treatValidationWarningsAsErrors: "If set, warnings emitted during validation will be treated as errors. This option cannot be used to disable treatWarningsAsErrors for validation warnings";
|
|
219
233
|
readonly help_intentionallyNotExported: "A list of types which should not produce 'referenced but not documented' warnings";
|
|
220
234
|
readonly help_requiredToBeDocumented: "A list of reflection kinds that must be documented";
|
|
235
|
+
readonly help_intentionallyNotDocumented: "A list of full reflection names which should not produce warnings about not being documented";
|
|
221
236
|
readonly help_validation: "Specify which validation steps TypeDoc should perform on your generated documentation";
|
|
222
237
|
readonly unknown_option_0_you_may_have_meant_1: "Unknown option '{0}' You may have meant:\n\t{1}";
|
|
223
238
|
readonly option_0_must_be_between_1_and_2: "{0} must be between {1} and {2}";
|
|
@@ -234,7 +249,7 @@ declare const _default: {
|
|
|
234
249
|
readonly highlightLanguages_contains_invalid_languages_0: "highlightLanguages contains invalid languages: {0}, run typedoc --help for a list of supported languages";
|
|
235
250
|
readonly hostedBaseUrl_must_start_with_http: "hostedBaseUrl must start with http:// or https://";
|
|
236
251
|
readonly useHostedBaseUrlForAbsoluteLinks_requires_hostedBaseUrl: "The useHostedBaseUrlForAbsoluteLinks option requires that hostedBaseUrl be set";
|
|
237
|
-
readonly favicon_must_have_one_of_the_following_extensions_0: "Favicon must have
|
|
252
|
+
readonly favicon_must_have_one_of_the_following_extensions_0: "Favicon must have one of the following extensions: {0}";
|
|
238
253
|
readonly option_0_must_be_an_object: "The '{0}' option must be a non-array object";
|
|
239
254
|
readonly option_0_must_be_a_function: "The '{0}' option must be a function";
|
|
240
255
|
readonly option_0_must_be_object_with_urls: "{0} must be an object with string labels as keys and URL values";
|
|
@@ -336,6 +351,7 @@ declare const _default: {
|
|
|
336
351
|
readonly theme_search: "Search";
|
|
337
352
|
readonly theme_menu: "Menu";
|
|
338
353
|
readonly theme_permalink: "Permalink";
|
|
354
|
+
readonly theme_folder: "Folder";
|
|
339
355
|
readonly theme_copy: "Copy";
|
|
340
356
|
readonly theme_copied: "Copied!";
|
|
341
357
|
readonly theme_normally_hidden: "This member is normally hidden due to your filter settings.";
|