diff --git a/packages/cli/src/server/studioServer.ts b/packages/cli/src/server/studioServer.ts index 5666ca3799..b58207112d 100644 --- a/packages/cli/src/server/studioServer.ts +++ b/packages/cli/src/server/studioServer.ts @@ -209,6 +209,12 @@ export function createStudioServer(options: StudioServerOptions): StudioServer { } }, + async transformPreviewHtml({ html }) { + const { injectDeterministicFontFaces } = + await import("../../../producer/src/services/deterministicFonts.js"); + return injectDeterministicFontFaces(html); + }, + getProjectSignature(dir: string): string { if (resolve(dir) !== resolve(projectDir)) return createProjectSignature(dir); cachedProjectSignature ??= createProjectSignature(projectDir); diff --git a/packages/core/src/studio-api/routes/preview.test.ts b/packages/core/src/studio-api/routes/preview.test.ts index 1c5b1c9521..276d0b7c31 100644 --- a/packages/core/src/studio-api/routes/preview.test.ts +++ b/packages/core/src/studio-api/routes/preview.test.ts @@ -143,6 +143,56 @@ describe("registerPreviewRoutes", () => { expect(html).toContain("compositions/scene.html"); }); + it("applies adapter preview transforms to bundled root previews", async () => { + const projectDir = createProjectDir(); + const app = new Hono(); + registerPreviewRoutes( + app, + createAdapter(projectDir, { + bundle: async () => "
Preview", + transformPreviewHtml: async ({ html, activeCompositionPath }) => + html.replace( + "", + ``, + ), + }), + ); + + const response = await app.request("http://localhost/projects/demo/preview"); + const html = await response.text(); + + expect(response.status).toBe(200); + expect(html).toContain(''); + }); + + it("applies adapter preview transforms to sub-composition previews", async () => { + const projectDir = createProjectDir(); + mkdirSync(join(projectDir, "compositions"), { recursive: true }); + writeFileSync( + join(projectDir, "compositions/scene.html"), + ``, + ); + const app = new Hono(); + registerPreviewRoutes( + app, + createAdapter(projectDir, { + transformPreviewHtml: async ({ html, activeCompositionPath }) => + html.replace( + "", + ``, + ), + }), + ); + + const response = await app.request( + "http://localhost/projects/demo/preview/comp/compositions/scene.html", + ); + const html = await response.text(); + + expect(response.status).toBe(200); + expect(html).toContain(''); + }); + it("uses the adapter project signature when available", async () => { const projectDir = createProjectDir(); const getProjectSignature = vi.fn(() => "cached-signature"); diff --git a/packages/core/src/studio-api/routes/preview.ts b/packages/core/src/studio-api/routes/preview.ts index 447d080f18..d65348484b 100644 --- a/packages/core/src/studio-api/routes/preview.ts +++ b/packages/core/src/studio-api/routes/preview.ts @@ -124,6 +124,20 @@ function injectStudioPreviewAugmentations( ); } +async function transformPreviewHtml( + html: string, + adapter: StudioApiAdapter, + project: { id: string; dir: string; title?: string; sessionId?: string }, + activeCompositionPath: string, +): Promise