Spaces:
Running
Running
File size: 1,223 Bytes
80ab124 e3223f8 abbdcdd 80ab124 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | import { marked } from 'marked';
import DOMPurify from 'dompurify';
marked.setOptions({
gfm: true,
breaks: true,
});
function escapeHtml(s) {
return String(s)
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>');
}
// Wrap each fenced code block in a container with a copy button.
// The click handler lives in TraceViewer (event delegation on .copy-btn).
marked.use({
renderer: {
code({ text, lang }) {
const langClass = lang
? ` class="language-${String(lang).replace(/[^\w-]/g, '')}"`
: '';
return `<div class="code-block"><button type="button" class="copy-btn" aria-label="Copy code">Copy</button><pre><code${langClass}>${escapeHtml(text)}</code></pre></div>`;
},
},
});
// All rendered links open in a new tab and are sandboxed against
// window.opener / referrer leaks.
DOMPurify.addHook('afterSanitizeAttributes', (node) => {
if (node.tagName === 'A') {
node.setAttribute('target', '_blank');
node.setAttribute('rel', 'noopener noreferrer');
}
});
export function renderMarkdown(text) {
if (!text) return '';
const html = marked.parse(String(text));
return DOMPurify.sanitize(html, { ADD_ATTR: ['target', 'rel'] });
}
|