typedoc 0.27.0-beta.1 → 0.27.0

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.
@@ -125,7 +125,7 @@ export declare class Application extends AbstractComponent<Application, Applicat
125
125
  */
126
126
  getTypeScriptPath(): string;
127
127
  getTypeScriptVersion(): string;
128
- getEntryPoints(): Promise<DocumentationEntryPoint[] | undefined>;
128
+ getEntryPoints(): DocumentationEntryPoint[] | undefined;
129
129
  /**
130
130
  * Gets the entry points to be documented according to the current `entryPoints` and `entryPointStrategy` options.
131
131
  * May return undefined if entry points fail to be expanded.
@@ -52,7 +52,6 @@ import { findTsConfigFile } from "./utils/tsconfig.js";
52
52
  import { deriveRootDir, glob, readFile } from "./utils/fs.js";
53
53
  import { addInferredDeclarationMapPaths } from "./models/reflections/ReflectionSymbolId.js";
54
54
  import { Internationalization, } from "./internationalization/internationalization.js";
55
- import { loadShikiMetadata } from "./utils/highlighter.js";
56
55
  import { ValidatingFileRegistry, FileRegistry } from "./models/FileRegistry.js";
57
56
  import { readFileSync } from "fs";
58
57
  import { fileURLToPath } from "url";
@@ -215,7 +214,6 @@ let Application = (() => {
215
214
  * Initialize TypeDoc, loading plugins if applicable.
216
215
  */
