// A tiny Markdown renderer for the rules. It supports exactly what the rules use: #, ##, ### headings, // paragraphs, - and 1. lists (no nesting), **bold**, *italic*, `code`, pipe tables, --- and > quotes. // Everything is escaped first, so a rules file can never inject markup. import { esc } from "./desk.js"; function inline(text) { return esc(text) .replace(/`([^`]+)`/g, "$1") .replace(/\*\*([^*]+)\*\*/g, "$1") .replace(/(^|[^*\w])\*([^*\s][^*]*?)\*(?![*\w])/g, "$1$2"); } const cells = (line) => line.trim().replace(/^\||\|$/g, "").split("|").map((c) => c.trim()); export function renderMarkdown(src) { const lines = src.replace(/\r\n?/g, "\n").split("\n"); const out = []; let i = 0; while (i < lines.length) { const line = lines[i]; if (!line.trim()) { i++; continue; } const h = /^(#{1,3})\s+(.*)$/.exec(line); if (h) { out.push(`${inline(h[2])}`); i++; continue; } if (/^-{3,}\s*$/.test(line)) { out.push("
"); i++; continue; } if (/^\|.*\|\s*$/.test(line) && /^\|[\s:|-]+\|\s*$/.test(lines[i + 1] ?? "")) { const head = cells(line); i += 2; const rows = []; while (i < lines.length && /^\|.*\|\s*$/.test(lines[i])) rows.push(cells(lines[i++])); out.push( `${head.map((c) => ``).join("")}` + `${rows.map((r) => `${r.map((c) => ``).join("")}`).join("")}
${inline(c)}
${inline(c)}
`, ); continue; } if (/^>\s?/.test(line)) { const quote = []; while (i < lines.length && /^>\s?/.test(lines[i])) quote.push(lines[i++].replace(/^>\s?/, "")); out.push(`
${quote.map(inline).join(" ")}
`); continue; } const list = /^(-|\d+\.)\s+/.exec(line); if (list) { const tag = list[1] === "-" ? "ul" : "ol"; const re = tag === "ul" ? /^-\s+(.*)$/ : /^\d+\.\s+(.*)$/; const items = []; while (i < lines.length && re.test(lines[i])) items.push(re.exec(lines[i++])[1]); out.push(`<${tag}>${items.map((x) => `
  • ${inline(x)}
  • `).join("")}`); continue; } const para = []; while (i < lines.length && lines[i].trim() && !/^(#{1,3}\s|-{3,}\s*$|>|\||(-|\d+\.)\s)/.test(lines[i])) para.push(lines[i++]); out.push(`

    ${inline(para.join(" "))}

    `); } return out.join("\n"); }