import { marked } from 'marked' import { markedHighlight } from 'marked-highlight' import hljs from 'highlight.js' import 'highlight.js/styles/github-dark.css' import katex from 'katex' import 'katex/dist/katex.min.css' import DOMPurify from 'dompurify' marked.use(markedHighlight({ langPrefix: 'hljs language-', highlight(code, lang) { if (lang && hljs.getLanguage(lang)) { return hljs.highlight(code, { language: lang }).value } return hljs.highlightAuto(code).value }, })) marked.setOptions({ breaks: true, gfm: true }) // LaTeX-Mathe via KaTeX. Eigene marked-Extensions (statt marked-katex-extension, // die marked v18 hinterherhinkt). marked tokenisiert Code zuerst → $…$ in Code- // Blöcken wird NICHT als Mathe erkannt. throwOnError:false zeigt defektes TeX rot. function renderTex(tex, displayMode) { return katex.renderToString(tex, { displayMode, throwOnError: false, output: 'html' }) } const blockMath = { name: 'blockMath', level: 'block', start(src) { const i = src.indexOf('$$'); return i < 0 ? undefined : i }, tokenizer(src) { const m = /^\$\$([\s\S]+?)\$\$/.exec(src) if (m) return { type: 'blockMath', raw: m[0], text: m[1].trim() } }, renderer(token) { return renderTex(token.text, true) }, } const inlineMath = { name: 'inlineMath', level: 'inline', start(src) { const i = src.indexOf('$'); return i < 0 ? undefined : i }, tokenizer(src) { // $…$: kein $$, kein Leerzeichen direkt hinter dem öffnenden $ und vor dem // schließenden $ (pandoc-Stil) → mindert Kollisionen mit Fließtext-Dollarzeichen. const m = /^\$(?![\s$])((?:\\\$|[^$])+?)\$/.exec(src) if (!m || /\s$/.test(m[1])) return return { type: 'inlineMath', raw: m[0], text: m[1].trim() } }, renderer(token) { return renderTex(token.text, false) }, } marked.use({ extensions: [blockMath, inlineMath] }) // Rohes HTML im Markdown (z. B.
, ohne Backticks aus Agenten-Output)
// als Text anzeigen statt rendern — sonst verschluckt der Browser den Inhalt.
marked.use({
renderer: {
html(token) {
const text = typeof token === 'string' ? token : token.text
return text.replace(/&/g, '&').replace(//g, '>')
},
},
})
export function renderMarkdown(text) {
return DOMPurify.sanitize(marked.parse(text || ''))
}