@vizhub/runtime 0.3.0 → 0.3.2
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/dist/cjs/buildHTML.js +71 -0
- package/dist/cjs/common/packageJson.js +81 -0
- package/dist/cjs/common/packageJson.test.js +148 -0
- package/dist/cjs/common/sucrasePlugin.js +27 -0
- package/dist/cjs/common/virtualFileSystem.js +79 -0
- package/dist/cjs/determineRuntimeVersion.js +26 -0
- package/dist/cjs/determineRuntimeVersion.test.js +103 -0
- package/dist/cjs/index.js +9 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/test/fixtures/v1/basicHTML.js +18 -0
- package/dist/cjs/test/fixtures/v1/fetchProxy.js +15 -0
- package/dist/cjs/test/fixtures/v1/index.js +15 -0
- package/dist/cjs/test/fixtures/v1/jsScriptTag.js +12 -0
- package/dist/cjs/test/fixtures/v1/protocolTest.js +18 -0
- package/dist/cjs/test/fixtures/v1/styleTest.js +18 -0
- package/dist/cjs/test/fixtures/v1/xmlTest.js +22 -0
- package/dist/cjs/test/fixtures/v2/basicBundle.js +8 -0
- package/dist/cjs/test/fixtures/v2/basicBundleNoExtension.js +8 -0
- package/dist/cjs/test/fixtures/v2/d3Import.js +10 -0
- package/dist/cjs/test/fixtures/v2/d3ImportPkg.js +22 -0
- package/dist/cjs/test/fixtures/v2/d3RosettaImportPkg.js +22 -0
- package/dist/cjs/test/fixtures/v2/es6Preserve.js +9 -0
- package/dist/cjs/test/fixtures/v2/generatorSupport.js +9 -0
- package/dist/cjs/test/fixtures/v2/index.js +45 -0
- package/dist/cjs/test/fixtures/v2/jsxTranspile.js +9 -0
- package/dist/cjs/test/fixtures/v2/reactDomImport.js +11 -0
- package/dist/cjs/test/fixtures/v2/reactDomImportPkg.js +27 -0
- package/dist/cjs/test/fixtures/v2/reactImport.js +10 -0
- package/dist/cjs/test/fixtures/v2/reactImportPkg.js +20 -0
- package/dist/cjs/test/fixtures/v2/sourceMapErrorFixture.js +22 -0
- package/dist/cjs/test/fixtures/v2/unicodeSupport.js +9 -0
- package/dist/cjs/test/fixtures/v3/basicIndexJS.js +10 -0
- package/dist/cjs/test/fixtures/v3/cssImport.js +12 -0
- package/dist/cjs/test/fixtures/v3/csvImport.js +14 -0
- package/dist/cjs/test/fixtures/v3/csvStrangeChars.js +15 -0
- package/dist/cjs/test/fixtures/v3/index.js +25 -0
- package/dist/cjs/test/fixtures/v3/jsExport.js +13 -0
- package/dist/cjs/test/fixtures/v3/sourcemap.js +13 -0
- package/dist/cjs/test/fixtures/v3/svelte.js +21 -0
- package/dist/cjs/test/fixtures/v3/vizContent.js +14 -0
- package/dist/cjs/test/fixtures/v3/vizImport.js +88 -0
- package/dist/cjs/test/fixtures/v4/d3Usage.js +34 -0
- package/dist/cjs/test/fixtures/v4/esmBuild.js +21 -0
- package/dist/cjs/test/fixtures/v4/fetchInterception.js +21 -0
- package/dist/cjs/test/fixtures/v4/index.js +21 -0
- package/dist/cjs/test/fixtures/v4/jsScriptTagTypeModule.js +21 -0
- package/dist/cjs/test/fixtures/v4/jsScriptTagTypeModules.js +15 -0
- package/dist/cjs/test/fixtures/v4/reactHooks.js +50 -0
- package/dist/cjs/test/fixtures/v4/reactJsx.js +37 -0
- package/dist/cjs/test/fixtures/v4/threeJsUsage.js +27 -0
- package/dist/cjs/test/fixtures/v4/typeScriptSupport.js +32 -0
- package/dist/cjs/test/testInBrowser.js +50 -0
- package/dist/cjs/test/testStackTrace.js +58 -0
- package/dist/cjs/test/v1.test.js +70 -0
- package/dist/cjs/test/v2.test.js +124 -0
- package/dist/cjs/test/v3.test.js +119 -0
- package/dist/cjs/test/v4.test.js +105 -0
- package/dist/cjs/types.js +2 -0
- package/dist/cjs/utils/vizContentToFileCollection.js +23 -0
- package/dist/cjs/utils/vizContentToFileCollection.test.js +77 -0
- package/dist/cjs/v2/computeBundleJSV2.js +33 -0
- package/dist/cjs/v2/getComputedIndexHtml.js +86 -0
- package/dist/cjs/v2/getComputedIndexHtml.test.js +136 -0
- package/dist/cjs/v2/index.js +5 -0
- package/dist/cjs/v2/v2Build.js +15 -0
- package/dist/cjs/v3/cleanRollupErrorMessage.js +13 -0
- package/dist/cjs/v3/computeBundleJSV3.js +52 -0
- package/dist/cjs/v3/createVizContent.js +27 -0
- package/dist/cjs/v3/extractVizImport.js +27 -0
- package/dist/cjs/v3/extractVizImport.test.js +32 -0
- package/dist/cjs/v3/htmlTemplate.js +93 -0
- package/dist/cjs/v3/index.js +5 -0
- package/dist/cjs/v3/parseId.js +9 -0
- package/dist/cjs/v3/parseId.test.js +27 -0
- package/dist/cjs/v3/setupV3Runtime.js +345 -0
- package/dist/cjs/v3/slugCache.js +39 -0
- package/dist/cjs/v3/slugCache.test.js +107 -0
- package/dist/cjs/v3/transformDSV/dsvParseSrc.js +124 -0
- package/dist/cjs/v3/transformDSV/index.js +44 -0
- package/dist/cjs/v3/transformSvelte.js +81 -0
- package/dist/cjs/v3/types.js +2 -0
- package/dist/cjs/v3/v3Build.js +34 -0
- package/dist/cjs/v3/vizCache.js +40 -0
- package/dist/cjs/v3/vizCache.test.js +100 -0
- package/dist/cjs/v3/vizLoad.js +50 -0
- package/dist/cjs/v3/vizResolve.js +73 -0
- package/dist/cjs/v4/index.js +138 -0
- package/dist/esm/buildHTML.js +67 -0
- package/dist/esm/common/packageJson.js +71 -0
- package/dist/esm/common/packageJson.test.js +146 -0
- package/dist/esm/common/sucrasePlugin.js +24 -0
- package/dist/esm/common/virtualFileSystem.js +75 -0
- package/dist/esm/determineRuntimeVersion.js +22 -0
- package/dist/esm/determineRuntimeVersion.test.js +101 -0
- package/dist/esm/index.js +3 -0
- package/dist/esm/test/fixtures/v1/basicHTML.js +15 -0
- package/dist/esm/test/fixtures/v1/fetchProxy.js +12 -0
- package/dist/esm/test/fixtures/v1/index.js +6 -0
- package/dist/esm/test/fixtures/v1/jsScriptTag.js +9 -0
- package/dist/esm/test/fixtures/v1/protocolTest.js +15 -0
- package/dist/esm/test/fixtures/v1/styleTest.js +15 -0
- package/dist/esm/test/fixtures/v1/xmlTest.js +19 -0
- package/dist/esm/test/fixtures/v2/basicBundle.js +5 -0
- package/dist/esm/test/fixtures/v2/basicBundleNoExtension.js +5 -0
- package/dist/esm/test/fixtures/v2/d3Import.js +7 -0
- package/dist/esm/test/fixtures/v2/d3ImportPkg.js +19 -0
- package/dist/esm/test/fixtures/v2/d3RosettaImportPkg.js +19 -0
- package/dist/esm/test/fixtures/v2/es6Preserve.js +6 -0
- package/dist/esm/test/fixtures/v2/generatorSupport.js +6 -0
- package/dist/esm/test/fixtures/v2/index.js +15 -0
- package/dist/esm/test/fixtures/v2/jsxTranspile.js +6 -0
- package/dist/esm/test/fixtures/v2/reactDomImport.js +8 -0
- package/dist/esm/test/fixtures/v2/reactDomImportPkg.js +24 -0
- package/dist/esm/test/fixtures/v2/reactImport.js +7 -0
- package/dist/esm/test/fixtures/v2/reactImportPkg.js +17 -0
- package/dist/esm/test/fixtures/v2/sourceMapErrorFixture.js +19 -0
- package/dist/esm/test/fixtures/v2/unicodeSupport.js +6 -0
- package/dist/esm/test/fixtures/v3/basicIndexJS.js +7 -0
- package/dist/esm/test/fixtures/v3/cssImport.js +9 -0
- package/dist/esm/test/fixtures/v3/csvImport.js +11 -0
- package/dist/esm/test/fixtures/v3/csvStrangeChars.js +12 -0
- package/dist/esm/test/fixtures/v3/index.js +9 -0
- package/dist/esm/test/fixtures/v3/jsExport.js +10 -0
- package/dist/esm/test/fixtures/v3/sourcemap.js +10 -0
- package/dist/esm/test/fixtures/v3/svelte.js +18 -0
- package/dist/esm/test/fixtures/v3/vizContent.js +11 -0
- package/dist/esm/test/fixtures/v3/vizImport.js +85 -0
- package/dist/esm/test/fixtures/v4/d3Usage.js +31 -0
- package/dist/esm/test/fixtures/v4/esmBuild.js +18 -0
- package/dist/esm/test/fixtures/v4/fetchInterception.js +18 -0
- package/dist/esm/test/fixtures/v4/index.js +9 -0
- package/dist/esm/test/fixtures/v4/jsScriptTagTypeModule.js +18 -0
- package/dist/esm/test/fixtures/v4/jsScriptTagTypeModules.js +12 -0
- package/dist/esm/test/fixtures/v4/reactHooks.js +47 -0
- package/dist/esm/test/fixtures/v4/reactJsx.js +34 -0
- package/dist/esm/test/fixtures/v4/threeJsUsage.js +24 -0
- package/dist/esm/test/fixtures/v4/typeScriptSupport.js +29 -0
- package/dist/esm/test/testInBrowser.js +47 -0
- package/dist/esm/test/testStackTrace.js +55 -0
- package/dist/esm/test/v1.test.js +65 -0
- package/dist/esm/test/v2.test.js +121 -0
- package/dist/esm/test/v3.test.js +114 -0
- package/dist/esm/test/v4.test.js +100 -0
- package/dist/esm/types.js +1 -0
- package/dist/esm/utils/vizContentToFileCollection.js +19 -0
- package/dist/esm/utils/vizContentToFileCollection.test.js +75 -0
- package/dist/esm/v2/computeBundleJSV2.js +29 -0
- package/dist/esm/v2/getComputedIndexHtml.js +81 -0
- package/dist/esm/v2/getComputedIndexHtml.test.js +134 -0
- package/dist/esm/v2/index.js +1 -0
- package/dist/esm/v2/v2Build.js +11 -0
- package/dist/esm/v3/cleanRollupErrorMessage.js +9 -0
- package/dist/esm/v3/computeBundleJSV3.js +48 -0
- package/dist/esm/v3/createVizContent.js +23 -0
- package/dist/esm/v3/extractVizImport.js +23 -0
- package/dist/esm/v3/extractVizImport.test.js +30 -0
- package/dist/esm/v3/htmlTemplate.js +89 -0
- package/dist/esm/v3/index.js +1 -0
- package/dist/esm/v3/parseId.js +5 -0
- package/dist/esm/v3/parseId.test.js +25 -0
- package/dist/esm/v3/setupV3Runtime.js +341 -0
- package/dist/esm/v3/slugCache.js +35 -0
- package/dist/esm/v3/slugCache.test.js +105 -0
- package/dist/esm/v3/transformDSV/dsvParseSrc.js +121 -0
- package/dist/esm/v3/transformDSV/index.js +40 -0
- package/dist/esm/v3/transformSvelte.js +77 -0
- package/dist/esm/v3/types.js +1 -0
- package/dist/esm/v3/v3Build.js +30 -0
- package/dist/esm/v3/vizCache.js +36 -0
- package/dist/esm/v3/vizCache.test.js +98 -0
- package/dist/esm/v3/vizLoad.js +46 -0
- package/dist/esm/v3/vizResolve.js +69 -0
- package/dist/esm/v4/index.js +134 -0
- package/dist/types/buildHTML.d.ts +14 -0
- package/dist/types/common/packageJson.d.ts +39 -0
- package/dist/types/common/packageJson.test.d.ts +1 -0
- package/dist/types/common/sucrasePlugin.d.ts +2 -0
- package/dist/types/common/virtualFileSystem.d.ts +3 -0
- package/dist/types/determineRuntimeVersion.d.ts +3 -0
- package/dist/types/determineRuntimeVersion.test.d.ts +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/test/fixtures/v1/basicHTML.d.ts +3 -0
- package/dist/types/test/fixtures/v1/fetchProxy.d.ts +5 -0
- package/dist/types/test/fixtures/v1/index.d.ts +6 -0
- package/dist/types/test/fixtures/v1/jsScriptTag.d.ts +4 -0
- package/dist/types/test/fixtures/v1/protocolTest.d.ts +3 -0
- package/dist/types/test/fixtures/v1/styleTest.d.ts +4 -0
- package/dist/types/test/fixtures/v1/xmlTest.d.ts +4 -0
- package/dist/types/test/fixtures/v2/basicBundle.d.ts +5 -0
- package/dist/types/test/fixtures/v2/basicBundleNoExtension.d.ts +5 -0
- package/dist/types/test/fixtures/v2/d3Import.d.ts +4 -0
- package/dist/types/test/fixtures/v2/d3ImportPkg.d.ts +5 -0
- package/dist/types/test/fixtures/v2/d3RosettaImportPkg.d.ts +5 -0
- package/dist/types/test/fixtures/v2/es6Preserve.d.ts +4 -0
- package/dist/types/test/fixtures/v2/generatorSupport.d.ts +4 -0
- package/dist/types/test/fixtures/v2/index.d.ts +14 -0
- package/dist/types/test/fixtures/v2/jsxTranspile.d.ts +4 -0
- package/dist/types/test/fixtures/v2/reactDomImport.d.ts +4 -0
- package/dist/types/test/fixtures/v2/reactDomImportPkg.d.ts +5 -0
- package/dist/types/test/fixtures/v2/reactImport.d.ts +4 -0
- package/dist/types/test/fixtures/v2/reactImportPkg.d.ts +5 -0
- package/dist/types/test/fixtures/v2/sourceMapErrorFixture.d.ts +5 -0
- package/dist/types/test/fixtures/v2/unicodeSupport.d.ts +4 -0
- package/dist/types/test/fixtures/v3/basicIndexJS.d.ts +3 -0
- package/dist/types/test/fixtures/v3/cssImport.d.ts +4 -0
- package/dist/types/test/fixtures/v3/csvImport.d.ts +4 -0
- package/dist/types/test/fixtures/v3/csvStrangeChars.d.ts +4 -0
- package/dist/types/test/fixtures/v3/index.d.ts +9 -0
- package/dist/types/test/fixtures/v3/jsExport.d.ts +4 -0
- package/dist/types/test/fixtures/v3/sourcemap.d.ts +3 -0
- package/dist/types/test/fixtures/v3/svelte.d.ts +4 -0
- package/dist/types/test/fixtures/v3/vizContent.d.ts +2 -0
- package/dist/types/test/fixtures/v3/vizImport.d.ts +6 -0
- package/dist/types/test/fixtures/v4/d3Usage.d.ts +5 -0
- package/dist/types/test/fixtures/v4/esmBuild.d.ts +5 -0
- package/dist/types/test/fixtures/v4/fetchInterception.d.ts +5 -0
- package/dist/types/test/fixtures/v4/index.d.ts +9 -0
- package/dist/types/test/fixtures/v4/jsScriptTagTypeModule.d.ts +4 -0
- package/dist/types/test/fixtures/v4/jsScriptTagTypeModules.d.ts +5 -0
- package/dist/types/test/fixtures/v4/reactHooks.d.ts +6 -0
- package/dist/types/test/fixtures/v4/reactJsx.d.ts +6 -0
- package/dist/types/test/fixtures/v4/threeJsUsage.d.ts +4 -0
- package/dist/types/test/fixtures/v4/typeScriptSupport.d.ts +5 -0
- package/dist/types/test/testInBrowser.d.ts +15 -0
- package/dist/types/test/testStackTrace.d.ts +9 -0
- package/dist/types/test/v1.test.d.ts +1 -0
- package/dist/types/test/v2.test.d.ts +1 -0
- package/dist/types/test/v3.test.d.ts +1 -0
- package/dist/types/test/v4.test.d.ts +1 -0
- package/dist/types/types.d.ts +1 -0
- package/dist/types/utils/vizContentToFileCollection.d.ts +7 -0
- package/dist/types/utils/vizContentToFileCollection.test.d.ts +1 -0
- package/dist/types/v2/computeBundleJSV2.d.ts +7 -0
- package/dist/types/v2/getComputedIndexHtml.d.ts +4 -0
- package/dist/types/v2/getComputedIndexHtml.test.d.ts +1 -0
- package/dist/types/v2/index.d.ts +1 -0
- package/dist/types/v2/v2Build.d.ts +7 -0
- package/dist/types/v3/cleanRollupErrorMessage.d.ts +4 -0
- package/dist/types/v3/computeBundleJSV3.d.ts +17 -0
- package/dist/types/v3/createVizContent.d.ts +8 -0
- package/dist/types/v3/extractVizImport.d.ts +6 -0
- package/dist/types/v3/extractVizImport.test.d.ts +1 -0
- package/dist/types/v3/htmlTemplate.d.ts +5 -0
- package/dist/types/v3/index.d.ts +1 -0
- package/dist/types/v3/parseId.d.ts +6 -0
- package/dist/types/v3/parseId.test.d.ts +1 -0
- package/dist/types/v3/setupV3Runtime.d.ts +15 -0
- package/dist/types/v3/slugCache.d.ts +11 -0
- package/dist/types/v3/slugCache.test.d.ts +1 -0
- package/dist/types/v3/transformDSV/dsvParseSrc.d.ts +1 -0
- package/dist/types/v3/transformDSV/index.d.ts +2 -0
- package/dist/types/v3/transformSvelte.d.ts +8 -0
- package/dist/types/v3/types.d.ts +65 -0
- package/dist/types/v3/v3Build.d.ts +14 -0
- package/dist/types/v3/vizCache.d.ts +10 -0
- package/dist/types/v3/vizCache.test.d.ts +1 -0
- package/dist/types/v3/vizLoad.d.ts +7 -0
- package/dist/types/v3/vizResolve.d.ts +7 -0
- package/dist/types/v4/index.d.ts +10 -0
- package/package.json +14 -7
@@ -0,0 +1,75 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import { vizContentToFileCollection } from "./vizContentToFileCollection";
|
3
|
+
describe("vizContentToFileCollection", () => {
|
4
|
+
it("should convert VizContent files to FileCollection format", () => {
|
5
|
+
const mockVizContent = {
|
6
|
+
id: "test-viz-123",
|
7
|
+
files: {
|
8
|
+
file1: {
|
9
|
+
name: "index.html",
|
10
|
+
text: "<html>Test</html>",
|
11
|
+
},
|
12
|
+
file2: {
|
13
|
+
name: "script.js",
|
14
|
+
text: 'console.log("Hello");',
|
15
|
+
},
|
16
|
+
},
|
17
|
+
};
|
18
|
+
const result = vizContentToFileCollection(mockVizContent);
|
19
|
+
expect(result).toEqual({
|
20
|
+
"index.html": "<html>Test</html>",
|
21
|
+
"script.js": 'console.log("Hello");',
|
22
|
+
});
|
23
|
+
});
|
24
|
+
it("should return an empty object when no files exist", () => {
|
25
|
+
const mockVizContent = {
|
26
|
+
id: "empty-viz",
|
27
|
+
files: {},
|
28
|
+
};
|
29
|
+
const result = vizContentToFileCollection(mockVizContent);
|
30
|
+
expect(result).toEqual({});
|
31
|
+
});
|
32
|
+
it("should return an empty object when no files property", () => {
|
33
|
+
const mockVizContent = {
|
34
|
+
id: "empty-viz",
|
35
|
+
// @ts-ignore
|
36
|
+
files: undefined,
|
37
|
+
};
|
38
|
+
const result = vizContentToFileCollection(mockVizContent);
|
39
|
+
expect(result).toEqual({});
|
40
|
+
});
|
41
|
+
it("should handle files with special characters in names", () => {
|
42
|
+
const mockVizContent = {
|
43
|
+
id: "special-chars-viz",
|
44
|
+
files: {
|
45
|
+
fileId1: {
|
46
|
+
name: "file with spaces.txt",
|
47
|
+
text: "content",
|
48
|
+
},
|
49
|
+
fileId2: { name: "data.csv", text: "a,b,c\n1,2,3" },
|
50
|
+
},
|
51
|
+
};
|
52
|
+
const result = vizContentToFileCollection(mockVizContent);
|
53
|
+
expect(result).toEqual({
|
54
|
+
"file with spaces.txt": "content",
|
55
|
+
"data.csv": "a,b,c\n1,2,3",
|
56
|
+
});
|
57
|
+
});
|
58
|
+
it("should preserve file content exactly", () => {
|
59
|
+
const longText = `function complex() {
|
60
|
+
return {
|
61
|
+
nested: {
|
62
|
+
data: [1, 2, 3]
|
63
|
+
}
|
64
|
+
};
|
65
|
+
}`;
|
66
|
+
const mockVizContent = {
|
67
|
+
id: "preserve-content-viz",
|
68
|
+
files: {
|
69
|
+
fileId: { name: "complex.js", text: longText },
|
70
|
+
},
|
71
|
+
};
|
72
|
+
const result = vizContentToFileCollection(mockVizContent);
|
73
|
+
expect(result["complex.js"]).toBe(longText);
|
74
|
+
});
|
75
|
+
});
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { virtualFileSystem } from "../common/virtualFileSystem";
|
2
|
+
import { sucrasePlugin } from "../common/sucrasePlugin";
|
3
|
+
import { getGlobals, packageJSON, } from "../common/packageJson";
|
4
|
+
export const computeBundleJSV2 = async ({ files, rollup, enableSourcemap = true, }) => {
|
5
|
+
const indexJSContent = files["index.js"];
|
6
|
+
if (!indexJSContent) {
|
7
|
+
throw new Error("Missing index.js");
|
8
|
+
}
|
9
|
+
const inputOptions = {
|
10
|
+
input: "./index.js",
|
11
|
+
plugins: [virtualFileSystem(files), sucrasePlugin()],
|
12
|
+
onwarn(warning, warn) {
|
13
|
+
// Suppress "treating module as external dependency" warnings
|
14
|
+
if (warning.code === "UNRESOLVED_IMPORT")
|
15
|
+
return;
|
16
|
+
warn(warning);
|
17
|
+
},
|
18
|
+
};
|
19
|
+
const bundle = await rollup(inputOptions);
|
20
|
+
const pkg = packageJSON(files);
|
21
|
+
const globals = getGlobals(pkg);
|
22
|
+
const outputOptions = {
|
23
|
+
format: "iife",
|
24
|
+
globals,
|
25
|
+
sourcemap: enableSourcemap,
|
26
|
+
};
|
27
|
+
const { output } = await bundle.generate(outputOptions);
|
28
|
+
return output[0].code;
|
29
|
+
};
|
@@ -0,0 +1,81 @@
|
|
1
|
+
import { dependencies, getConfiguredLibraries, dependencySource, } from "../common/packageJson";
|
2
|
+
let parser;
|
3
|
+
const DEBUG = false;
|
4
|
+
// Expose a way to inject a DOMParser implementation
|
5
|
+
// when we're in a Node environment (tests, API server).
|
6
|
+
export const setJSDOM = (JSDOMInstance) => {
|
7
|
+
const dom = new JSDOMInstance();
|
8
|
+
parser = new dom.window.DOMParser();
|
9
|
+
};
|
10
|
+
// If we're in the browser, use native DOMParser.
|
11
|
+
if (typeof window !== "undefined") {
|
12
|
+
parser = new DOMParser();
|
13
|
+
}
|
14
|
+
const injectScripts = (htmlTemplate, files) => {
|
15
|
+
if (!parser) {
|
16
|
+
throw new Error("DOM parser is not defined. Did you forget to call setJSDOM()?");
|
17
|
+
}
|
18
|
+
const doc = parser.parseFromString(htmlTemplate, "text/html");
|
19
|
+
// Ensure we have a head element
|
20
|
+
if (!doc.head) {
|
21
|
+
const head = doc.createElement("head");
|
22
|
+
doc.documentElement.insertBefore(head, doc.documentElement.firstChild);
|
23
|
+
}
|
24
|
+
// Ensure we have a body element
|
25
|
+
if (!doc.body) {
|
26
|
+
const body = doc.createElement("body");
|
27
|
+
doc.documentElement.appendChild(body);
|
28
|
+
}
|
29
|
+
// Handle dependencies first (in head)
|
30
|
+
const deps = Object.entries(dependencies(files));
|
31
|
+
if (deps.length > 0) {
|
32
|
+
const libraries = getConfiguredLibraries(files);
|
33
|
+
// Remove any existing dependency scripts
|
34
|
+
deps.forEach(([name]) => {
|
35
|
+
const selector = `script[src*="${name}@"]`;
|
36
|
+
const existingScripts = doc.querySelectorAll(selector);
|
37
|
+
existingScripts.forEach((script) => script.remove());
|
38
|
+
});
|
39
|
+
// Add dependency scripts in order
|
40
|
+
deps
|
41
|
+
.map(([name, version]) => dependencySource({ name, version }, libraries))
|
42
|
+
.forEach((url) => {
|
43
|
+
const scriptTag = doc.createElement("script");
|
44
|
+
scriptTag.src = url;
|
45
|
+
doc.head.appendChild(scriptTag);
|
46
|
+
});
|
47
|
+
}
|
48
|
+
// Handle bundle.js (in body)
|
49
|
+
if (files["bundle.js"] || files["index.js"]) {
|
50
|
+
// Remove any existing bundle.js script tags
|
51
|
+
const existingScripts = doc.querySelectorAll('script[src="bundle.js"]');
|
52
|
+
existingScripts.forEach((script) => script.remove());
|
53
|
+
const bundleScriptTag = doc.createElement("script");
|
54
|
+
bundleScriptTag.src = "bundle.js";
|
55
|
+
doc.body.appendChild(bundleScriptTag);
|
56
|
+
}
|
57
|
+
return `<!DOCTYPE html>${doc.documentElement.outerHTML}`;
|
58
|
+
};
|
59
|
+
// Compute the index.html file from the files.
|
60
|
+
// Includes:
|
61
|
+
// - bundle.js script tag
|
62
|
+
// - dependencies script tag(s)
|
63
|
+
export const getComputedIndexHtml = (files) => {
|
64
|
+
// Isolate the index.html file.
|
65
|
+
const htmlTemplate = files["index.html"];
|
66
|
+
// If there is no index.html file, return an empty string.
|
67
|
+
if (!htmlTemplate &&
|
68
|
+
!files["index.js"] &&
|
69
|
+
!files["bundle.js"]) {
|
70
|
+
DEBUG &&
|
71
|
+
console.log("[getComputedIndexHtml] No index.html file found");
|
72
|
+
return "";
|
73
|
+
}
|
74
|
+
// If index.html is empty but we have JS files, create a minimal HTML template
|
75
|
+
const template = htmlTemplate ||
|
76
|
+
"<!DOCTYPE html><html><head></head><body></body></html>";
|
77
|
+
const indexHtml = injectScripts(template, files);
|
78
|
+
DEBUG &&
|
79
|
+
console.log("[getComputedIndexHtml] indexHtml", indexHtml);
|
80
|
+
return indexHtml;
|
81
|
+
};
|
@@ -0,0 +1,134 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import { getComputedIndexHtml, setJSDOM, } from "./getComputedIndexHtml";
|
3
|
+
import { JSDOM } from "jsdom";
|
4
|
+
import { d3ImportPkg } from "../test/fixtures/v2/d3ImportPkg";
|
5
|
+
setJSDOM(JSDOM);
|
6
|
+
describe("v2 getComputedIndexHtml", () => {
|
7
|
+
it("should return empty string if missing index.html", async () => {
|
8
|
+
const files = {};
|
9
|
+
expect(getComputedIndexHtml(files)).toEqual(``);
|
10
|
+
});
|
11
|
+
it("should preserve existing index.html if no bundle and no package.json", async () => {
|
12
|
+
const text = "<!DOCTYPE html><html><head></head><body><h1>Hello World</h1></body></html>";
|
13
|
+
const files = { "index.html": text };
|
14
|
+
expect(getComputedIndexHtml(files)).toEqual(text);
|
15
|
+
});
|
16
|
+
it("should add bundle.js, no package.json", async () => {
|
17
|
+
const text = '<!DOCTYPE html><html><head></head><body><script src="bundle.js"></script></body></html>';
|
18
|
+
const files = {
|
19
|
+
"index.html": text,
|
20
|
+
"index.js": 'console.log("Hello")',
|
21
|
+
};
|
22
|
+
// console.log(JSON.stringify(getComputedIndexHtml(files), null, 2));
|
23
|
+
expect(getComputedIndexHtml(files)).toEqual(text);
|
24
|
+
});
|
25
|
+
it("should handle d3 dependency from package.json", async () => {
|
26
|
+
const files = d3ImportPkg;
|
27
|
+
const result = getComputedIndexHtml(files);
|
28
|
+
// Create a DOM to parse and check the result
|
29
|
+
const dom = new JSDOM(result);
|
30
|
+
const document = dom.window.document;
|
31
|
+
// Check that we have the d3 script in the head
|
32
|
+
const d3Script = document.querySelector('head script[src*="d3@6.7.0"]');
|
33
|
+
expect(d3Script).not.toBeNull();
|
34
|
+
// Check that we have the bundle.js script in the body
|
35
|
+
const bundleScript = document.querySelector('body script[src="bundle.js"]');
|
36
|
+
expect(bundleScript).not.toBeNull();
|
37
|
+
// Verify the order: d3 in head, bundle.js in body
|
38
|
+
expect(result.indexOf("d3@6.7.0")).toBeLessThan(result.indexOf("<body>"));
|
39
|
+
expect(result.indexOf("<body>")).toBeLessThan(result.indexOf("bundle.js"));
|
40
|
+
});
|
41
|
+
// Edge cases and degenerate inputs
|
42
|
+
it("should handle malformed HTML in index.html", async () => {
|
43
|
+
const malformedHtml = "<html><head>No closing head tag<body>No closing body tag";
|
44
|
+
const files = {
|
45
|
+
"index.html": malformedHtml,
|
46
|
+
"index.js": 'console.log("Hello")',
|
47
|
+
};
|
48
|
+
const result = getComputedIndexHtml(files);
|
49
|
+
// Should still have both head and body tags
|
50
|
+
expect(result).toContain("<head>");
|
51
|
+
expect(result).toContain("</head>");
|
52
|
+
expect(result).toContain("<body>");
|
53
|
+
expect(result).toContain("</body>");
|
54
|
+
// Should have bundle.js in the body
|
55
|
+
const dom = new JSDOM(result);
|
56
|
+
const bundleScript = dom.window.document.querySelector('body script[src="bundle.js"]');
|
57
|
+
expect(bundleScript).not.toBeNull();
|
58
|
+
});
|
59
|
+
it("should handle HTML without html, head, or body tags", async () => {
|
60
|
+
const minimalHtml = "<div>Just a div</div>";
|
61
|
+
const files = {
|
62
|
+
"index.html": minimalHtml,
|
63
|
+
"index.js": 'console.log("Hello")',
|
64
|
+
"package.json": JSON.stringify({
|
65
|
+
dependencies: {
|
66
|
+
d3: "6.7.0",
|
67
|
+
},
|
68
|
+
}),
|
69
|
+
};
|
70
|
+
const result = getComputedIndexHtml(files);
|
71
|
+
// Should create proper HTML structure
|
72
|
+
expect(result).toContain("<html>");
|
73
|
+
expect(result).toContain("<head>");
|
74
|
+
expect(result).toContain("<body>");
|
75
|
+
// Should have d3 in head and bundle.js in body
|
76
|
+
const dom = new JSDOM(result);
|
77
|
+
const document = dom.window.document;
|
78
|
+
const d3Script = document.querySelector('head script[src*="d3@6.7.0"]');
|
79
|
+
expect(d3Script).not.toBeNull();
|
80
|
+
const bundleScript = document.querySelector('body script[src="bundle.js"]');
|
81
|
+
expect(bundleScript).not.toBeNull();
|
82
|
+
// Original content should be preserved
|
83
|
+
expect(result).toContain("<div>Just a div</div>");
|
84
|
+
});
|
85
|
+
it("should handle empty index.html", async () => {
|
86
|
+
const files = {
|
87
|
+
"index.html": "",
|
88
|
+
"index.js": 'console.log("Hello")',
|
89
|
+
};
|
90
|
+
const result = getComputedIndexHtml(files);
|
91
|
+
// Should create a minimal HTML structure with bundle.js
|
92
|
+
expect(result).toContain("<html>");
|
93
|
+
expect(result).toContain("<body>");
|
94
|
+
expect(result).toContain('script src="bundle.js"');
|
95
|
+
});
|
96
|
+
it("should handle multiple existing script tags", async () => {
|
97
|
+
const html = `
|
98
|
+
<!DOCTYPE html>
|
99
|
+
<html>
|
100
|
+
<head>
|
101
|
+
<script src="existing1.js"></script>
|
102
|
+
<script src="bundle.js"></script>
|
103
|
+
</head>
|
104
|
+
<body>
|
105
|
+
<script src="existing2.js"></script>
|
106
|
+
<script src="bundle.js"></script>
|
107
|
+
</body>
|
108
|
+
</html>
|
109
|
+
`;
|
110
|
+
const files = {
|
111
|
+
"index.html": html,
|
112
|
+
"index.js": 'console.log("Hello")',
|
113
|
+
"package.json": JSON.stringify({
|
114
|
+
dependencies: {
|
115
|
+
d3: "6.7.0",
|
116
|
+
},
|
117
|
+
}),
|
118
|
+
};
|
119
|
+
const result = getComputedIndexHtml(files);
|
120
|
+
// Create DOM to analyze the result
|
121
|
+
const dom = new JSDOM(result);
|
122
|
+
const document = dom.window.document;
|
123
|
+
// Should keep existing scripts
|
124
|
+
expect(document.querySelectorAll('script[src="existing1.js"]').length).toBe(1);
|
125
|
+
expect(document.querySelectorAll('script[src="existing2.js"]').length).toBe(1);
|
126
|
+
// Should have exactly one bundle.js script in the body
|
127
|
+
const bundleScripts = document.querySelectorAll('script[src="bundle.js"]');
|
128
|
+
expect(bundleScripts.length).toBe(1);
|
129
|
+
expect(bundleScripts[0].parentElement).toBe(document.body);
|
130
|
+
// Should have d3 script in the head
|
131
|
+
const d3Script = document.querySelector('head script[src*="d3@6.7.0"]');
|
132
|
+
expect(d3Script).not.toBeNull();
|
133
|
+
});
|
134
|
+
});
|
@@ -0,0 +1 @@
|
|
1
|
+
export { v2Build } from "./v2Build.js";
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { getComputedIndexHtml } from "./getComputedIndexHtml.js";
|
2
|
+
import { computeBundleJSV2 } from "./computeBundleJSV2.js";
|
3
|
+
export const v2Build = async ({ files, rollup, enableSourcemap, }) => ({
|
4
|
+
...files,
|
5
|
+
"bundle.js": await computeBundleJSV2({
|
6
|
+
files,
|
7
|
+
rollup,
|
8
|
+
enableSourcemap,
|
9
|
+
}),
|
10
|
+
"index.html": getComputedIndexHtml(files),
|
11
|
+
});
|
@@ -0,0 +1,9 @@
|
|
1
|
+
// We want to remove the vizId from the error message
|
2
|
+
// to make it more user-friendly.
|
3
|
+
// Example error message before and after:
|
4
|
+
// Before: "7f0b69fcb754479699172d1887817027/index.js (14:8): Expected ';', '}' or <eof>"
|
5
|
+
// After: "./index.js (14:8): Expected ';', '}' or <eof>"
|
6
|
+
export const cleanRollupErrorMessage = ({ rawMessage, vizId, }) => {
|
7
|
+
const regex = new RegExp(vizId, "g");
|
8
|
+
return rawMessage?.replace(regex, ".");
|
9
|
+
};
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { sucrasePlugin } from "../common/sucrasePlugin";
|
2
|
+
import { getGlobals, packageJSON, } from "../common/packageJson";
|
3
|
+
import { transformDSV } from "./transformDSV";
|
4
|
+
import { vizResolve } from "./vizResolve";
|
5
|
+
import { vizLoad } from "./vizLoad";
|
6
|
+
import { transformSvelte, } from "./transformSvelte";
|
7
|
+
export const computeBundleJSV3 = async ({ files, rollup, enableSourcemap = true, vizCache, vizId, slugCache, getSvelteCompiler, }) => {
|
8
|
+
// Track CSS imports
|
9
|
+
const cssFilesSet = new Set();
|
10
|
+
const trackCSSImport = (cssFile) => {
|
11
|
+
cssFilesSet.add(cssFile);
|
12
|
+
};
|
13
|
+
const indexJSContent = files["index.js"];
|
14
|
+
if (!indexJSContent) {
|
15
|
+
throw new Error("Missing index.js");
|
16
|
+
}
|
17
|
+
const inputOptions = {
|
18
|
+
input: "./index.js",
|
19
|
+
plugins: [
|
20
|
+
vizResolve({ vizId, slugCache }),
|
21
|
+
transformDSV(),
|
22
|
+
sucrasePlugin(),
|
23
|
+
transformSvelte({ getSvelteCompiler }),
|
24
|
+
vizLoad({ vizCache, trackCSSImport }),
|
25
|
+
],
|
26
|
+
onwarn(warning, warn) {
|
27
|
+
// Suppress "treating module as external dependency" warnings
|
28
|
+
if (warning.code === "UNRESOLVED_IMPORT")
|
29
|
+
return;
|
30
|
+
warn(warning);
|
31
|
+
},
|
32
|
+
};
|
33
|
+
const bundle = await rollup(inputOptions);
|
34
|
+
const pkg = packageJSON(files);
|
35
|
+
const globals = getGlobals(pkg);
|
36
|
+
const outputOptions = {
|
37
|
+
format: "umd",
|
38
|
+
name: "Viz",
|
39
|
+
sourcemap: enableSourcemap ? true : false,
|
40
|
+
compact: true,
|
41
|
+
globals,
|
42
|
+
};
|
43
|
+
const { output } = await bundle.generate(outputOptions);
|
44
|
+
return {
|
45
|
+
src: output[0].code,
|
46
|
+
cssFiles: Array.from(cssFilesSet),
|
47
|
+
};
|
48
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import { v4 as uuidv4 } from "uuid";
|
2
|
+
/**
|
3
|
+
* Creates a VizContent object with the given files
|
4
|
+
* @param files An object with file names as keys and file content as values
|
5
|
+
* @param title Optional title for the content
|
6
|
+
* @returns A VizContent object with randomly generated IDs
|
7
|
+
*/
|
8
|
+
export const createVizContent = (files, title = "Sample Content for Exporting") => {
|
9
|
+
const contentId = uuidv4().replace(/-/g, "");
|
10
|
+
const contentFiles = {};
|
11
|
+
Object.entries(files).forEach(([fileName, fileContent]) => {
|
12
|
+
const fileId = Math.floor(Math.random() * 10000000).toString();
|
13
|
+
contentFiles[fileId] = {
|
14
|
+
name: fileName,
|
15
|
+
text: fileContent,
|
16
|
+
};
|
17
|
+
});
|
18
|
+
return {
|
19
|
+
id: contentId,
|
20
|
+
files: contentFiles,
|
21
|
+
title,
|
22
|
+
};
|
23
|
+
};
|
@@ -0,0 +1,23 @@
|
|
1
|
+
export const extractVizImport = (str) => {
|
2
|
+
// Updated regular expression pattern
|
3
|
+
// Username: Alphanumeric characters, including underscores and hyphens
|
4
|
+
// ID: Alphanumeric characters, including underscores, hyphens, and possibly other special characters
|
5
|
+
const pattern = /^@([a-zA-Z0-9_-]+)\/([a-zA-Z0-9_-]+)$/;
|
6
|
+
const match = str.match(pattern);
|
7
|
+
if (match) {
|
8
|
+
// Extract the username and id
|
9
|
+
return {
|
10
|
+
userName: match[1],
|
11
|
+
idOrSlug: match[2],
|
12
|
+
};
|
13
|
+
}
|
14
|
+
else {
|
15
|
+
// Return null if the string does not match
|
16
|
+
return null;
|
17
|
+
}
|
18
|
+
};
|
19
|
+
// // Example usages
|
20
|
+
// const result1 = extractDetails("@curran/21f72bf74ef04ea0b9c9b82aaaec859a");
|
21
|
+
// console.log(result1); // { username: "curran", id: "21f72bf74ef04ea0b9c9b82aaaec859a" }
|
22
|
+
// const result2 = extractDetails("@curran/scatter-plot");
|
23
|
+
// console.log(result2); // { username: "curran", id: "scatter-plot" }
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import { extractVizImport } from "./extractVizImport";
|
3
|
+
describe("v3 extractVizImport", () => {
|
4
|
+
it("should correctly extract username and viz id", () => {
|
5
|
+
const result = extractVizImport("@curran/21f72bf74ef04ea0b9c9b82aaaec859a");
|
6
|
+
expect(result).toEqual({
|
7
|
+
userName: "curran",
|
8
|
+
idOrSlug: "21f72bf74ef04ea0b9c9b82aaaec859a",
|
9
|
+
});
|
10
|
+
});
|
11
|
+
it("should correctly extract username and alphanumeric id", () => {
|
12
|
+
const result = extractVizImport("@curran/scatter-plot");
|
13
|
+
expect(result).toEqual({
|
14
|
+
userName: "curran",
|
15
|
+
idOrSlug: "scatter-plot",
|
16
|
+
});
|
17
|
+
});
|
18
|
+
it("should return null for non-matching strings", () => {
|
19
|
+
const result = extractVizImport("not-a-matching-string");
|
20
|
+
expect(result).toBeNull();
|
21
|
+
});
|
22
|
+
it("should handle cases with invalid characters in username", () => {
|
23
|
+
const result = extractVizImport("@c!urran/valid-id");
|
24
|
+
expect(result).toBeNull();
|
25
|
+
});
|
26
|
+
it("should handle cases with invalid characters in id", () => {
|
27
|
+
const result = extractVizImport("@curran/invalid id");
|
28
|
+
expect(result).toBeNull();
|
29
|
+
});
|
30
|
+
});
|
@@ -0,0 +1,89 @@
|
|
1
|
+
function randomDigits() {
|
2
|
+
return Math.random().toString().slice(2, 7);
|
3
|
+
}
|
4
|
+
export const htmlTemplate = ({ cdn, src, styles, }) => {
|
5
|
+
// Random container id to avoid conflicts and guarantee
|
6
|
+
// the code is portable.
|
7
|
+
const containerSuffix = randomDigits();
|
8
|
+
const vizContainerId = `viz-container-${containerSuffix}`;
|
9
|
+
return `<!DOCTYPE html>
|
10
|
+
<html>
|
11
|
+
<head>
|
12
|
+
<meta charset="utf-8">${cdn}${styles}
|
13
|
+
<style>
|
14
|
+
body {
|
15
|
+
margin: 0;
|
16
|
+
overflow: hidden;
|
17
|
+
}
|
18
|
+
#${vizContainerId} {
|
19
|
+
height: 100vh;
|
20
|
+
}
|
21
|
+
</style>
|
22
|
+
</head>
|
23
|
+
<body>
|
24
|
+
<div id="${vizContainerId}"></div>
|
25
|
+
<script id="injected-script">${src}</script>
|
26
|
+
<script>
|
27
|
+
(() => {
|
28
|
+
let cleanup;
|
29
|
+
const render = () => {
|
30
|
+
const container = document.getElementById('${vizContainerId}');
|
31
|
+
typeof cleanup === 'function' && cleanup();
|
32
|
+
cleanup = Viz.main(container, { state: window.state, setState, writeFile });
|
33
|
+
};
|
34
|
+
const setState = (next) => {
|
35
|
+
window.state = next(window.state);
|
36
|
+
render();
|
37
|
+
};
|
38
|
+
const writeFile = (fileName, content) => {
|
39
|
+
parent.postMessage({ type: 'writeFile', fileName, content }, "*");
|
40
|
+
};
|
41
|
+
const run = () => {
|
42
|
+
try {
|
43
|
+
setState((state) => state || {});
|
44
|
+
} catch (error) {
|
45
|
+
console.error(error);
|
46
|
+
parent.postMessage({ type: 'runError', error }, "*");
|
47
|
+
}
|
48
|
+
}
|
49
|
+
run();
|
50
|
+
const runJS = (src) => {
|
51
|
+
document.getElementById('injected-script')?.remove();
|
52
|
+
const script = document.createElement('script');
|
53
|
+
script.textContent = src;
|
54
|
+
script.id = 'injected-script';
|
55
|
+
document.body.appendChild(script);
|
56
|
+
run();
|
57
|
+
};
|
58
|
+
const runCSS = (src, id) => {
|
59
|
+
const styleElementId = 'injected-style' + id;
|
60
|
+
let style = document.getElementById(styleElementId);
|
61
|
+
if (!style) {
|
62
|
+
style = document.createElement('style');
|
63
|
+
style.type = 'text/css';
|
64
|
+
style.id = styleElementId;
|
65
|
+
document.head.appendChild(style);
|
66
|
+
}
|
67
|
+
style.textContent = src;
|
68
|
+
};
|
69
|
+
onmessage = (message) => {
|
70
|
+
switch (message.data.type) {
|
71
|
+
case 'runJS':
|
72
|
+
runJS(message.data.src);
|
73
|
+
parent.postMessage({ type: 'runDone' }, "*");
|
74
|
+
break;
|
75
|
+
case 'runCSS':
|
76
|
+
runCSS(message.data.src, message.data.id);
|
77
|
+
break;
|
78
|
+
case 'ping':
|
79
|
+
parent.postMessage({ type: 'pong' }, "*");
|
80
|
+
break;
|
81
|
+
default:
|
82
|
+
break;
|
83
|
+
}
|
84
|
+
}
|
85
|
+
})();
|
86
|
+
</script>
|
87
|
+
</body>
|
88
|
+
</html>`;
|
89
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export { v3Build } from "./v3Build.js";
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
2
|
+
import { parseId } from "./parseId";
|
3
|
+
describe("parseId", () => {
|
4
|
+
it("should correctly parse viz id and filename", () => {
|
5
|
+
const result = parseId("21f72bf74ef04ea0b9c9b82aaaec859a/index.js");
|
6
|
+
expect(result).toEqual({
|
7
|
+
vizId: "21f72bf74ef04ea0b9c9b82aaaec859a",
|
8
|
+
fileName: "index.js",
|
9
|
+
});
|
10
|
+
});
|
11
|
+
it("should handle alphanumeric ids", () => {
|
12
|
+
const result = parseId("scatter-plot/visualization.js");
|
13
|
+
expect(result).toEqual({
|
14
|
+
vizId: "scatter-plot",
|
15
|
+
fileName: "visualization.js",
|
16
|
+
});
|
17
|
+
});
|
18
|
+
it("should handle complex filenames", () => {
|
19
|
+
const result = parseId("my-viz/nested/path/file.test.js");
|
20
|
+
expect(result).toEqual({
|
21
|
+
vizId: "my-viz",
|
22
|
+
fileName: "nested/path/file.test.js",
|
23
|
+
});
|
24
|
+
});
|
25
|
+
});
|