@pre-markdown/renderer 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @pre-markdown/renderer\n *\n * Renders AST to DOM (HTML string) or DOM nodes.\n */\n\nimport type {\n Document,\n BlockNode,\n InlineNode,\n ASTNode,\n Heading,\n Paragraph,\n Blockquote,\n List,\n ListItem,\n CodeBlock,\n ThematicBreak,\n HtmlBlock,\n Table,\n TableRow,\n TableCell,\n MathBlock,\n Container,\n Details,\n TOC,\n Text,\n Emphasis,\n Strong,\n Strikethrough,\n InlineCode,\n Link,\n Image,\n Break,\n SoftBreak,\n MathInline,\n Highlight,\n Superscript,\n Subscript,\n FontColor,\n FontSize,\n FontBgColor,\n HtmlInline,\n FootnoteReference,\n Autolink,\n Audio,\n Video,\n Ruby,\n Emoji,\n} from '@pre-markdown/core'\nimport type { PluginManager, RenderContext } from '@pre-markdown/core'\n\n/** Renderer options */\nexport interface RendererOptions {\n /** Sanitize HTML output (default: true) */\n sanitize?: boolean\n /** Enable syntax highlighting for code blocks */\n highlight?: (code: string, lang?: string) => string\n /** Custom heading ID generator (null = no id attribute, default: null) */\n headingId?: ((text: string, depth: number) => string) | null\n /** Base URL for relative links */\n baseUrl?: string\n /** Inline parser for lazy-parsed nodes (nodes with _raw) */\n inlineParser?: ((raw: string) => InlineNode[]) | null\n /** Plugin manager for render hooks */\n plugins?: PluginManager | null\n}\n\n// ============================================================\n// Fast escapeHtml — single-pass scan, no intermediate strings\n// ============================================================\n\nconst ESCAPE_HTML_RE = /[&<>\"]/\n\nfunction escapeHtml(str: string): string {\n // Fast path: no special chars → return original (zero-copy)\n if (!ESCAPE_HTML_RE.test(str)) return str\n\n let out = ''\n let last = 0\n for (let i = 0; i < str.length; i++) {\n const ch = str.charCodeAt(i)\n let esc: string | undefined\n if (ch === 38) esc = '&amp;' // &\n else if (ch === 60) esc = '&lt;' // <\n else if (ch === 62) esc = '&gt;' // >\n else if (ch === 34) esc = '&quot;' // \"\n if (esc !== undefined) {\n if (last < i) out += str.slice(last, i)\n out += esc\n last = i + 1\n }\n }\n if (last === 0) return str\n if (last < str.length) out += str.slice(last)\n return out\n}\n\nfunction escapeAttr(str: string): string {\n if (!ESCAPE_HTML_RE.test(str) && !str.includes(\"'\")) return str\n\n let out = ''\n let last = 0\n for (let i = 0; i < str.length; i++) {\n const ch = str.charCodeAt(i)\n let esc: string | undefined\n if (ch === 38) esc = '&amp;'\n else if (ch === 34) esc = '&quot;'\n else if (ch === 39) esc = '&#39;'\n else if (ch === 60) esc = '&lt;'\n else if (ch === 62) esc = '&gt;'\n if (esc !== undefined) {\n if (last < i) out += str.slice(last, i)\n out += esc\n last = i + 1\n }\n }\n if (last === 0) return str\n if (last < str.length) out += str.slice(last)\n return out\n}\n\n// ============================================================\n// Main renderer\n// ============================================================\n\n/**\n * Render a Document AST to an HTML string.\n */\nexport function renderToHtml(doc: Document, options?: RendererOptions): string {\n const opts: Required<RendererOptions> = {\n sanitize: true,\n highlight: escapeHtml,\n headingId: null,\n baseUrl: '',\n inlineParser: null,\n plugins: null,\n ...options,\n }\n\n // Apply plugin transform hooks before rendering\n let finalDoc = doc\n if (opts.plugins && opts.plugins.hasTransformHooks()) {\n finalDoc = opts.plugins.applyTransforms(doc)\n }\n\n return renderBlockNodes(finalDoc.children, opts)\n}\n\n/**\n * Resolve lazy inline content: if a node has _raw and empty children,\n * parse the raw text and cache the result in children.\n */\nfunction resolveInline(\n node: { children: InlineNode[]; _raw?: string },\n opts: Required<RendererOptions>,\n): InlineNode[] {\n if (node._raw !== undefined && node.children.length === 0 && opts.inlineParser) {\n node.children = opts.inlineParser(node._raw)\n // Clear _raw after resolution to avoid double parsing\n node._raw = undefined\n }\n return node.children\n}\n\nfunction renderBlockNodes(nodes: BlockNode[], opts: Required<RendererOptions>): string {\n // Use array + join for many nodes (faster than += for > 3 elements)\n const len = nodes.length\n if (len === 0) return ''\n if (len === 1) return renderBlockNode(nodes[0]!, opts)\n const parts: string[] = new Array(len)\n for (let i = 0; i < len; i++) {\n parts[i] = renderBlockNode(nodes[i]!, opts)\n }\n return parts.join('')\n}\n\nfunction renderBlockNode(node: BlockNode, opts: Required<RendererOptions>): string {\n // Plugin render hook dispatch\n if (opts.plugins && opts.plugins.hasRenderHook(node.type)) {\n const defaultHtml = renderBlockNodeDefault(node, opts)\n const pluginResult = opts.plugins.tryRender({\n node,\n defaultHtml,\n renderChildren: (children) => {\n // Determine if children are block or inline\n if (children.length > 0 && 'type' in children[0]!) {\n const first = children[0] as any\n if (first.type === 'text' || first.type === 'emphasis' || first.type === 'strong' ||\n first.type === 'inlineCode' || first.type === 'link' || first.type === 'image') {\n return renderInlineNodes(children as InlineNode[], opts)\n }\n }\n return renderBlockNodes(children as BlockNode[], opts)\n },\n })\n if (pluginResult !== undefined) return pluginResult\n return defaultHtml\n }\n return renderBlockNodeDefault(node, opts)\n}\n\nfunction renderBlockNodeDefault(node: BlockNode, opts: Required<RendererOptions>): string {\n switch (node.type) {\n case 'heading':\n return renderHeading(node, opts)\n case 'paragraph':\n return renderParagraph(node, opts)\n case 'blockquote':\n return renderBlockquote(node, opts)\n case 'list':\n return renderList(node, opts)\n case 'listItem':\n return renderListItem(node, opts)\n case 'codeBlock':\n return renderCodeBlock(node, opts)\n case 'thematicBreak':\n return '<hr />\\n'\n case 'htmlBlock':\n return (opts.sanitize ? escapeHtml(node.value) : node.value) + '\\n'\n case 'table':\n return renderTable(node, opts)\n case 'tableRow':\n return ''\n case 'tableCell':\n return '<td>' + renderInlineNodes(resolveInline(node, opts), opts) + '</td>'\n case 'mathBlock':\n return '<div class=\"math-block\">' + escapeHtml(node.value) + '</div>\\n'\n case 'container':\n return renderContainer(node, opts)\n case 'details':\n return renderDetails(node, opts)\n case 'toc':\n return '<nav class=\"toc\" data-toc></nav>\\n'\n case 'footnoteDefinition':\n return '<div class=\"footnote\" id=\"fn-' + escapeHtml(node.identifier) + '\"><sup>' + escapeHtml(node.label) + '</sup>' + renderBlockNodes(node.children, opts) + '</div>\\n'\n default:\n return ''\n }\n}\n\nfunction renderHeading(node: Heading, opts: Required<RendererOptions>): string {\n const children = resolveInline(node, opts)\n const inner = renderInlineNodes(children, opts)\n if (opts.headingId) {\n const text = getPlainText(children)\n const id = opts.headingId(text, node.depth)\n if (id) return '<h' + node.depth + ' id=\"' + escapeAttr(id) + '\">' + inner + '</h' + node.depth + '>\\n'\n }\n return '<h' + node.depth + '>' + inner + '</h' + node.depth + '>\\n'\n}\n\nfunction renderParagraph(node: Paragraph, opts: Required<RendererOptions>): string {\n return '<p>' + renderInlineNodes(resolveInline(node, opts), opts) + '</p>\\n'\n}\n\nfunction renderBlockquote(node: Blockquote, opts: Required<RendererOptions>): string {\n return '<blockquote>\\n' + renderBlockNodes(node.children, opts) + '</blockquote>\\n'\n}\n\nfunction renderList(node: List, opts: Required<RendererOptions>): string {\n const tag = node.ordered ? 'ol' : 'ul'\n const startAttr = node.ordered && node.start !== undefined && node.start !== 1\n ? ' start=\"' + node.start + '\"'\n : ''\n const len = node.children.length\n const parts: string[] = new Array(len)\n const loose = node.spread\n for (let i = 0; i < len; i++) {\n parts[i] = renderListItem(node.children[i]!, opts, loose)\n }\n return '<' + tag + startAttr + '>\\n' + parts.join('') + '</' + tag + '>\\n'\n}\n\nfunction renderListItem(node: ListItem, opts: Required<RendererOptions>, loose = true): string {\n let content: string\n\n if (!loose && node.children.length === 1 && node.children[0]!.type === 'paragraph') {\n content = renderInlineNodes(resolveInline(node.children[0] as Paragraph, opts), opts)\n } else if (!loose && node.children.every(c => c.type === 'paragraph')) {\n content = node.children\n .map(c => renderInlineNodes(resolveInline(c as Paragraph, opts), opts))\n .join('\\n')\n } else {\n content = '\\n' + renderBlockNodes(node.children, opts)\n }\n\n if (node.checked !== undefined) {\n const checked = node.checked ? ' checked disabled' : ' disabled'\n return '<li class=\"task-list-item\"><input type=\"checkbox\"' + checked + ' /> ' + content + '</li>\\n'\n }\n\n return '<li>' + content + '</li>\\n'\n}\n\nfunction renderCodeBlock(node: CodeBlock, opts: Required<RendererOptions>): string {\n let code = node.value\n if (code.length > 0 && code.charCodeAt(code.length - 1) !== 10) {\n code += '\\n'\n }\n const highlighted = opts.highlight(code, node.lang)\n if (node.lang) {\n return '<pre><code class=\"language-' + escapeAttr(node.lang) + '\">' + highlighted + '</code></pre>\\n'\n }\n return '<pre><code>' + highlighted + '</code></pre>\\n'\n}\n\nfunction renderTable(node: Table, opts: Required<RendererOptions>): string {\n const parts: string[] = ['<table>']\n let inHeader = true\n\n for (let i = 0; i < node.children.length; i++) {\n const row = node.children[i]!\n if (row.isHeader) {\n if (i === 0) parts.push('<thead>')\n } else if (inHeader) {\n parts.push('</thead><tbody>')\n inHeader = false\n }\n parts.push('<tr>')\n const cellTag = row.isHeader ? 'th' : 'td'\n for (let j = 0; j < row.children.length; j++) {\n const cell = row.children[j]!\n const align = node.align[j]\n const cellChildren = resolveInline(cell, opts)\n if (align) {\n parts.push('<' + cellTag + ' style=\"text-align:' + align + '\">' + renderInlineNodes(cellChildren, opts) + '</' + cellTag + '>')\n } else {\n parts.push('<' + cellTag + '>' + renderInlineNodes(cellChildren, opts) + '</' + cellTag + '>')\n }\n }\n parts.push('</tr>')\n }\n\n if (inHeader && node.children.some(r => r.isHeader)) {\n parts.push('</thead>')\n } else if (!inHeader) {\n parts.push('</tbody>')\n }\n parts.push('</table>\\n')\n return parts.join('')\n}\n\nfunction renderContainer(node: Container, opts: Required<RendererOptions>): string {\n const title = node.title ? '<p class=\"container-title\">' + escapeHtml(node.title) + '</p>' : ''\n return '<div class=\"container container-' + escapeAttr(node.kind) + '\">' + title + renderBlockNodes(node.children, opts) + '</div>\\n'\n}\n\nfunction renderDetails(node: Details, opts: Required<RendererOptions>): string {\n return '<details><summary>' + escapeHtml(node.summary) + '</summary>' + renderBlockNodes(node.children, opts) + '</details>\\n'\n}\n\n// ============================================================\n// Inline Rendering — optimized with string concat (faster than template literals for hot path)\n// ============================================================\n\nfunction renderInlineNodes(nodes: InlineNode[], opts: Required<RendererOptions>): string {\n const len = nodes.length\n if (len === 0) return ''\n if (len === 1) return renderInlineNode(nodes[0]!, opts)\n let out = ''\n for (let i = 0; i < len; i++) {\n out += renderInlineNode(nodes[i]!, opts)\n }\n return out\n}\n\nfunction renderInlineNode(node: InlineNode, opts: Required<RendererOptions>): string {\n // Plugin render hook dispatch\n if (opts.plugins && opts.plugins.hasRenderHook(node.type)) {\n const defaultHtml = renderInlineNodeDefault(node, opts)\n const pluginResult = opts.plugins.tryRender({\n node,\n defaultHtml,\n renderChildren: (children) => renderInlineNodes(children as InlineNode[], opts),\n })\n if (pluginResult !== undefined) return pluginResult\n return defaultHtml\n }\n return renderInlineNodeDefault(node, opts)\n}\n\nfunction renderInlineNodeDefault(node: InlineNode, opts: Required<RendererOptions>): string {\n switch (node.type) {\n case 'text':\n return escapeHtml(node.value)\n case 'emphasis':\n return '<em>' + renderInlineNodes(node.children, opts) + '</em>'\n case 'strong':\n return '<strong>' + renderInlineNodes(node.children, opts) + '</strong>'\n case 'strikethrough':\n return '<del>' + renderInlineNodes(node.children, opts) + '</del>'\n case 'inlineCode':\n return '<code>' + escapeHtml(node.value) + '</code>'\n case 'link': {\n const safeUrl = opts.sanitize ? sanitizeUrl(node.url) : node.url\n let r = '<a href=\"' + escapeAttr(encodeUrl(safeUrl)) + '\"'\n if (node.title) r += ' title=\"' + escapeAttr(node.title) + '\"'\n return r + '>' + renderInlineNodes(node.children, opts) + '</a>'\n }\n case 'image': {\n const safeSrc = opts.sanitize ? sanitizeUrl(node.url) : node.url\n let r = '<img src=\"' + escapeAttr(encodeUrl(safeSrc)) + '\" alt=\"' + escapeAttr(node.alt) + '\"'\n if (node.title) r += ' title=\"' + escapeAttr(node.title) + '\"'\n if (node.width) r += ' width=\"' + node.width + '\"'\n if (node.height) r += ' height=\"' + node.height + '\"'\n return r + ' />'\n }\n case 'htmlInline':\n return opts.sanitize ? escapeHtml(node.value) : node.value\n case 'break':\n return '<br />\\n'\n case 'softBreak':\n return '\\n'\n case 'footnoteReference':\n return '<sup class=\"footnote-ref\"><a href=\"#fn-' + escapeAttr(node.identifier) + '\">[' + escapeHtml(node.label) + ']</a></sup>'\n case 'mathInline':\n return '<span class=\"math-inline\">' + escapeHtml(node.value) + '</span>'\n case 'highlight':\n return '<mark>' + renderInlineNodes(node.children, opts) + '</mark>'\n case 'superscript':\n return '<sup>' + renderInlineNodes(node.children, opts) + '</sup>'\n case 'subscript':\n return '<sub>' + renderInlineNodes(node.children, opts) + '</sub>'\n case 'fontColor': {\n const safeColor = opts.sanitize ? sanitizeCssValue(node.color) : node.color\n return '<span style=\"color:' + escapeAttr(safeColor) + '\">' + renderInlineNodes(node.children, opts) + '</span>'\n }\n case 'fontSize': {\n const safeSize = opts.sanitize ? sanitizeCssValue(node.size) : node.size\n return '<span style=\"font-size:' + escapeAttr(safeSize) + '\">' + renderInlineNodes(node.children, opts) + '</span>'\n }\n case 'fontBgColor': {\n const safeBgColor = opts.sanitize ? sanitizeCssValue(node.color) : node.color\n return '<span style=\"background-color:' + escapeAttr(safeBgColor) + '\">' + renderInlineNodes(node.children, opts) + '</span>'\n }\n case 'ruby':\n return '<ruby>' + escapeHtml(node.base) + '<rp>(</rp><rt>' + escapeHtml(node.annotation) + '</rt><rp>)</rp></ruby>'\n case 'emoji':\n return node.value\n case 'audio': {\n const safeAudioUrl = opts.sanitize ? sanitizeUrl(node.url) : node.url\n let r = '<audio controls preload=\"metadata\" src=\"' + escapeAttr(safeAudioUrl) + '\"'\n if (node.title) r += ' title=\"' + escapeAttr(node.title) + '\"'\n const audioAlt = node.title || 'Audio'\n return r + '>' + escapeHtml(audioAlt) + '</audio>'\n }\n case 'video': {\n const safeVideoUrl = opts.sanitize ? sanitizeUrl(node.url) : node.url\n let r = '<video controls preload=\"metadata\" src=\"' + escapeAttr(safeVideoUrl) + '\"'\n if (node.title) r += ' title=\"' + escapeAttr(node.title) + '\"'\n const videoAlt = node.title || 'Video'\n return r + '>' + escapeHtml(videoAlt) + '</video>'\n }\n case 'autolink':\n return '<a href=\"' + escapeAttr(node.url) + '\">' + escapeHtml(node.url.replace(/^mailto:/, '')) + '</a>'\n case 'underline':\n return '<span style=\"text-decoration:underline\">' + renderInlineNodes(node.children, opts) + '</span>'\n default:\n return ''\n }\n}\n\n// ============================================================\n// Utility Functions\n// ============================================================\n\n/** Sanitize a URL — block dangerous protocols */\nfunction sanitizeUrl(url: string): string {\n const trimmed = url.trim().toLowerCase()\n if (\n trimmed.startsWith('javascript:') ||\n trimmed.startsWith('vbscript:') ||\n (trimmed.startsWith('data:') && !trimmed.startsWith('data:image/'))\n ) {\n return ''\n }\n return url\n}\n\n/** Percent-encode non-ASCII and special chars in URLs (CommonMark spec) */\nfunction encodeUrl(url: string): string {\n // Encode chars that are not in the URL-safe set\n // But preserve already-encoded %XX sequences and common URL chars\n try {\n // encodeURI handles most cases but doesn't encode some chars CommonMark needs\n return url.replace(/[^\\x21-\\x7E]/g, (ch) => {\n try {\n return encodeURIComponent(ch)\n } catch {\n return ch\n }\n })\n } catch {\n return url\n }\n}\n\n/** Sanitize a CSS value — strip anything that looks like script injection */\nfunction sanitizeCssValue(value: string): string {\n return value\n .replace(/expression\\s*\\(/gi, '')\n .replace(/url\\s*\\(/gi, '')\n .replace(/javascript\\s*:/gi, '')\n .replace(/;[^}]*$/g, '')\n}\n\nfunction getPlainText(nodes: InlineNode[]): string {\n let out = ''\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!\n if (node.type === 'text') out += node.value\n else if (node.type === 'inlineCode') out += node.value\n else if ('children' in node) out += getPlainText(node.children)\n }\n return out\n}\n\n// ============================================================\n// DOM Renderer — creates real DOM nodes, skips innerHTML parse\n// ============================================================\n\n/**\n * Render a Document AST directly to DOM nodes.\n * Faster than renderToHtml + innerHTML for incremental updates.\n */\nexport function renderToDOM(doc: Document, options?: RendererOptions): DocumentFragment {\n const opts: Required<RendererOptions> = {\n sanitize: true,\n highlight: escapeHtml,\n headingId: null,\n baseUrl: '',\n inlineParser: null,\n plugins: null,\n ...options,\n }\n\n // Apply plugin transform hooks before rendering\n let finalDoc = doc\n if (opts.plugins && opts.plugins.hasTransformHooks()) {\n finalDoc = opts.plugins.applyTransforms(doc)\n }\n\n const frag = document.createDocumentFragment()\n for (let i = 0; i < finalDoc.children.length; i++) {\n const el = renderBlockToDOM(finalDoc.children[i]!, opts)\n if (el) frag.appendChild(el)\n }\n return frag\n}\n\nfunction renderBlockToDOM(node: BlockNode, opts: Required<RendererOptions>): Node | null {\n switch (node.type) {\n case 'heading': {\n const el = document.createElement('h' + node.depth)\n const children = resolveInline(node, opts)\n appendInlineToDOM(el, children, opts)\n if (opts.headingId) {\n const text = getPlainText(children)\n const id = opts.headingId(text, node.depth)\n if (id) el.setAttribute('id', id)\n }\n return el\n }\n case 'paragraph': {\n const el = document.createElement('p')\n appendInlineToDOM(el, resolveInline(node, opts), opts)\n return el\n }\n case 'blockquote': {\n const el = document.createElement('blockquote')\n appendBlocksToDOM(el, node.children, opts)\n return el\n }\n case 'list': {\n const el = document.createElement(node.ordered ? 'ol' : 'ul')\n if (node.ordered && node.start !== undefined && node.start !== 1) {\n el.setAttribute('start', String(node.start))\n }\n for (let i = 0; i < node.children.length; i++) {\n const li = renderListItemToDOM(node.children[i]!, opts, node.spread)\n if (li) el.appendChild(li)\n }\n return el\n }\n case 'codeBlock': {\n const pre = document.createElement('pre')\n const code = document.createElement('code')\n if (node.lang) code.className = 'language-' + node.lang\n let content = node.value\n if (content.length > 0 && content.charCodeAt(content.length - 1) !== 10) {\n content += '\\n'\n }\n code.innerHTML = opts.highlight(content, node.lang)\n pre.appendChild(code)\n return pre\n }\n case 'thematicBreak':\n return document.createElement('hr')\n case 'htmlBlock': {\n if (opts.sanitize) {\n const span = document.createElement('span')\n span.textContent = node.value\n return span\n }\n const tmpl = document.createElement('template')\n tmpl.innerHTML = node.value\n return tmpl.content\n }\n case 'table':\n return renderTableToDOM(node, opts)\n case 'mathBlock': {\n const div = document.createElement('div')\n div.className = 'math-block'\n div.textContent = node.value\n return div\n }\n case 'container': {\n const div = document.createElement('div')\n div.className = 'container container-' + node.kind\n if (node.title) {\n const p = document.createElement('p')\n p.className = 'container-title'\n p.textContent = node.title\n div.appendChild(p)\n }\n appendBlocksToDOM(div, node.children, opts)\n return div\n }\n case 'details': {\n const details = document.createElement('details')\n const summary = document.createElement('summary')\n summary.textContent = node.summary\n details.appendChild(summary)\n appendBlocksToDOM(details, node.children, opts)\n return details\n }\n case 'toc': {\n const nav = document.createElement('nav')\n nav.className = 'toc'\n nav.setAttribute('data-toc', '')\n return nav\n }\n case 'footnoteDefinition': {\n const div = document.createElement('div')\n div.className = 'footnote'\n div.id = 'fn-' + node.identifier\n const sup = document.createElement('sup')\n sup.textContent = node.label\n div.appendChild(sup)\n appendBlocksToDOM(div, node.children, opts)\n return div\n }\n default:\n return null\n }\n}\n\nfunction renderListItemToDOM(node: ListItem, opts: Required<RendererOptions>, loose: boolean): HTMLElement {\n const li = document.createElement('li')\n if (node.checked !== undefined) {\n li.className = 'task-list-item'\n const cb = document.createElement('input')\n cb.type = 'checkbox'\n cb.disabled = true\n if (node.checked) cb.checked = true\n li.appendChild(cb)\n li.appendChild(document.createTextNode(' '))\n }\n\n if (!loose && node.children.length === 1 && node.children[0]!.type === 'paragraph') {\n appendInlineToDOM(li, resolveInline(node.children[0] as Paragraph, opts), opts)\n } else if (!loose && node.children.every(c => c.type === 'paragraph')) {\n for (let i = 0; i < node.children.length; i++) {\n if (i > 0) li.appendChild(document.createTextNode('\\n'))\n appendInlineToDOM(li, resolveInline(node.children[i] as Paragraph, opts), opts)\n }\n } else {\n appendBlocksToDOM(li, node.children, opts)\n }\n return li\n}\n\nfunction renderTableToDOM(node: Table, opts: Required<RendererOptions>): HTMLElement {\n const table = document.createElement('table')\n let thead: HTMLElement | null = null\n let tbody: HTMLElement | null = null\n\n for (let i = 0; i < node.children.length; i++) {\n const row = node.children[i]!\n const tr = document.createElement('tr')\n\n for (let j = 0; j < row.children.length; j++) {\n const cell = row.children[j]!\n const cellEl = document.createElement(row.isHeader ? 'th' : 'td')\n const align = node.align[j]\n if (align) cellEl.style.textAlign = align\n appendInlineToDOM(cellEl, resolveInline(cell, opts), opts)\n tr.appendChild(cellEl)\n }\n\n if (row.isHeader) {\n if (!thead) { thead = document.createElement('thead'); table.appendChild(thead) }\n thead.appendChild(tr)\n } else {\n if (!tbody) { tbody = document.createElement('tbody'); table.appendChild(tbody) }\n tbody.appendChild(tr)\n }\n }\n\n return table\n}\n\nfunction appendBlocksToDOM(parent: Node, blocks: BlockNode[], opts: Required<RendererOptions>): void {\n for (let i = 0; i < blocks.length; i++) {\n const el = renderBlockToDOM(blocks[i]!, opts)\n if (el) parent.appendChild(el)\n }\n}\n\nfunction appendInlineToDOM(parent: Node, nodes: InlineNode[], opts: Required<RendererOptions>): void {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!\n const el = renderInlineToDOM(node, opts)\n if (el) parent.appendChild(el)\n }\n}\n\nfunction renderInlineToDOM(node: InlineNode, opts: Required<RendererOptions>): Node | null {\n switch (node.type) {\n case 'text':\n return document.createTextNode(node.value)\n case 'emphasis': {\n const em = document.createElement('em')\n appendInlineToDOM(em, node.children, opts)\n return em\n }\n case 'strong': {\n const strong = document.createElement('strong')\n appendInlineToDOM(strong, node.children, opts)\n return strong\n }\n case 'strikethrough': {\n const del = document.createElement('del')\n appendInlineToDOM(del, node.children, opts)\n return del\n }\n case 'inlineCode': {\n const code = document.createElement('code')\n code.textContent = node.value\n return code\n }\n case 'link': {\n const a = document.createElement('a')\n const safeUrl = opts.sanitize ? sanitizeUrl(node.url) : node.url\n a.href = encodeUrl(opts.baseUrl ? opts.baseUrl + safeUrl : safeUrl)\n if (node.title) a.title = node.title\n appendInlineToDOM(a, node.children, opts)\n return a\n }\n case 'image': {\n const img = document.createElement('img')\n const safeSrc = opts.sanitize ? sanitizeUrl(node.url) : node.url\n img.src = encodeUrl(opts.baseUrl ? opts.baseUrl + safeSrc : safeSrc)\n img.alt = node.alt\n if (node.title) img.title = node.title\n return img\n }\n case 'break':\n return document.createElement('br')\n case 'softBreak':\n return document.createTextNode('\\n')\n case 'htmlInline': {\n if (opts.sanitize) return document.createTextNode(node.value)\n const span = document.createElement('span')\n span.innerHTML = node.value\n return span\n }\n case 'mathInline': {\n const span = document.createElement('span')\n span.className = 'math-inline'\n span.textContent = node.value\n return span\n }\n case 'highlight': {\n const mark = document.createElement('mark')\n appendInlineToDOM(mark, node.children, opts)\n return mark\n }\n case 'superscript': {\n const sup = document.createElement('sup')\n appendInlineToDOM(sup, node.children, opts)\n return sup\n }\n case 'subscript': {\n const sub = document.createElement('sub')\n appendInlineToDOM(sub, node.children, opts)\n return sub\n }\n case 'fontColor': {\n const span = document.createElement('span')\n span.style.color = opts.sanitize ? sanitizeCssValue(node.color) : node.color\n appendInlineToDOM(span, node.children, opts)\n return span\n }\n case 'fontSize': {\n const span = document.createElement('span')\n const size = /^\\d+$/.test(node.size) ? node.size + 'px' : node.size\n span.style.fontSize = opts.sanitize ? sanitizeCssValue(size) : size\n appendInlineToDOM(span, node.children, opts)\n return span\n }\n case 'fontBgColor': {\n const span = document.createElement('span')\n span.style.backgroundColor = opts.sanitize ? sanitizeCssValue(node.color) : node.color\n appendInlineToDOM(span, node.children, opts)\n return span\n }\n case 'footnoteReference': {\n const sup = document.createElement('sup')\n const a = document.createElement('a')\n a.href = '#fn-' + node.identifier\n a.className = 'footnote-ref'\n a.textContent = node.label\n sup.appendChild(a)\n return sup\n }\n case 'autolink': {\n const a = document.createElement('a')\n a.href = node.isEmail ? 'mailto:' + node.url : node.url\n a.textContent = node.url\n return a\n }\n case 'emoji': {\n const span = document.createElement('span')\n span.className = 'emoji'\n span.textContent = node.value || ':' + node.shortcode + ':'\n return span\n }\n case 'ruby': {\n const ruby = document.createElement('ruby')\n ruby.appendChild(document.createTextNode(node.base))\n const rp1 = document.createElement('rp')\n rp1.textContent = '('\n ruby.appendChild(rp1)\n const rt = document.createElement('rt')\n rt.textContent = node.annotation\n ruby.appendChild(rt)\n const rp2 = document.createElement('rp')\n rp2.textContent = ')'\n ruby.appendChild(rp2)\n return ruby\n }\n case 'audio': {\n const audio = document.createElement('audio')\n audio.controls = true\n audio.preload = 'metadata'\n audio.src = node.url\n audio.textContent = node.title || 'Audio'\n return audio\n }\n case 'video': {\n const video = document.createElement('video')\n video.controls = true\n video.preload = 'metadata'\n video.src = node.url\n video.textContent = node.title || 'Video'\n return video\n }\n case 'underline': {\n const u = document.createElement('u')\n appendInlineToDOM(u, node.children, opts)\n return u\n }\n default:\n return null\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,34 @@
1
+ import { InlineNode, PluginManager, Document } from '@pre-markdown/core';
2
+
3
+ /**
4
+ * @pre-markdown/renderer
5
+ *
6
+ * Renders AST to DOM (HTML string) or DOM nodes.
7
+ */
8
+
9
+ /** Renderer options */
10
+ interface RendererOptions {
11
+ /** Sanitize HTML output (default: true) */
12
+ sanitize?: boolean;
13
+ /** Enable syntax highlighting for code blocks */
14
+ highlight?: (code: string, lang?: string) => string;
15
+ /** Custom heading ID generator (null = no id attribute, default: null) */
16
+ headingId?: ((text: string, depth: number) => string) | null;
17
+ /** Base URL for relative links */
18
+ baseUrl?: string;
19
+ /** Inline parser for lazy-parsed nodes (nodes with _raw) */
20
+ inlineParser?: ((raw: string) => InlineNode[]) | null;
21
+ /** Plugin manager for render hooks */
22
+ plugins?: PluginManager | null;
23
+ }
24
+ /**
25
+ * Render a Document AST to an HTML string.
26
+ */
27
+ declare function renderToHtml(doc: Document, options?: RendererOptions): string;
28
+ /**
29
+ * Render a Document AST directly to DOM nodes.
30
+ * Faster than renderToHtml + innerHTML for incremental updates.
31
+ */
32
+ declare function renderToDOM(doc: Document, options?: RendererOptions): DocumentFragment;
33
+
34
+ export { type RendererOptions, renderToDOM, renderToHtml };
@@ -0,0 +1,34 @@
1
+ import { InlineNode, PluginManager, Document } from '@pre-markdown/core';
2
+
3
+ /**
4
+ * @pre-markdown/renderer
5
+ *
6
+ * Renders AST to DOM (HTML string) or DOM nodes.
7
+ */
8
+
9
+ /** Renderer options */
10
+ interface RendererOptions {
11
+ /** Sanitize HTML output (default: true) */
12
+ sanitize?: boolean;
13
+ /** Enable syntax highlighting for code blocks */
14
+ highlight?: (code: string, lang?: string) => string;
15
+ /** Custom heading ID generator (null = no id attribute, default: null) */
16
+ headingId?: ((text: string, depth: number) => string) | null;
17
+ /** Base URL for relative links */
18
+ baseUrl?: string;
19
+ /** Inline parser for lazy-parsed nodes (nodes with _raw) */
20
+ inlineParser?: ((raw: string) => InlineNode[]) | null;
21
+ /** Plugin manager for render hooks */
22
+ plugins?: PluginManager | null;
23
+ }
24
+ /**
25
+ * Render a Document AST to an HTML string.
26
+ */
27
+ declare function renderToHtml(doc: Document, options?: RendererOptions): string;
28
+ /**
29
+ * Render a Document AST directly to DOM nodes.
30
+ * Faster than renderToHtml + innerHTML for incremental updates.
31
+ */
32
+ declare function renderToDOM(doc: Document, options?: RendererOptions): DocumentFragment;
33
+
34
+ export { type RendererOptions, renderToDOM, renderToHtml };