Skip to content

Commit f97c5ab

Browse files
committed
docs: enhance markdown transformation with symbol link replacement
- Added `replaceSymbolLinks` to convert symbol tokens into markdown links. - Introduced `loadSymbolIndex` for resolving symbols to their API paths using a cached index. - Refactored imports and logic for improved maintainability.
1 parent d1997b8 commit f97c5ab

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

docs/.vitepress/scripts/build-llm-contents.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ import {copyFiles} from "./llm/copy-files.js";
66
import {buildReferenceSidebar} from "./llm/sidebar.js";
77

88
const DOCS_ROOT = join(import.meta.dirname, "..", "..");
9+
/**
10+
* Each entry describes a docs directory to copy into /public/ai.
11+
* Markdown is normalized (remark), snippet directives are inlined,
12+
* and @@Symbol@@ tokens are rewritten to /ai/api links.
13+
*/
914
const DOC_SECTIONS = [
1015
{
1116
source: "guide",

docs/.vitepress/scripts/llm/markdown.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ const markdownProcessor = unified()
1111
.use(remarkStringify, {fences: true, bullet: "-"})
1212
.use(remarkCleanApiMarkdown);
1313
const INLINE_SNIPPET_RE = /^<<<\s+@\/([^\s]+?)(?:\s+\[(.+?)\])?\s*$/gm;
14+
const SYMBOL_TOKEN_RE = /@@([A-Za-z0-9_.-]+)@@/g;
15+
const symbolIndexCache = new Map();
1416

1517
export async function transformMarkdown(content, options = {}) {
1618
const {docsRoot} = options;
1719
let nextContent = content;
1820

1921
if (docsRoot) {
2022
nextContent = await inlineExampleBlocks(nextContent, docsRoot);
23+
nextContent = await replaceSymbolLinks(nextContent, docsRoot);
2124
}
2225

2326
const {frontmatter, body} = extractFrontmatter(nextContent);
@@ -57,6 +60,41 @@ async function inlineExampleBlocks(content, docsRoot) {
5760
return result;
5861
}
5962

63+
async function replaceSymbolLinks(content, docsRoot) {
64+
const index = await loadSymbolIndex(docsRoot);
65+
return content.replace(SYMBOL_TOKEN_RE, (match, symbolName) => {
66+
const entry = index.get(symbolName);
67+
68+
if (!entry) {
69+
console.warn(`[build-llm-contents] Unable to resolve symbol ${symbolName}`);
70+
return match;
71+
}
72+
73+
return `[${symbolName}](/ai${entry.path}.md)`;
74+
});
75+
}
76+
77+
async function loadSymbolIndex(docsRoot) {
78+
if (symbolIndexCache.has(docsRoot)) {
79+
return symbolIndexCache.get(docsRoot);
80+
}
81+
82+
const apiPath = join(docsRoot, "public/api.json");
83+
const data = JSON.parse(await readFile(apiPath, "utf8"));
84+
const map = new Map();
85+
86+
Object.values(data.modules ?? {}).forEach((module) => {
87+
module.symbols?.forEach((symbol) => {
88+
if (symbol.symbolName && symbol.path) {
89+
map.set(symbol.symbolName, symbol);
90+
}
91+
});
92+
});
93+
94+
symbolIndexCache.set(docsRoot, map);
95+
return map;
96+
}
97+
6098
async function loadSnippetBlock(entry, docsRoot) {
6199
const absolutePath = join(docsRoot, entry.relativePath);
62100

0 commit comments

Comments
 (0)