Skip to content

Commit a4b022e

Browse files
committed
Fix externalSymbolLinkMappings # urls
Resolves #2921
1 parent de0271f commit a4b022e

File tree

9 files changed

+64
-57
lines changed

9 files changed

+64
-57
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ title: Changelog
1212
that function's type parameters as the class type parameters, #2914.
1313
- When printing entry point globs which fail to match any paths, TypeDoc will no longer normalize the glob, #2918.
1414
- Inlining types can now handle more type variants, #2920.
15+
- Fixed behavior of `externalSymbolLinkMappings` option when URL is set to `#`, #2921.
1516
- API: `toString` on types containing index signatures now behave correctly, #2917.
1617

1718
## v0.28.1 (2025-03-20)

scripts/rebuild_specs.js

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,21 @@
44
Error.stackTraceLimit = 50;
55
import ts from "typescript";
66
import fs from "fs";
7-
import { rm } from "fs/promises";
87
import path, { basename, join } from "path";
98
import * as td from "../dist/index.js";
109
import { getExpandedEntryPointsForPaths } from "../dist/lib/utils/index.js";
1110
import { ok } from "assert";
1211
import { fileURLToPath } from "url";
1312
import { diagnostics } from "../dist/lib/utils/loggers.js";
14-
import { getConverter2App, getConverter2Project, getConverterApp } from "../dist/test/programs.js";
15-
import { TestRouter, TestTheme } from "../dist/test/renderer/testRendererUtils.js";
13+
import { getConverterApp } from "../dist/test/programs.js";
14+
import { buildRendererSpecs } from "../dist/test/renderer/testRendererUtils.js";
1615

1716
const base = path.join(
1817
fileURLToPath(import.meta.url),
1918
"../../src/test/converter",
2019
);
2120

2221
const app = getConverterApp();
23-
const app2 = getConverter2App();
24-
25-
app2.renderer.defineTheme("test-theme", TestTheme);
26-
app2.renderer.defineRouter("test-router", TestRouter);
2722

