import { readFileSync, writeFileSync } from 'node:fs' import { dirname, join } from 'node:path' const src = readFileSync(process.argv[2], 'utf8') const out = process.argv[3] const esc = (s) => s.replace(/&/g, '&').replace(//g, '>') const inline = (s) => esc(s) .replace(/`([^`]+)`/g, '$1') .replace(/\*\*([^*]+)\*\*/g, '$1') .replace(/\*([^*]+)\*/g, '$1') .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '$1') .replace(/→/g, '→') const slug = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, '') const lines = src.split('\n') let html = [] const toc = [] let i = 0 let para = [] const flushPara = () => { if (para.length) { html.push(`

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

`) para = [] } } let titleLine = null let subtitle = null let meta = null while (i < lines.length) { const line = lines[i] if (line.startsWith('```')) { flushPara() const lang = line.slice(3).trim() const buf = [] i++ while (i < lines.length && !lines[i].startsWith('```')) buf.push(lines[i++]) i++ if (lang === 'mermaid') html.push(`
${esc(buf.join('\n'))}
`) else html.push(`
${esc(buf.join('\n'))}
`) continue } if (/^#{1,3} /.test(line)) { flushPara() const level = line.match(/^#+/)[0].length const text = line.replace(/^#+ /, '') if (level === 1 && titleLine === null) { titleLine = text; i++; continue } const id = slug(text) if (level === 2) toc.push({ id, text }) html.push(`${inline(text)}`) i++ continue } if (line.startsWith('|')) { flushPara() const rows = [] while (i < lines.length && lines[i].startsWith('|')) rows.push(lines[i++]) const cells = (r) => r.replace(/^\|/, '').replace(/\|$/, '').split('|').map((c) => c.trim()) const head = cells(rows[0]) const body = rows.slice(2).map(cells) let t = '
' + head.map((h) => ``).join('') + '' for (const r of body) t += '' + r.map((c) => ``).join('') + '' t += '
${inline(h)}
${inline(c)}
' html.push(t) continue } if (/^[-*] /.test(line) || /^\d+\. /.test(line)) { flushPara() const ordered = /^\d+\. /.test(line) const items = [] while (i < lines.length && (/^[-*] /.test(lines[i]) || /^\d+\. /.test(lines[i]))) { let item = lines[i].replace(/^([-*]|\d+\.) /, '') i++ while (i < lines.length && /^\s{2,}\S/.test(lines[i])) item += ' ' + lines[i++].trim() items.push(item) } const tag = ordered ? 'ol' : 'ul' html.push(`<${tag}>` + items.map((it) => `
  • ${inline(it)}
  • `).join('') + ``) continue } if (/^!\[[^\]]*\]\([^)]+\)$/.test(line.trim())) { flushPara() const m = line.trim().match(/^!\[([^\]]*)\]\(([^)]+)\)$/) const data = readFileSync(join(dirname(process.argv[2]), m[2])).toString('base64') html.push(`
    ${esc(m[1])}
    `) i++ continue } if (line.trim() === '---') { flushPara(); html.push('
    '); i++; continue } if (line.trim() === '') { flushPara(); i++; continue } if (titleLine !== null && subtitle === null && line.startsWith('**')) { subtitle = line.replace(/\*\*/g, ''); i++; continue } if (subtitle !== null && meta === null && line.startsWith('*')) { meta = line.replace(/^\*|\*$/g, ''); i++; continue } para.push(line.trim()) i++ } flushPara() // drop the first hr (after meta) const firstHr = html.indexOf('
    ') if (firstHr === 0) html.splice(0, 1) const metaParts = (meta || '').split('·').map((s) => s.trim()) const page = `${process.env.PAGE_LANG ? `` : ''}${process.env.PAGE_TITLE || 'VPP AI Platform Architecture'}
    ${process.env.PAGE_EYEBROW ? `

    ${process.env.PAGE_EYEBROW}

    ` : ''}

    ${inline(titleLine.trim())}

    ${inline(subtitle || '')}

    ${meta ? `
    ${metaParts.map((m) => `${inline(m)}`).join('')}
    ` : ''}
    ${html.join('\n')}
    ` writeFileSync(out, page) console.log('wrote', out, page.length, 'bytes; toc', toc.length)