diff --git a/apps/cli/sync.ts b/apps/cli/sync.ts index 777de88..d548fd3 100755 --- a/apps/cli/sync.ts +++ b/apps/cli/sync.ts @@ -5,8 +5,8 @@ * - New problems get a full page (frontmatter, badge, warning, examples, * constraints, solution) in the gold-standard format. * - Already-ported pages only get their script-owned parts regenerated — the - * `` line and the `## Solution` section — so hand-curated prose is - * never touched. + * frontmatter `icon:` (`PAGE_ICON`), the `` line and the + * `## Solution` section — so hand-curated prose is never touched. * - When a problem is solved in both JavaScript and Python the solution * renders as a (Python first); single-language solutions * render as a plain fence. @@ -417,6 +417,9 @@ function warningText(h: Header): string { ); } +/** Sidebar/page icon for every problem page (Lucide, resolved by Blume). */ +const PAGE_ICON = "line-dot-left-horizontal"; + function badgeLine(sol: Solution): string { return `${sol.category}`; } @@ -431,6 +434,7 @@ function renderPage(sol: Solution): string { "---", `title: '${h.num}. ${h.title.replaceAll("'", "''")}'`, /[:#]/.test(description) ? `description: '${description.replaceAll("'", "''")}'` : `description: ${description}`, + `icon: ${PAGE_ICON}`, "sidebar:", ` label: '${h.title.replaceAll("'", "''")}'`, ` badge: '${h.difficulty}'`, @@ -508,6 +512,17 @@ function ensureLabel(page: string, h: Header): string { return page.replace(/^sidebar:$/m, `sidebar:\n${label}`); } +/** Set the frontmatter's top-level `icon:` to `PAGE_ICON`, inserting it before `sidebar:`. */ +function ensureIcon(page: string): string { + const fm = page.match(/^---\n[\s\S]*?\n---/); + if (!fm) return page; + const line = `icon: ${PAGE_ICON}`; + const next = /^icon: .*$/m.test(fm[0]) + ? fm[0].replace(/^icon: .*$/m, line) + : fm[0].replace(/^sidebar:$/m, `${line}\nsidebar:`); + return next + page.slice(fm[0].length); +} + /** * Offset just past the script-owned `## Solution` section: the next top-level * heading that is not inside a code fence, or end of file. Sections a human @@ -564,7 +579,7 @@ for (const sol of ordered) { } const tail = page.slice(solutionEnd(page, at)); const body = page.slice(0, at) + solutionSection(sol) + (tail ? `\n${tail}` : ""); - const next = ensureLabel(body, sol.header).replace(/^.*<\/Badge>$/m, badgeLine(sol)); + const next = ensureIcon(ensureLabel(body, sol.header)).replace(/^.*<\/Badge>$/m, badgeLine(sol)); const actions: string[] = []; if (existing !== name) { await rename(join(DOCS, existing), join(DOCS, name));