feat: render AI response as markdown (marked.js)
This commit is contained in:
parent
40882b62ea
commit
5b13383d5b
@ -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; }
|
.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); } }
|
@keyframes spin { to { transform: rotate(360deg); } }
|
||||||
.ai-result.hidden { display: none; }
|
.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 { 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); }
|
.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; }
|
.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>
|
||||||
</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/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 src="https://cdn.jsdelivr.net/npm/chartjs-plugin-annotation@3.0.1/dist/chartjs-plugin-annotation.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
@ -1156,7 +1191,17 @@ async function runAiAnalysis() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function showAiLoading(show){document.getElementById('ai-loading').classList.toggle('hidden',!show);}
|
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 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);}
|
function restoreAiCache(){const c=sessionStorage.getItem('lastAiResponse');if(c)showAiResult(c);}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user