feat: render AI response as markdown (marked.js)

This commit is contained in:
Kyrykbaev-I 2026-06-01 10:48:48 +05:00
parent 40882b62ea
commit 5b13383d5b

View File

@ -151,7 +151,41 @@ body { font-family: var(--font-base); background: var(--color-bg); color: var(--
.spinner { width: 18px; height: 18px; border: 2px solid var(--color-border); border-top-color: var(--color-brand); border-radius: 50%; animation: spin 0.7s linear infinite; flex-shrink: 0; }
@keyframes spin { to { transform: rotate(360deg); } }
.ai-result.hidden { display: none; }
#ai-text { font-size: 13px; line-height: 1.65; white-space: pre-wrap; max-height: 420px; overflow-y: auto; padding: 12px; background: var(--color-bg); border-radius: 8px; margin-bottom: 10px; }
#ai-text {
font-size: 13px; line-height: 1.65;
max-height: 460px; overflow-y: auto;
padding: 14px 16px; background: var(--color-bg);
border-radius: 8px; margin-bottom: 10px;
}
/* Markdown typography inside AI response */
#ai-text h1,#ai-text h2,#ai-text h3,#ai-text h4 {
font-weight: 700; color: var(--color-text-primary);
margin: 14px 0 6px; line-height: 1.3;
}
#ai-text h1 { font-size: 15px; border-bottom: 1px solid var(--color-border); padding-bottom: 4px; }
#ai-text h2 { font-size: 14px; }
#ai-text h3 { font-size: 13px; color: var(--color-brand); }
#ai-text h4 { font-size: 13px; color: var(--color-text-secondary); }
#ai-text p { margin: 6px 0; }
#ai-text ul,#ai-text ol { margin: 6px 0 6px 18px; }
#ai-text li { margin: 3px 0; }
#ai-text li::marker { color: var(--color-brand); }
#ai-text strong { font-weight: 700; color: var(--color-text-primary); }
#ai-text em { font-style: italic; color: var(--color-text-secondary); }
#ai-text code {
font-family: var(--font-mono); font-size: 11px;
background: rgba(0,82,204,0.08); color: var(--color-brand);
padding: 1px 5px; border-radius: 4px;
}
#ai-text blockquote {
border-left: 3px solid var(--color-brand);
margin: 8px 0; padding: 4px 12px;
color: var(--color-text-secondary); background: rgba(0,82,204,0.04);
border-radius: 0 6px 6px 0;
}
#ai-text hr { border: none; border-top: 1px solid var(--color-border); margin: 10px 0; }
#ai-text > *:first-child { margin-top: 0; }
#ai-text > *:last-child { margin-bottom: 0; }
.btn-copy { width: 100%; padding: 8px; background: var(--color-bg); color: var(--color-text-secondary); border: 1px solid var(--color-border); border-radius: var(--radius-btn); font-size: 13px; font-weight: 500; cursor: pointer; font-family: var(--font-base); transition: all 0.15s; }
.btn-copy:hover { border-color: var(--color-brand); color: var(--color-brand); }
.ai-error { font-size: 13px; color: var(--color-red); background: var(--color-red-bg); padding: 10px 12px; border-radius: 8px; margin-top: 8px; }
@ -308,6 +342,7 @@ body { font-family: var(--font-base); background: var(--color-bg); color: var(--
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/marked@12/marked.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@3.0.1/dist/chartjs-plugin-annotation.min.js"></script>
<script>
@ -1156,7 +1191,17 @@ async function runAiAnalysis() {
}
function showAiLoading(show){document.getElementById('ai-loading').classList.toggle('hidden',!show);}
function showAiResult(text){document.getElementById('ai-text').textContent=text;document.getElementById('ai-result').classList.remove('hidden');}
function showAiResult(text){
const el = document.getElementById('ai-text');
if (window.marked) {
// Configure marked: safe renderer, no mangling
marked.setOptions({ breaks: true, gfm: true });
el.innerHTML = marked.parse(text);
} else {
el.textContent = text; // fallback if CDN failed
}
document.getElementById('ai-result').classList.remove('hidden');
}
function showAiError(msg){const el=document.getElementById('ai-error');if(msg){el.textContent=msg;el.classList.remove('hidden');}else el.classList.add('hidden');}
function restoreAiCache(){const c=sessionStorage.getItem('lastAiResponse');if(c)showAiResult(c);}