217
216
  static async bootstrapWithPlugins(options = {}, readers = DEFAULT_READERS) {
218
- await loadShikiMetadata();
219
217
  const app = new Application(DETECTOR);
220
218
  readers.forEach((r) => app.options.addReader(r));
221
219
  app.options.reset();
@@ -239,7 +237,6 @@ let Application = (() => {
239
237
  * @param readers Option readers to use to discover options from config files.
240
238
  */
241
239
  static async bootstrap(options = {}, readers = DEFAULT_READERS) {
242
- await loadShikiMetadata();
243
240
  const app = new Application(DETECTOR);
244
241
  readers.forEach((r) => app.options.addReader(r));
245
242
  await app._bootstrap(options);
@@ -300,7 +297,7 @@ let Application = (() => {
300
297
  getTypeScriptVersion() {
301
298
  return ts.version;
302
299
  }
303
- async getEntryPoints() {
300
+ getEntryPoints() {
304
301
  if (this.options.isSet("entryPoints")) {
305
302
  return this.getDefinedEntryPoints();
306
303
  }
@@ -333,7 +330,7 @@ let Application = (() => {
333
330
  if (!supportedVersionMajorMinor.some((version) => version == ts.versionMajorMinor)) {
334
331
  this.logger.warn(this.i18n.unsupported_ts_version_0(supportedVersionMajorMinor.join(", ")));
335
332
  }
336
- const entryPoints = await this.getEntryPoints();
333
+ const entryPoints = this.getEntryPoints();
337
334
  if (!entryPoints) {
338
335
  // Fatal error already reported.
339
336
  return;
@@ -169,7 +169,15 @@ function convertNamespace(context, symbol, exportSymbol) {
169
169
  reflection = existingReflection;
170
170
  }
171
171
  else {
172
- reflection = context.createDeclarationReflection(ReflectionKind.Namespace, symbol, exportSymbol);
172
+ let kind = ReflectionKind.Namespace;
173
+ let nameOverride;
174
+ // #2778 - always treat declare module "foo" as a module, not a namespace
175
+ const declareModule = symbol.declarations?.find((mod) => ts.isModuleDeclaration(mod) && ts.isStringLiteral(mod.name));
176
+ if (declareModule) {
177
+ kind = ReflectionKind.Module;
178
+ nameOverride = declareModule.name.text;
179
+ }
180
+ reflection = context.createDeclarationReflection(kind, symbol, exportSymbol, nameOverride);
173
181
  context.finalizeDeclarationReflection(reflection);
174
182
  }
175
183
  convertSymbols(context.withScope(reflection), context.checker
@@ -231,8 +231,7 @@ const importType = {
231
231
  kind: [ts.SyntaxKind.ImportType],
232
232
  convert(context, node) {
233
233
  const name = node.qualifier?.getText() ?? "__module";
234
- const symbol = context.checker.getSymbolAtLocation(node);
235
- assert(symbol, "Missing symbol when converting import type node");
234
+ const symbol = context.expectSymbolAtLocation(node.qualifier || node);
236
235
  return ReferenceType.createSymbolReference(context.resolveAliasedSymbol(symbol), context, name);
237
236
  },
238
237
  convertType(context, type) {
@@ -189,6 +189,7 @@ module.exports = localeUtils.buildIncompleteTranslation({
189
189
  help_headings: "确定标题是否需要被渲染",
190
190
  help_sluggerConfiguration: "确定渲染的 HTML 中锚点的确定方式",
191
191
  help_navigation: "确定导航侧边栏的组织方式",
192
+ help_includeHierarchySummary: "如果设置,反射的层级一览将被渲染至概述页面。默认为 `true`",
192
193
  help_visibilityFilters: "根据修饰符标签指定内置过滤器和附加过滤器的默认可见性",
193
194
  help_searchCategoryBoosts: "配置搜索以提高所选类别的相关性",
194
195
  help_searchGroupBoosts: "配置搜索以增强所选种类(例如“类别”)的相关性",
@@ -316,6 +317,8 @@ module.exports = localeUtils.buildIncompleteTranslation({
316
317
  theme_type_declaration: "类型声明",
317
318
  theme_index: "索引",
318
319
  theme_hierarchy: "层级",
320
+ theme_hierarchy_summary: "层级一览",
321
+ theme_hierarchy_view_summary: "查看层级一览",
319
322
  theme_implemented_by: "实现于",
320
323
  theme_defined_in: "定义于",
321
324
  theme_implementation_of: "实现了",
@@ -339,6 +342,8 @@ module.exports = localeUtils.buildIncompleteTranslation({
339
342
  theme_copy: "复制",
340
343
  theme_copied: "已复制!",
341
344
  theme_normally_hidden: "由于您的过滤器设置,该成员已被隐藏。",
345
+ theme_hierarchy_expand: "展开",
346
+ theme_hierarchy_collapse: "折叠",
342
347
  tag_defaultValue: "默认值",
343
348
  tag_deprecated: "已被弃用",
344
349
  tag_example: "示例",
@@ -184,6 +184,7 @@ declare const _default: {
184
184
  help_headings: string;
185
185
  help_sluggerConfiguration: string;
186
186
  help_navigation: string;
187
+ help_includeHierarchySummary: string;
187
188
  help_visibilityFilters: string;
188
189
  help_searchCategoryBoosts: string;
189
190
  help_searchGroupBoosts: string;
@@ -311,6 +312,8 @@ declare const _default: {
311
312
  theme_type_declaration: string;
312
313
  theme_index: string;
313
314
  theme_hierarchy: string;
315
+ theme_hierarchy_summary: string;
316
+ theme_hierarchy_view_summary: string;
314
317
  theme_implemented_by: string;
315
318
  theme_defined_in: string;
316
319
  theme_implementation_of: string;
@@ -334,6 +337,8 @@ declare const _default: {
334
337
  theme_copy: string;
335
338
  theme_copied: string;
336
339
  theme_normally_hidden: string;
340
+ theme_hierarchy_expand: string;
341
+ theme_hierarchy_collapse: string;
337
342
  tag_defaultValue: string;
338
343
  tag_deprecated: string;
339
344
  tag_example: string;
@@ -1,6 +1,6 @@
1
1
  import { ContextAwareRendererComponent } from "../components.js";
2
2
  import { MarkdownEvent, RendererEvent, type PageEvent } from "../events.js";
3
- import type { BundledTheme } from "shiki" with { "resolution-mode": "import" };
3
+ import type { BundledTheme } from "@gerrit0/mini-shiki";
4
4
  import type { DefaultThemeRenderContext, Renderer } from "../index.js";
5
5
  import { type CommentDisplayPart } from "../../models/index.js";
6
6
  /**
@@ -36,7 +36,7 @@ export interface DocumentEntryPoint {
36
36
  displayName: string;
37
37
  path: string;
38
38
  }
39
- export declare function inferEntryPoints(logger: Logger, options: Options): Promise<DocumentationEntryPoint[]>;
39
+ export declare function inferEntryPoints(logger: Logger, options: Options): DocumentationEntryPoint[];
40
40
  export declare function getEntryPoints(logger: Logger, options: Options): DocumentationEntryPoint[] | undefined;
41
41
  /**
42
42
  * Document entry points are markdown documents that the user has requested we include in the project with
@@ -1,12 +1,10 @@
1
- import { dirname, join, relative, resolve } from "path";
1
+ import { join, relative, resolve } from "path";
2
2
  import ts from "typescript";
3
3
  import * as FS from "fs";
4
4
  import { expandPackages } from "./package-manifest.js";
5
5
  import { createMinimatch, matchesAny, nicePath, normalizePath, } from "./paths.js";
6
- import { deriveRootDir, discoverPackageJson, getCommonDirectory, glob, isDir, } from "./fs.js";
6
+ import { deriveRootDir, discoverPackageJson, getCommonDirectory, glob, inferPackageEntryPointPaths, isDir, } from "./fs.js";
7
7
  import { assertNever } from "./general.js";
8
- import { resolveAllExports } from "resolve-import/resolve-all-exports";
9
- import { fileURLToPath } from "url";
10
8
  /**
11
9
  * Defines how entry points are interpreted.
12
10
  * @enum
@@ -32,32 +30,13 @@ export const EntryPointStrategy = {
32
30
  */
33
31
  Merge: "merge",
34
32
  };
35
- export async function inferEntryPoints(logger, options) {
33
+ export function inferEntryPoints(logger, options) {
36
34
  const packageJson = discoverPackageJson(process.cwd());
37
35
  if (!packageJson) {
38
36
  logger.warn(logger.i18n.no_entry_points_provided());
39
37
  return [];
40
38
  }
41
- const entries = await resolveAllExports(packageJson.file, {
42
- conditions: ["typedoc", "import", "node"],
43
- });
44
- const pathEntries = Object.entries(entries).map(([k, v]) => {
45
- if (typeof v === "object") {
46
- return [k, fileURLToPath(v)];
47
- }
48
- return [k, v];
49
- });
50
- // resolveAllExports doesn't create a fake export for "main"
51
- // so do that here if we don't have any exports.
52
- if (pathEntries.length === 0) {
53
- if ("main" in packageJson.content &&
54
- typeof packageJson.content["main"] === "string") {
55
- pathEntries.push([
56
- ".",
57
- resolve(dirname(packageJson.file), packageJson.content["main"]),
58
- ]);
59
- }
60
- }
39
+ const pathEntries = inferPackageEntryPointPaths(packageJson.file);
61
40
  const entryPoints = [];
62
41
  const programs = getEntryPrograms(pathEntries.map((p) => p[1]), logger, options);
63
42
  // See also: addInferredDeclarationMapPaths in ReflectionSymbolId
@@ -35,6 +35,15 @@ export declare function writeFile(fileName: string, data: string): Promise<void>
35
35
  */
36
36
  export declare function copy(src: string, dest: string): Promise<void>;
37
37
  export declare function copySync(src: string, dest: string): void;
38
+ export interface DiscoverFilesController {
39
+ shouldRecurse(childPath: string[]): boolean;
40
+ matches(path: string): boolean;
41
+ /** Defaults to false */
42
+ matchDirectories?: boolean;
43
+ /** Defaults to false */
44
+ followSymlinks?: boolean;
45
+ }
46
+ export declare function discoverFiles(rootDir: string, controller: DiscoverFilesController): string[];
38
47
  /**
39
48
  * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules.
40
49
  */
@@ -61,3 +70,4 @@ export declare function discoverPackageJson(dir: string): {
61
70
  };
62
71
  } | undefined;
63
72
  export declare function findPackageForPath(sourcePath: string): string | undefined;
73
+ export declare function inferPackageEntryPointPaths(packagePath: string): [importPath: string, resolvedPath: string][];
@@ -5,6 +5,8 @@ import { dirname, join, relative, resolve } from "path";
5
5
  import { optional, validate } from "./validation.js";
6
6
  import { createMinimatch, normalizePath } from "./paths.js";
7
7
  import { filterMap } from "./array.js";
8
+ import { escapeRegExp } from "./general.js";
9
+ import { ok } from "assert";
8
10
  export function isFile(file) {
9
11
  try {
10
12
  return fs.statSync(file).isFile();
@@ -144,33 +146,24 @@ export function copySync(src, dest) {
144
146
  // Do nothing for FIFO, special devices.
145
147
  }
146
148
  }
147
- /**
148
- * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules.
149
- */
150
- export function glob(pattern, root, options = {}) {
149
+ // cache of fs.realpathSync results to avoid extra I/O
150
+ const realpathCache = new Map();
151
+ export function discoverFiles(rootDir, controller) {
151
152
  const result = [];
152
- const mini = new Minimatch(normalizePath(pattern));
153
- const dirs = [normalizePath(root).split("/")];
153
+ const dirs = [normalizePath(rootDir).split("/")];
154
154
  // cache of real paths to avoid infinite recursion
155
155
  const symlinkTargetsSeen = new Set();
156
- // cache of fs.realpathSync results to avoid extra I/O
157
- const realpathCache = new Map();
158
- const { includeDirectories = false, followSymlinks = false } = options;
159
- // if we _specifically asked_ for something in node_modules, fine, otherwise ignore it
160
- // to avoid globs like '**/*.ts' finding all the .d.ts files in node_modules.
161
- // however, if the pattern is something like `!**/node_modules/**`, this will also
162
- // cause node_modules to be considered, though it will be discarded by minimatch.
163
- const shouldIncludeNodeModules = pattern.includes("node_modules");
156
+ const { matchDirectories = false, followSymlinks = false } = controller;
164
157
  let dir = dirs.shift();
165
158
  const handleFile = (path) => {
166
159
  const childPath = [...dir, path].join("/");
167
- if (mini.match(childPath)) {
160
+ if (controller.matches(childPath)) {
168
161
  result.push(childPath);
169
162
  }
170
163
  };
171
164
  const handleDirectory = (path) => {
172
165
  const childPath = [...dir, path];
173
- if (mini.set.some((row) => mini.matchOne(childPath, row, /* partial */ true))) {
166
+ if (controller.shouldRecurse(childPath)) {
174
167
  dirs.push(childPath);
175
168
  }
176
169
  };
@@ -212,7 +205,7 @@ export function glob(pattern, root, options = {}) {
212
205
  }
213
206
  };
214
207
  while (dir) {
215
- if (includeDirectories && mini.match(dir.join("/"))) {
208
+ if (matchDirectories && controller.matches(dir.join("/"))) {
216
209
  result.push(dir.join("/"));
217
210
  }
218
211
  for (const child of fs.readdirSync(dir.join("/"), {
@@ -222,9 +215,7 @@ export function glob(pattern, root, options = {}) {
222
215
  handleFile(child.name);
223
216
  }
224
217
  else if (child.isDirectory()) {
225
- if (shouldIncludeNodeModules || child.name !== "node_modules") {
226
- handleDirectory(child.name);
227
- }
218
+ handleDirectory(child.name);
228
219
  }
229
220
  else if (followSymlinks && child.isSymbolicLink()) {
230
221
  handleSymlink(child.name);
@@ -234,6 +225,32 @@ export function glob(pattern, root, options = {}) {
234
225
  }
235
226
  return result;
236
227
  }
228
+ /**
229
+ * Simpler version of `glob.sync` that only covers our use cases, always ignoring node_modules.
230
+ */
231
+ export function glob(pattern, root, options = {}) {
232
+ const mini = new Minimatch(normalizePath(pattern));
233
+ const shouldIncludeNodeModules = pattern.includes("node_modules");
234
+ const controller = {
235
+ matches(path) {
236
+ return mini.match(path);
237
+ },
238
+ shouldRecurse(childPath) {
239
+ // if we _specifically asked_ for something in node_modules, fine, otherwise ignore it
240
+ // to avoid globs like '**/*.ts' finding all the .d.ts files in node_modules.
241
+ // however, if the pattern is something like `!**/node_modules/**`, this will also
242
+ // cause node_modules to be considered, though it will be discarded by minimatch.
243
+ if (childPath[childPath.length - 1] === "node_modules" &&
244
+ !shouldIncludeNodeModules) {
245
+ return false;
246
+ }
247
+ return mini.set.some((row) => mini.matchOne(childPath, row, /* partial */ true));
248
+ },
249
+ matchDirectories: options.includeDirectories,
250
+ followSymlinks: options.followSymlinks,
251
+ };
252
+ return discoverFiles(root, controller);
253
+ }
237
254
  export function hasTsExtension(path) {
238
255
  return /\.[cm]?ts$|\.tsx$/.test(path);
239
256
  }
@@ -311,3 +328,100 @@ export function findPackageForPath(sourcePath) {
311
328
  return packageJson.content.name;
312
329
  }
313
330
  }
331
+ export function inferPackageEntryPointPaths(packagePath) {
332
+ const packageDir = dirname(packagePath);
333
+ const packageJson = JSON.parse(readFile(packagePath));
334
+ const exports = packageJson.exports;
335
+ if (typeof exports === "string") {
336
+ return resolveExport(packageDir, ".", exports, false);
337
+ }
338
+ if (!exports || typeof exports !== "object") {
339
+ if (typeof packageJson.main === "string") {
340
+ return [[".", resolve(packageDir, packageJson.main)]];
341
+ }
342
+ return [];
343
+ }
344
+ const results = [];
345
+ if (Array.isArray(exports)) {
346
+ results.push(...resolveExport(packageDir, ".", exports, true));
347
+ }
348
+ else {
349
+ for (const [importPath, exp] of Object.entries(exports)) {
350
+ results.push(...resolveExport(packageDir, importPath, exp, false));
351
+ }
352
+ }
353
+ return results;
354
+ }
355
+ function resolveExport(packageDir, name, exportDeclaration, validatePath) {
356
+ if (typeof exportDeclaration === "string") {
357
+ return resolveStarredExport(packageDir, name, exportDeclaration, validatePath);
358
+ }
359
+ if (Array.isArray(exportDeclaration)) {
360
+ for (const item of exportDeclaration) {
361
+ const result = resolveExport(packageDir, name, item, true);
362
+ if (result.length) {
363
+ return result;
364
+ }
365
+ }
366
+ return [];
367
+ }
368
+ const EXPORT_CONDITIONS = ["typedoc", "types", "import", "node", "default"];
369
+ for (const cond in exportDeclaration) {
370
+ if (EXPORT_CONDITIONS.includes(cond)) {
371
+ return resolveExport(packageDir, name, exportDeclaration[cond], false);
372
+ }
373
+ }
374
+ // No recognized export condition
375
+ return [];
376
+ }
377
+ function isWildcardName(name) {
378
+ let starCount = 0;
379
+ for (let i = 0; i < name.length; ++i) {
380
+ if (name[i] === "*") {
381
+ ++starCount;
382
+ }
383
+ }
384
+ return starCount === 1;
385
+ }
386
+ function resolveStarredExport(packageDir, name, exportDeclaration, validatePath) {
387
+ // Wildcards only do something if there is exactly one star in the name
388
+ // If there isn't any star in the destination, all entries map to one file
389
+ // so don't bother enumerating possible files.
390
+ if (isWildcardName(name) && exportDeclaration.includes("*")) {
391
+ // Construct a pattern which we can use to determine if a wildcard matches
392
+ // This will look something like: /^/app\/package\/(.*).js$/
393
+ // The destination may have multiple wildcards, in which case they should
394
+ // contain the same text, so we replace "*" with backreferences for all
395
+ // but the first occurrence.
396
+ let first = true;
397
+ const matcher = new RegExp("^" +
398
+ escapeRegExp(normalizePath(packageDir) +
399
+ "/" +
400
+ exportDeclaration.replace(/^\.\//, "")).replaceAll("\\*", () => {
401
+ if (first) {
402
+ first = false;
403
+ return "(.*)";
404
+ }
405
+ return "\\1";
406
+ }) +
407
+ "$");
408
+ const matchedFiles = discoverFiles(packageDir, {
409
+ matches(path) {
410
+ return matcher.test(path);
411
+ },
412
+ shouldRecurse(path) {
413
+ return path[path.length - 1] !== "node_modules";
414
+ },
415
+ });
416
+ return matchedFiles.flatMap((path) => {
417
+ const starContent = path.match(matcher);
418
+ ok(starContent, "impossible, discoverFiles uses matcher");
419
+ return [[name.replace("*", starContent[1]), path]];
420
+ });
421
+ }
422
+ const exportPath = resolve(packageDir, exportDeclaration);
423
+ if (validatePath && !fs.existsSync(exportPath)) {
424
+ return [];
425
+ }
426
+ return [[name, exportPath]];
427
+ }
@@ -39,9 +39,11 @@ export type Chars<T extends string> = T extends `${infer C}${infer R}` ? C | Cha
39
39
  * Utility to help type checking ensure that there is no uncovered case.
40
40
  */
41
41
  export declare function assertNever(x: never): never;
42
+ export declare function escapeRegExp(s: string): string;
42
43
  export declare function editDistance(s: string, t: string): number;
43
44
  export declare function getSimilarValues(values: Iterable<string>, compareTo: string): string[];
44
45
  export declare function NonEnumerable(_cls: unknown, context: ClassFieldDecoratorContext): void;
46
+ export declare const TYPEDOC_ROOT: string;
45
47
  export declare function hasBeenLoadedMultipleTimes(): boolean;
46
48
  export declare function getLoadedPaths(): string[];
47
49
  export {};
@@ -8,6 +8,10 @@ import { DefaultMap } from "./map.js";
8
8
  export function assertNever(x) {
9
9
  throw new Error(`Expected handling to cover all possible cases, but it didn't cover: ${Util.inspect(x)}`);
10
10
  }
11
+ // From MDN
12
+ export function escapeRegExp(s) {
13
+ return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
14
+ }
11
15
  // Based on https://en.wikipedia.org/wiki/Levenshtein_distance#Iterative_with_two_matrix_rows
12
16
  // Slightly modified for improved match results for options
13
17
  export function editDistance(s, t) {
@@ -59,6 +63,8 @@ export function NonEnumerable(_cls, context) {
59
63
  });
60
64
  });
61
65
  }
66
+ // transform /abs/path/to/typedoc/dist/lib/utils/general -> /abs/path/to/typedoc
67
+ export const TYPEDOC_ROOT = dirname(dirname(dirname(dirname(url.fileURLToPath(import.meta.url)))));
62
68
  /**
63
69
  * This is a hack to make it possible to detect and warn about installation setups
64
70
  * which result in TypeDoc being installed multiple times. If TypeDoc has been loaded
@@ -69,8 +75,7 @@ const pathSymbol = Symbol.for("typedoc_paths");
69
75
  const g = globalThis;
70
76
  g[loadSymbol] = (g[loadSymbol] || 0) + 1;
71
77
  g[pathSymbol] ||= [];
72
- // transform /abs/path/to/typedoc/dist/lib/utils/general -> /abs/path/to/typedoc
73
- g[pathSymbol].push(dirname(dirname(dirname(dirname(url.fileURLToPath(import.meta.url))))));
78
+ g[pathSymbol].push(TYPEDOC_ROOT);
74
79
  export function hasBeenLoadedMultipleTimes() {
75
80
  return g[loadSymbol] !== 1;
76
81
  }
@@ -1,6 +1,5 @@
1
- import type { BundledLanguage, BundledTheme } from "shiki" with { "resolution-mode": "import" };
2
- export declare function loadShikiMetadata(): Promise<void>;
3
- export declare function loadHighlighter(lightTheme: BundledTheme, darkTheme: BundledTheme, langs: BundledLanguage[]): Promise<void>;
1
+ import * as shiki from "@gerrit0/mini-shiki";
2
+ export declare function loadHighlighter(lightTheme: shiki.BundledTheme, darkTheme: shiki.BundledTheme, langs: shiki.BundledLanguage[]): Promise<void>;
4
3
  export declare function isSupportedLanguage(lang: string): boolean;
5
4
  export declare function getSupportedLanguages(): string[];
6
5
  export declare function getSupportedLanguagesWithoutAliases(): string[];
@@ -1,31 +1,24 @@
1
- import { ok as assert, ok } from "assert";
1
+ import * as shiki from "@gerrit0/mini-shiki";
2
2
  import * as JSX from "./jsx.js";
3
3
  import { unique } from "./array.js";
4
+ import assert from "assert";
4
5
  const aliases = new Map();
5
- let supportedLanguagesWithoutAliases = [];
6
- let supportedLanguages = [];
7
- let supportedThemes = [];
8
- const plaintextLanguages = ["txt", "text"];
9
- export async function loadShikiMetadata() {
10
- if (aliases.size)
11
- return;
12
- const shiki = await import("shiki");
13
- for (const lang of shiki.bundledLanguagesInfo) {
14
- for (const alias of lang.aliases || []) {
15
- aliases.set(alias, lang.id);
16
- }
6
+ for (const lang of shiki.bundledLanguagesInfo) {
7
+ for (const alias of lang.aliases || []) {
8
+ aliases.set(alias, lang.id);
17
9
  }
18
- supportedLanguages = unique([
19
- ...plaintextLanguages,
20
- ...aliases.keys(),
21
- ...shiki.bundledLanguagesInfo.map((lang) => lang.id),
22
- ]).sort();
23
- supportedLanguagesWithoutAliases = unique([
24
- ...plaintextLanguages,
25
- ...shiki.bundledLanguagesInfo.map((lang) => lang.id),
26
- ]);
27
- supportedThemes = Object.keys(shiki.bundledThemes);
28
10
  }
11
+ const plaintextLanguages = ["txt", "text"];
12
+ const supportedLanguagesWithoutAliases = unique([
13
+ ...plaintextLanguages,
14
+ ...shiki.bundledLanguagesInfo.map((lang) => lang.id),
15
+ ]);
16
+ const supportedLanguages = unique([
17
+ ...plaintextLanguages,
18
+ ...aliases.keys(),
19
+ ...shiki.bundledLanguagesInfo.map((lang) => lang.id),
20
+ ]).sort();
21
+ const supportedThemes = Object.keys(shiki.bundledThemes);
29
22
  class DoubleHighlighter {
30
23
  highlighter;
31
24
  light;
@@ -40,7 +33,7 @@ class DoubleHighlighter {
40
33
  return this.highlighter.getLoadedLanguages().includes(lang);
41
34
  }
42
35
  highlight(code, lang) {
43
- const tokens = this.highlighter.codeToTokensWithThemes(code, {
36
+ const tokens = shiki.codeToTokensWithThemes(this.highlighter, code, {
44
37
  themes: { light: this.light, dark: this.dark },
45
38
  lang: lang,
46
39
  });
@@ -101,27 +94,32 @@ class DoubleHighlighter {
101
94
  return scheme;
102
95
  }
103
96
  }
97
+ let shikiEngine;
104
98
  let highlighter;
105
99
  export async function loadHighlighter(lightTheme, darkTheme, langs) {
106
100
  if (highlighter)
107
101
  return;
108
- const shiki = await import("shiki");
109
- const hl = await shiki.createHighlighter({ themes: [lightTheme, darkTheme], langs });
102
+ if (!shikiEngine) {
103
+ await shiki.loadBuiltinWasm();
104
+ shikiEngine = await shiki.createOnigurumaEngine();
105
+ }
106
+ const hl = await shiki.createShikiInternal({
107
+ engine: shikiEngine,
108
+ themes: [shiki.bundledThemes[lightTheme], shiki.bundledThemes[darkTheme]],
109
+ langs: langs.map((lang) => shiki.bundledLanguages[lang]),
110
+ });
110
111
  highlighter = new DoubleHighlighter(hl, lightTheme, darkTheme);
111
112
  }
112
113
  export function isSupportedLanguage(lang) {
113
114
  return getSupportedLanguages().includes(lang);
114
115
  }
115
116
  export function getSupportedLanguages() {
116
- ok(supportedLanguages.length > 0, "loadShikiMetadata has not been called");
117
117
  return supportedLanguages;
118
118
  }
119
119
  export function getSupportedLanguagesWithoutAliases() {
120
- ok(supportedLanguagesWithoutAliases.length > 0, "loadShikiMetadata has not been called");
121
- return supportedLanguages;
120
+ return supportedLanguagesWithoutAliases;
122
121
  }
123
122
  export function getSupportedThemes() {
124
- ok(supportedThemes.length > 0, "loadShikiMetadata has not been called");
125
123
  return supportedThemes;
126
124
  }
127
125
  export function isLoadedLanguage(lang) {
@@ -5,7 +5,7 @@ export { EventDispatcher } from "./events.js";
5
5
  export { isFile, copy, copySync, getCommonDirectory, readFile, writeFile, writeFileSync, discoverInParentDir, discoverPackageJson, } from "./fs.js";
6
6
  export { normalizePath } from "./paths.js";
7
7
  export type { IfInternal, NeverIfInternal, Chars } from "./general.js";
8
- export { assertNever } from "./general.js";
8
+ export { assertNever, TYPEDOC_ROOT } from "./general.js";
9
9
  export { ConsoleLogger, Logger, LogLevel } from "./loggers.js";
10
10
  export { DefaultMap } from "./map.js";
11
11
  export { ArgumentsReader, Option, CommentStyle, Options, PackageJsonReader, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, OptionDefaults, } from "./options/index.js";
@@ -4,7 +4,7 @@ export * from "./enum.js";
4
4
  export { EventDispatcher } from "./events.js";
5
5
  export { isFile, copy, copySync, getCommonDirectory, readFile, writeFile, writeFileSync, discoverInParentDir, discoverPackageJson, } from "./fs.js";
6
6
  export { normalizePath } from "./paths.js";
7
- export { assertNever } from "./general.js";
7
+ export { assertNever, TYPEDOC_ROOT } from "./general.js";
8
8
  export { ConsoleLogger, Logger, LogLevel } from "./loggers.js";
9
9
  export { DefaultMap } from "./map.js";
10
10
  export { ArgumentsReader, Option, CommentStyle, Options, PackageJsonReader, ParameterHint, ParameterType, TSConfigReader, TypeDocReader, OptionDefaults, } from "./options/index.js";
@@ -1,4 +1,4 @@
1
- import type { BundledTheme as ShikiTheme } from "shiki" with { "resolution-mode": "import" };
1
+ import type { BundledTheme as ShikiTheme } from "@gerrit0/mini-shiki";
2
2
  import type { LogLevel } from "../loggers.js";
3
3
  import type { SortStrategy } from "../sort.js";
4
4
  import type { EntryPointStrategy } from "../entry-point.js";
@@ -1,4 +1,4 @@
1
- import type { BundledLanguage } from "shiki" with { "resolution-mode": "import" };
1
+ import type { BundledLanguage } from "@gerrit0/mini-shiki";
2
2
  import type { EnumKeys } from "../enum.js";
3
3
  import type { ReflectionKind } from "../../models/index.js";
4
4
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typedoc",
3
3
  "description": "Create api documentation for TypeScript projects.",
4
- "version": "0.27.0-beta.1",
4
+ "version": "0.27.0",
5
5
  "homepage": "https://typedoc.org",
6
6
  "type": "module",
7
7
  "exports": {
@@ -25,11 +25,10 @@
25
25
  "node": ">= 18"
26
26
  },
27
27
  "dependencies": {
28
+ "@gerrit0/mini-shiki": "^1.23.2",
28
29
  "lunr": "^2.3.9",
29
30
  "markdown-it": "^14.1.0",
30
- "minimatch": "^10.0.1",
31
- "resolve-import": "^1.4.6",
32
- "shiki": "^1.23.1",
31
+ "minimatch": "^9.0.5",
33
32
  "yaml": "^2.6.1"
34
33
  },
35
34
  "peerDependencies": {