@vizhub/runtime 4.4.0 → 4.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,8 @@
5
5
 
6
6
  A powerful, flexible runtime environment for executing code sandboxes in the browser. `@vizhub/runtime` powers [VizHub](https://vizhub.com/) and can be used to build similar interactive coding platforms.
7
7
 
8
+ > **Latest (v4.6.0):** Upgraded all dependencies (Vite 8, Vitest 4, TS 6, Puppeteer 25, Svelte 5.56+), hardened test infrastructure, improved TypeScript config, and added a React+D3 combo demo fixture — see [Changelog](#changelog).
9
+
8
10
  ## Overview
9
11
 
10
12
  `@vizhub/runtime` intelligently detects the appropriate runtime version based on the provided files and generates executable HTML that can be used within an iframe's `srcdoc` attribute. It handles everything from simple HTML/JS/CSS combinations to complex module bundling, dependency resolution, and cross-viz imports.
@@ -365,7 +367,8 @@ const runtime = createRuntime({
365
367
  setBuildErrorMessage?: (error: string | null) => void,
366
368
  getLatestContent?: (vizId: string) => Promise<VizContent | null>,
367
369
  resolveSlugKey?: (slugKey: string) => Promise<string | null>,
368
- writeFile?: (fileName: string, content: string) => void
370
+ writeFile?: (fileName: string, content: string) => void,
371
+ handleRuntimeError?: (formattedErrorMessage: string) => void
369
372
  });
370
373
  ```
371
374
 
@@ -373,10 +376,13 @@ const runtime = createRuntime({
373
376
 
374
377
  - **iframe**: `HTMLIFrameElement` - The iframe element where the viz will be rendered
375
378
  - **worker**: `Worker` - Web Worker instance that handles code building
376
- - **setBuildErrorMessage**: `(error: string | null) => void` - Optional callback for handling build errors
379
+ - **setBuildErrorMessage**: `(error: string | null) => void` - Optional callback for handling build-time errors
377
380
  - **getLatestContent**: `(vizId: string) => Promise<VizContent | null>` - Optional function to fetch viz content for cross-viz imports
378
381
  - **resolveSlugKey**: `(slugKey: string) => Promise<string | null>` - Optional function to resolve viz slugs to IDs
379
382
  - **writeFile**: `(fileName: string, content: string) => void` - Optional callback when code running in the iframe writes files
383
+ - **handleRuntimeError**: `(formattedErrorMessage: string) => void` - Optional callback for handling runtime errors (exceptions thrown during viz execution)
384
+
385
+ > **Security note (v4.5.1):** The `windowListener` inside `createRuntime` now filters messages by `event.source` to ensure it only processes messages from its own iframe. Previously, any `window.postMessage` with matching types (`runtimeError`, `runError`, `runDone`, `writeFile`) from any iframe on the page would be handled by this runtime, which could cause cross-iframe contamination when multiple runtimes are active (e.g., on an AI edit review page showing a "Before" and "After" comparison).
380
386
 
381
387
  ##### Returns
382
388
 
@@ -434,6 +440,12 @@ runtime.run({
434
440
  runtime.cleanup();
435
441
  ```
436
442
 
443
+ ### Running in Multiple-Iframe Pages
444
+
445
+ When using multiple `createRuntime` instances on the same page (e.g., a before/after comparison view), each runtime previously processed `window.postMessage` events from all iframes, not just its own. This caused runtime errors from one viz to appear as errors in an unrelated viz.
446
+
447
+ As of v4.5.1, each runtime filters messages by `event.source`, so errors only display in the correct iframe.
448
+
437
449
  ### Building HTML Only
438
450
 
439
451
  ```javascript
@@ -611,6 +623,50 @@ Before finalizing a PR and marking it ready for review, please ensure that:
611
623
  - Running `npm run preflight` passes without errors
612
624
  - The demo app is still working - run `npm run demo` and click through the green buttons to see if everything still works
613
625
 
626
+ ## Changelog
627
+
628
+ ### v4.6.0 — Dependency upgrades & test infrastructure hardening
629
+
630
+ **Dependency upgrades:**
631
+
632
+ - Vite 7 → 8
633
+ - Vitest 3 → 4
634
+ - TypeScript 5 → 6
635
+ - Puppeteer 24 → 25
636
+ - Svelte 5.38 → 5.56
637
+ - Rollup 4.50 → 4.62
638
+ - All other devDeps and runtime deps updated to latest
639
+
640
+ **Test infrastructure hardening:**
641
+
642
+ - Added `--no-sandbox` flag to all Puppeteer `launch()` calls for CI compatibility
643
+ - Safer `browser.close()` with null guard in `afterAll` hooks
644
+ - Type-safe stack trace parsing in `testStackTrace.ts` (error instanceof Error check, safer line number extraction)
645
+ - Cleaned up stale comments and removed unused imports
646
+
647
+ **TypeScript config:**
648
+
649
+ - Added `rootDir: "./src"` for correct declaration output structure
650
+ - Changed `moduleResolution` to `"bundler"` for alignment with Vite's resolution strategy
651
+
652
+ **Demo app:**
653
+
654
+ - Added new `reactD3Combo` fixture demonstrating React + D3 integration
655
+ - Fixed Vite `optimizeDeps.include` for transitive CJS deps (sucrase, ts-interface-checker)
656
+ - Extended `server.fs.allow` for WASM file access from @rollup/browser
657
+
658
+ ### v4.5.1 — Cross-iframe message contamination fix
659
+
660
+ **Fixed:** The `windowListener` in `createRuntime` now checks `event.source !== iframe.contentWindow` before processing `runDone`, `runError`, `runtimeError`, and `writeFile` messages.
661
+
662
+ **Background:** When multiple `createRuntime` instances (or a `createRuntime` plus raw srcdoc-based iframes built via `buildPreviewHtml`) coexist on the same page, all iframes call `parent.postMessage(...)` with the same message types. Without the source check, one runtime could display errors from another iframe's viz, leading to confusing error reports in the wrong view (e.g., an "After" variant's AI-generated code error showing up in the "Before" comparison panel).
663
+
664
+ **Impact:** All consumers of `@vizhub/runtime` that run multiple iframes on one page benefit from this fix automatically — no code changes required.
665
+
666
+ ### v4.5.0 — Original release (current feature set)
667
+
668
+ Supports runtime versions v1–v4 with Rollup bundling, Svelte compilation, cross-viz imports, import maps, hot reloading, and more.
669
+
614
670
  ## License
615
671
 
616
672
  This project is licensed under the MIT License - see the LICENSE file for details.
@@ -0,0 +1,301 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports),s=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},c=(n,r,a)=>(a=n==null?{}:e(i(n)),s(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));let l=require("magic-sandbox"),u=require("@vizhub/viz-utils"),d=require("sucrase");var f=()=>(Math.random()+``).slice(2);function p(e={}){return{name:`sucrase`,transform(t,n){if(!n.match(/\.(?:js|[jt]sx)$/))return null;let r=(0,d.transform)(t,{transforms:[`jsx`,`typescript`],filePath:n,sourceMapOptions:{compiledFilename:`bundle.js`},production:!0,...e});return{code:r.code,map:r.sourceMap}}}}var m={dependencies:{},vizhub:{},license:`MIT`},h=e=>{let t=e[`package.json`];try{return t?JSON.parse(t):m}catch{return m}},g=e=>h(e).dependencies||{},_=e=>(h(e).vizhub||{}).libraries||{},v=({name:e,version:t},n,r=`jsdelivr`)=>{let i=n[e]&&n[e].path||``;return r===`jsdelivr`?`https://cdn.jsdelivr.net/npm/${e}@${t}${i}`:`https://unpkg.com/${e}@${t}${i}`},y=e=>{let t=e?.vizhub?.libraries;return t?Object.entries(t).reduce((e,[t,n])=>(n.global&&(e[t]=n.global),e),{}):{}},ee={d3:`d3`,react:`React`,"react-dom":`ReactDOM`},b=e=>{let t=y(e);return{...ee,...t}},x=e=>{let[t,...n]=e.split(`/`);return{vizId:t,fileName:n.join(`/`)}},te=`var EOL = {},
2
+ EOF = {},
3
+ QUOTE = 34,
4
+ NEWLINE = 10,
5
+ RETURN = 13;
6
+
7
+ function objectConverter(columns) {
8
+ return new Function(
9
+ 'd',
10
+ 'return {' +
11
+ columns
12
+ .map(function (name, i) {
13
+ return (
14
+ JSON.stringify(name) + ': d[' + i + '] || ""'
15
+ );
16
+ })
17
+ .join(',') +
18
+ '}',
19
+ );
20
+ }
21
+
22
+ function customConverter(columns, f) {
23
+ var object = objectConverter(columns);
24
+ return function (row, i) {
25
+ return f(object(row), i, columns);
26
+ };
27
+ }
28
+
29
+ function dsv(delimiter) {
30
+ var DELIMITER = delimiter.charCodeAt(0);
31
+
32
+ function parse(text, f) {
33
+ var convert,
34
+ columns,
35
+ rows = parseRows(text, function (row, i) {
36
+ if (convert) return convert(row, i - 1);
37
+ (columns = row),
38
+ (convert = f
39
+ ? customConverter(row, f)
40
+ : objectConverter(row));
41
+ });
42
+ rows.columns = columns || [];
43
+ return rows;
44
+ }
45
+
46
+ function parseRows(text, f) {
47
+ var rows = [], // output rows
48
+ N = text.length,
49
+ I = 0, // current character index
50
+ n = 0, // current line number
51
+ t, // current token
52
+ eof = N <= 0, // current token followed by EOF?
53
+ eol = false; // current token followed by EOL?
54
+
55
+ // Strip the trailing newline.
56
+ if (text.charCodeAt(N - 1) === NEWLINE) --N;
57
+ if (text.charCodeAt(N - 1) === RETURN) --N;
58
+
59
+ function token() {
60
+ if (eof) return EOF;
61
+ if (eol) return (eol = false), EOL;
62
+
63
+ // Unescape quotes.
64
+ var i,
65
+ j = I,
66
+ c;
67
+ if (text.charCodeAt(j) === QUOTE) {
68
+ while (
69
+ (I++ < N && text.charCodeAt(I) !== QUOTE) ||
70
+ text.charCodeAt(++I) === QUOTE
71
+ );
72
+ if ((i = I) >= N) eof = true;
73
+ else if ((c = text.charCodeAt(I++)) === NEWLINE)
74
+ eol = true;
75
+ else if (c === RETURN) {
76
+ eol = true;
77
+ if (text.charCodeAt(I) === NEWLINE) ++I;
78
+ }
79
+ return text.slice(j + 1, i - 1).replace(/""/g, '"');
80
+ }
81
+
82
+ // Find next delimiter or newline.
83
+ while (I < N) {
84
+ if ((c = text.charCodeAt((i = I++))) === NEWLINE)
85
+ eol = true;
86
+ else if (c === RETURN) {
87
+ eol = true;
88
+ if (text.charCodeAt(I) === NEWLINE) ++I;
89
+ } else if (c !== DELIMITER) continue;
90
+ return text.slice(j, i);
91
+ }
92
+
93
+ // Return last token before EOF.
94
+ return (eof = true), text.slice(j, N);
95
+ }
96
+
97
+ while ((t = token()) !== EOF) {
98
+ var row = [];
99
+ while (t !== EOL && t !== EOF)
100
+ row.push(t), (t = token());
101
+ if (f && (row = f(row, n++)) == null) continue;
102
+ rows.push(row);
103
+ }
104
+
105
+ return rows;
106
+ }
107
+
108
+ return {
109
+ parse: parse,
110
+ };
111
+ }
112
+
113
+ var csv = dsv(',');
114
+
115
+ var csvParse = csv.parse;
116
+
117
+ var tsv = dsv(' ');
118
+
119
+ var tsvParse = tsv.parse;
120
+
121
+ export { csvParse, tsvParse };`,S=e=>e.replace(/\\/g,`\\\\`).replace(/`/g,"\\`"),C=()=>({name:`transformDSV`,transform:async(e,t)=>{let{vizId:n,fileName:r}=x(t),i=r.endsWith(`.csv`),a=r.endsWith(`.tsv`);if(i||a)return{code:`
122
+ ${te}
123
+ const data = ${i?`csvParse`:`tsvParse`}(\`${S(e)}\`);
124
+ export default data;
125
+ `,map:{mappings:``}}}}),w=e=>{let t=e.match(/^@([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)$/);return t?{userName:t[1],idOrSlug:t[2]}:null},T=({vizId:e,slugCache:t})=>({name:`vizResolve`,resolveId:async(n,r)=>{if(n.startsWith(`./`)&&!r?.startsWith(`https://`)){let t=n.substring(2);if(!t.endsWith(`.js`)&&!t.endsWith(`.css`)&&!t.endsWith(`.csv`)&&!t.endsWith(`.svelte`)&&!t.endsWith(`.png`)&&!t.endsWith(`.jpg`)&&!t.endsWith(`.jpeg`)&&!t.endsWith(`.gif`)&&!t.endsWith(`.svg`)&&!t.endsWith(`.webp`)&&!t.endsWith(`.bmp`)&&(t+=`.js`),r){let{vizId:e,fileName:n}=x(r),i=n.split(`/`).slice(0,-1).join(`/`);return`${e}/${i?`${i}/${t}`:t}`}return e+`/`+t}let i=w(n);if(i){let e;if((0,u.isVizId)(i.idOrSlug))e=i.idOrSlug;else{if(!t)throw Error(`slugCache is required to import by slug in v3 runtime`);e=await t.get(`${i.userName}/${i.idOrSlug}`)}return e+`/index.js`}}}),ne=[`.jpg`,`.jpeg`,`.png`,`.gif`,`.svg`,`.webp`,`.bmp`],E=e=>{let t=e.toLowerCase().split(`.`).pop();return t?ne.includes(`.${t}`):!1},re=e=>{switch(e.toLowerCase().split(`.`).pop()){case`jpg`:case`jpeg`:return`image/jpeg`;case`png`:return`image/png`;case`gif`:return`image/gif`;case`svg`:return`image/svg+xml`;case`webp`:return`image/webp`;case`bmp`:return`image/bmp`;default:return`image/png`}},ie=e=>{let t=e.replace(/\s/g,``);return/^[A-Za-z0-9+/]*={0,2}$/.test(t)},D=(e,t)=>{let n=re(e);return e.toLowerCase().split(`.`).pop()===`svg`&&!ie(t)?`data:${n};utf8,${encodeURIComponent(t)}`:`data:${n};base64,${t}`},O=(e,t)=>e.replace(/<img([^>]*)\s+src=["']([^"']+)["']([^>]*)>/gi,(e,n,r,i)=>t[r]!==void 0&&E(r)?`<img${n} src="${D(r,t[r])}"${i}>`:e),ae=({vizCache:e,trackCSSImport:t,vizId:n,files:r})=>({name:`vizLoad`,load:async i=>{let a=x(i),o=a.vizId,s=a.fileName;if(s.endsWith(`.css`))return t(i),``;let c=null;if(c=o===n&&r?r[s]||null:(0,u.getFileText)(await e.get(o),s),c===null)throw Error(`Imported file "${s}" not found.`);return E(s)?`export default "${D(s,c)}";`:c}}),k=new Map,A=new Map,j,M=`https://cdn.jsdelivr.net/npm/svelte@5.37.1`,N=`${M}/compiler/index.js`;async function P(e){let t=A.get(e);if(t)return t;for(let t of[`.js`,`/index.js`]){let n=`${e}${t}`;try{if((await fetch(n,{method:`HEAD`})).ok)return A.set(e,n),n}catch{continue}}let n=`${e}.js`;return A.set(e,n),n}var oe=({getSvelteCompiler:e})=>({name:`transformSvelte`,load:async e=>{if(e===`virtual:esm-env`)return`
126
+ export const BROWSER = true;
127
+ export const DEV = true;
128
+ export const NODE = false;
129
+ export const PROD = false;
130
+ `;if(!e.startsWith(M))return;let t=k.get(e);if(t)return t;let n=await fetch(e).then(e=>e.text());return k.set(e,n),n},resolveId:async(e,t)=>{if(e===`esm-env`)return`virtual:esm-env`;if(e===`svelte`)return`${M}/src/index-client.js`;if(e.startsWith(`svelte/`))return await P(`${M}/src/${e.slice(7)}`);if(e.startsWith(`#client/`))return await P(`${M}/src/internal/client/${e.slice(8)}`);if(/^https?:/.test(e))return e;if(e.startsWith(`.`)&&t&&t.startsWith(M)){let n=new URL(e,t).href;return new URL(e,t).href,n}},transform:async(t,n)=>{let{fileName:r}=x(n);if(r.endsWith(`.svelte`)){if(!j){if(!e)throw Error(`Svelte compiler not available`);j=await e()}let n=j(t,{filename:r,generate:`client`,css:`external`,dev:!1}),i=n.js.code;return n.css&&n.css.code&&(i=`
131
+ // Auto-inject CSS for Svelte component
132
+ (function() {
133
+ if (typeof document !== 'undefined') {
134
+ const style = document.createElement('style');
135
+ style.textContent = ${JSON.stringify(n.css.code)};
136
+ document.head.appendChild(style);
137
+ }
138
+ })();
139
+ `+i),i}}}),F=async({files:e,rollup:t,enableSourcemap:n=!0,vizCache:r,vizId:i,slugCache:a,getSvelteCompiler:o})=>{let s=new Set,c=e=>{s.add(e)};if(!e[`index.js`])throw Error(`Missing index.js`);let l={name:`replace`,transform(e,t){let n=!1,r=e;return r.includes(`process.env.NODE_ENV`)&&(r=r.replace(/\bprocess\.env\.NODE_ENV\b/g,JSON.stringify(`production`)),n=!0),n?{code:r,map:null}:null}},u={input:`./index.js`,plugins:[...i?[T({vizId:i,slugCache:a})]:[],C(),p(),oe({getSvelteCompiler:o}),l,...r?[ae({vizCache:r,trackCSSImport:c,vizId:i,files:e})]:[]],onwarn(e,t){e.code!==`UNRESOLVED_IMPORT`&&t(e)}},d={format:`umd`,name:`Viz`,sourcemap:!!n,compact:!0},f=h(e);if(f){let e=b(f);e&&(u.external=Object.keys(e),d.globals=e)}u.external||=[],d.globals||={},Array.isArray(u.external)&&(u.external=u.external.filter(e=>typeof e==`string`&&!e.startsWith(`#client/`)));let{output:m}=await(await t(u)).generate(d);return{src:m[0].code,cssFiles:Array.from(s)}},se=e=>{if(e instanceof Error){let t=e.stack||``,n=e.message||`Unknown error`;return`${e.name||`Error`}: ${n}\n${t}`}else if(`error`in e&&e.error instanceof Error){let t=e.error,n=t.stack||``,r=t.message||`Unknown error`,i=`filename`in e?e.filename:``,a=`lineno`in e?e.lineno:``,o=`colno`in e?e.colno:``,s=``;return i&&a&&(s=` at ${i}:${a}`,o&&(s+=`:${o}`)),`${t.name||`Error`}: ${r}${s}\n${n}`}else if(`reason`in e){let t=e.reason;if(t instanceof Error){let e=t.stack||``,n=t.message||`Unknown error`;return`Unhandled Promise Rejection - ${t.name||`Error`}: ${n}\n${e}`}else return`Unhandled Promise Rejection: ${String(t)}`}else return`Unknown runtime error: ${String(e)}`},I=()=>`
140
+ // Global error handling for runtime errors
141
+ (() => {
142
+ const formatRuntimeError = ${se.toString()};
143
+
144
+ // Handle uncaught JavaScript errors
145
+ window.addEventListener('error', (event) => {
146
+ const formattedErrorMessage = formatRuntimeError(event);
147
+ parent.postMessage({
148
+ type: 'runtimeError',
149
+ formattedErrorMessage
150
+ }, "*");
151
+ });
152
+
153
+ // Handle unhandled promise rejections
154
+ window.addEventListener('unhandledrejection', (event) => {
155
+ const formattedErrorMessage = formatRuntimeError(event);
156
+ parent.postMessage({
157
+ type: 'runtimeError',
158
+ formattedErrorMessage
159
+ }, "*");
160
+ });
161
+ })();
162
+ `;function L(){return Math.random().toString().slice(2,7)}var R=({cdn:e,src:t,styles:n})=>{let r=`viz-container-${L()}`;return`<!DOCTYPE html>
163
+ <html>
164
+ <head>
165
+ <meta charset="utf-8">${e}${n}
166
+ <style>
167
+ body {
168
+ margin: 0;
169
+ overflow: hidden;
170
+ }
171
+ #${r} {
172
+ height: 100vh;
173
+ }
174
+ </style>
175
+ </head>
176
+ <body>
177
+ <div id="${r}"></div>
178
+ <script>${I()}<\/script>
179
+ <script id="injected-script">${t}<\/script>
180
+ <script>
181
+ (() => {
182
+ let cleanup;
183
+ const render = () => {
184
+ const container = document.getElementById('${r}');
185
+ typeof cleanup === 'function' && cleanup();
186
+ cleanup = (Viz.viz || Viz.main)(container, { state: window.state, setState, writeFile });
187
+ };
188
+ const setState = (next) => {
189
+ window.state = next(window.state);
190
+ render();
191
+ };
192
+ const writeFile = (fileName, content) => {
193
+ parent.postMessage({ type: 'writeFile', fileName, content }, "*");
194
+ };
195
+ const run = () => {
196
+ try {
197
+ setState((state) => state || {});
198
+ } catch (error) {
199
+ console.error(error);
200
+ parent.postMessage({ type: 'runError', error }, "*");
201
+ }
202
+ }
203
+ run();
204
+ const runJS = (src) => {
205
+ document.getElementById('injected-script')?.remove();
206
+ const script = document.createElement('script');
207
+ script.textContent = src;
208
+ script.id = 'injected-script';
209
+ document.body.appendChild(script);
210
+ run();
211
+ };
212
+ const runCSS = (css) => {
213
+ let style = document.getElementById('injected-style');
214
+ if (!style) {
215
+ style = document.createElement('style');
216
+ style.type = 'text/css';
217
+ style.id = 'injected-style';
218
+ document.head.appendChild(style);
219
+ }
220
+ style.textContent = css;
221
+ };
222
+ onmessage = (message) => {
223
+ switch (message.data.type) {
224
+ case 'runJS':
225
+ runJS(message.data.js);
226
+ parent.postMessage({ type: 'runDone' }, "*");
227
+ break;
228
+ case 'runCSS':
229
+ runCSS(message.data.css);
230
+ break;
231
+ case 'ping':
232
+ parent.postMessage({ type: 'pong' }, "*");
233
+ break;
234
+ default:
235
+ break;
236
+ }
237
+ }
238
+ })();
239
+ <\/script>
240
+ </body>
241
+ </html>`},z=async({files:e,rollup:t,enableSourcemap:n=!0,vizCache:r,vizId:i,slugCache:a,getSvelteCompiler:o})=>{let{src:s,cssFiles:c}=await F({files:e,rollup:t,enableSourcemap:n,vizCache:r,vizId:i,slugCache:a,getSvelteCompiler:o}),l=[];if(c.length>0)for(let t=0;t<c.length;t++){let n=c[t],a=x(n),o=a.vizId,s=a.fileName,d=null;d=o===i&&e?e[s]||null:(0,u.getFileText)(await r.get(o),s),d&&l.push(d)}let d=l.join(`
242
+ `),f=`\n <style id="injected-style">${d}</style>`,p=``,m=Object.entries(g(e));if(m.length>0){let t=_(e);p=m.map(([e,n],r)=>{let i=v({name:e,version:n},t);return`${r>0?` `:`
243
+ `}<script src="${i}"><\/script>`}).join(``)}return{html:R({cdn:p,src:s,styles:f}),css:d,js:s,runtimeVersion:`v3`}},B=({initialContents:e,handleCacheMiss:t})=>{let n=new Map(e.map(e=>[e.id,e]));return{get:async e=>{let r=n.get(e);if(r!==void 0)return r;if(!t)throw Error(`Unresolved import from vizId ${e}, cache miss handler not provided.`);let i=await t(e);if(i)return n.set(e,i),i;throw Error(`Unresolved import from vizId ${e}`)},set:e=>{n.set(e.id,e)},invalidate:e=>{n.delete(e)}}},V=({initialMappings:e={},handleCacheMiss:t})=>({get:async n=>{let r=e[n];if(r!==void 0)return r;if(!t)throw Error(`Unresolved slug ${n}, cache miss handler not provided.`);let i=await t(n);if(i)return e[n]=i,i;throw Error(`Unresolved slug ${n}`)},set:(t,n)=>{e[t]=n},invalidate:t=>{delete e[t]}}),H=({rawMessage:e,vizId:t})=>{let n=new RegExp(t,`g`);return e?.replace(n,`.`)},U=(e,t=`Sample Content for Exporting`,n=(0,u.generateVizId)())=>({id:n,files:(0,u.fileCollectionToVizFiles)(e),title:t}),W=e=>{if(Object.keys(e).length===0)return null;let t=`index.html`in e,n=`index.js`in e,r=`index.jsx`in e;return t?e[`index.html`].includes(`type="module"`)?`v4`:n||r?`v2`:`v1`:!t&&n?`v3`:null},G=(e,t)=>RegExp(`<${t}\\b`,`i`).test(e)&&RegExp(`</${t}>`,`i`).test(e),K=e=>{let t=e.trim();return G(t,`html`)&&G(t,`head`)&&G(t,`body`)?t:`<html><head></head><body>${t}</body></html>`},ce=(e,t)=>e.replace(RegExp(`<script[^>]*src=["'][^"']*${t.source}[^"']*["'][^>]*>\\s*<\/script>`,`gi`),``),q=(e,t,n)=>e.replace(new RegExp(t,`i`),`${n}${t}`),le=(e,t)=>{let n=K(e),r=Object.entries(g(t));if(r.length){let e=_(t);r.forEach(([e])=>{n=ce(n,RegExp(`${e}@`))});let i=r.map(([t,n])=>v({name:t,version:n},e)).map(e=>`<script src="${e}"><\/script>`).join(`
244
+ `);n=q(n,`</head>`,i+`
245
+ `)}if(t[`bundle.js`]!==void 0||t[`index.js`]!==void 0){let e=/<script\b[^>]*\bsrc=["']bundle\.js["'][^>]*>\s*<\/script>/gi,t=[...n.matchAll(e)];t.length===1&&(()=>{let e=t[0].index??-1;if(e===-1)return!1;let r=n.search(/<body\b[^>]*>/i),i=n.search(/<\/body>/i);return r!==-1&&i!==-1&&e>r&&e<i})()||(n=n.replace(e,``),n=q(n,`</body>`,`<script src="bundle.js"><\/script>`))}let i=`<script>${I()}<\/script>\n`;return n=q(n,`</head>`,i),/^\s*<!DOCTYPE/i.test(n)?n:`<!DOCTYPE html>${n}`},ue=e=>{let t=e[`index.html`];return!t&&!e[`index.js`]&&!e[`bundle.js`]?``:le(t||`<!DOCTYPE html><html><head></head><body></body></html>`,e)},de=c(o(((e,t)=>{t.exports={d3:`d3`,"d3-array":`d3`,"d3-axis":`d3`,"d3-brush":`d3`,"d3-chord":`d3`,"d3-collection":`d3`,"d3-color":`d3`,"d3-contour":`d3`,"d3-dispatch":`d3`,"d3-drag":`d3`,"d3-dsv":`d3`,"d3-ease":`d3`,"d3-fetch":`d3`,"d3-force":`d3`,"d3-format":`d3`,"d3-geo":`d3`,"d3-hierarchy":`d3`,"d3-interpolate":`d3`,"d3-path":`d3`,"d3-polygon":`d3`,"d3-quadtree":`d3`,"d3-random":`d3`,"d3-scale":`d3`,"d3-scale-chromatic":`d3`,"d3-selection":`d3`,"d3-shape":`d3`,"d3-tile":`d3`,"d3-time":`d3`,"d3-time-format":`d3`,"d3-timer":`d3`,"d3-transition":`d3`,"d3-voronoi":`d3`,"d3-zoom":`d3`,react:`React`,"react-dom":`ReactDOM`,"react-dropdown-browser":`ReactDropdown`,"react-dropdown":`ReactDropdown`,three:`THREE`,vega:`vega`,"vega-embed":`vegaEmbed`,"vega-lite":`vegaLite`,"vega-lite-api":`vl`,"vega-tooltip":`vegaTooltip`,"vega-themes":`vegaThemes`,"vizhub-vega-lite-config":`vizhubVegaLiteConfig`,semiotic:`Semiotic`,"viz.js":`Viz`}}))(),1),J=`\0virtual:`,fe=e=>{let t=e.replace(/^\.\//,``);return t=t.replace(/\/+/g,`/`),t=t.replace(/\/$/,``),t},pe=(e,t)=>{let n=e.includes(`/`)?e.slice(0,e.lastIndexOf(`/`)):``,r=t.split(`/`),i=n?n.split(`/`):[];for(let e of r)e===`..`?i.pop():e!==`.`&&e!==``&&i.push(e);return i.join(`/`)},Y=e=>({name:`virtual-file-system`,resolveId(t,n){let r=n?.startsWith(`\0virtual:`)?n.slice(9):n;if(t.startsWith(`./`)||t.startsWith(`../`)){let n=fe(r?pe(r,t):t);if(e[n])return J+n;for(let t of[`.js`,`.jsx`,`.ts`,`.tsx`]){let r=n+t;if(e[r])return J+r}}if(e[t])return J+t;for(let n of[`.js`,`.jsx`,`.ts`,`.tsx`]){let r=t+n;if(e[r])return J+r}return null},load(t){if(t.startsWith(`\0virtual:`)){let n=t.slice(9);if(e[n])return E(n)?`export default "${D(n,e[n])}";`:e[n]}return null}}),me=async({files:e,rollup:t,enableSourcemap:n=!0})=>{let r=`index.js`;if(!e[r]&&(r=`index.jsx`,!e[r]))throw Error(`Missing entry point, can't find index.js or index.jsx`);let i={input:`./`+r,plugins:[Y(e),p()],onwarn(e,t){e.code!==`UNRESOLVED_IMPORT`&&t(e)}},a={format:`iife`,sourcemap:n},o=h(e);if(o){let e={...de.default,...b(o)};e&&(i.external=Object.keys(e),a.globals=e)}let{output:s}=await(await t(i)).generate(a);return s[0].code},he=async({files:e,rollup:t,enableSourcemap:n})=>({...e,"bundle.js":await me({files:e,rollup:t,enableSourcemap:n}),"index.html":ue(e)}),ge=e=>{let t=[],n=[],r=/<script\b([^>]*)>([\s\S]*?)<\/script>/gi,i,a=0;for(;(i=r.exec(e))!==null;){let e=i[1],r=i[2];if(!/\btype\s*=\s*["']module["']/i.test(e))continue;let o=e.match(/\bsrc\s*=\s*["']([^"']+)["']/i);if(o)t.push(o[1]);else if(r.trim()){let e=`__inline_script_${a++}.js`;n.push({id:e,content:r.trim()}),t.push(e)}}return{entryPoints:t,inlineScripts:n}},_e=()=>({name:`catch-all-prevent-fs`,resolveId(e,t){return{id:e,external:!0}}}),ve=async({entryPoint:e,files:t,rollup:n,enableSourcemap:r=!0})=>{let{output:i}=await(await n({input:e.startsWith(`./`)?e:`./${e}`,plugins:[Y(t),p({jsxRuntime:`automatic`}),_e()],onwarn(e,t){}})).generate({format:`es`,sourcemap:r});return i[0].code},X=(e,t)=>RegExp(`<${t}\\b`,`i`).test(e)&&RegExp(`</${t}>`,`i`).test(e),ye=e=>{let t=e.trim();return X(t,`html`)&&X(t,`head`)&&X(t,`body`)?t:`<html><head></head><body>${t}</body></html>`},Z=e=>e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`),Q=(e,t,n)=>e.replace(new RegExp(t,`i`),`${n}${t}`),be=e=>{let t=g(e);if(Object.keys(t).length===0)return null;let n=_(e),r={};for(let[e,i]of Object.entries(t))r[e]=v({name:e,version:i},n);return JSON.stringify({imports:r},null,2)},xe=()=>`
246
+ // V4 Hot Reloading Support
247
+ (() => {
248
+ const runJS = (js) => {
249
+ // Remove all existing bundled module scripts
250
+ const existingScripts = document.querySelectorAll('script[type="module"]');
251
+ existingScripts.forEach(script => {
252
+ // Only remove scripts that contain bundled code (not import maps or external scripts)
253
+ if (script.textContent && script.textContent.trim()) {
254
+ script.remove();
255
+ }
256
+ });
257
+
258
+ // Create new script with updated bundled code
259
+ const script = document.createElement('script');
260
+ script.type = 'module';
261
+ script.textContent = js;
262
+ document.body.appendChild(script);
263
+ };
264
+
265
+ const runCSS = (css) => {
266
+ let style = document.getElementById('v4-injected-style');
267
+ if (!style) {
268
+ style = document.createElement('style');
269
+ style.type = 'text/css';
270
+ style.id = 'v4-injected-style';
271
+ document.head.appendChild(style);
272
+ }
273
+ style.textContent = css;
274
+ };
275
+
276
+ // Listen for hot reload messages
277
+ window.addEventListener('message', (message) => {
278
+ switch (message.data.type) {
279
+ case 'runJS':
280
+ try {
281
+ runJS(message.data.js);
282
+ parent.postMessage({ type: 'runDone' }, "*");
283
+ } catch (error) {
284
+ console.error('V4 Hot reload error:', error);
285
+ parent.postMessage({ type: 'runError', error }, "*");
286
+ }
287
+ break;
288
+ case 'runCSS':
289
+ runCSS(message.data.css);
290
+ break;
291
+ case 'ping':
292
+ parent.postMessage({ type: 'pong' }, "*");
293
+ break;
294
+ default:
295
+ break;
296
+ }
297
+ });
298
+ })();
299
+ `,Se=(e,t,n=[],r=!1)=>{if(!e[`index.html`])return``;let i=ye(e[`index.html`]);t.forEach((e,t)=>{if(n.some(e=>e.id===t)){let r=Z(n.find(e=>e.id===t)?.content||``),a=RegExp(`<script\\b[^>]*\\btype=["']module["'][^>]*>\\s*${r}\\s*<\/script>`,`gi`);i=i.replace(a,`<script type="module">\n${e}\n<\/script>`)}else{let n=RegExp(`<script\\b[^>]*\\bsrc=["']${Z(t)}["'][^>]*>[^<]*<\/script>`,`gi`);i=i.replace(n,`<script type="module">\n${e}\n<\/script>`)}});let a=be(e);if(a&&!/<script\b[^>]*type=["']importmap["'][^>]*>/i.test(i)){let e=`<script type="importmap">\n${a}\n<\/script>\n`;i=Q(i,`</head>`,e)}let o=`<script>${I()}<\/script>\n`;if(i=Q(i,`</head>`,o),r){let e=`<script>${xe()}<\/script>\n`;i=Q(i,`</body>`,e)}return/^\s*<!DOCTYPE/i.test(i)?i:`<!DOCTYPE html>${i}`},Ce=async({files:e,rollup:t,enableSourcemap:n=!0})=>{let{entryPoints:r,inlineScripts:i}=ge(e[`index.html`]||``);if(r.length===0)return{files:e,bundledJS:``};let a={...e};for(let e of i)a[e.id]=e.content;let o=new Map,s=[];for(let e of r){let r=await ve({entryPoint:e,files:a,rollup:t,enableSourcemap:n});o.set(e,r),s.push(r)}let c=Se(a,o,i,!0),l=s.join(`
300
+ `);return{files:{...e,"index.html":c},bundledJS:l}},we=e=>{let t=`<script>${I()}<\/script>`;return e.includes(`</head>`)?e.replace(`</head>`,`${t}\n</head>`):e.includes(`</body>`)?e.replace(`</body>`,`${t}\n</body>`):e+t},$=e=>{let t={...e};for(let[n,r]of Object.entries(t))n.toLowerCase().endsWith(`.html`)&&(t[n]=O(r,e));return t},Te=async({files:e,rollup:t,enableSourcemap:n=!0,vizCache:r,vizId:i,slugCache:a,getSvelteCompiler:o})=>{try{if(!e&&!r)throw Error(`Either files or vizCache is required`);if(!e&&r&&!i)throw Error(`vizId is required when using vizCache`);if(!e&&r&&i&&(e=(0,u.vizFilesToFileCollection)((await r.get(i))?.files)),!e)throw Error(`Upable to extract viz files`);let s=W(e);if(s===`v1`)return{html:we((0,l.magicSandbox)($(e))),runtimeVersion:s};if(s===`v2`){if(!t)throw Error(`Rollup is required for v2 runtime`);return{html:(0,l.magicSandbox)($(await he({files:e,rollup:t,enableSourcemap:n}))),runtimeVersion:s}}if(s===`v3`){if(!t)throw Error(`Rollup is required for v3 runtime`);if(!r&&!i){let t=U(e);i=t.id,r=B({initialContents:[t],handleCacheMiss:async()=>{throw Error(`Cache miss handler not implemented`)}})}if(!r)throw Error(`vizCache is required for v3 runtime`);if(!i)throw Error(`vizId is required for v3 runtime if vizCache is provided`);return await z({files:e,rollup:t,vizCache:r,vizId:i,slugCache:a,getSvelteCompiler:o})}if(s===`v4`){if(!t)throw Error(`Rollup is required for v4 runtime`);let r=await Ce({files:e,rollup:t,enableSourcemap:n});return{html:(0,l.magicSandbox)($(r.files)),js:r.bundledJS,runtimeVersion:s}}throw Error(`Unsupported runtime version: ${s}`)}catch(e){throw e instanceof Error&&e.message.indexOf(`\0virtual:`)&&(e.message=e.message.replace(J,``)),e}};Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return V}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return F}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return H}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return N}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return W}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return B}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return U}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return z}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return Te}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return f}});
301
+ //# sourceMappingURL=build-BiyVcX4s.cjs.map