import { readFileSync, writeFileSync } from 'node:fs'; import { marked } from 'marked'; import sanitizeHtml from 'sanitize-html'; const markdown = readFileSync(new URL('./release-notes.md', import.meta.url), 'utf8'); // Parse before sanitizing so escaped code stays literal while raw HTML is filtered. const content = sanitizeHtml(marked.parse(markdown, { gfm: true }), { allowedTags: [ 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p', 'br', 'hr', 'strong', 'em', 'del', 'blockquote', 'ul', 'ol', 'li', 'table', 'thead', 'tbody', 'tr', 'th', 'td', 'pre', 'code', 'a', ], allowedAttributes: { a: ['href', 'title'], code: ['class'], th: ['align'], td: ['align'], ol: ['start'], }, allowedClasses: { code: ['language-*'] }, allowedSchemes: ['https', 'http', 'mailto'], allowProtocolRelative: false, }); const html = ` Trail Notes — Release notes
${content}
`; writeFileSync(new URL('./page.html', import.meta.url), html); console.log('Generated page.html');