Use marked.js for Markdown and add React artifact renderer
Build Claw Telegram / build (push) Successful in 4m30s
Build Claw Telegram / cleanup (push) Successful in 1s

- Markdown: swap regex converter for marked.js (full GFM support)
- JSX/TSX: render in sandboxed iframe with React 18 + Babel standalone

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Wylabb
2026-04-05 13:10:25 +02:00
parent 1cf06bfa69
commit 0f0d41bd8d
+42 -12
View File
@@ -475,6 +475,7 @@ async fn artifact_viewer(
"html" | "htm" => "html",
"md" | "markdown" => "markdown",
"json" => "json",
"jsx" | "tsx" => "react",
_ => "code",
};
let escaped_name = meta.file_name.replace('<', "&lt;").replace('>', "&gt;");
@@ -486,6 +487,7 @@ async fn artifact_viewer(
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<title>{escaped_name}</title>
<script src="https://telegram.org/js/telegram-web-app.js"></script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<style>
:root {{ --bg: #1a1a2e; --panel: #16213e; --ink: #e0e0e0; --accent: #0f3460; --code-bg: #0d1117; }}
* {{ margin: 0; padding: 0; box-sizing: border-box; }}
@@ -541,13 +543,19 @@ iframe {{ width: 100%; min-height: 80vh; border: 1px solid #333; border-radius:
el.querySelector("iframe").srcdoc = text;
}} else if (renderMode === "markdown") {{
el.classList.add("md");
el.innerHTML = simpleMarkdown(text);
if (typeof marked !== "undefined") {{
el.innerHTML = marked.parse(text);
}} else {{
el.innerHTML = "<pre>" + escapeHtml(text) + "</pre>";
}}
}} else if (renderMode === "json") {{
try {{
el.innerHTML = "<pre>" + escapeHtml(JSON.stringify(JSON.parse(text), null, 2)) + "</pre>";
}} catch(_) {{
el.innerHTML = "<pre>" + escapeHtml(text) + "</pre>";
}}
}} else if (renderMode === "react") {{
renderReactArtifact(el, text);
}} else {{
el.innerHTML = "<pre>" + escapeHtml(text) + "</pre>";
}}
@@ -559,17 +567,39 @@ iframe {{ width: 100%; min-height: 80vh; border: 1px solid #333; border-radius:
return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
}}
function simpleMarkdown(md) {{
return md
.replace(/^### (.+)$/gm, "<h3>$1</h3>")
.replace(/^## (.+)$/gm, "<h2>$1</h2>")
.replace(/^# (.+)$/gm, "<h1>$1</h1>")
.replace(/\*\*(.+?)\*\*/g, "<strong>$1</strong>")
.replace(/`([^`]+)`/g, "<code>$1</code>")
.replace(/^- (.+)$/gm, "<li>$1</li>")
.replace(/(<li>.*<\/li>)/s, "<ul>$1</ul>")
.replace(/\n\n/g, "</p><p>")
.replace(/^/, "<p>").replace(/$/, "</p>");
function renderReactArtifact(container, source) {{
const html = `<!DOCTYPE html>
<html><head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<script src="https://cdn.jsdelivr.net/npm/react@18/umd/react.production.min.js"><\/script>
<script src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.production.min.js"><\/script>
<script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js"><\/script>
<style>*{{margin:0;padding:0;box-sizing:border-box}}body{{font-family:-apple-system,system-ui,sans-serif;padding:16px}}</style>
</head><body>
<div id="root"></div>
<script type="text/babel" data-type="module">
${{source}}
// Auto-mount: find the default export or last component
const __moduleKeys = Object.keys(window).filter(k => /^[A-Z]/.test(k) && typeof window[k] === 'function');
try {{
// Try rendering the source as-is (may contain its own ReactDOM.render)
const root = document.getElementById('root');
if (!root.hasChildNodes()) {{
// If nothing rendered, look for an App or default component
const App = window.App || window.default || (typeof exports !== 'undefined' && exports.default);
if (App) {{
ReactDOM.createRoot(root).render(React.createElement(App));
}}
}}
}} catch(e) {{
document.getElementById('root').innerHTML = '<pre style="color:red">' + e.message + '</pre>';
}}
<\/script>
</body></html>`;
container.innerHTML = '<iframe sandbox="allow-scripts allow-same-origin" style="width:100%;min-height:80vh;border:1px solid #333;border-radius:6px;background:#fff" srcdoc=""></iframe>';
container.querySelector("iframe").srcdoc = html;
}}
}})();
</script>