black-yt commited on
Commit
80d3a08
·
1 Parent(s): 806e417

Improve frontend markdown rendering

Browse files
VERSION CHANGED
@@ -1 +1 @@
1
- v0.0.43
 
1
+ v0.0.44
frontend/static/app.css CHANGED
@@ -610,6 +610,16 @@ button {
610
  border-radius: 14px;
611
  }
612
 
 
 
 
 
 
 
 
 
 
 
613
  .markdown-body table {
614
  width: 100%;
615
  border-collapse: collapse;
 
610
  border-radius: 14px;
611
  }
612
 
613
+ .mermaid-chart {
614
+ margin: 0.85rem 0;
615
+ overflow-x: auto;
616
+ }
617
+
618
+ .mermaid-chart svg {
619
+ max-width: 100%;
620
+ height: auto;
621
+ }
622
+
623
  .markdown-body table {
624
  width: 100%;
625
  border-collapse: collapse;
frontend/static/app.js CHANGED
@@ -152,6 +152,7 @@
152
  var workspaceMeta = document.getElementById("workspaceMeta");
153
  var downloadWorkspaceBtn = document.getElementById("downloadWorkspaceBtn");
154
  var defaultPromptPlaceholder = promptInput.getAttribute("placeholder") || "Message ResearchHarness";
 
155
 
156
  function escapeHtml(value) {
157
  return String(value || "")
@@ -197,6 +198,12 @@
197
  return template.innerHTML;
198
  }
199
 
 
 
 
 
 
 
200
  function renderMathInMarkdown(container) {
201
  if (!window.renderMathInElement) return;
202
  container.querySelectorAll(".markdown-body").forEach(function (body) {
@@ -216,13 +223,37 @@
216
  });
217
  }
218
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
  function renderMarkdown(text) {
220
  if (!window.marked || !window.DOMPurify) {
221
  console.warn("Markdown renderer unavailable; falling back to plain text.");
222
  return "<pre>" + escapeHtml(text) + "</pre>";
223
  }
224
  try {
225
- var protectedMath = protectMathSegments(text);
226
  var rawHtml = window.marked.parse(protectedMath.text, { gfm: true, breaks: false, async: false });
227
  rawHtml = rewriteWorkspaceImageSources(rawHtml);
228
  var safeHtml = window.DOMPurify.sanitize(rawHtml, { USE_PROFILES: { html: true } });
@@ -538,6 +569,7 @@
538
  });
539
  timeline.appendChild(node);
540
  renderMathInMarkdown(node);
 
541
  setEventExpanded(node, true, false);
542
  scrollTimeline(shouldFollow);
543
  }
 
152
  var workspaceMeta = document.getElementById("workspaceMeta");
153
  var downloadWorkspaceBtn = document.getElementById("downloadWorkspaceBtn");
154
  var defaultPromptPlaceholder = promptInput.getAttribute("placeholder") || "Message ResearchHarness";
155
+ var mermaidCounter = 0;
156
 
157
  function escapeHtml(value) {
158
  return String(value || "")
 
198
  return template.innerHTML;
199
  }
200
 
201
+ function unwrapFullMarkdownFence(text) {
202
+ var source = String(text || "").trim();
203
+ var match = /^(```|~~~)[ \t]*(markdown|md|gfm)[^\n]*\n([\s\S]*?)\n\1[ \t]*$/i.exec(source);
204
+ return match ? match[3] : text;
205
+ }
206
+
207
  function renderMathInMarkdown(container) {
208
  if (!window.renderMathInElement) return;
209
  container.querySelectorAll(".markdown-body").forEach(function (body) {
 
223
  });
224
  }
225
 
226
+ function renderMermaidInMarkdown(container) {
227
+ if (!window.mermaid) return;
228
+ try {
229
+ window.mermaid.initialize({ startOnLoad: false, securityLevel: "strict" });
230
+ } catch (e) {
231
+ console.warn("Mermaid initialization failed.", e);
232
+ return;
233
+ }
234
+ container.querySelectorAll(".markdown-body pre code.language-mermaid").forEach(function (code) {
235
+ var pre = code.closest("pre");
236
+ if (!pre) return;
237
+ var source = code.textContent || "";
238
+ var target = document.createElement("div");
239
+ var id = "rh-mermaid-" + (++mermaidCounter);
240
+ target.className = "mermaid-chart";
241
+ window.mermaid.render(id, source).then(function (result) {
242
+ target.innerHTML = result.svg || "";
243
+ pre.replaceWith(target);
244
+ }).catch(function (e) {
245
+ console.warn("Mermaid rendering failed.", e);
246
+ });
247
+ });
248
+ }
249
+
250
  function renderMarkdown(text) {
251
  if (!window.marked || !window.DOMPurify) {
252
  console.warn("Markdown renderer unavailable; falling back to plain text.");
253
  return "<pre>" + escapeHtml(text) + "</pre>";
254
  }
255
  try {
256
+ var protectedMath = protectMathSegments(unwrapFullMarkdownFence(text));
257
  var rawHtml = window.marked.parse(protectedMath.text, { gfm: true, breaks: false, async: false });
258
  rawHtml = rewriteWorkspaceImageSources(rawHtml);
259
  var safeHtml = window.DOMPurify.sanitize(rawHtml, { USE_PROFILES: { html: true } });
 
569
  });
570
  timeline.appendChild(node);
571
  renderMathInMarkdown(node);
572
+ renderMermaidInMarkdown(node);
573
  setEventExpanded(node, true, false);
574
  scrollTimeline(shouldFollow);
575
  }
frontend/static/index.html CHANGED
@@ -74,6 +74,7 @@
74
  <script src="https://cdn.jsdelivr.net/npm/marked@15.0.12/marked.min.js"></script>
75
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
76
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"></script>
 
77
  <script src="/static/app.js"></script>
78
  </body>
79
  </html>
 
74
  <script src="https://cdn.jsdelivr.net/npm/marked@15.0.12/marked.min.js"></script>
75
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
76
  <script src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"></script>
77
+ <script src="https://cdn.jsdelivr.net/npm/mermaid@11.12.0/dist/mermaid.min.js"></script>
78
  <script src="/static/app.js"></script>
79
  </body>
80
  </html>