Skip to content

Commit c326633

Browse files
committed
fix(docs): strip .md from TypeDoc link hrefs to fix overview 404s
Next.js routes are extensionless — generated hrefs like (Class-ClientManager.md) resolve to /api/core/Class-ClientManager.md which 404s. The sidebar worked because Nextra builds its own <Link> from _meta.js keys without extensions. Add MD_EXT_RE to fixDotSlugs: strips .md from all relative link hrefs in generated markdown, skipping https:// and anchor-only (#) hrefs. GitHub source code deep-links (https://github.com/.../file.ts#L118) are correctly left untouched.
1 parent 01577a8 commit c326633

File tree

1 file changed

+25
-17
lines changed

1 file changed

+25
-17
lines changed

docs-site/scripts/generate-api-docs.mjs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import { execSync } from 'child_process';
1515
import {
1616
existsSync,
1717
mkdirSync,
18-
readFileSync,
1918
readdirSync,
19+
readFileSync,
2020
renameSync,
2121
writeFileSync,
2222
} from 'fs';
@@ -98,7 +98,13 @@ const TYPE_SECTIONS = [
9898
{ prefix: 'Enumeration', title: 'Enumerations' },
9999
];
100100

101-
const TYPEDOC_BIN = join(DOCS_SITE, 'node_modules', 'typedoc', 'bin', 'typedoc');
101+
const TYPEDOC_BIN = join(
102+
DOCS_SITE,
103+
'node_modules',
104+
'typedoc',
105+
'bin',
106+
'typedoc'
107+
);
102108

103109
// ── Helpers ──────────────────────────────────────────────────────────────────
104110

@@ -108,39 +114,41 @@ const TYPEDOC_BIN = join(DOCS_SITE, 'node_modules', 'typedoc', 'bin', 'typedoc')
108114
* folder segment, producing broken links like `/api/Class.ClientManager`
109115
* instead of `/api/core/Class.ClientManager`.
110116
*
117+
* Next.js also routes pages without file extensions, so any `href.md` in
118+
* generated markdown link hrefs will 404 — they must be stripped to `href`.
119+
*
111120
* This function:
112-
* 1. Rewrites cross-reference links in all .md files
113-
* `Type.Name.md` → `Type-Name.md`
114-
* `README.md` → `index.md` (TypeDoc breadcrumb links)
115-
* 2. Renames every `Type.Name.md` file`Type-Name.md`
121+
* 1. Rewrites cross-reference links: Type.Name.md → Type-Name.md
122+
* 2. Rewrites breadcrumb links: README.md → index.md
123+
* 3. Strips .md extension from ALL relative link hrefs ()(path.md) → (path)
124+
* 4. Renames files: Type.Name.md → Type-Name.md
116125
*/
117126
function fixDotSlugs(pkgOut) {
118127
const TYPE_PREFIXES =
119128
'Class|Interface|TypeAlias|Function|Variable|Enumeration';
120-
const LINK_RE = new RegExp(
121-
`(${TYPE_PREFIXES})\\.([^)"\\s]+\\.md)`,
122-
'g',
123-
);
129+
const LINK_RE = new RegExp(`(${TYPE_PREFIXES})\\.([^)"\\s]+\\.md)`, 'g');
130+
// Strip .md from relative link hrefs — skip http(s) and anchor-only hrefs
131+
const MD_EXT_RE = /(\]\()((?!https?:\/\/)(?!#)[^)]+)\.md\)/g;
124132

125133
const files = readdirSync(pkgOut).filter((f) => f.endsWith('.md'));
126134

127135
// Step 1 — rewrite links inside every file before renaming
128136
for (const file of files) {
129137
const path = join(pkgOut, file);
130138
const original = readFileSync(path, 'utf8');
131-
let rewritten = original
132-
// Type.Name.md → Type-Name.md
139+
const rewritten = original
140+
// Type.Name.md → Type-Name.md (must run before MD_EXT_RE)
133141
.replace(LINK_RE, (_, type, rest) => `${type}-${rest}`)
134142
// README.md → index.md (TypeDoc breadcrumb links)
135-
.replace(/\(README\.md\)/g, '(index.md)');
143+
.replace(/\(README\.md\)/g, '(index.md)')
144+
// Strip .md extension from all remaining relative link hrefs
145+
.replace(MD_EXT_RE, (_, open, href) => `${open}${href})`);
136146
if (rewritten !== original) writeFileSync(path, rewritten);
137147
}
138148

139149
// Step 2 — rename the files themselves
140150
for (const file of files) {
141-
const match = file.match(
142-
new RegExp(`^(${TYPE_PREFIXES})\\.(.+\\.md)$`),
143-
);
151+
const match = file.match(new RegExp(`^(${TYPE_PREFIXES})\\.(.+\\.md)$`));
144152
if (match) {
145153
renameSync(join(pkgOut, file), join(pkgOut, `${match[1]}-${match[2]}`));
146154
}
@@ -238,7 +246,7 @@ for (const pkg of PACKAGES) {
238246
'false',
239247
'--hidePageTitle',
240248
'false',
241-
].join(' '),
249+
].join(' ')
242250
);
243251

244252
// TypeDoc outputs README.md as the overview page — rename to index.md

0 commit comments

Comments
 (0)