// ============================================================================ // Project : modelmap // File : site/lib/render.js // Purpose : HTML layout, markdown/code rendering, confidence-level widgets // Author : Simon-Pierre Boucher // Contact : contact@spboucher.ai // Website : https://modelmap.io // Created : 2026-08-12 // Modified : 2026-08-12 // Platform : macOS / Apple Silicon (arm64) — Node.js (deployed on MacLustr) // License : All rights reserved (research code) // ============================================================================ "use strict"; const { marked } = require("marked"); const hljs = require("highlight.js"); function esc(s) { return String(s).replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" }[c])); } // Rewrite relative markdown links to platform routes; highlight code blocks. const renderer = new marked.Renderer(); renderer.code = function ({ text, lang }) { let html; if (lang && hljs.getLanguage(lang)) { html = hljs.highlight(text, { language: lang }).value; } else { html = esc(text); } return `
${html}
`; }; function markdownToHtml(md, baseRel) { marked.use({ renderer, walkTokens(token) { if (token.type === "link" && token.href && !/^(https?:|mailto:|#|\/)/.test(token.href)) { const base = baseRel.includes("/") ? baseRel.slice(0, baseRel.lastIndexOf("/")) : ""; const joined = (base ? base + "/" : "") + token.href; const norm = joined.split("/").reduce((acc, part) => { if (part === "..") acc.pop(); else if (part !== "." && part !== "") acc.push(part); return acc; }, []).join("/"); token.href = norm.endsWith(".md") ? "/doc/" + norm : "/file/" + norm; } }, }); return marked.parse(md); } function highlightFile(text, filename) { const ext = filename.slice(filename.lastIndexOf(".") + 1).toLowerCase(); const langMap = { py: "python", sh: "bash", js: "javascript", css: "css", json: "json", toml: "ini", yaml: "yaml", yml: "yaml", cff: "yaml", md: "markdown", metal: "cpp", cpp: "cpp", h: "cpp", hpp: "cpp", swift: "swift", m: "objectivec", }; const lang = filename === "Makefile" ? "makefile" : langMap[ext]; if (lang && hljs.getLanguage(lang)) return hljs.highlight(text, { language: lang }).value; return esc(text); } const NAV = [ ["/", "Home"], ["/research", "Research"], ["/experiments", "Experiments"], ["/atlas", "Atlas"], ["/publications", "Publications"], ["/results", "Results"], ["/code", "Code"], ["/comments", "Comments"], ["/about", "About"], ]; const LEVELS = [ ["0", "anecdotal", "single run, no controls — never published alone"], ["1", "correlational", "controlled, replicated ≥3 seeds, ≥2 datasets"], ["2", "method-robust", "Level 1 + agreement across ≥2 independent techniques"], ["3", "causal", "Level 2 + intervention confirms the claim"], ]; /** Confidence badge for an atlas entry (null level → "unrated"). */ function levelBadge(level) { if (level === null || level === undefined) { return `unrated`; } return `Level ${level} — ${LEVELS[level][1]}`; } /** The confidence taxonomy ladder (used on Home / Atlas / About). */ function confidenceLadder() { return `
    ` + LEVELS.map( ([n, name, desc]) => `
  1. L${n}
    ${name}${desc}
  2. ` ).join("") + `
`; } /** Small inline SVG logo — contour lines, a nod to cartography. */ const LOGO = ``; function layout({ title, active, body, buildInfo = {} }) { const nav = NAV.map( ([href, label]) => `${label}` ).join(""); const commit = buildInfo.commit ? buildInfo.commit.slice(0, 7) : "dev"; const synced = buildInfo.generated ? buildInfo.generated.slice(0, 10) : ""; return ` ${esc(title)} · modelmap
${body}
`; } module.exports = { esc, markdownToHtml, highlightFile, layout, levelBadge, confidenceLadder, LEVELS };