').addClass('acc-message-content');
if (role === 'thought') {
msgDiv.addClass('acc-thought-message');
contentDiv.css({
'font-style': 'italic',
'color': '#aaa',
'font-size': '0.9em'
});
}
msgDiv.append(avatarDiv);
msgDiv.append(contentDiv);
stream.append(msgDiv);
contentDiv.html(formattedContent);
stream.scrollTop(stream[0].scrollHeight);
}
function parseMarkdown(text) {
if (!text) return '';
// 1. Escape HTML (basic)
let html = text
.replace(/&/g, "&")
.replace(//g, ">");
// 2. Code Blocks (```...```)
html = html.replace(/```([\s\S]*?)```/g, '
$1
');
// 3. Inline Code (`...`)
html = html.replace(/`([^`]+)`/g, '
$1');
// 4. Headers
html = html.replace(/^#### (.*$)/gm, '
$1
');
html = html.replace(/^### (.*$)/gm, '
$1
');
html = html.replace(/^## (.*$)/gm, '
$1
');
html = html.replace(/^# (.*$)/gm, '
$1
');
// 5. Bold & Italic
html = html.replace(/\*\*(.*?)\*\*/g, '
$1');
html = html.replace(/\*(.*?)\*/g, '
$1');
// 6. Horizontal Rules
html = html.replace(/^[\*\-]{3,}$/gm, '
');
// 7. Lists
// Replace * or - at start of line with a bullet point
html = html.replace(/^\s*[\-\*]\s+(.*$)/gm, '
$1');
// 8. Line breaks
// We want to preserve line breaks, but block elements (h1-h6, pre, li) handle their own spacing.
// We can replace newlines with
ONLY if they are not around block tags.
// A simpler approach for chat: just replace all \n with
, and let CSS handle the extra spacing or remove it.
// But
content shouldn't have
.
// Let's just replace \n with
globally, but we need to protect blocks.
// Actually, the code block regex above already consumed the newlines inside it.
// So we can just replace remaining \n.
html = html.replace(/\n/g, '
');
return html;
}
function renderEditor() {
const container = $('#acc-preview-container');
const tabsContainer = $('.acc-preview-tabs');
// Don't fully empty if we want to preserve state, but for simplicity we re-render tabs
// To preserve scroll position or focus, we might need more complex logic.
// For now, re-rendering is acceptable as long as data is in openedFiles.
container.empty();
tabsContainer.empty();
if (openedFiles.size === 0) {
container.html('');
return;
}
// Ensure activeFileId is valid
if (!activeFileId || !openedFiles.has(activeFileId)) {
activeFileId = openedFiles.keys().next().value;
}
openedFiles.forEach((file, id) => {
const isActive = id === activeFileId;
const tabBtn = $('