2025-08-22 23:42:34 +02:00
|
|
|
export function markdownToHTML(text) {
|
|
|
|
|
// 0) Remove <think>...</think>/<thinking>...</thinking> blocks
|
2025-08-25 21:13:09 +02:00
|
|
|
// This regex will match an an opening <think> or <thinking> tag,
|
|
|
|
|
// followed by any characters (non-greedy), until either a closing
|
|
|
|
|
// </think> or </thinking> tag is found, OR the end of the string ($).
|
|
|
|
|
text = text.replace(/<think(?:ing)?>[\s\S]*?(?:<\/think(?:ing)?>|$)/gi, '');
|
2025-08-22 23:42:34 +02:00
|
|
|
|
2025-08-26 05:32:45 +02:00
|
|
|
text = balanceStreamingCodeFence(text);
|
|
|
|
|
|
2025-08-22 23:42:34 +02:00
|
|
|
// 1) Normalize line endings
|
|
|
|
|
let tmp = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 2) Extract code blocks and replace with placeholders (protect from all formatting)
|
2025-08-22 23:42:34 +02:00
|
|
|
const codeblocks = [];
|
|
|
|
|
const placeholder = idx => `@@CODEBLOCK${idx}@@`;
|
2025-08-23 16:45:46 +02:00
|
|
|
tmp = tmp.replace(/```([^\n]*)\n([\s\S]*?)```/g, (_, lang, code) => {
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// Strip trailing whitespace-only lines at the end of the block
|
|
|
|
|
let cleaned = (code || '').replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
|
|
|
const lines = cleaned.split('\n');
|
|
|
|
|
while (lines.length > 0 && /^\s*$/.test(lines[lines.length - 1])) lines.pop();
|
|
|
|
|
cleaned = lines.join('\n');
|
|
|
|
|
codeblocks.push({ lang: (lang || '').trim(), code: cleaned });
|
2025-08-22 23:42:34 +02:00
|
|
|
return placeholder(codeblocks.length - 1);
|
|
|
|
|
});
|
|
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 3) HTML-escape special characters (outside of code blocks)
|
2025-08-22 23:42:34 +02:00
|
|
|
let escaped = tmp
|
|
|
|
|
.replace(/&/g, "&")
|
|
|
|
|
.replace(/</g, "<")
|
|
|
|
|
.replace(/>/g, ">");
|
|
|
|
|
|
|
|
|
|
// 4) Headings
|
|
|
|
|
escaped = escaped
|
|
|
|
|
.replace(/^#### (.+)$/gm, "<h4>$1</h4>")
|
|
|
|
|
.replace(/^### (.+)$/gm, "<h3>$1</h3>")
|
|
|
|
|
.replace(/^## (.+)$/gm, "<h2>$1</h2>")
|
|
|
|
|
.replace(/^# (.+)$/gm, "<h1>$1</h1>");
|
|
|
|
|
|
2025-08-23 16:45:46 +02:00
|
|
|
// 4.2) Remove blank empty lines immediately after headings
|
|
|
|
|
escaped = escaped.replace(
|
|
|
|
|
/(<h[1-4]>.*?<\/h[1-4]>)[ \t]*\n(?:[ \t]*\n)+/g,
|
|
|
|
|
"$1\n"
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-25 21:13:09 +02:00
|
|
|
// 4.3) Blockquotes
|
|
|
|
|
escaped = escaped.replace(
|
|
|
|
|
/(^|\n)([ \t]*> .+(?:\n[ \t]*> .+)*)/g,
|
|
|
|
|
(_, lead, blockquoteBlock) => {
|
|
|
|
|
const lines = blockquoteBlock
|
|
|
|
|
.split(/\n/)
|
|
|
|
|
.map(line => line.replace(/^[ \t]*>\s*/, '').trim())
|
|
|
|
|
.join('\n');
|
|
|
|
|
return `${lead}<blockquote>${lines}</blockquote>`;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-22 23:42:34 +02:00
|
|
|
// 4.5) Unordered lists
|
|
|
|
|
escaped = escaped.replace(
|
2025-08-25 21:13:09 +02:00
|
|
|
/(^|\n)([ \t]*[-*] .+(?:\n[ \t]*[-*] .+)*)/g,
|
2025-08-22 23:42:34 +02:00
|
|
|
(_, lead, listBlock) => {
|
|
|
|
|
const items = listBlock
|
|
|
|
|
.split(/\n/)
|
2025-08-25 21:13:09 +02:00
|
|
|
.map(line => line.replace(/^[ \t]*[-*]\s+/, '').trim())
|
2025-08-22 23:42:34 +02:00
|
|
|
.map(item => `<li>${item}</li>`)
|
|
|
|
|
.join('');
|
|
|
|
|
return `${lead}<ul>${items}</ul>`;
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
|
2025-08-23 16:45:46 +02:00
|
|
|
// 4.6) Markdown tables (GitHub-style). Strict: requires header, separator, ≥2 cols.
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
const mdTableBlockRe =
|
|
|
|
|
/(^\|[^\n]*\|?\s*\n\|\s*[:\-]+(?:\s*\|\s*[:\-]+)+\s*\|?\s*\n(?:\|[^\n]*\|?\s*(?:\n|$))*)/gm;
|
|
|
|
|
|
|
|
|
|
escaped = escaped.replace(mdTableBlockRe, (block) => {
|
|
|
|
|
const hadTrailingNewline = /\n$/.test(block);
|
|
|
|
|
const lines = block.replace(/\n$/, '').split('\n');
|
|
|
|
|
|
|
|
|
|
const split = (line) => line.replace(/^\||\|$/g, '').split('|').map(s => s.trim());
|
|
|
|
|
|
|
|
|
|
const headers = split(lines[0]);
|
|
|
|
|
const seps = split(lines[1]);
|
|
|
|
|
if (headers.length < 2 || seps.length < 2) return block;
|
|
|
|
|
if (!seps.every(s => /^[ :\-]+$/.test(s) && /-/.test(s))) return block;
|
|
|
|
|
|
|
|
|
|
const aligns = seps.map(seg => {
|
|
|
|
|
const s = seg.replace(/\s+/g,'');
|
|
|
|
|
const left = s.startsWith(':');
|
|
|
|
|
const right = s.endsWith(':');
|
|
|
|
|
if (left && right) return 'center';
|
|
|
|
|
if (right) return 'right';
|
|
|
|
|
return 'left';
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const bodyLines = lines.slice(2).filter(l => /^\|/.test(l.trim()));
|
|
|
|
|
const cellStyle = (i) =>
|
|
|
|
|
` style="text-align:${aligns[i] || 'left'};vertical-align:top;padding:.6rem .75rem"`;
|
|
|
|
|
|
|
|
|
|
const ths = headers.map((h,i)=>`<th${cellStyle(i)}>${h}</th>`).join('');
|
|
|
|
|
const rows = bodyLines.map(line => {
|
|
|
|
|
const cells = split(line);
|
|
|
|
|
const tds = cells.map((c,i)=>`<td${cellStyle(i)}>${c}</td>`).join('');
|
|
|
|
|
return `<tr>${tds}</tr>`;
|
|
|
|
|
}).join('');
|
|
|
|
|
|
|
|
|
|
const table = `<table class="nice" style="border-collapse:separate;border-spacing:0;width:100%;margin:1rem 0"><thead><tr>${ths}</tr></thead><tbody>${rows}</tbody></table>`;
|
|
|
|
|
|
|
|
|
|
return table + (hadTrailingNewline ? '\n' : '');
|
2025-08-23 16:45:46 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 4.75) Horizontal rules
|
|
|
|
|
escaped = escaped.replace(/^---\s*$/gm, "<hr>");
|
|
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 5) Bold, italic, inline code (inline code only; fenced were extracted)
|
2025-08-22 23:42:34 +02:00
|
|
|
let html = escaped
|
|
|
|
|
.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>")
|
|
|
|
|
.replace(/(?<!\*)\*(.+?)\*(?!\*)/g, "<i>$1</i>")
|
|
|
|
|
.replace(/`(.+?)`/g, "<code>$1</code>");
|
|
|
|
|
|
2025-08-23 16:45:46 +02:00
|
|
|
// 5.5) Links
|
|
|
|
|
html = html.replace(/\[([^\]]+?)\]\(([^)]+?)\)/g, '<a href="$2" target="_blank"><span>$1</span> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" class="feather feather-external-link"><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg><span class="tooltip">$2</span></a>');
|
|
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 6) Convert line-breaks to <br> for NON-code content (code is still placeholdered)
|
2025-08-22 23:42:34 +02:00
|
|
|
html = html.replace(/\n/g, "<br>");
|
|
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 6.1) Cleanup stray <br> around lists/tables/wrappers that already exist
|
2025-08-22 23:42:34 +02:00
|
|
|
html = html
|
|
|
|
|
.replace(/<br>\s*(<ul>)/g, "$1")
|
2025-08-23 16:45:46 +02:00
|
|
|
.replace(/(<\/ul>)\s*<br>/g, "$1")
|
|
|
|
|
.replace(/<br>\s*(<div class="md-table"[^>]*>)/g, "$1")
|
|
|
|
|
.replace(/(<\/div>)\s*<br>/g, "$1")
|
|
|
|
|
.replace(/<br>\s*(<table\b[^>]*>)/g, "$1")
|
2025-08-25 21:13:09 +02:00
|
|
|
.replace(/(<\/table>)\s*<br>/g, "$1")
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
.replace(/<br>\s*(<blockquote>)/g, "$1")
|
|
|
|
|
.replace(/(<\/blockquote>)\s*<br>/g, "$1");
|
|
|
|
|
|
|
|
|
|
// 6.2) Trim spaces/tabs and remove empty newline(s) after <hr>, blockquote, ul
|
|
|
|
|
html = html
|
|
|
|
|
.replace(/(<hr>)[ \t]+/g, "$1")
|
|
|
|
|
.replace(/(<hr>)(?:[ \t]*<br>)+/g, "$1")
|
|
|
|
|
.replace(/(<\/blockquote>)(?:[ \t]*<br>)+/g, "$1")
|
|
|
|
|
.replace(/(<\/ul>)(?:[ \t]*<br>)+/g, "$1");
|
|
|
|
|
|
|
|
|
|
// 7) Restore code blocks with title bar (language) + copy button (no inline handlers)
|
|
|
|
|
html = html.replace(/@@CODEBLOCK(\d+)@@/g, (_, idx) => {
|
|
|
|
|
const { lang, code } = codeblocks[+idx];
|
|
|
|
|
const title = (lang && lang.trim()) ? lang.trim() : 'code';
|
|
|
|
|
|
|
|
|
|
// Escape only for HTML rendering inside <code>; keep raw \n (no <br> here!)
|
|
|
|
|
const escapedCode = code
|
|
|
|
|
.replace(/&/g, "&")
|
|
|
|
|
.replace(/</g, "<")
|
|
|
|
|
.replace(/>/g, ">");
|
|
|
|
|
|
|
|
|
|
// Single-line header to avoid global <br> interference
|
|
|
|
|
const head = `<div class="codeblock__header"><div class="codeblock__lang">${title}</div><button type="button" class="codeblock__copy" aria-label="Copy code" title="Copy code"><svg class="icon icon-copy" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M16 1H4a2 2 0 0 0-2 2v12h2V3h12V1zm3 4H8a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2zm0 16H8V7h11v14z"/></svg></button></div>`;
|
|
|
|
|
|
|
|
|
|
// Ensure wrapping inside container and preserve newlines for copy/paste
|
|
|
|
|
const body = `<pre class="codeblock__pre" style="margin:0;padding:.75rem;border:0;overflow:auto;max-width:100%"><code class="codeblock__code language-${title}" style="display:block;white-space:pre-wrap;word-break:break-word;overflow-wrap:anywhere;max-width:100%">${escapedCode}</code></pre>`;
|
|
|
|
|
|
|
|
|
|
return `<div class="codeblock" style="margin:1rem 0;border:1px solid var(--border);border-radius:12px;overflow:hidden">${head}${body}</div>`;
|
|
|
|
|
});
|
2025-08-23 16:45:46 +02:00
|
|
|
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
// 8) Final cleanup around codeblocks specifically (remove stray <br> added next to placeholders)
|
2025-08-23 16:45:46 +02:00
|
|
|
html = html
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
.replace(/<br>\s*(?=<div class="codeblock"\b)/g, "") // <br> before opening
|
|
|
|
|
.replace(/(<div class="codeblock"[^>]*>[\s\S]*?<\/div>)\s*<br>/g, "$1"); // <br> right after closing
|
2025-08-22 23:42:34 +02:00
|
|
|
|
|
|
|
|
return html;
|
2025-08-26 05:32:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Virtually close an unfinished fenced code block so it renders during streaming.
|
|
|
|
|
function balanceStreamingCodeFence(md) {
|
|
|
|
|
// Split into lines; we only consider fences that start a line.
|
|
|
|
|
const lines = md.split(/\r?\n/);
|
|
|
|
|
|
|
|
|
|
// Track the last unmatched opening fence we see while scanning.
|
|
|
|
|
// { fenceChar: '`' or '~', fenceLen: number }
|
|
|
|
|
let open = null;
|
|
|
|
|
|
|
|
|
|
for (let i = 0; i < lines.length; i++) {
|
|
|
|
|
const line = lines[i];
|
|
|
|
|
|
|
|
|
|
// Opening fence? ^\s*([`~]{3,})(.*)$
|
|
|
|
|
if (!open) {
|
|
|
|
|
const m = line.match(/^\s*([`~]{3,})([^\s]*)?.*$/);
|
|
|
|
|
if (m) {
|
|
|
|
|
// Treat as an opening fence
|
|
|
|
|
open = { fenceChar: m[1][0], fenceLen: m[1].length };
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// Closing fence: must match same char and length or longer
|
|
|
|
|
const re = new RegExp(`^\\s*(${open.fenceChar}{${open.fenceLen},})\\s*$`);
|
|
|
|
|
if (re.test(line)) {
|
|
|
|
|
// Closed
|
|
|
|
|
open = null;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
// Otherwise still inside the code block; keep scanning
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (open) {
|
|
|
|
|
// Virtually close with the same fence so the block renders now
|
|
|
|
|
const virtual = `${open.fenceChar.repeat(open.fenceLen)}`;
|
|
|
|
|
return md.endsWith('\n') ? md + virtual : md + '\n' + virtual;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return md;
|
Add streaming unread logic, copy button, and improved Markdown rendering
Implemented robust streaming handling for assistant replies: a placeholder message is inserted, unread sessions are flagged when the user is in a different chat, and scroll‑to‑bottom/ tip logic is applied once the stream completes.
• Added copy‑to‑clipboard support for code blocks with visual feedback.
• Re‑implemented Markdown to clean trailing whitespace in code blocks, preserve formatting, add copy buttons, and refine table & blockquote handling.
• Introduced new CSS classes (.codeblock, .codeblock__header, .codeblock__copy, etc.) to style the code block wrapper, header bar, copy button, and pre/code area.
• Updated the front‑end to wire up the new copy handler, manage pending scroll targets, and keep unread state in sync.
• Minor cleanup of stray tags and comments throughout the renderer.
• Minor fixes to ensure proper scrolling behavior when the user scrolls away from the bottom during streaming.
• Added descriptive comments and ensured cross‑browser copy functionality via navigator.clipboard.
• Updated the markdown renderer to keep raw newlines for copy‑paste fidelity and to escape HTML entities correctly.
• Adjusted CSS to match existing theme variables and provide smooth copy button transitions.
2025-08-26 02:56:56 +02:00
|
|
|
}
|