import { apiFetch } from "./api.js"; import { dom } from "./dom.js"; import { state } from "./state.js"; function escapeHtml(text) { return text .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">"); } function slugify(text) { return text .toLowerCase() .trim() .replace(/[^\w\u4e00-\u9fa5]+/g, "-") .replace(/^-+|-+$/g, ""); } function parseMarkdown(text) { const lines = text.split(/\r?\n/); const blocks = []; const headings = []; let inCode = false; let codeBuffer = []; let paragraph = []; const flushParagraph = () => { if (!paragraph.length) { return; } blocks.push(`

${escapeHtml(paragraph.join(" "))}

`); paragraph = []; }; const flushCode = () => { if (!codeBuffer.length) { return; } blocks.push(`
${escapeHtml(codeBuffer.join("\n"))}
`); codeBuffer = []; }; lines.forEach((line) => { if (line.startsWith("```")) { if (inCode) { flushCode(); } else { flushParagraph(); } inCode = !inCode; return; } if (inCode) { codeBuffer.push(line); return; } const heading = line.match(/^(#{1,4})\s+(.*)$/); if (heading) { flushParagraph(); const level = heading[1].length; const textValue = heading[2].trim(); const id = slugify(textValue); headings.push({ level, text: textValue, id }); blocks.push(`${escapeHtml(textValue)}`); return; } if (!line.trim()) { flushParagraph(); return; } paragraph.push(line.trim()); }); flushParagraph(); flushCode(); return { html: blocks.join(""), headings }; } export async function loadApiDoc() { const text = await apiFetch("/api/docs/api-md"); const { html, headings } = parseMarkdown(text || ""); dom.apiDocContent.innerHTML = html || "

API.md 为空

"; dom.apiDocToc.innerHTML = headings.length ? headings .map( (item) => `${escapeHtml(item.text)}`, ) .join("") : "
未解析到标题
"; dom.apiDocToc.querySelectorAll("a").forEach((link) => { link.addEventListener("click", (event) => { event.preventDefault(); const id = link.getAttribute("href")?.slice(1); if (!id) { return; } dom.apiDocContent.querySelector(`#${CSS.escape(id)}`)?.scrollIntoView({ behavior: "smooth", block: "start", }); }); }); state.apiDocLoaded = true; } export async function openApiDocDrawer() { dom.apiDocDrawer.classList.remove("hidden"); if (!state.apiDocLoaded) { await loadApiDoc(); } } export function closeApiDocDrawer() { dom.apiDocDrawer.classList.add("hidden"); }