Merge pull request #18068 from rgaricano/dev-FEAT_Vega_Visualizer

UPD: Add Validators & Error Toast for Mermaid & Vega diagrams
This commit is contained in:
Tim Jaeryang Baek 2025-10-05 21:39:25 -05:00 committed by GitHub
commit 08f8713ee1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 37 additions and 33 deletions

View file

@ -326,12 +326,26 @@
const render = async () => { const render = async () => {
onUpdate(token); onUpdate(token);
if (lang === 'mermaid' && (token?.raw ?? '').slice(-4).includes('```')) { if (lang === 'mermaid' && (token?.raw ?? '').slice(-4).includes('```')) {
mermaidHtml = await renderMermaidDiagram(code); try {
mermaidHtml = await renderMermaidDiagram(code);
} catch (error) {
console.error('Failed to render mermaid diagram:', error);
const errorMsg = error instanceof Error ? error.message : String(error);
toast.error($i18n.t('Failed to render diagram') + `: ${errorMsg}`);
mermaidHtml = null;
}
} else if ( } else if (
(lang === 'vega' || lang === 'vega-lite') && (lang === 'vega' || lang === 'vega-lite') &&
(token?.raw ?? '').slice(-4).includes('```') (token?.raw ?? '').slice(-4).includes('```')
) { ) {
vegaHtml = await renderVegaVisualization(code); try {
vegaHtml = await renderVegaVisualization(code);
} catch (error) {
console.error('Failed to render Vega visualization:', error);
const errorMsg = error instanceof Error ? error.message : String(error);
toast.error($i18n.t('Failed to render diagram') + `: ${errorMsg}`);
vegaHtml = null;
}
} }
}; };

View file

@ -1580,39 +1580,29 @@ export const decodeString = (str: string) => {
}; };
export const renderMermaidDiagram = async (code: string) => { export const renderMermaidDiagram = async (code: string) => {
try { const { default: mermaid } = await import('mermaid');
const { default: mermaid } = await import('mermaid'); mermaid.initialize({
mermaid.initialize({ startOnLoad: false, // Should be false when using render API
startOnLoad: true, theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default',
theme: document.documentElement.classList.contains('dark') ? 'dark' : 'default', securityLevel: 'loose'
securityLevel: 'loose' });
}); const parseResult = await mermaid.parse(code, { suppressErrors: false });
if (await mermaid.parse(code)) { if (parseResult) {
const { svg } = await mermaid.render(`mermaid-${uuidv4()}`, code); const { svg } = await mermaid.render(`mermaid-${uuidv4()}`, code);
return svg; return svg;
}
} catch (error) {
console.log('Failed to render mermaid diagram:', error);
return '';
} }
return '';
}; };
export const renderVegaVisualization = async (spec: string) => { export const renderVegaVisualization = async (spec: string, i18n?: any) => {
try { const vega = await import('vega');
const vega = await import('vega'); const parsedSpec = JSON.parse(spec);
const parsedSpec = JSON.parse(spec); let vegaSpec = parsedSpec;
let vegaSpec; if (parsedSpec.$schema && parsedSpec.$schema.includes('vega-lite')) {
if (parsedSpec.$schema && parsedSpec.$schema.includes('vega-lite')) { const vegaLite = await import('vega-lite');
const vegaLite = await import('vega-lite'); vegaSpec = vegaLite.compile(parsedSpec).spec;
vegaSpec = vegaLite.compile(parsedSpec).spec;
} else {
vegaSpec = parsedSpec;
}
const view = new vega.View(vega.parse(vegaSpec), {renderer: 'none'});
const svg = await view.toSVG();
return svg;
} catch (error) {
console.log('Failed to render Vega visualization:', error);
return '';
} }
const view = new vega.View(vega.parse(vegaSpec), { renderer: 'none' });
const svg = await view.toSVG();
return svg;
}; };