diff --git a/.prettierignore b/.prettierignore index 6b44e5f0b..4cfcedd6e 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,3 +5,4 @@ d2renderers/d2latex/polyfills.js d2renderers/d2latex/setup.js d2renderers/d2sketch/rough.js lib/png/generate_png.js +d2js diff --git a/d2js/js/.prettierignore b/d2js/js/.prettierignore new file mode 100644 index 000000000..96bbfb74b --- /dev/null +++ b/d2js/js/.prettierignore @@ -0,0 +1 @@ +src/platform.browser.js diff --git a/d2js/js/build.js b/d2js/js/build.js index a3d3a145f..d8ae1969a 100644 --- a/d2js/js/build.js +++ b/d2js/js/build.js @@ -23,7 +23,6 @@ await writeFile( ); const commonConfig = { - sourcemap: "external", minify: true, }; @@ -54,10 +53,7 @@ async function buildAndCopy(buildType) { format: "esm", target: "browser", platform: "browser", - loader: { - ".js": "jsx", - }, - entrypoints: [resolve(SRC_DIR, "index.js"), resolve(SRC_DIR, "worker.js")], + entrypoints: [resolve(SRC_DIR, "index.js")], }, "node-esm": { outdir: resolve(ROOT_DIR, "dist/node-esm"), @@ -86,7 +82,9 @@ async function buildAndCopy(buildType) { }); if (!result.outputs || result.outputs.length === 0) { - throw new Error(`No outputs generated for ${buildType} build`); + throw new Error( + `No outputs generated for ${buildType} build. Result: ${JSON.stringify(result)}` + ); } if (buildType !== "browser") { diff --git a/d2js/js/package.json b/d2js/js/package.json index 535b1c938..1836dba84 100644 --- a/d2js/js/package.json +++ b/d2js/js/package.json @@ -2,7 +2,7 @@ "name": "@terrastruct/d2", "author": "Terrastruct, Inc.", "description": "D2.js is a wrapper around the WASM build of D2, the modern text-to-diagram language.", - "version": "0.1.19", + "version": "0.1.20", "repository": { "type": "git", "url": "git+https://github.com/terrastruct/d2.git", diff --git a/d2js/js/src/platform.browser.js b/d2js/js/src/platform.browser.js index 052149742..2f71daaf8 100644 --- a/d2js/js/src/platform.browser.js +++ b/d2js/js/src/platform.browser.js @@ -1,4 +1,5 @@ import { wasmBinary, wasmExecJs } from "./wasm-loader.browser.js"; +import workerScript from "./worker.js" with { type: "text" }; export async function loadFile(path) { if (path === "./d2.wasm") { @@ -11,13 +12,6 @@ export async function loadFile(path) { } export async function createWorker() { - let response = await fetch(new URL("./worker.js", import.meta.url)); - if (!response.ok) - throw new Error( - `Failed to load worker.js: ${response.status} ${response.statusText}` - ); - let workerScript = await response.text(); - let blob = new Blob([wasmExecJs, workerScript], { type: "text/javascript;charset=utf-8", }); diff --git a/d2js/js/src/worker.browser.js b/d2js/js/src/worker.browser.js index 361432b0d..5fa95510f 100644 --- a/d2js/js/src/worker.browser.js +++ b/d2js/js/src/worker.browser.js @@ -1,4 +1,55 @@ -import { setupMessageHandler } from "./worker.shared.js"; +let currentPort; +let d2; + +export function setupMessageHandler(isNode, port, initWasm) { + currentPort = port; + + const handleMessage = async (e) => { + const { type, data } = e; + + switch (type) { + case "init": + try { + if (isNode) { + eval(data.wasmExecContent); + } + d2 = await initWasm(data.wasm); + currentPort.postMessage({ type: "ready" }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + + case "compile": + try { + const result = await d2.compile(JSON.stringify(data)); + const response = JSON.parse(result); + if (response.error) throw new Error(response.error.message); + currentPort.postMessage({ type: "result", data: response.data }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + + case "render": + try { + const result = await d2.render(JSON.stringify(data)); + const response = JSON.parse(result); + if (response.error) throw new Error(response.error.message); + currentPort.postMessage({ type: "result", data: atob(response.data) }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + } + }; + + if (isNode) { + port.on("message", handleMessage); + } else { + port.onmessage = (e) => handleMessage(e.data); + } +} async function initWasmBrowser(wasmBinary) { const go = new Go(); diff --git a/d2js/js/src/worker.node.js b/d2js/js/src/worker.node.js index 0f65334ef..ff7d9ec08 100644 --- a/d2js/js/src/worker.node.js +++ b/d2js/js/src/worker.node.js @@ -1,5 +1,57 @@ import { parentPort } from "node:worker_threads"; -import { setupMessageHandler } from "./worker.shared.js"; + +let currentPort; +let d2; + +export function setupMessageHandler(isNode, port, initWasm) { + currentPort = port; + + const handleMessage = async (e) => { + const { type, data } = e; + + switch (type) { + case "init": + try { + if (isNode) { + eval(data.wasmExecContent); + } + d2 = await initWasm(data.wasm); + currentPort.postMessage({ type: "ready" }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + + case "compile": + try { + const result = await d2.compile(JSON.stringify(data)); + const response = JSON.parse(result); + if (response.error) throw new Error(response.error.message); + currentPort.postMessage({ type: "result", data: response.data }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + + case "render": + try { + const result = await d2.render(JSON.stringify(data)); + const response = JSON.parse(result); + if (response.error) throw new Error(response.error.message); + currentPort.postMessage({ type: "result", data: atob(response.data) }); + } catch (err) { + currentPort.postMessage({ type: "error", error: err.message }); + } + break; + } + }; + + if (isNode) { + port.on("message", handleMessage); + } else { + port.onmessage = (e) => handleMessage(e.data); + } +} async function initWasmNode(wasmBinary) { const go = new Go(); diff --git a/d2js/js/src/worker.shared.js b/d2js/js/src/worker.shared.js deleted file mode 100644 index bbd1293e8..000000000 --- a/d2js/js/src/worker.shared.js +++ /dev/null @@ -1,52 +0,0 @@ -let currentPort; -let d2; - -export function setupMessageHandler(isNode, port, initWasm) { - currentPort = port; - - const handleMessage = async (e) => { - const { type, data } = e; - - switch (type) { - case "init": - try { - if (isNode) { - eval(data.wasmExecContent); - } - d2 = await initWasm(data.wasm); - currentPort.postMessage({ type: "ready" }); - } catch (err) { - currentPort.postMessage({ type: "error", error: err.message }); - } - break; - - case "compile": - try { - const result = await d2.compile(JSON.stringify(data)); - const response = JSON.parse(result); - if (response.error) throw new Error(response.error.message); - currentPort.postMessage({ type: "result", data: response.data }); - } catch (err) { - currentPort.postMessage({ type: "error", error: err.message }); - } - break; - - case "render": - try { - const result = await d2.render(JSON.stringify(data)); - const response = JSON.parse(result); - if (response.error) throw new Error(response.error.message); - currentPort.postMessage({ type: "result", data: atob(response.data) }); - } catch (err) { - currentPort.postMessage({ type: "error", error: err.message }); - } - break; - } - }; - - if (isNode) { - port.on("message", handleMessage); - } else { - port.onmessage = (e) => handleMessage(e.data); - } -}