ソースを参照

Merge pull request #18033 from rgaricano/dev-FEAT_Vega_Visualizer

FEAT: Add Vega Char Visualizer Renderer
Tim Jaeryang Baek 3 日 前
コミット
0a4922b40f
3 ファイル変更31 行追加1 行削除
  1. 1 0
      package.json
  2. 17 1
      src/lib/components/chat/Messages/CodeBlock.svelte
  3. 13 0
      src/lib/utils/index.ts

+ 1 - 0
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",

+ 17 - 1
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}
 				<pre class="mermaid">{code}</pre>
 			{/if}
+		{:else if lang === 'vega' || lang === 'vega-lite'}
+			{#if vegaHtml}
+				<SvgPanZoom
+					className="rounded-3xl max-h-fit overflow-hidden"
+					svg={vegaHtml}
+					content={_token.text}
+				/>
+			{:else}
+				<pre class="vega">{code}</pre>
+			{/if}
 		{:else}
 			<div
 				class="absolute left-0 right-0 py-2.5 pr-3 text-text-300 pl-4.5 text-xs font-medium dark:text-white"

+ 13 - 0
src/lib/utils/index.ts

@@ -1596,3 +1596,16 @@ export const renderMermaidDiagram = async (code: string) => {
 		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 '';
+	}
+};