diff --git a/package.json b/package.json index 658964de0b..57aa011167 100644 --- a/package.json +++ b/package.json @@ -137,6 +137,7 @@ "turndown-plugin-gfm": "^1.0.2", "undici": "^7.3.0", "uuid": "^9.0.1", + "vega": "^6.2.0", "vite-plugin-static-copy": "^2.2.0", "y-prosemirror": "^1.3.7", "yaml": "^2.7.1", diff --git a/src/lib/components/chat/Messages/CodeBlock.svelte b/src/lib/components/chat/Messages/CodeBlock.svelte index 6d6f0a5124..13bc7ec2a1 100644 --- a/src/lib/components/chat/Messages/CodeBlock.svelte +++ b/src/lib/components/chat/Messages/CodeBlock.svelte @@ -6,7 +6,7 @@ import PyodideWorker from '$lib/workers/pyodide.worker?worker'; import { executeCode } from '$lib/apis/utils'; - import { copyToClipboard, renderMermaidDiagram } from '$lib/utils'; + import { copyToClipboard, renderMermaidDiagram, renderVegaVisualization } from '$lib/utils'; import 'highlight.js/styles/github-dark.min.css'; @@ -55,6 +55,7 @@ let _token = null; let mermaidHtml = null; + let vegaHtml = null; let highlightedCode = null; let executing = false; @@ -326,6 +327,11 @@ onUpdate(token); if (lang === 'mermaid' && (token?.raw ?? '').slice(-4).includes('```')) { mermaidHtml = await renderMermaidDiagram(code); + } else if ( + (lang === 'vega' || lang === 'vega-lite') && + (token?.raw ?? '').slice(-4).includes('```') + ) { + vegaHtml = await renderVegaVisualization(code); } }; @@ -397,6 +403,16 @@ {:else}
{code}
{/if} + {:else if lang === 'vega' || lang === 'vega-lite'} + {#if vegaHtml} + + {:else} +
{code}
+ {/if} {:else}
{ return ''; } }; + +export const renderVegaVisualization = async (spec: string) => { + try { + const vega = await import('vega'); + const parsedSpec = JSON.parse(spec); + const view = new vega.View(vega.parse(parsedSpec), { renderer: 'none' }); + const svg = await view.toSVG(); + return svg; + } catch (error) { + console.log('Failed to render Vega visualization:', error); + return ''; + } +};