feat(sync): organize solution docs by category and add sidebar labels

This commit is contained in:
Prad Nukala
2026-08-20 13:47:54 -04:00
parent a990d912d8
commit 1b4501e419
2 changed files with 26 additions and 13 deletions
+21 -9
View File
@@ -10,7 +10,7 @@
* renders as a <CodeGroup> (Python first); single-language solutions
* render as a plain fence.
*/
import { readdir, rename } from "node:fs/promises";
import { mkdir, rename } from "node:fs/promises";
import { basename, join } from "node:path";
const ROOT = join(import.meta.dir, "..");
@@ -284,6 +284,7 @@ function renderPage(sol: Solution, topic: string): string {
`title: '${h.num}. ${h.title.replaceAll("'", "''")}'`,
/[:#]/.test(description) ? `description: '${description.replaceAll("'", "''")}'` : `description: ${description}`,
"sidebar:",
` label: '${h.title.replaceAll("'", "''")}'`,
` badge: '${h.difficulty}'`,
"---",
"",
@@ -346,12 +347,20 @@ for await (const rel of new Bun.Glob("**/*.{js,py}").scan(WORK)) {
const topics = await readmeTopics();
/** Insert a number-free `sidebar.label` into existing frontmatter when missing. */
function ensureLabel(page: string, h: Header): string {
const fm = page.match(/^---\n[\s\S]*?\n---/);
if (!fm || /^ {2}label: /m.test(fm[0])) return page;
const label = ` label: '${h.title.replaceAll("'", "''")}'`;
return page.replace(/^sidebar:$/m, `sidebar:\n${label}`);
}
// Existing docs pages, keyed by leetcode number from the frontmatter title.
const pages = new Map<number, string>(); // num -> filename
for (const f of (await readdir(DOCS)).filter((f) => f.endsWith(".mdx")).sort()) {
const text = await Bun.file(join(DOCS, f)).text();
const pages = new Map<number, string>(); // num -> path relative to DOCS
for (const rel of (await Array.fromAsync(new Bun.Glob("**/*.mdx").scan(DOCS))).sort()) {
const text = await Bun.file(join(DOCS, rel)).text();
const t = text.match(/^title: '(\d+)\./m);
if (t) pages.set(Number(t[1]), f);
if (t) pages.set(Number(t[1]), rel);
}
const report: [string, string, string][] = [];
@@ -360,8 +369,11 @@ const ordered = [...solutions.values()].sort((a, b) => a.num - b.num);
for (const sol of ordered) {
const langs = Object.keys(sol.code).sort().join("+");
const workRef = `${sol.num}.${sol.slug} (${langs})`;
const name = `${sol.num}-${sol.slug}.mdx`; // prefix = leetcode number (numeric sidebar order, stripped from the URL)
// (category) group folder + leetcode-number prefix: numeric sidebar order, both stripped from the URL.
const group = `(${sol.category.toLowerCase().replaceAll(" ", "-")})`;
const name = `${group}/${sol.num}-${sol.slug}.mdx`;
const existing = pages.get(sol.num);
await mkdir(join(DOCS, group), { recursive: true });
if (existing) {
const page = await Bun.file(join(DOCS, existing)).text();
@@ -370,15 +382,15 @@ for (const sol of ordered) {
report.push([workRef, existing, "ERROR: no '## Solution' heading"]);
continue;
}
const next = page.slice(0, at) + solutionSection(sol);
const next = ensureLabel(page.slice(0, at) + solutionSection(sol), sol.header);
const actions: string[] = [];
if (existing !== name) {
await rename(join(DOCS, existing), join(DOCS, name));
actions.push("renamed");
actions.push("moved");
}
if (next !== page) {
await Bun.write(join(DOCS, name), next);
actions.push("updated (solution)");
actions.push("updated");
}
report.push([workRef, name, actions.join(" + ") || "skipped (in sync)"]);
} else {