2823
app.serializer.addSerializer({
2924
priority: -1,
@@ -128,19 +123,7 @@ function rebuildConverterTests(dirs) {
128123
/** @param {string} specPath */
129124
async function rebuildRendererTest(specPath) {
130125
console.log(specPath);
131-
await rm(specPath, { recursive: true, force: true });
132-
133-
app2.options.setValue("theme", "test-theme");
134-
app2.options.setValue("router", "test-router");
135-
app2.options.setValue("disableGit", true);
136-
app2.options.setValue("sourceLinkTemplate", "{path}");
137-
138-
td.resetReflectionID();
139-
const project = getConverter2Project(["renderer"], ".");
140-
project.readme = [{ kind: "text", text: "Readme text" }];
141-
await app2.generateDocs(project, specPath);
142-
await rm(`${specPath}/assets`, { recursive: true });
143-
await rm(`${specPath}/.nojekyll`);
126+
await buildRendererSpecs(specPath);
144127
}
145128

146129
async function main() {

src/lib/output/renderer.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ export class Renderer extends AbstractComponent<Application, RendererEvents> {
288288
this.themes.set(name, theme);
289289
}
290290

291+
/** @internal intended for test usage only */
292+
removeTheme(name: string) {
293+
this.themes.delete(name);
294+
}
295+
291296
/**
292297
* Define a new router that can be used to determine the output structure.
293298
* @param name
@@ -300,6 +305,11 @@ export class Renderer extends AbstractComponent<Application, RendererEvents> {
300305
this.routers.set(name, router);
301306
}
302307

308+
/** @internal intended for test usage only */
309+
removeRouter(name: string) {
310+
this.routers.delete(name);
311+
}
312+
303313
/**
304314
* Render the given project reflection to the specified output directory.
305315
*

src/lib/output/themes/MarkedPlugin.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export class MarkedPlugin extends ContextAwareRendererComponent {
159159
let url: string | undefined;
160160
let kindClass: string | undefined;
161161
if (typeof part.target === "string") {
162-
url = part.target;
162+
url = part.target === "#" ? undefined : part.target;
163163
} else if ("id" in part.target) {
164164
// No point in trying to resolve a ReflectionSymbolId at this point, we've already
165165
// tried and failed during the resolution step. Warnings related to those broken links

src/test/converter2/typedoc.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
"path": "../../../docs/docs.json"
1212
}
1313
],
14+
"disableGit": true,
15+
"sourceLinkTemplate": "{path}",
16+
"excludeExternals": true,
17+
"tsconfig": "tsconfig.json",
18+
"validation": true,
19+
"skipErrorChecking": true,
1420
"externalSymbolLinkMappings": {
1521
// used by {@link !Promise}
1622
"global": {

src/test/output/output.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ describe("Output", () => {
2424
});
2525

2626
beforeEach(() => {
27+
// Throw away output configuration for debug rendering of c2 projects
28+
app.options.reset();
29+
2730
outputs = new Outputs(app);
2831
outputs.addOutput("html", () => {
2932
htmlWritten = true;

src/test/programs.ts

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { createAppForTesting } from "../lib/application.js";
1515
import { existsSync } from "fs";
1616
import { clearCommentCache } from "../lib/converter/comments/index.js";
1717
import { diagnostics } from "../lib/utils/loggers.js";
18+
import { readFile } from "#node-utils";
1819

1920
let converterApp: Application | undefined;
2021
let converterProgram: ts.Program | undefined;
@@ -112,18 +113,14 @@ export function getConverter2Base() {
112113
export function getConverter2App() {
113114
if (!converter2App) {
114115
converter2App = createAppForTesting();
115-
for (
116-
const [name, value] of Object.entries(
117-
{
118-
excludeExternals: true,
119-
tsconfig: join(getConverter2Base(), "tsconfig.json"),
120-
validation: true,
121-
skipErrorChecking: true,
122-
} satisfies TypeDocOptions,
123-
)
124-
) {
125-
converter2App.options.setValue(name as never, value as never);
116+
117+
// This is a base-bones version of the TypeDocReader's read method
118+
// which doesn't handle a JS config, so can be done synchronously
119+
const result = ts.readConfigFile(join(getConverter2Base(), "typedoc.json"), readFile);
120+
for (const [name, value] of Object.entries(result.config)) {
121+
converter2App.options.setValue(name as never, value as never, getConverter2Base());
126122
}
123+
127124
new TSConfigReader().read(
128125
converter2App.options,
129126
converter2App.logger,

src/test/renderer/DefaultTheme.test.ts

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,15 @@
1-
import { rm } from "fs/promises";
2-
import { getConverter2App, getConverter2Project } from "../programs.js";
3-
import { TestRouter, TestTheme } from "./testRendererUtils.js";
1+
import { buildRendererSpecs } from "./testRendererUtils.js";
42
import { deepEqual as equal } from "assert/strict";
53
import { glob, readFile } from "#node-utils";
64
import type { GlobString, NormalizedPath } from "#utils";
75
import { join, relative } from "path";
8-
import { resetReflectionID } from "#models";
9-
10-
const app = getConverter2App();
11-
12-
app.renderer.defineTheme("test-theme", TestTheme);
13-
app.renderer.defineRouter("test-router", TestRouter);
146

157
describe("DefaultTheme", () => {
16-
afterEach(() => {
17-
app.options.reset();
18-
});
19-
208
it("Matches render snapshot", async function () {
219
const SPEC_PATH = "src/test/renderer/specs" as NormalizedPath;
2210
const outPath = "tmp/renderer" as NormalizedPath;
2311

24-
app.options.setValue("theme", "test-theme");
25-
app.options.setValue("router", "test-router");
26-
app.options.setValue("disableGit", true);
27-
app.options.setValue("sourceLinkTemplate", "{path}");
28-
29-
resetReflectionID();
30-
const project = getConverter2Project(["renderer"], ".");
31-
project.readme = [{ kind: "text", text: "Readme text" }];
32-
await app.generateDocs(project, outPath);
33-
await rm(outPath + "/assets", { recursive: true });
34-
await rm(outPath + "/.nojekyll");
12+
await buildRendererSpecs(outPath);
3513

3614
const expectedFiles = glob("**/*" as GlobString, SPEC_PATH);
3715
const actualFiles = glob("**/*" as GlobString, outPath);

src/test/renderer/testRendererUtils.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import type { Reflection } from "#models";
1+
import { type Reflection, resetReflectionID } from "#models";
22
import { loadTestHighlighter } from "#node-utils";
3+
import { rm } from "node:fs/promises";
34
import { DefaultTheme, KindRouter, PageEvent, PageKind, type RenderTemplate } from "../../lib/output/index.js";
45
import { type JsxChildren, type JsxElement, JsxFragment } from "../../lib/utils-common/jsx.elements.js";
56
import { Raw } from "../../lib/utils-common/jsx.js";
7+
import { getConverter2App, getConverter2Project } from "../programs.js";
68

79
function shouldIgnoreElement(el: JsxElement) {
810
switch (el.tag) {
@@ -135,3 +137,30 @@ export class TestTheme extends DefaultTheme {
135137
export class TestRouter extends KindRouter {
136138
override extension = ".json";
137139
}
140+
141+
export async function buildRendererSpecs(specPath: string) {
142+
await rm(specPath, { recursive: true, force: true });
143+
144+
const app2 = getConverter2App();
145+
app2.renderer.defineTheme("test-theme", TestTheme);
146+
app2.renderer.defineRouter("test-router", TestRouter);
147+
148+
const snap = app2.options.snapshot();
149+
150+
app2.options.setValue("options", "src/test/converter2/typedoc.json");
151+
await app2.options.read(app2.logger);
152+
153+
app2.options.setValue("theme", "test-theme");
154+
app2.options.setValue("router", "test-router");
155+
156+
resetReflectionID();
157+
const project = getConverter2Project(["renderer"], ".");
158+
project.readme = [{ kind: "text", text: "Readme text" }];
159+
await app2.generateDocs(project, specPath);
160+
await rm(`${specPath}/assets`, { recursive: true });
161+
await rm(`${specPath}/.nojekyll`);
162+
163+
app2.renderer.removeTheme("test-theme");
164+
app2.renderer.removeRouter("test-router");
165+
app2.options.restore(snap);
166+
}

0 commit comments

Comments
 (0)