Offer the assistant the same formatting the mesh composer has, and drop the mark lower

Colour is chosen by name and mapped to a fixed value here, so the model never writes a style property — the same closed-set rule the mesh store uses.
This commit is contained in:
Gmer4Lfe
2026-08-17 18:01:45 -04:00
parent 2e646f82b4
commit 4eb0a9c608
3 changed files with 48 additions and 2 deletions
+21 -1
View File
@@ -162,7 +162,7 @@ function vv_ai_chat_assets(): void {
.vv-ai-chat-wrap { background:#0b0b0b; border-radius:6px; }
.vv-ai-chat-wrap::before {
content:''; position:absolute; inset:0; z-index:0; pointer-events:none;
background:url('/plugins/varaverk/icons/varaverk.png') center 58%/min(84%,520px) no-repeat;
background:url('/plugins/varaverk/icons/varaverk.png') center 74%/min(84%,520px) no-repeat;
opacity:.032; filter:grayscale(1);
}
.vv-ai-empty { color:#3a3a3a; font-size:12px; text-align:center; padding:60px 20px; line-height:1.7; }
@@ -789,12 +789,32 @@ vv_ai_profiles_script();
+ `<pre><code>${body}</code></pre></div>`;
}
// The same palette the mesh composer offers, by NAME only. The model never supplies a colour
// value — it picks from this list and the hex is looked up here, so nothing it writes can
// become a style property. Same closed-set principle as vv_nc_clean_style() on the server.
const FMT_COLORS = { green:'#4caf50', blue:'#4a9eff', amber:'#ff9800',
red:'#ef5350', violet:'#ab7df6', grey:'#bdbdbd' };
// ── Minimal markdown, applied strictly after escaping ────────────────
function fmt(text) {
let h = esc(text);
h = h.replace(/```(\w*)\n([\s\S]*?)```/g, (m, l, c) => codeCard(l, c));
h = h.replace(/`([^`\n]+)`/g, '<code>$1</code>');
h = h.replace(/\*\*([^*\n]+)\*\*/g, '<strong>$1</strong>');
// Emphasis and size. Single-asterisk italics run after bold so ** is already consumed.
h = h.replace(/(^|[^*])\*([^*\n]+)\*(?!\*)/g, '$1<em>$2</em>');
h = h.replace(/__([^_\n]+)__/g, '<u>$1</u>');
h = h.replace(/\{big\}([\s\S]*?)\{\/big\}/g, '<span style="font-size:15px">$1</span>');
h = h.replace(/\{small\}([\s\S]*?)\{\/small\}/g, '<span style="font-size:11px">$1</span>');
// {green}…{/green}. An unknown name is left as written rather than guessed at — a colour
// nobody chose is worse than a pair of braces the reader can see and ignore.
h = h.replace(/\{(\w+)\}([\s\S]*?)\{\/\1\}/g, (m, name, inner) => {
const c = FMT_COLORS[name.toLowerCase()];
return c ? `<span style="color:${c}">${inner}</span>` : m;
});
h = h.replace(/\[(\d+)\]/g, '<span class="vv-ai-cite" data-cite="$1">[$1]</span>');
return h;
}