From 59f1d9d28a7177b6f6c227de8846ee2a615ba023 Mon Sep 17 00:00:00 2001 From: Ajay Ghanwat Date: Mon, 19 Oct 2026 14:06:20 +0530 Subject: [PATCH] fix(studio): resolve exact component filenames for Linux previews --- bun.lock | 2 +- .../2026-10-19-studio-linux-preview.md | 16 ++++++++ packages/design-studio/package.json | 2 +- packages/design-studio/src/preview.ts | 9 ++--- .../design-studio/test/preview-case.test.ts | 40 +++++++++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 docs/releases/2026-10-19-studio-linux-preview.md create mode 100644 packages/design-studio/test/preview-case.test.ts diff --git a/bun.lock b/bun.lock index 774c7392..fc7d6ca7 100644 --- a/bun.lock +++ b/bun.lock @@ -391,7 +391,7 @@ }, "packages/design-studio": { "name": "@wrnexus/design-studio", - "version": "0.1.0", + "version": "0.1.1", "dependencies": { "@wrnexus/ai": "workspace:*", "@wrnexus/compiler": "workspace:*", diff --git a/docs/releases/2026-10-19-studio-linux-preview.md b/docs/releases/2026-10-19-studio-linux-preview.md new file mode 100644 index 00000000..1dc3ec7e --- /dev/null +++ b/docs/releases/2026-10-19-studio-linux-preview.md @@ -0,0 +1,16 @@ +# Design Studio 0.1.1 — Linux preview lookup + +Composed and gallery previews previously inferred a component's filename from +its public name (Input -> Input.wrn). Some shipped components use lowercase +filenames (input.wrn), so the lookup happened to work on Windows and failed on +Linux with ENOENT. Previews now use uiComponentPath from the shipped UI registry, +which resolves declared names to their exact source files, including ComboBox. + +A subprocess regression test enforces exact filesystem casing even on Windows +and renders the composed preview and all seven gallery pages (104 components). +All 42 Studio tests and the workspace TypeScript check pass. Existing component +APIs, design schemas, browser drafts and generation contracts are unchanged. + +Private package publication and the standalone component site's dependency pin +are updated as part of this fix. The VM must install the updated lockfile, +rebuild and restart before the live preview error can disappear. diff --git a/packages/design-studio/package.json b/packages/design-studio/package.json index 69909e5f..a97981e6 100644 --- a/packages/design-studio/package.json +++ b/packages/design-studio/package.json @@ -1,6 +1,6 @@ { "name": "@wrnexus/design-studio", - "version": "0.1.0", + "version": "0.1.1", "private": true, "type": "module", "main": "src/index.ts", diff --git a/packages/design-studio/src/preview.ts b/packages/design-studio/src/preview.ts index 6c30d3b0..2eb122b5 100644 --- a/packages/design-studio/src/preview.ts +++ b/packages/design-studio/src/preview.ts @@ -1,14 +1,14 @@ import { validateAgentPage } from "./agent-pages.ts"; import { readFileSync, mkdirSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; -import { join, resolve } from "node:path"; +import { join } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; import { createHash } from "node:crypto"; import { compileWrnFile } from "@wrnexus/compiler"; import { runWithRequestContext } from "@wrnexus/core"; import { REACTIVE_RUNTIME } from "@wrnexus/csr"; import { renderDocument } from "@wrnexus/ssr"; -import { uiCss, uiComponentsDir } from "@wrnexus/ui/registry"; +import { uiCss, uiComponentPath } from "@wrnexus/ui/registry"; import { resolveThemeConfig, renderThemeCss } from "@wrnexus/styles/theme"; import { COMPONENT_CONTRACTS, @@ -25,10 +25,7 @@ const escape = (text: string) => async function component(name: string, props: Record = {}) { if (!Object.hasOwn(COMPONENT_CONTRACTS, name)) throw Error("Unknown component."); if (!modules.has(name)) { - const sourcePath = resolve( - uiComponentsDir(), - name === "ComboBox" ? "Combobox.wrn" : `${name}.wrn`, - ); + const sourcePath = uiComponentPath(name); const source = readFileSync(sourcePath, "utf8"); const directory = join(tmpdir(), "wrnexus-design-studio"); mkdirSync(directory, { recursive: true }); diff --git a/packages/design-studio/test/preview-case.test.ts b/packages/design-studio/test/preview-case.test.ts new file mode 100644 index 00000000..79bf0d2f --- /dev/null +++ b/packages/design-studio/test/preview-case.test.ts @@ -0,0 +1,40 @@ +import { expect, test } from "bun:test"; +import { pathToFileURL } from "node:url"; +import { resolve } from "node:path"; + +test("composed and catalog previews use exact shipped filename casing on every platform", () => { + const preview = pathToFileURL(resolve(import.meta.dir, "../src/preview.ts")).href; + const probe = ` + import { mock } from "bun:test"; + import { readFileSync, readdirSync } from "node:fs"; + import { dirname, basename } from "node:path"; + import { uiComponentsDir } from "@wrnexus/ui/registry"; + import { CORE_DESIGN_SYSTEMS } from "@wrnexus/design-system"; + const directory = uiComponentsDir(); + const names = new Set(readdirSync(directory)); + const originalRead = readFileSync; + let checked = 0; + mock.module("node:fs", () => ({ readFileSync(path, ...options) { + if (typeof path === "string" && dirname(path) === directory && path.endsWith(".wrn")) { + if (!names.has(basename(path))) throw Error("Case-sensitive component lookup failed: " + basename(path)); + checked++; + } + return originalRead(path, ...options); + }})); + const { previewDocument } = await import(${JSON.stringify(preview)}); + await previewDocument(CORE_DESIGN_SYSTEMS.square); + for (let page = 0; page < 7; page++) await previewDocument(CORE_DESIGN_SYSTEMS.soft, { content: "catalog", page }); + if (checked < 104) throw Error("Incomplete component coverage: " + checked); + console.log("Exact filename casing verified for all 104 preview components."); + `; + const result = Bun.spawnSync([process.execPath, "--eval", probe], { + cwd: resolve(import.meta.dir, "../../.."), + stdout: "pipe", + stderr: "pipe", + }); + expect(new TextDecoder().decode(result.stderr)).not.toContain( + "Case-sensitive component lookup failed", + ); + expect(result.exitCode).toBe(0); + expect(new TextDecoder().decode(result.stdout)).toContain("all 104 preview components"); +});