Skip to content
This repository was archived by the owner on Aug 6, 2026. It is now read-only.

Commit 92e218d

Browse files
authored
feat(canvas): first-class inlined asset imports in the build recipe
Phase 4 (runtime expansion, code side) of the canvas application build pipeline plan: svg imports now compile to data URLs (usable directly as img/css sources) alongside json imports, with a shared contract fixture so the cloud adapter must inline them identically. Binary asset formats, workers, and WebAssembly need a binary source representation and land with the build-service schema evolution. Generated-By: PostHog Code Task-Id: 9e9a7b3c-f90d-4867-aa0d-b9acc83e26e1
1 parent 599abfc commit 92e218d

3 files changed

Lines changed: 43 additions & 1 deletion

File tree

packages/shared/src/canvas-build-fixtures.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,27 @@ export const CANVAS_BUILD_CONTRACT_FIXTURES: CanvasBuildContractFixture[] = [
125125
}),
126126
expected: { status: "ready" },
127127
},
128+
{
129+
name: "asset imports (svg data-url + json)",
130+
project: project({
131+
[CANVAS_ENTRY_HTML]: HTML_SHELL(
132+
' <div id="root"></div>\n <script type="module" src="/src/main.ts"></script>',
133+
),
134+
"src/main.ts": [
135+
'import logo from "./logo.svg";',
136+
'import config from "./config.json";',
137+
'const img = document.createElement("img");',
138+
"img.src = logo;",
139+
"img.alt = config.title;",
140+
'document.getElementById("root")?.append(img);',
141+
"export {};",
142+
].join("\n"),
143+
"src/logo.svg":
144+
'<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8"><rect width="8" height="8" fill="#f54d00"/></svg>',
145+
"src/config.json": '{ "title": "hedgehog" }',
146+
}),
147+
expected: { status: "ready" },
148+
},
128149
{
129150
name: "import of a non-admitted package",
130151
project: project(

packages/workspace-server/src/services/canvas-build/canvas-build.test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ describe("CanvasBuildService", () => {
9797
expect(imports).not.toContain("dayjs");
9898
});
9999

100+
it("inlines svg and json asset imports into the bundle", async () => {
101+
const fixture = CANVAS_BUILD_CONTRACT_FIXTURES.find(
102+
(f) => f.name === "asset imports (svg data-url + json)",
103+
);
104+
if (!fixture) throw new Error("asset fixture missing");
105+
const result = await service.buildCanvas({
106+
project: fixture.project,
107+
mode: "validate",
108+
});
109+
110+
expect(result.status).toBe("ready");
111+
const js = result.files?.find((f) => f.path.endsWith(".js"));
112+
// The svg became a data URL and the json a literal — no asset fetches at
113+
// runtime and nothing left for the sandbox CSP to block.
114+
expect(js?.content).toContain("data:image/svg+xml");
115+
expect(js?.content).toContain("hedgehog");
116+
});
117+
100118
it("reports bundle errors with the failing file and line", async () => {
101119
const project = createCanvasStarterProject();
102120
project.files["src/main.ts"] =

packages/workspace-server/src/services/canvas-build/canvas-build.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ const LOADERS: Record<string, esbuild.Loader> = {
6161
".jsx": "jsx",
6262
".css": "css",
6363
".json": "json",
64-
".svg": "text",
64+
// Inlined assets: importing an svg yields a data URL usable directly as an
65+
// img/css source. Binary formats need a binary source representation and
66+
// land with the build-service schema evolution.
67+
".svg": "dataurl",
6568
".txt": "text",
6669
};
6770

0 commit comments

Comments
 (0)