Rich Markdown rendering with LaTeX math, Mermaid diagrams, and syntax-highlighted code — with first-class streaming support for LLM chat interfaces. Renders all elements live as content arrives chunk by chunk, with smart caching to keep it fast.
- Streaming Rendering: Renders math, diagrams, and highlighted code in real time as LLM output streams in — not after it finishes
- LaTeX Math: Inline (
$...$) and display ($$...$$) math via KaTeX, with smart$disambiguation that won't mangle your currency values - Mermaid Diagrams: 23 diagram types rendered as SVGs, cached across re-renders during streaming
- Syntax Highlighting: Automatic code block highlighting via highlight.js with language detection
- Self-Correcting Render: When LLM-generated mermaid/KaTeX has syntax errors, call your own fix callback (e.g., another LLM) to auto-repair and retry
- XSS Protection: Built-in HTML sanitization via DOMPurify
- Static Rendering: Also works as a straightforward one-shot Markdown → HTML renderer
npm install mertex.mdimport { MertexMD } from 'mertex.md';
const renderer = new MertexMD();
const html = await renderer.render('# Hello **World**\n\n$E = mc^2$');
document.getElementById('content').innerHTML = html;import { MertexMD } from 'mertex.md';
const renderer = new MertexMD();
const targetElement = document.getElementById('content');
const stream = renderer.createStreamRenderer(targetElement);
// As chunks arrive from your streaming source:
await stream.appendContent('# Hello ');
await stream.appendContent('**World**\n\n');
await stream.appendContent('$E = mc^2$');
// When streaming completes:
await stream.finalize();
// Reset for new content:
stream.reset();<!-- Dependencies -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/dompurify/dist/purify.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/katex/dist/katex.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/katex/dist/contrib/auto-render.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/highlight.js/lib/core.min.js"></script>
<!-- Mertex.md -->
<script src="path/to/mertex.umd.js"></script>
<script>
const renderer = new MertexMD.default();
renderer.render('# Hello $E=mc^2$').then(html => {
document.getElementById('content').innerHTML = html;
});
</script>const renderer = new MertexMD({
breaks: true, // Convert line breaks to <br>
gfm: true, // GitHub Flavored Markdown
headerIds: true, // Add IDs to headers
katex: true, // Enable KaTeX math rendering
mermaid: true, // Enable Mermaid diagram rendering
highlight: true, // Enable syntax highlighting
sanitize: true, // Enable HTML sanitization
protectMath: true, // Protect math from markdown corruption
renderOnRestore: true, // Render math during restore phase
selfCorrect: { // Optional: auto-fix broken renders
fix: async (code, format, error) => correctedCode,
maxRetries: 1 // 1-3, default 1
}
});All render methods are async and return Promises:
render(markdown)- Render markdown to HTML stringrenderFull(markdown)- Render and return{ html, mermaidMap, katexMap }createStreamRenderer(element)- Create a streaming rendererrenderInElement(element, markdown)- Render into a DOM elementautoRender(selector)- Auto-render all matching elementsinit()- Initialize auto-rendering on DOMContentLoaded
const stream = renderer.createStreamRenderer(element);
await stream.appendContent(chunk); // Append new content chunk
await stream.setContent(content); // Replace content entirely
await stream.finalize(); // Complete rendering
stream.reset(); // Reset for new content
stream.getContent(); // Get current content
stream.getStats(); // Get rendering statisticsWhen mermaid or KaTeX rendering fails, mertex can call a consumer-provided fix callback to attempt correction. This enables LLM-powered auto-repair of broken syntax.
const renderer = new MertexMD({
selfCorrect: {
fix: async (code, format, error) => {
// code: the broken source (mermaid definition or LaTeX expression)
// format: "mermaid" or "katex"
// error: the error message from the failed render
// Return the corrected code string
const response = await callLLM(`Fix this ${format} code:\n${code}\n\nError: ${error}`);
return response;
},
maxRetries: 1, // default 1, max 3
},
});When self-correction is in progress, placeholder elements receive the .mertex-fixing CSS class, which consumers can style to show a loading state.
The selfCorrectRender utility is also exported for direct use:
import { selfCorrectRender } from 'mertex.md';
const result = await selfCorrectRender(code, 'mermaid', errorMsg, renderFn, {
fix: myFixCallback,
maxRetries: 2,
});
// result: { success: boolean, result?: any, code?: string }See docs/ for detailed documentation:
- Architecture — System design, components, data flow, dependencies
- Guides — Getting started, streaming, self-correcting render, API reference
- KaTeX - Math rendering
- Mermaid - Diagram rendering
- highlight.js - Syntax highlighting
npm install
npm run buildThis generates:
dist/mertex.esm.js- ES module versiondist/mertex.umd.js- UMD version for browsersdist/mertex.min.js- Minified UMD versiondist/mertex.bundled.min.js- Minified with marked/DOMPurify bundled
MIT © Gary Ferguson