| 123456789101112131415161718192021222324252627282930313233343536373839 |
- /* Markdown rendering shared by streamed and completed assistant replies.
- * Marked 17.0.5 is vendored with its license. Only allowlisted DOM is copied. */
- (function () {
- const tags = new Set('P BR H1 H2 H3 H4 H5 H6 UL OL LI STRONG EM DEL BLOCKQUOTE PRE CODE HR TABLE THEAD TBODY TR TH TD A'.split(' '));
- const drop = new Set('SCRIPT STYLE IFRAME OBJECT EMBED SVG MATH TEMPLATE FORM INPUT IMG VIDEO AUDIO SOURCE LINK META'.split(' '));
- function safeCopy(node) {
- if (node.nodeType === Node.TEXT_NODE) return document.createTextNode(node.textContent);
- const fragment = document.createDocumentFragment();
- if (node.nodeType !== Node.ELEMENT_NODE || drop.has(node.tagName)) return fragment;
- const out = tags.has(node.tagName) ? document.createElement(node.tagName.toLowerCase()) : fragment;
- if (node.tagName === 'A') {
- const href = node.getAttribute('href') || '';
- try {
- const url = new URL(href, location.href);
- if (['http:', 'https:', 'mailto:'].includes(url.protocol)) {
- out.setAttribute('href', url.href);
- out.setAttribute('target', '_blank');
- out.setAttribute('rel', 'noopener noreferrer');
- }
- } catch (_) {}
- }
- if (node.tagName === 'OL' && /^\d+$/.test(node.getAttribute('start') || '')) out.setAttribute('start', node.getAttribute('start'));
- for (const child of node.childNodes) out.appendChild(safeCopy(child));
- return out;
- }
- window.renderAnswer = function (element, text) {
- element.classList.add('markdown-body');
- const raw = String(text || '');
- try {
- const template = document.createElement('template');
- template.innerHTML = marked.parse(raw, {gfm: true, breaks: true, async: false});
- const clean = document.createDocumentFragment();
- for (const node of template.content.childNodes) clean.appendChild(safeCopy(node));
- element.replaceChildren(clean);
- } catch (_) {
- element.textContent = raw;
- }
- };
- })();
|