export type Heading = { id: string; text: string; level: number; line: number }; export function headingsFor(content: string): Heading[] { let fenced = false; const counts = new Map(); return content.split("\n").flatMap((line, index) => { if (/^\s*(```|~~~)/.test(line)) { fenced = !fenced; return []; } const match = !fenced && line.match(/^(#{2,3})\s+(.+?)\s*#*$/); if (!match) return []; const text = match[2].replace(/[`*_]/g, ""); const base = text .toLowerCase() .replace(/[^\p{L}\p{N}\s-]/gu, "") .trim() .replace(/\s+/g, "-") || "section"; const count = counts.get(base) ?? 0; counts.set(base, count + 1); return [ { id: count ? `${base}-${count}` : base, text, level: match[1].length, line: index + 1, }, ]; }); }