From f180dbc842afda07d347b1e383f61644e495ca3e Mon Sep 17 00:00:00 2001 From: Meleki Date: Sat, 4 Apr 2026 22:56:53 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20Code-Bl=C3=B6cke=20vor=20LaTeX-Parsing?= =?UTF-8?q?=20sch=C3=BCtzen=20($-Zeichen=20in=20Code=20nicht=20mehr=20als?= =?UTF-8?q?=20Math=20interpretiert)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 --- wwwroot/js/markdown.js | 45 ++++++++++++++++++++++++++++++------------ 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/wwwroot/js/markdown.js b/wwwroot/js/markdown.js index f52fded..ea90ef6 100644 --- a/wwwroot/js/markdown.js +++ b/wwwroot/js/markdown.js @@ -6,7 +6,21 @@ function renderMarkdown(text) { if (!text) return ''; var src = text.trim(); - // 1) LaTeX-Ausdrücke VOR dem Markdown-Parsing schützen + // 1) Code-Blöcke VOR dem LaTeX-Parsing schützen + // Sonst werden $-Zeichen in Code (z.B. PowerShell $Variable) als Math interpretiert + var preCodeBlocks = []; + // Fenced code blocks: ```...``` + src = src.replace(/```[\s\S]*?```/g, function(m) { + preCodeBlocks.push(m); + return '%%PRECODE' + (preCodeBlocks.length - 1) + '%%'; + }); + // Inline code: `...` + src = src.replace(/`[^`]+`/g, function(m) { + preCodeBlocks.push(m); + return '%%PRECODE' + (preCodeBlocks.length - 1) + '%%'; + }); + + // 2) LaTeX-Ausdrücke VOR dem Markdown-Parsing schützen // Reihenfolge: zuerst Block ($$...$$), dann Inline ($...$) var mathBlocks = []; // Block-Math: $$...$$ (auch mehrzeilig) @@ -20,48 +34,53 @@ function renderMarkdown(text) { return '%%MATH' + (mathBlocks.length - 1) + '%%'; }); - // 2) Markdown parsen + // 3) Code-Blöcke wiederherstellen (damit Markdown sie korrekt parst) + src = src.replace(/%%PRECODE(\d+)%%/g, function(m, idx) { + return preCodeBlocks[parseInt(idx)]; + }); + + // 4) Markdown parsen var html = marked.parse(src); - // 3) Code-Blöcke schützen (damit Emojis/Krea dort nicht greifen) + // 5) Code-Blöcke schützen (damit Emojis/Krea dort nicht greifen) var codeBlocks = []; html = html.replace(/][\s\S]*?<\/pre>|][\s\S]*?<\/code>/gi, function(m) { codeBlocks.push(m); return '%%CODE' + (codeBlocks.length - 1) + '%%'; }); - // 4a) [Review: AgentName] prefix → Review-Header + // 6a) [Review: AgentName] prefix → Review-Header html = html.replace(/\[Review:\s*([^\]]+)\]\s*/g, function(match, agentName) { return ' ' + esc(agentName.trim()) + ' '; }); - // 4a2) [Finalizer: AgentName] prefix → Finalizer-Header + // 6a2) [Finalizer: AgentName] prefix → Finalizer-Header html = html.replace(/\[Finalizer:\s*([^\]]+)\]\s*/g, function(match, agentName) { return ' ' + esc(agentName.trim()) + ' '; }); - // 4a3) [Preparer: AgentName] prefix → Preparer-Header + // 6a3) [Preparer: AgentName] prefix → Preparer-Header html = html.replace(/\[Preparer:\s*([^\]]+)\]\s*/g, function(match, agentName) { return ' ' + esc(agentName.trim()) + ' '; }); - // 4a4) [Vorbereitet von AgentName]: → Preparer-Forwarded-Header + // 6a4) [Vorbereitet von AgentName]: → Preparer-Forwarded-Header html = html.replace(/\[Vorbereitet von\s+([^\]]+)\]:\s*/g, function(match, agentName) { return '
Vorbereitet von ' + esc(agentName.trim()) + '
'; }); - // 4b) [Review-Feedback von AgentName (Runde X/Y)]: → Review-Feedback-Header + // 6b) [Review-Feedback von AgentName (Runde X/Y)]: → Review-Feedback-Header html = html.replace(/\[Review-Feedback von\s+([^\(]+)\(Runde\s+(\d+)\/(\d+)\)\]:\s*/g, function(match, agentName, round, maxRounds) { return '
Feedback von ' + esc(agentName.trim()) + ' Runde ' + esc(round) + '/' + esc(maxRounds) + '
'; }); - // 4c) [APPROVED], [FORWARD], [QUESTION] und [FEEDBACK] ausblenden + // 6c) [APPROVED], [FORWARD], [QUESTION] und [FEEDBACK] ausblenden html = html.replace(/\[APPROVED\]/g, ''); html = html.replace(/\[FORWARD\]\s*/g, ''); html = html.replace(/\[QUESTION\]\s*/g, ''); html = html.replace(/\[FEEDBACK\]\s*/g, ''); - // 4d) [Krea: dateiname.png] → Inline-Thumbnail mit Klick für Vollbild + // 6d) [Krea: dateiname.png] → Inline-Thumbnail mit Klick für Vollbild html = html.replace(/\[Krea:\s*([^\]]+)\]/g, function(match, filename) { var fn = filename.trim(); var safeFn = esc(fn); @@ -72,15 +91,15 @@ function renderMarkdown(text) { + ''; }); - // 5) Unicode-Emojis durch Fluent Emoji 3D ersetzen (außerhalb von Code-Blöcken) + // 7) Unicode-Emojis durch Fluent Emoji 3D ersetzen (außerhalb von Code-Blöcken) html = replaceEmojisWithFluent(html); - // 6) Code-Blöcke wiederherstellen + // 8) Code-Blöcke wiederherstellen html = html.replace(/%%CODE(\d+)%%/g, function(m, idx) { return codeBlocks[parseInt(idx)]; }); - // 7) LaTeX-Platzhalter durch KaTeX-gerenderten HTML ersetzen + // 9) LaTeX-Platzhalter durch KaTeX-gerenderten HTML ersetzen html = html.replace(/%%MATH(\d+)%%/g, function(m, idx) { var block = mathBlocks[parseInt(idx)]; try {