Changeset 0.4.1 (#33)
This commit is contained in:
52
src/js/ui.js
52
src/js/ui.js
@@ -205,7 +205,7 @@ async function loadProviderList() {
|
||||
<div class="provider-row">
|
||||
<div class="provider-info">
|
||||
<span class="provider-name">${escapeHtmlUI(c.name)}</span>
|
||||
<span class="provider-meta">${c.provider} · ${c.model_default || 'no default'}</span>
|
||||
<span class="provider-meta">${escapeHtmlUI(c.provider)} · ${escapeHtmlUI(c.model_default || 'no default')}</span>
|
||||
</div>
|
||||
<div class="provider-actions">
|
||||
<span class="admin-badge admin-badge-active">${c.has_key ? '🔑' : '⚠️'}</span>
|
||||
@@ -214,7 +214,7 @@ async function loadProviderList() {
|
||||
</div>
|
||||
`).join('');
|
||||
} catch (e) {
|
||||
container.innerHTML = '<div class="admin-error">Failed to load providers: ' + e.message + '</div>';
|
||||
container.innerHTML = '<div class="admin-error">Failed to load providers: ' + escapeHtmlUI(e.message) + '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,53 +361,55 @@ function createMessageHTML(message, index) {
|
||||
|
||||
function formatMessage(content) {
|
||||
let formatted = content;
|
||||
|
||||
// Extract and format thinking blocks FIRST (before escaping)
|
||||
const thinkingBlocks = [];
|
||||
|
||||
// Extract thinking blocks FIRST (before escaping)
|
||||
if (State.settings.showThinking) {
|
||||
formatted = formatted.replace(/<thinking>([\s\S]*?)<\/thinking>/gi, (match, thinkingContent) => {
|
||||
const escapedContent = escapeHtml(thinkingContent.trim());
|
||||
const blockId = 'thinking-' + Math.random().toString(36).substr(2, 9);
|
||||
return `__THINKING_BLOCK_${blockId}__${escapedContent}__END_THINKING_BLOCK__`;
|
||||
// Store raw content; we'll escape it when reinserting
|
||||
thinkingBlocks.push({ id: blockId, content: thinkingContent.trim() });
|
||||
return `__THINKPLACEHOLDER_${blockId}__`;
|
||||
});
|
||||
} else {
|
||||
// Remove thinking blocks if setting is off
|
||||
formatted = formatted.replace(/<thinking>[\s\S]*?<\/thinking>/gi, '');
|
||||
}
|
||||
|
||||
// Now escape HTML for the rest
|
||||
|
||||
// Escape HTML for the entire string (placeholders are plain text, safe to escape)
|
||||
formatted = escapeHtml(formatted);
|
||||
|
||||
// Restore thinking blocks with proper HTML
|
||||
formatted = formatted.replace(/__THINKING_BLOCK_([\w-]+)__([\s\S]*?)__END_THINKING_BLOCK__/g, (match, blockId, content) => {
|
||||
return `
|
||||
<div class="thinking-block" id="${blockId}">
|
||||
<div class="thinking-header" onclick="toggleThinkingBlock('${blockId}')">
|
||||
|
||||
// Restore thinking blocks with properly-escaped content (single escape only)
|
||||
for (const block of thinkingBlocks) {
|
||||
const escapedContent = escapeHtml(block.content).replace(/\n/g, '<br>');
|
||||
formatted = formatted.replace(`__THINKPLACEHOLDER_${block.id}__`, `
|
||||
<div class="thinking-block" id="${block.id}">
|
||||
<div class="thinking-header" onclick="toggleThinkingBlock('${block.id}')">
|
||||
<span class="thinking-toggle">▼</span>
|
||||
<span class="thinking-label">💭 Thinking</span>
|
||||
</div>
|
||||
<div class="thinking-content">${content.replace(/\n/g, '<br>')}</div>
|
||||
<div class="thinking-content">${escapedContent}</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
|
||||
`);
|
||||
}
|
||||
|
||||
// Code blocks with copy button
|
||||
formatted = formatted.replace(/```(\w*)\n?([\s\S]*?)```/g, (match, lang, code) => {
|
||||
const codeId = 'code-' + Math.random().toString(36).substr(2, 9);
|
||||
return `<pre><code id="${codeId}" class="language-${lang}">${code.trim()}</code><button class="copy-code-btn" onclick="copyCode('${codeId}')">Copy</button></pre>`;
|
||||
});
|
||||
|
||||
|
||||
// Inline code
|
||||
formatted = formatted.replace(/`([^`]+)`/g, '<code>$1</code>');
|
||||
|
||||
|
||||
// Bold
|
||||
formatted = formatted.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
|
||||
|
||||
// Italic
|
||||
|
||||
// Italic
|
||||
formatted = formatted.replace(/\*([^*]+)\*/g, '<em>$1</em>');
|
||||
|
||||
|
||||
// Line breaks (but not inside pre/code)
|
||||
formatted = formatted.replace(/\n/g, '<br>');
|
||||
|
||||
|
||||
return formatted;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user