Skip to content

Commit 3de9e24

Browse files
committed
fix: add basePath to internal links for GitHub Pages deployment
Internal links (starting with /) were missing the /documents base path when deployed to GitHub Pages, causing 404 errors. - Add basePath to marked link renderer for HTML output - Add basePath to JSDoc {@link} tag processing - Add rewriteMarkdownLinks() for raw Markdown endpoints
1 parent 73e34f7 commit 3de9e24

2 files changed

Lines changed: 32 additions & 6 deletions

File tree

lib/markdown.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* Markdown rendering utilities
33
*/
44
import { marked, type Tokens } from "marked";
5+
import { basePath } from "../data/docs.ts";
56

67
/** Generate slug from text (for heading IDs) */
78
function slugify(text: string): string {
@@ -13,7 +14,7 @@ function slugify(text: string): string {
1314
.replace(/\s+/g, "-");
1415
}
1516

16-
// Configure marked with custom heading renderer for IDs
17+
// Configure marked with custom heading and link renderers
1718
marked.use({
1819
gfm: true, // GitHub Flavored Markdown
1920
breaks: false,
@@ -26,6 +27,15 @@ marked.use({
2627
: token.text;
2728
return `<h${token.depth} id="${id}">${text}</h${token.depth}>\n`;
2829
},
30+
link(token: Tokens.Link): string {
31+
// Add basePath to internal links (starting with /)
32+
let href = token.href;
33+
if (href.startsWith("/") && !href.startsWith("//")) {
34+
href = `${basePath}${href}`;
35+
}
36+
const title = token.title ? ` title="${token.title}"` : "";
37+
return `<a href="${href}"${title}>${token.text}</a>`;
38+
},
2939
},
3040
});
3141

@@ -74,14 +84,14 @@ function processJsDocLinks(
7484

7585
// Check if it's a local type in the current package
7686
if (localTypes?.has(name) && currentPackage) {
77-
href = `/api/${currentPackage}#${name.toLowerCase()}`;
87+
href = `${basePath}/api/${currentPackage}#${name.toLowerCase()}`;
7888
} // Check if it's in another package
7989
else if (typeToPackage?.has(name)) {
8090
const targetPackage = typeToPackage.get(name)!;
81-
href = `/api/${targetPackage}#${name.toLowerCase()}`;
91+
href = `${basePath}/api/${targetPackage}#${name.toLowerCase()}`;
8292
} // Default: link to current package anchor (best effort)
8393
else if (currentPackage) {
84-
href = `/api/${currentPackage}#${name.toLowerCase()}`;
94+
href = `${basePath}/api/${currentPackage}#${name.toLowerCase()}`;
8595
}
8696

8797
// Format the display text
@@ -121,6 +131,21 @@ export function extractTitle(content: string): string | undefined {
121131
return match?.[1];
122132
}
123133

134+
/**
135+
* Rewrite internal links in markdown content to include basePath.
136+
* Transforms [text](/path) to [text](/basePath/path) for internal links.
137+
*/
138+
export function rewriteMarkdownLinks(content: string): string {
139+
if (!basePath) return content;
140+
141+
// Match markdown links: [text](url) or [text](url "title")
142+
// Only rewrite internal links starting with /
143+
return content.replace(
144+
/\[([^\]]*)\]\((\/)([^)"'\s]*)((?:\s+"[^"]*")?\))/g,
145+
(_, text, _slash, path, rest) => `[${text}](${basePath}/${path}${rest}`,
146+
);
147+
}
148+
124149
/** Extract table of contents from markdown headings (h2 only) */
125150
export function extractToc(
126151
content: string,

main.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { docPages } from "./data/docs.ts";
55
import type { PackageDoc } from "./lib/api-docs.ts";
66
import { generateApiMarkdown } from "./lib/api-markdown.ts";
77
import { generateLlmsTxt } from "./lib/llms.ts";
8+
import { rewriteMarkdownLinks } from "./lib/markdown.ts";
89
import { ApiIndexPage, PackagePage } from "./templates/api/ApiPage.tsx";
910
import { MarkdownDocFromFile } from "./templates/docs/MarkdownDoc.tsx";
1011
import { HomePage } from "./templates/home.tsx";
@@ -41,7 +42,7 @@ app.get("/index.md", async (c) => {
4142
"",
4243
content,
4344
].join("\n");
44-
return c.text(modified, 200, {
45+
return c.text(rewriteMarkdownLinks(modified), 200, {
4546
"Content-Type": "text/markdown; charset=utf-8",
4647
});
4748
});
@@ -71,7 +72,7 @@ for (const doc of docPages) {
7172
: `${doc.path}.md`;
7273
app.get(mdPath, async (c) => {
7374
const content = await Deno.readTextFile(doc.file);
74-
return c.text(content, 200, {
75+
return c.text(rewriteMarkdownLinks(content), 200, {
7576
"Content-Type": "text/markdown; charset=utf-8",
7677
});
7778
});

0 commit comments

Comments
 (0)