@weasel-js/forge 1.5.0 → 1.5.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/{FrameController-Ba3LaWfq.d.ts → FrameController-eZM3hlcE.d.ts} +74 -1
- package/dist/{chunk-O5OQZQRZ.js → chunk-2JDYOBWM.js} +5 -5
- package/dist/chunk-2JDYOBWM.js.map +1 -0
- package/dist/{chunk-KKF7ZX5E.js → chunk-5YHEO26U.js} +133 -23
- package/dist/chunk-5YHEO26U.js.map +1 -0
- package/dist/{chunk-UZCXH724.js → chunk-6SRQIHJQ.js} +3 -8
- package/dist/chunk-6SRQIHJQ.js.map +1 -0
- package/dist/{chunk-IOBG7GZQ.js → chunk-FTFR2YPM.js} +2 -2
- package/dist/chunk-FTFR2YPM.js.map +1 -0
- package/dist/chunk-TLO6UHF2.js +103 -0
- package/dist/chunk-TLO6UHF2.js.map +1 -0
- package/dist/{config-DdumOfyd.d.ts → config-CSVP6duU.d.ts} +6 -2
- package/dist/csf/preview-api.js +2 -2
- package/dist/frame/index.d.ts +5 -4
- package/dist/frame/index.js +5 -5
- package/dist/index.d.ts +97 -5
- package/dist/index.js.map +1 -1
- package/dist/shell/index.css +209 -12
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +62 -4
- package/dist/shell/index.js +712 -182
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.d.ts +2 -2
- package/dist/test/index.js +7 -7
- package/dist/test/index.js.map +1 -1
- package/dist/test/play.d.ts +25 -0
- package/dist/test/play.js +14 -0
- package/dist/test/play.js.map +1 -0
- package/dist/vite/index.js +72 -20
- package/dist/vite/index.js.map +1 -1
- package/package.json +14 -5
- package/dist/chunk-IOBG7GZQ.js.map +0 -1
- package/dist/chunk-KKF7ZX5E.js.map +0 -1
- package/dist/chunk-KKVTFMWV.js +0 -59
- package/dist/chunk-KKVTFMWV.js.map +0 -1
- package/dist/chunk-O5OQZQRZ.js.map +0 -1
- package/dist/chunk-UZCXH724.js.map +0 -1
package/dist/test/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { loadStories, startFrame } from '../chunk-
|
|
1
|
+
import { loadStories, startFrame } from '../chunk-5YHEO26U.js';
|
|
2
2
|
import '../chunk-2GXKNXTJ.js';
|
|
3
|
-
import '../chunk-
|
|
4
|
-
import { openChannel } from '../chunk-
|
|
5
|
-
import '../chunk-
|
|
6
|
-
import '../chunk-
|
|
3
|
+
import '../chunk-6SRQIHJQ.js';
|
|
4
|
+
import { openChannel } from '../chunk-2JDYOBWM.js';
|
|
5
|
+
import '../chunk-TLO6UHF2.js';
|
|
6
|
+
import '../chunk-FTFR2YPM.js';
|
|
7
7
|
|
|
8
8
|
// src/test/runStory.ts
|
|
9
9
|
function phased(phase, error) {
|
|
@@ -62,11 +62,11 @@ var settle = () => new Promise((resolve) => {
|
|
|
62
62
|
});
|
|
63
63
|
var leftover = null;
|
|
64
64
|
var pageSize = null;
|
|
65
|
-
async function runStory(mod, exportName, file,
|
|
65
|
+
async function runStory(mod, exportName, file, autoTitle, { setup, viewport } = {}) {
|
|
66
66
|
leftover?.();
|
|
67
67
|
let story;
|
|
68
68
|
try {
|
|
69
|
-
story = loadStories(mod,
|
|
69
|
+
story = loadStories(mod, autoTitle, setup?.parameters).find((s) => s.exportName === exportName);
|
|
70
70
|
} catch (error) {
|
|
71
71
|
throw phased("load", error);
|
|
72
72
|
}
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/test/runStory.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { type FrameSetup, startFrame } from '../frame/FrameController';\nimport { loadStories } from '../frame/mountFrame';\nimport { type Channel, openChannel } from '../protocol/channel';\nimport type { FromFrame, ToFrame, Viewport } from '../protocol/messages';\n\ntype Received<T extends FromFrame['type']> = Extract<FromFrame, { type: T }>;\n\n/** Prefixes `error` with the phase it came from, keeping its stack. */\nfunction phased(phase: string, error: unknown): Error {\n const message = error instanceof Error ? error.message : String(error);\n const out = new Error(`${phase} fault: ${message}`, { cause: error });\n if (error instanceof Error && error.stack) out.stack = `${phase} fault: ${error.stack}`;\n return out;\n}\n\nfunction inbox(channel: Channel<FromFrame, ToFrame>) {\n const received: FromFrame[] = [];\n let failure: Error | null = null;\n const wake = new Set<() => void>();\n const off = channel.on((msg) => {\n if (msg.type === 'fault' && !failure) {\n failure = new Error(`${msg.phase} fault: ${msg.message}`);\n if (msg.stack) failure.stack = `${msg.phase} fault: ${msg.stack}`;\n }\n received.push(msg);\n for (const fn of [...wake]) fn();\n });\n\n const check = () => {\n if (failure) throw failure;\n };\n\n const next = <T extends FromFrame['type']>(type: T): Promise<Received<T>> =>\n new Promise((resolve, reject) => {\n const poll = () => {\n if (failure) {\n wake.delete(poll);\n reject(failure);\n return;\n }\n const at = received.findIndex((m) => m.type === type);\n if (at === -1) return;\n wake.delete(poll);\n resolve(received.splice(at, 1)[0] as Received<T>);\n };\n wake.add(poll);\n poll();\n });\n\n /** The first fault, if one arrives by the next macrotask. */\n const fault = (): Promise<Error | null> =>\n new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n wake.delete(onMessage);\n resolve(failure);\n };\n const onMessage = () => {\n if (failure) done();\n };\n const timer = setTimeout(done, 0);\n wake.add(onMessage);\n onMessage();\n });\n\n return { next, check, fault, close: off };\n}\n\nconst settle = () =>\n new Promise<void>((resolve) => {\n requestAnimationFrame(() => setTimeout(resolve, 0));\n });\n\nexport interface RunStoryOptions {\n /** The frame config (`frameConfig`). */\n setup?: FrameSetup;\n /** Resizes the page, for a story that names a viewport. Without it, stories run at whatever size the page is. */\n viewport?: (width: number, height: number) => Promise<void>;\n}\n\n/** Stops the story a timed-out test left mounted. */\nlet leftover: (() => unknown) | null = null;\n/** The page's size before any story resized it; a story with no viewport runs at this size. */\nlet pageSize: Viewport | null = null;\n\n/**\n * Renders one story the way the workshop's frame does — defaults, no state, no globals — then plays it.\n * Throws on any fault the frame reports, or a play function that fails.\n */\nexport async function runStory(\n mod: Record<string, unknown>,\n exportName: string,\n file: string,\n root: string,\n { setup, viewport }: RunStoryOptions = {},\n): Promise<void> {\n leftover?.();\n let story: ReturnType<typeof loadStories>[number] | undefined;\n try {\n story = loadStories(mod, file, root, setup?.parameters).find((s) => s.exportName === exportName);\n } catch (error) {\n throw phased('load', error);\n }\n if (!story) throw new Error(`load fault: ${file} has no story export \"${exportName}\"`);\n\n pageSize ??= { width: window.innerWidth, height: window.innerHeight };\n const size = story.viewport ?? pageSize;\n if (viewport && (window.innerWidth !== size.width || window.innerHeight !== size.height)) {\n await viewport(size.width, size.height);\n }\n\n const { port1, port2 } = new MessageChannel();\n const shell = openChannel<FromFrame, ToFrame>(port1);\n const frame = openChannel<ToFrame, FromFrame>(port2);\n const messages = inbox(shell);\n const container = document.createElement('div');\n document.body.append(container);\n let stopFrame: (() => void) | undefined;\n /** Returns what `stopFrame` threw, having released everything else regardless. */\n const cleanup = (): { error: unknown } | null => {\n if (leftover === cleanup) leftover = null;\n let thrown: { error: unknown } | null = null;\n try {\n messages.close();\n stopFrame?.();\n } catch (error) {\n thrown = { error };\n } finally {\n stopFrame = undefined;\n shell.close();\n frame.close();\n container.remove();\n }\n return thrown;\n };\n leftover = cleanup;\n\n let failure: { error: unknown } | null = null;\n try {\n try {\n stopFrame = startFrame({ story, channel: frame, container, setup });\n } catch (error) {\n throw phased('mount', error);\n }\n await messages.next('ready');\n shell.send({ type: 'init', config: story.config.defaults(), state: null, globals: {} });\n await messages.next('answers');\n await settle();\n messages.check();\n if (story.play) {\n shell.send({ type: 'play' });\n const played = await messages.next('played');\n if (!played.ok) throw (await messages.fault()) ?? new Error(`play fault: ${played.message ?? 'failed'}`);\n await settle();\n }\n messages.check();\n } catch (error) {\n failure = { error };\n }\n const cleanupError = cleanup();\n if (failure) throw failure.error;\n if (cleanupError) throw phased('cleanup', cleanupError.error);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/test/runStory.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { type FrameSetup, startFrame } from '../frame/FrameController';\nimport { loadStories } from '../frame/mountFrame';\nimport { type Channel, openChannel } from '../protocol/channel';\nimport type { FromFrame, ToFrame, Viewport } from '../protocol/messages';\n\ntype Received<T extends FromFrame['type']> = Extract<FromFrame, { type: T }>;\n\n/** Prefixes `error` with the phase it came from, keeping its stack. */\nfunction phased(phase: string, error: unknown): Error {\n const message = error instanceof Error ? error.message : String(error);\n const out = new Error(`${phase} fault: ${message}`, { cause: error });\n if (error instanceof Error && error.stack) out.stack = `${phase} fault: ${error.stack}`;\n return out;\n}\n\nfunction inbox(channel: Channel<FromFrame, ToFrame>) {\n const received: FromFrame[] = [];\n let failure: Error | null = null;\n const wake = new Set<() => void>();\n const off = channel.on((msg) => {\n if (msg.type === 'fault' && !failure) {\n failure = new Error(`${msg.phase} fault: ${msg.message}`);\n if (msg.stack) failure.stack = `${msg.phase} fault: ${msg.stack}`;\n }\n received.push(msg);\n for (const fn of [...wake]) fn();\n });\n\n const check = () => {\n if (failure) throw failure;\n };\n\n const next = <T extends FromFrame['type']>(type: T): Promise<Received<T>> =>\n new Promise((resolve, reject) => {\n const poll = () => {\n if (failure) {\n wake.delete(poll);\n reject(failure);\n return;\n }\n const at = received.findIndex((m) => m.type === type);\n if (at === -1) return;\n wake.delete(poll);\n resolve(received.splice(at, 1)[0] as Received<T>);\n };\n wake.add(poll);\n poll();\n });\n\n /** The first fault, if one arrives by the next macrotask. */\n const fault = (): Promise<Error | null> =>\n new Promise((resolve) => {\n const done = () => {\n clearTimeout(timer);\n wake.delete(onMessage);\n resolve(failure);\n };\n const onMessage = () => {\n if (failure) done();\n };\n const timer = setTimeout(done, 0);\n wake.add(onMessage);\n onMessage();\n });\n\n return { next, check, fault, close: off };\n}\n\nconst settle = () =>\n new Promise<void>((resolve) => {\n requestAnimationFrame(() => setTimeout(resolve, 0));\n });\n\nexport interface RunStoryOptions {\n /** The frame config (`frameConfig`). */\n setup?: FrameSetup;\n /** Resizes the page, for a story that names a viewport. Without it, stories run at whatever size the page is. */\n viewport?: (width: number, height: number) => Promise<void>;\n}\n\n/** Stops the story a timed-out test left mounted. */\nlet leftover: (() => unknown) | null = null;\n/** The page's size before any story resized it; a story with no viewport runs at this size. */\nlet pageSize: Viewport | null = null;\n\n/**\n * Renders one story the way the workshop's frame does — defaults, no state, no globals — then plays it.\n * Throws on any fault the frame reports, or a play function that fails.\n */\nexport async function runStory(\n mod: Record<string, unknown>,\n exportName: string,\n file: string,\n autoTitle: string,\n { setup, viewport }: RunStoryOptions = {},\n): Promise<void> {\n leftover?.();\n let story: ReturnType<typeof loadStories>[number] | undefined;\n try {\n story = loadStories(mod, autoTitle, setup?.parameters).find((s) => s.exportName === exportName);\n } catch (error) {\n throw phased('load', error);\n }\n if (!story) throw new Error(`load fault: ${file} has no story export \"${exportName}\"`);\n\n pageSize ??= { width: window.innerWidth, height: window.innerHeight };\n const size = story.viewport ?? pageSize;\n if (viewport && (window.innerWidth !== size.width || window.innerHeight !== size.height)) {\n await viewport(size.width, size.height);\n }\n\n const { port1, port2 } = new MessageChannel();\n const shell = openChannel<FromFrame, ToFrame>(port1);\n const frame = openChannel<ToFrame, FromFrame>(port2);\n const messages = inbox(shell);\n const container = document.createElement('div');\n document.body.append(container);\n let stopFrame: (() => void) | undefined;\n /** Returns what `stopFrame` threw, having released everything else regardless. */\n const cleanup = (): { error: unknown } | null => {\n if (leftover === cleanup) leftover = null;\n let thrown: { error: unknown } | null = null;\n try {\n messages.close();\n stopFrame?.();\n } catch (error) {\n thrown = { error };\n } finally {\n stopFrame = undefined;\n shell.close();\n frame.close();\n container.remove();\n }\n return thrown;\n };\n leftover = cleanup;\n\n let failure: { error: unknown } | null = null;\n try {\n try {\n stopFrame = startFrame({ story, channel: frame, container, setup });\n } catch (error) {\n throw phased('mount', error);\n }\n await messages.next('ready');\n shell.send({ type: 'init', config: story.config.defaults(), state: null, globals: {} });\n await messages.next('answers');\n await settle();\n messages.check();\n if (story.play) {\n shell.send({ type: 'play' });\n const played = await messages.next('played');\n if (!played.ok) throw (await messages.fault()) ?? new Error(`play fault: ${played.message ?? 'failed'}`);\n await settle();\n }\n messages.check();\n } catch (error) {\n failure = { error };\n }\n const cleanupError = cleanup();\n if (failure) throw failure.error;\n if (cleanupError) throw phased('cleanup', cleanupError.error);\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ExpectStatic } from '@vitest/expect';
|
|
2
|
+
export { screen, waitFor, within } from '@testing-library/dom';
|
|
3
|
+
export { default as userEvent } from '@testing-library/user-event';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* What a CSF `play` function asserts with.
|
|
7
|
+
*
|
|
8
|
+
* A play runs inside the story's frame — a real browser document, driven by
|
|
9
|
+
* `forgeTest` under vitest or by the workshop — so it cannot import `vitest`,
|
|
10
|
+
* whose entry only exists inside a test worker. This module assembles the same
|
|
11
|
+
* `expect` vitest hands a test: chai carrying `@vitest/expect`'s jest-style
|
|
12
|
+
* matchers. Queries and input come from testing-library, which is already
|
|
13
|
+
* browser-only.
|
|
14
|
+
*
|
|
15
|
+
* No jest-dom matchers. They install through `expect.extend`, which wants the
|
|
16
|
+
* matcher state a test worker sets up, and there is none here — the call
|
|
17
|
+
* throws at module scope. Assert on the DOM directly instead:
|
|
18
|
+
* `expect(el.textContent).toBe(…)` for `toHaveTextContent`,
|
|
19
|
+
* `expect(el).not.toBeNull()` for `toBeInTheDocument`.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
/** `expect`, with jest's matchers. */
|
|
23
|
+
declare const expect: ExpectStatic;
|
|
24
|
+
|
|
25
|
+
export { expect };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { JestExtend, JestChaiExpect, JestAsymmetricMatchers } from '@vitest/expect';
|
|
2
|
+
import * as chai from 'chai';
|
|
3
|
+
export { screen, waitFor, within } from '@testing-library/dom';
|
|
4
|
+
export { default as userEvent } from '@testing-library/user-event';
|
|
5
|
+
|
|
6
|
+
// src/test/play.ts
|
|
7
|
+
chai.use(JestExtend);
|
|
8
|
+
chai.use(JestChaiExpect);
|
|
9
|
+
chai.use(JestAsymmetricMatchers);
|
|
10
|
+
var expect2 = chai.expect;
|
|
11
|
+
|
|
12
|
+
export { expect2 as expect };
|
|
13
|
+
//# sourceMappingURL=play.js.map
|
|
14
|
+
//# sourceMappingURL=play.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/test/play.ts"],"names":["expect"],"mappings":";;;;;;AAmBK,IAAA,CAAA,GAAA,CAAI,UAAU,CAAA;AACd,IAAA,CAAA,GAAA,CAAI,cAAc,CAAA;AAClB,IAAA,CAAA,GAAA,CAAI,sBAAsB,CAAA;AAGxB,IAAMA,OAAAA,GAAc,IAAA,CAAA","file":"play.js","sourcesContent":["/**\n * What a CSF `play` function asserts with.\n *\n * A play runs inside the story's frame — a real browser document, driven by\n * `forgeTest` under vitest or by the workshop — so it cannot import `vitest`,\n * whose entry only exists inside a test worker. This module assembles the same\n * `expect` vitest hands a test: chai carrying `@vitest/expect`'s jest-style\n * matchers. Queries and input come from testing-library, which is already\n * browser-only.\n *\n * No jest-dom matchers. They install through `expect.extend`, which wants the\n * matcher state a test worker sets up, and there is none here — the call\n * throws at module scope. Assert on the DOM directly instead:\n * `expect(el.textContent).toBe(…)` for `toHaveTextContent`,\n * `expect(el).not.toBeNull()` for `toBeInTheDocument`.\n */\nimport { type ExpectStatic, JestAsymmetricMatchers, JestChaiExpect, JestExtend } from '@vitest/expect';\nimport * as chai from 'chai';\n\nchai.use(JestExtend);\nchai.use(JestChaiExpect);\nchai.use(JestAsymmetricMatchers);\n\n/** `expect`, with jest's matchers. */\nexport const expect = chai.expect as unknown as ExpectStatic;\n\nexport { screen, waitFor, within } from '@testing-library/dom';\nexport { default as userEvent } from '@testing-library/user-event';\n"]}
|
package/dist/vite/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { storyNameFromExport, storyId } from '../chunk-6SRQIHJQ.js';
|
|
2
2
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, globSync } from 'fs';
|
|
3
3
|
import { resolve, relative, sep, matchesGlob, dirname, join, basename } from 'path';
|
|
4
4
|
import { fileURLToPath } from 'url';
|
|
@@ -46,15 +46,43 @@ function hoistPages(bundle, emit) {
|
|
|
46
46
|
emit({ type: "asset", fileName: `${name}.html`, source: up(asset.source) });
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
|
|
49
|
+
var posix = (path) => path.split(sep).join("/");
|
|
50
|
+
var dotted = (path) => /^\.{1,2}([/\\]|$)/.test(path) ? path : `./${path}`;
|
|
51
|
+
function globDirectory(pattern) {
|
|
52
|
+
const segments = pattern.split("/");
|
|
53
|
+
const magic = segments.findIndex((segment) => /^!|(^|[^\\])[*?[{(]/.test(segment));
|
|
54
|
+
return magic === -1 ? dirname(pattern) : segments.slice(0, magic).join("/");
|
|
55
|
+
}
|
|
56
|
+
function titleParts(parts) {
|
|
57
|
+
const last = parts[parts.length - 1];
|
|
58
|
+
if (last === void 0) return parts;
|
|
59
|
+
const stripped = last.replace(/(?:[.](?:story|stories))?([.][^.]+)$/i, "");
|
|
60
|
+
if (parts.length === 1) return [stripped];
|
|
61
|
+
const nextToLast = parts[parts.length - 2];
|
|
62
|
+
if (stripped && nextToLast && stripped.toLowerCase() === nextToLast.toLowerCase()) return [...parts.slice(0, -2), stripped];
|
|
63
|
+
if (stripped && (/^(story|stories)([.][^.]+)$/i.test(last) || /^index$/i.test(stripped))) return parts.slice(0, -1);
|
|
64
|
+
return [...parts.slice(0, -1), stripped];
|
|
65
|
+
}
|
|
66
|
+
var titleFrom = (importPath, directory) => titleParts(importPath.replace(directory, "").split("/").filter(Boolean)).join("/");
|
|
67
|
+
function autoTitle(file, root, stories) {
|
|
68
|
+
const path = posix(relative(root, file));
|
|
69
|
+
const importPath = dotted(path);
|
|
70
|
+
for (const pattern of stories) {
|
|
71
|
+
if (!matchesGlob(path, pattern.replace(/^\.\//, ""))) continue;
|
|
72
|
+
const directory = dotted(posix(relative(root, resolve(root, globDirectory(pattern))))).replace(/\/$/, "");
|
|
73
|
+
return titleFrom(importPath, directory);
|
|
74
|
+
}
|
|
75
|
+
return titleFrom(importPath, ".");
|
|
76
|
+
}
|
|
77
|
+
function indexFile(code, file, autoTitle2) {
|
|
50
78
|
try {
|
|
51
79
|
const plugins = ["typescript", "decorators-legacy", .../\.[jt]sx$/.test(file) ? ["jsx"] : []];
|
|
52
|
-
return indexProgram(parse(code, { sourceType: "module", plugins }).program, file,
|
|
80
|
+
return indexProgram(parse(code, { sourceType: "module", plugins }).program, file, autoTitle2);
|
|
53
81
|
} catch (err) {
|
|
54
82
|
throw new Error(`${file}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
55
83
|
}
|
|
56
84
|
}
|
|
57
|
-
function indexProgram(program, file,
|
|
85
|
+
function indexProgram(program, file, autoTitle2) {
|
|
58
86
|
const bindings = /* @__PURE__ */ new Map();
|
|
59
87
|
const wrappers = /* @__PURE__ */ new Set();
|
|
60
88
|
for (const stmt of program.body) {
|
|
@@ -71,39 +99,51 @@ function indexProgram(program, file, root) {
|
|
|
71
99
|
}
|
|
72
100
|
}
|
|
73
101
|
let metaNode;
|
|
102
|
+
let metaDoc;
|
|
74
103
|
const exported = [];
|
|
75
104
|
for (const stmt of program.body) {
|
|
76
|
-
if (stmt.type === "ExportDefaultDeclaration")
|
|
105
|
+
if (stmt.type === "ExportDefaultDeclaration") {
|
|
106
|
+
metaNode = stmt.declaration;
|
|
107
|
+
metaDoc = docOf(stmt);
|
|
108
|
+
}
|
|
77
109
|
if (stmt.type !== "ExportNamedDeclaration" || stmt.exportKind === "type") continue;
|
|
110
|
+
const doc = docOf(stmt);
|
|
78
111
|
const decl = stmt.declaration;
|
|
79
112
|
if (decl?.type === "VariableDeclaration") {
|
|
80
113
|
for (const d of decl.declarations) {
|
|
81
|
-
if (d.id.type === "Identifier") exported.push({ name: d.id.name, node: d.init ?? void 0 });
|
|
114
|
+
if (d.id.type === "Identifier") exported.push({ name: d.id.name, node: d.init ?? void 0, doc: docOf(d) ?? doc });
|
|
82
115
|
}
|
|
83
116
|
} else if (decl?.type === "FunctionDeclaration" && decl.id) {
|
|
84
|
-
exported.push({ name: decl.id.name, node: void 0 });
|
|
117
|
+
exported.push({ name: decl.id.name, node: void 0, doc });
|
|
85
118
|
}
|
|
86
119
|
for (const spec of stmt.specifiers) {
|
|
87
120
|
if (spec.type !== "ExportSpecifier" || spec.exportKind === "type") continue;
|
|
88
121
|
const name = exportedName(spec.exported);
|
|
89
122
|
const node = stmt.source ? void 0 : bindings.get(spec.local.name);
|
|
90
|
-
if (name === "default")
|
|
91
|
-
|
|
123
|
+
if (name === "default") {
|
|
124
|
+
metaNode = node;
|
|
125
|
+
metaDoc ??= doc;
|
|
126
|
+
} else exported.push({ name, node, doc });
|
|
92
127
|
}
|
|
93
128
|
}
|
|
94
129
|
if (!metaNode && !program.body.some(isDefaultExport)) return [];
|
|
95
130
|
const meta = objectOf(metaNode, bindings, wrappers);
|
|
96
|
-
const title = stringProp(meta, "title") ??
|
|
131
|
+
const title = stringProp(meta, "title") ?? autoTitle2;
|
|
97
132
|
const include = storyFilter(meta, "includeStories");
|
|
98
133
|
const exclude = storyFilter(meta, "excludeStories");
|
|
99
|
-
|
|
134
|
+
const componentNode = prop(meta, "component");
|
|
135
|
+
const componentName = componentNode?.type === "Identifier" ? componentNode.name : void 0;
|
|
136
|
+
return exported.filter(({ name }) => name !== "__namedExportsOrder").filter(({ name }) => (!include || include(name)) && (!exclude || !exclude(name))).map(({ name, node, doc }) => {
|
|
100
137
|
const spec = objectOf(node, bindings, wrappers);
|
|
101
138
|
return {
|
|
102
139
|
id: storyId(title, name),
|
|
103
140
|
title,
|
|
104
141
|
name: stringProp(spec, "name") ?? stringProp(spec, "storyName") ?? storyNameFromExport(name),
|
|
105
142
|
exportName: name,
|
|
106
|
-
file
|
|
143
|
+
file,
|
|
144
|
+
...doc === void 0 ? {} : { description: doc },
|
|
145
|
+
...metaDoc === void 0 ? {} : { componentDescription: metaDoc },
|
|
146
|
+
...componentName === void 0 ? {} : { componentName }
|
|
107
147
|
};
|
|
108
148
|
});
|
|
109
149
|
}
|
|
@@ -111,6 +151,13 @@ function isDefaultExport(stmt) {
|
|
|
111
151
|
if (stmt.type === "ExportDefaultDeclaration") return true;
|
|
112
152
|
return stmt.type === "ExportNamedDeclaration" && stmt.specifiers.some((s) => s.type === "ExportSpecifier" && exportedName(s.exported) === "default");
|
|
113
153
|
}
|
|
154
|
+
function docOf(node) {
|
|
155
|
+
const comments = node.leadingComments;
|
|
156
|
+
const last = comments?.[comments.length - 1];
|
|
157
|
+
if (last?.type !== "CommentBlock" || !last.value.startsWith("*")) return void 0;
|
|
158
|
+
const text = last.value.slice(1).split("\n").map((line) => line.replace(/^\s*\*/, "").trim()).join("\n").trim();
|
|
159
|
+
return text || void 0;
|
|
160
|
+
}
|
|
114
161
|
function exportedName(node) {
|
|
115
162
|
return node.type === "Identifier" ? node.name : node.value;
|
|
116
163
|
}
|
|
@@ -157,14 +204,18 @@ function storyFilter(obj, key) {
|
|
|
157
204
|
}
|
|
158
205
|
return null;
|
|
159
206
|
}
|
|
160
|
-
var
|
|
207
|
+
var SHIMS = [
|
|
208
|
+
[/^@?storybook\/preview-api$/, "@weasel-js/forge/preview-api"],
|
|
209
|
+
[/^@?storybook\/test$/, "@weasel-js/forge/play"]
|
|
210
|
+
];
|
|
161
211
|
function storybookShims() {
|
|
162
212
|
return {
|
|
163
213
|
name: "weaselforge:storybook-shims",
|
|
164
214
|
enforce: "pre",
|
|
165
215
|
resolveId(id) {
|
|
166
|
-
|
|
167
|
-
|
|
216
|
+
const hit = SHIMS.find(([pattern]) => pattern.test(id));
|
|
217
|
+
if (!hit) return void 0;
|
|
218
|
+
return this.resolve(hit[1], fileURLToPath(import.meta.url), { skipSelf: true });
|
|
168
219
|
}
|
|
169
220
|
};
|
|
170
221
|
}
|
|
@@ -200,7 +251,7 @@ function forge(options) {
|
|
|
200
251
|
const path = relative(root, file).split(sep).join("/");
|
|
201
252
|
return !path.split("/").includes("node_modules") && options.stories.some((pattern) => matchesGlob(path, pattern));
|
|
202
253
|
};
|
|
203
|
-
const read = (file) => indexFile(readFileSync(file, "utf8"), file, root);
|
|
254
|
+
const read = (file) => indexFile(readFileSync(file, "utf8"), file, autoTitle(file, root, options.stories));
|
|
204
255
|
const logError = (err) => logger?.error(`[forge] ${err instanceof Error ? err.message : String(err)}`);
|
|
205
256
|
const files = () => {
|
|
206
257
|
byFile ??= new Map(
|
|
@@ -250,7 +301,7 @@ import index from 'virtual:forge/index.js';
|
|
|
250
301
|
import importers from 'virtual:forge/importers.js';
|
|
251
302
|
import setup from 'virtual:forge/frame-config.js';
|
|
252
303
|
|
|
253
|
-
mountFrame({ index, importers,
|
|
304
|
+
mountFrame({ index, importers, setup });
|
|
254
305
|
`
|
|
255
306
|
};
|
|
256
307
|
function reindex(server, file, event) {
|
|
@@ -357,7 +408,8 @@ function forgeTest(options) {
|
|
|
357
408
|
},
|
|
358
409
|
transform(code, id) {
|
|
359
410
|
if (!matches(id)) return void 0;
|
|
360
|
-
const
|
|
411
|
+
const title = autoTitle(id, root, options.stories);
|
|
412
|
+
const entries = indexFile(code, id, title);
|
|
361
413
|
if (entries.length === 0) return void 0;
|
|
362
414
|
const q = (value) => JSON.stringify(value);
|
|
363
415
|
const lines = [
|
|
@@ -368,13 +420,13 @@ function forgeTest(options) {
|
|
|
368
420
|
`import "@weasel-js/forge/frame.css";`,
|
|
369
421
|
...options.frameConfig ? [`import __forge_frame_config from ${q(resolve(root, options.frameConfig))};`] : [],
|
|
370
422
|
`const __forge_file = ${q(id)};`,
|
|
371
|
-
`const
|
|
423
|
+
`const __forge_title = ${q(title)};`,
|
|
372
424
|
`const __forge_timeout = ${TIMEOUT_MS};`,
|
|
373
425
|
"const __forge_options = {",
|
|
374
426
|
` setup: ${options.frameConfig ? "__forge_frame_config" : "undefined"},`,
|
|
375
427
|
" viewport: (width, height) => __forge_page.viewport(width, height),",
|
|
376
428
|
"};",
|
|
377
|
-
"const __forge_run = async (exportName) => __forge_runStory(await import(/* @vite-ignore */ import.meta.url), exportName, __forge_file,
|
|
429
|
+
"const __forge_run = async (exportName) => __forge_runStory(await import(/* @vite-ignore */ import.meta.url), exportName, __forge_file, __forge_title, __forge_options);",
|
|
378
430
|
...entries.map(
|
|
379
431
|
(entry) => `__forge_test(${q(entry.name)}, () => __forge_run(${q(entry.exportName)}), __forge_timeout);`
|
|
380
432
|
)
|
package/dist/vite/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/vite/html.ts","../../src/vite/build.ts","../../src/vite/indexFile.ts","../../src/vite/storybookShims.ts","../../src/vite/plugin.ts","../../src/vite/forgeTest.ts"],"names":["PAGES","fileURLToPath","join","files","relative","sep","matchesGlob","resolve"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The document forge serves for `entry`, one of its `virtual:forge/*-entry.js` modules. A build hands the\n * bare id to its own resolver; the dev server needs the `/@id/` form a browser can request.\n */\nexport function html(entry: string, mode: 'serve' | 'build' = 'serve'): string {\n const src = `${mode === 'serve' ? '/@id/' : ''}virtual:forge/${entry}`;\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>weaselforge</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"${src}\"></script>\n </body>\n</html>\n`;\n}\n","import { mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { html } from './html';\n\nconst DIR = 'node_modules/.forge';\ntype Source = string | Uint8Array;\n\nconst PAGES: Record<string, string> = { index: 'shell-entry.js', frame: 'frame-entry.js' };\n\n/** Writes a build document per forge page under `<root>/node_modules/.forge`, returning them as build inputs. */\nexport function writePages(root: string): Record<string, string> {\n const dir = join(root, DIR);\n mkdirSync(dir, { recursive: true });\n return Object.fromEntries(\n Object.entries(PAGES).map(([name, entry]) => {\n const file = join(dir, `${name}.html`);\n writeFileSync(file, html(entry, 'build'));\n return [name, file];\n }),\n );\n}\n\n/** Vite wrote a relative base's urls from two directories down; the documents now sit at the output root. */\nconst up = (source: Source) =>\n (typeof source === 'string' ? source : new TextDecoder().decode(source)).replace(/(\\s(?:src|href)=\")\\.\\.\\/\\.\\.\\//g, '$1./');\n\n/** Replaces the documents vite emitted at their input path with copies at the output root. */\nexport function hoistPages(\n bundle: Record<string, { type: string; source?: Source }>,\n emit: (file: { type: 'asset'; fileName: string; source: Source }) => void,\n): void {\n for (const name of Object.keys(PAGES)) {\n const from = `${DIR}/${name}.html`;\n const asset = bundle[from];\n if (asset?.type !== 'asset' || asset.source === undefined) continue;\n delete bundle[from];\n emit({ type: 'asset', fileName: `${name}.html`, source: up(asset.source) });\n }\n}\n","import { type ParserPlugin, parse } from '@babel/parser';\nimport type * as t from '@babel/types';\nimport { storyId, storyNameFromExport, titleFromFile } from '../story/ids';\nimport type { IndexEntry } from '../story/types';\n\ntype Bindings = Map<string, t.Node>;\n\n/** The stories `code` declares, in source order, without running it. `file` is absolute. */\nexport function indexFile(code: string, file: string, root: string): IndexEntry[] {\n try {\n const plugins: ParserPlugin[] = ['typescript', 'decorators-legacy', ...(/\\.[jt]sx$/.test(file) ? (['jsx'] as const) : [])];\n return indexProgram(parse(code, { sourceType: 'module', plugins }).program, file, root);\n } catch (err) {\n throw new Error(`${file}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n }\n}\n\nfunction indexProgram(program: t.Program, file: string, root: string): IndexEntry[] {\n const bindings: Bindings = new Map();\n const wrappers = new Set<string>();\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration' && stmt.source.value === '@weasel-js/forge') {\n for (const spec of stmt.specifiers) {\n if (spec.type === 'ImportSpecifier' && ['meta', 'story'].includes(exportedName(spec.imported))) {\n wrappers.add(spec.local.name);\n }\n }\n }\n const decl = stmt.type === 'ExportNamedDeclaration' ? stmt.declaration : stmt;\n if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations) if (d.id.type === 'Identifier' && d.init) bindings.set(d.id.name, d.init);\n }\n }\n\n let metaNode: t.Node | undefined;\n const exported: { name: string; node: t.Node | undefined }[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ExportDefaultDeclaration') metaNode = stmt.declaration;\n if (stmt.type !== 'ExportNamedDeclaration' || stmt.exportKind === 'type') continue;\n const decl = stmt.declaration;\n if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations) {\n if (d.id.type === 'Identifier') exported.push({ name: d.id.name, node: d.init ?? undefined });\n }\n } else if (decl?.type === 'FunctionDeclaration' && decl.id) {\n exported.push({ name: decl.id.name, node: undefined });\n }\n for (const spec of stmt.specifiers) {\n if (spec.type !== 'ExportSpecifier' || spec.exportKind === 'type') continue;\n const name = exportedName(spec.exported);\n const node = stmt.source ? undefined : bindings.get(spec.local.name);\n if (name === 'default') metaNode = node;\n else exported.push({ name, node });\n }\n }\n if (!metaNode && !program.body.some(isDefaultExport)) return [];\n\n const meta = objectOf(metaNode, bindings, wrappers);\n const title = stringProp(meta, 'title') ?? titleFromFile(file, root);\n const include = storyFilter(meta, 'includeStories');\n const exclude = storyFilter(meta, 'excludeStories');\n\n return exported\n .filter(({ name }) => name !== '__namedExportsOrder')\n .filter(({ name }) => (!include || include(name)) && (!exclude || !exclude(name)))\n .map(({ name, node }) => {\n const spec = objectOf(node, bindings, wrappers);\n return {\n id: storyId(title, name),\n title,\n name: stringProp(spec, 'name') ?? stringProp(spec, 'storyName') ?? storyNameFromExport(name),\n exportName: name,\n file,\n };\n });\n}\n\nfunction isDefaultExport(stmt: t.Statement): boolean {\n if (stmt.type === 'ExportDefaultDeclaration') return true;\n return (\n stmt.type === 'ExportNamedDeclaration' &&\n stmt.specifiers.some((s) => s.type === 'ExportSpecifier' && exportedName(s.exported) === 'default')\n );\n}\n\nfunction exportedName(node: t.Identifier | t.StringLiteral): string {\n return node.type === 'Identifier' ? node.name : node.value;\n}\n\n/** The object literal `node` evaluates to, through casts, `meta(…)`/`story(…)` and top-level `const`s. */\nfunction objectOf(node: t.Node | undefined, bindings: Bindings, wrappers: Set<string>, depth = 0): t.ObjectExpression | null {\n if (!node || depth > 16) return null;\n switch (node.type) {\n case 'ObjectExpression':\n return node;\n case 'TSSatisfiesExpression':\n case 'TSAsExpression':\n case 'TSTypeAssertion':\n case 'TSNonNullExpression':\n case 'ParenthesizedExpression':\n return objectOf(node.expression, bindings, wrappers, depth + 1);\n case 'CallExpression':\n return node.callee.type === 'Identifier' && wrappers.has(node.callee.name)\n ? objectOf(node.arguments[0], bindings, wrappers, depth + 1)\n : null;\n case 'Identifier':\n return objectOf(bindings.get(node.name), bindings, wrappers, depth + 1);\n default:\n return null;\n }\n}\n\nfunction prop(obj: t.ObjectExpression | null, key: string): t.Node | undefined {\n for (const p of obj?.properties ?? []) {\n if (p.type !== 'ObjectProperty' || p.computed) continue;\n const name = p.key.type === 'Identifier' ? p.key.name : p.key.type === 'StringLiteral' ? p.key.value : null;\n if (name === key) return p.value;\n }\n return undefined;\n}\n\nfunction stringProp(obj: t.ObjectExpression | null, key: string): string | undefined {\n const value = prop(obj, key);\n return value?.type === 'StringLiteral' ? value.value : undefined;\n}\n\n/** `includeStories`/`excludeStories` as a predicate, when written as a string array or a regex literal. */\nfunction storyFilter(obj: t.ObjectExpression | null, key: string): ((name: string) => boolean) | null {\n const value = prop(obj, key);\n if (value?.type === 'RegExpLiteral') {\n const re = new RegExp(value.pattern, value.flags.replace(/[gy]/g, ''));\n return (name) => re.test(name);\n }\n if (value?.type === 'ArrayExpression' && value.elements.every((e) => e?.type === 'StringLiteral')) {\n const names = new Set(value.elements.map((e) => (e as t.StringLiteral).value));\n return (name) => names.has(name);\n }\n return null;\n}\n","import { fileURLToPath } from 'node:url';\nimport type { Plugin } from 'vite';\n\nconst PREVIEW_API = /^@?storybook\\/preview-api$/;\n\n/** Points `storybook/preview-api` and `@storybook/preview-api` at forge's shim. */\nexport function storybookShims(): Plugin {\n // Resolved from forge's own location, through the app's aliases, so a monorepo reaches source and an install reaches dist.\n return {\n name: 'weaselforge:storybook-shims',\n enforce: 'pre',\n resolveId(id) {\n if (!PREVIEW_API.test(id)) return undefined;\n return this.resolve('@weasel-js/forge/preview-api', fileURLToPath(import.meta.url), { skipSelf: true });\n },\n };\n}\n","import { existsSync, globSync, readFileSync } from 'node:fs';\nimport { basename, dirname, join, matchesGlob, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Logger, Plugin, ViteDevServer } from 'vite';\nimport type { IndexEntry } from '../story/types';\nimport { hoistPages, writePages } from './build';\nimport { html } from './html';\nimport { indexFile } from './indexFile';\nimport { storybookShims } from './storybookShims';\n\nexport interface ForgeOptions {\n /** Globs of story files, relative to the vite root. */\n stories: string[];\n /** Path to the frame config module, relative to the vite root. Only frame documents import it. Optional. */\n frameConfig?: string;\n /** Path to the shell config module, relative to the vite root. Only the workshop page imports it. Optional. */\n shellConfig?: string;\n /** Alias Storybook's runtime modules to forge shims (Task 13). Default true. */\n storybookShims?: boolean;\n}\n\nconst PREFIX = 'virtual:forge/';\nconst MODULES = new Set(['index.js', 'importers.js', 'frame-config.js', 'shell-config.js', 'shell-entry.js', 'frame-entry.js']);\nconst PAGES: Record<string, string> = { '/': 'shell-entry.js', '/index.html': 'shell-entry.js', '/frame.html': 'frame-entry.js' };\n\n/** forge's shell and frame entry modules: source beside this file in a checkout, the built entries in an install. */\nfunction ownEntries(): string[] {\n const here = fileURLToPath(import.meta.url);\n for (let dir = dirname(here); dir !== dirname(dir); dir = dirname(dir)) {\n const manifest = join(dir, 'package.json');\n if (!existsSync(manifest) || (JSON.parse(readFileSync(manifest, 'utf8')) as { name?: string }).name !== '@weasel-js/forge') {\n continue;\n }\n const source = !relative(join(dir, 'src'), here).startsWith('..');\n return ['shell', 'frame'].map((realm) => join(dir, source ? `src/${realm}/index.ts` : `dist/${realm}/index.js`));\n }\n return [];\n}\n\nexport function forge(options: ForgeOptions): Plugin[] {\n let root = process.cwd();\n let base = '/';\n let byFile: Map<string, IndexEntry[]> | null = null;\n let logger: Logger | undefined;\n\n const glob = (): string[] => {\n const files = options.stories.flatMap((pattern) =>\n globSync(pattern, { cwd: root, exclude: (name) => basename(String(name)) === 'node_modules' })\n .map((f) => resolve(root, f))\n .sort(),\n );\n return [...new Set(files)];\n };\n const matches = (file: string): boolean => {\n const path = relative(root, file).split(sep).join('/');\n return !path.split('/').includes('node_modules') && options.stories.some((pattern) => matchesGlob(path, pattern));\n };\n const read = (file: string) => indexFile(readFileSync(file, 'utf8'), file, root);\n const logError = (err: unknown) => logger?.error(`[forge] ${err instanceof Error ? err.message : String(err)}`);\n /** A file that fails to parse stays in the map with no entries, so an edit that fixes it re-indexes it. */\n const files = (): Map<string, IndexEntry[]> => {\n byFile ??= new Map(\n glob().map((file) => {\n try {\n return [file, read(file)];\n } catch (err) {\n logError(err);\n return [file, []];\n }\n }),\n );\n return byFile;\n };\n const index = () => [...files().values()].flat();\n\n const configModule = (path: string | undefined) =>\n path ? `export { default } from ${JSON.stringify(resolve(root, path))};\\n` : 'export default {};\\n';\n\n const modules: Record<string, () => string> = {\n 'index.js': () => `export default ${JSON.stringify(index())};\\n`,\n 'importers.js': () => {\n const lines = [...files()]\n .filter(([, entries]) => entries.length > 0)\n .map(([file]) => ` ${JSON.stringify(file)}: () => import(${JSON.stringify(file)}),`);\n return `export default {\\n${lines.join('\\n')}\\n};\\n`;\n },\n 'frame-config.js': () => configModule(options.frameConfig),\n 'shell-config.js': () => configModule(options.shellConfig),\n 'shell-entry.js': () => `import { mountWorkshop } from '@weasel-js/forge/shell';\nimport '@weasel-js/labkit/styles.css';\nimport '@weasel-js/forge/shell.css';\nimport index from 'virtual:forge/index.js';\nimport config from 'virtual:forge/shell-config.js';\n\nconst workshop = mountWorkshop({\n index,\n config,\n frameUrl: ${JSON.stringify(`${base}frame.html`)},\n stories: ${JSON.stringify(options.stories)},\n});\nimport.meta.hot?.on('forge:index', (next) => workshop.setIndex(next));\n`,\n 'frame-entry.js': () => `import { mountFrame } from '@weasel-js/forge/frame';\nimport '@weasel-js/forge/frame.css';\nimport index from 'virtual:forge/index.js';\nimport importers from 'virtual:forge/importers.js';\nimport setup from 'virtual:forge/frame-config.js';\n\nmountFrame({ index, importers, root: ${JSON.stringify(root)}, setup });\n`,\n };\n\n function reindex(server: ViteDevServer, file: string, event: 'add' | 'change' | 'unlink'): void {\n const current = files();\n if (event === 'change' && !current.has(file)) return;\n if (event === 'add' && !matches(file)) return;\n if (event === 'unlink' && !current.has(file)) return;\n\n const before = JSON.stringify(index());\n if (event === 'unlink') {\n current.delete(file);\n } else {\n try {\n current.set(file, read(file));\n } catch (err) {\n logError(err);\n return;\n }\n }\n const next = index();\n if (JSON.stringify(next) === before) return;\n\n for (const env of Object.values(server.environments)) {\n for (const name of ['index.js', 'importers.js']) {\n const mod = env.moduleGraph.getModuleById(`\\0${PREFIX}${name}`);\n if (mod) env.moduleGraph.invalidateModule(mod);\n }\n }\n server.ws.send({ type: 'custom', event: 'forge:index', data: next });\n }\n\n return [\n ...(options.storybookShims === false ? [] : [storybookShims()]),\n {\n name: 'weaselforge',\n config(config, { command }) {\n const at = resolve(config.root ?? process.cwd());\n // The pages are virtual, so vite's scan finds no entry of its own to crawl for dependencies.\n const entries = [\n ...options.stories,\n ...[options.frameConfig, options.shellConfig].flatMap((path) => (path ? [resolve(at, path)] : [])),\n ...ownEntries(),\n ];\n const optimizeDeps = { entries };\n if (command !== 'build') return { optimizeDeps };\n return { optimizeDeps, build: { rolldownOptions: { input: writePages(at) } } };\n },\n generateBundle: {\n order: 'post',\n handler(_, bundle) {\n hoistPages(bundle, (file) => this.emitFile(file));\n },\n },\n configResolved(config) {\n root = config.root;\n base = config.base;\n logger = config.logger;\n byFile = null;\n },\n resolveId(id) {\n return id.startsWith(PREFIX) && MODULES.has(id.slice(PREFIX.length)) ? `\\0${id}` : undefined;\n },\n load(id) {\n if (!id.startsWith(`\\0${PREFIX}`)) return undefined;\n return modules[id.slice(PREFIX.length + 1)]?.();\n },\n configureServer(server) {\n server.watcher.add([...files().keys()]);\n for (const event of ['add', 'change', 'unlink'] as const) {\n server.watcher.on(event, (file) => reindex(server, resolve(file), event));\n }\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? '/';\n const path = url.split('?')[0] ?? '/';\n const prefix = base.endsWith('/') ? base.slice(0, -1) : base;\n const page = path === prefix ? '/' : path.startsWith(`${prefix}/`) ? path.slice(prefix.length) : null;\n const entry = req.method === 'GET' && page !== null ? PAGES[page] : undefined;\n if (!entry) return next();\n server.transformIndexHtml(url, html(entry)).then(\n (doc) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(doc);\n },\n (err: unknown) => next(err),\n );\n });\n },\n },\n ];\n}\n","import { matchesGlob, relative, resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { indexFile } from './indexFile';\nimport { storybookShims } from './storybookShims';\n\nexport interface ForgeTestOptions {\n /** Globs of story files, relative to the vite root. Each matching file becomes a test file. */\n stories: string[];\n /** Path to the frame config module, relative to the vite root; it sets up every story. Optional. */\n frameConfig?: string;\n /** Alias Storybook's runtime modules to forge shims. Default true. */\n storybookShims?: boolean;\n}\n\nconst TIMEOUT_MS = 15_000;\n\n/**\n * A vite plugin for vitest browser mode: every story in a matching file runs as one test, rendered and played\n * through forge's frame in the test page itself.\n */\nexport function forgeTest(options: ForgeTestOptions): Plugin[] {\n let root = process.cwd();\n\n const matches = (id: string): boolean => {\n if (id.startsWith('\\0') || id.includes('?')) return false;\n const path = relative(root, id).split(sep).join('/');\n if (path.startsWith('../') || path.split('/').includes('node_modules')) return false;\n return options.stories.some((pattern) => matchesGlob(path, pattern));\n };\n\n return [\n ...(options.storybookShims === false ? [] : [storybookShims()]),\n {\n name: 'weaselforge:test',\n enforce: 'pre',\n configResolved(config) {\n root = config.root;\n },\n transform(code, id) {\n if (!matches(id)) return undefined;\n const entries = indexFile(code, id, root);\n if (entries.length === 0) return undefined;\n const q = (value: string) => JSON.stringify(value);\n // The module comes from its own URL at test time: vitest imports a test file with a cache-busting query,\n // so a static self-import would evaluate the file a second time and register every test twice.\n const lines = [\n '',\n `import { test as __forge_test } from \"vitest\";`,\n `import { page as __forge_page } from \"vitest/browser\";`,\n `import { runStory as __forge_runStory } from \"@weasel-js/forge/test\";`,\n `import \"@weasel-js/forge/frame.css\";`,\n ...(options.frameConfig ? [`import __forge_frame_config from ${q(resolve(root, options.frameConfig))};`] : []),\n `const __forge_file = ${q(id)};`,\n `const __forge_root = ${q(root)};`,\n `const __forge_timeout = ${TIMEOUT_MS};`,\n 'const __forge_options = {',\n ` setup: ${options.frameConfig ? '__forge_frame_config' : 'undefined'},`,\n ' viewport: (width, height) => __forge_page.viewport(width, height),',\n '};',\n 'const __forge_run = async (exportName) => __forge_runStory(await import(/* @vite-ignore */ import.meta.url), exportName, __forge_file, __forge_root, __forge_options);',\n ...entries.map(\n (entry) => `__forge_test(${q(entry.name)}, () => __forge_run(${q(entry.exportName)}), __forge_timeout);`,\n ),\n ];\n return { code: `${code}\\n${lines.join('\\n')}\\n`, map: null };\n },\n },\n ];\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/vite/html.ts","../../src/vite/build.ts","../../src/vite/autoTitle.ts","../../src/vite/indexFile.ts","../../src/vite/storybookShims.ts","../../src/vite/plugin.ts","../../src/vite/forgeTest.ts"],"names":["autoTitle","PAGES","fileURLToPath","dirname","join","relative","files","resolve","sep","matchesGlob"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The document forge serves for `entry`, one of its `virtual:forge/*-entry.js` modules. A build hands the\n * bare id to its own resolver; the dev server needs the `/@id/` form a browser can request.\n */\nexport function html(entry: string, mode: 'serve' | 'build' = 'serve'): string {\n const src = `${mode === 'serve' ? '/@id/' : ''}virtual:forge/${entry}`;\n return `<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n <title>weaselforge</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"${src}\"></script>\n </body>\n</html>\n`;\n}\n","import { mkdirSync, writeFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { html } from './html';\n\nconst DIR = 'node_modules/.forge';\ntype Source = string | Uint8Array;\n\nconst PAGES: Record<string, string> = { index: 'shell-entry.js', frame: 'frame-entry.js' };\n\n/** Writes a build document per forge page under `<root>/node_modules/.forge`, returning them as build inputs. */\nexport function writePages(root: string): Record<string, string> {\n const dir = join(root, DIR);\n mkdirSync(dir, { recursive: true });\n return Object.fromEntries(\n Object.entries(PAGES).map(([name, entry]) => {\n const file = join(dir, `${name}.html`);\n writeFileSync(file, html(entry, 'build'));\n return [name, file];\n }),\n );\n}\n\n/** Vite wrote a relative base's urls from two directories down; the documents now sit at the output root. */\nconst up = (source: Source) =>\n (typeof source === 'string' ? source : new TextDecoder().decode(source)).replace(/(\\s(?:src|href)=\")\\.\\.\\/\\.\\.\\//g, '$1./');\n\n/** Replaces the documents vite emitted at their input path with copies at the output root. */\nexport function hoistPages(\n bundle: Record<string, { type: string; source?: Source }>,\n emit: (file: { type: 'asset'; fileName: string; source: Source }) => void,\n): void {\n for (const name of Object.keys(PAGES)) {\n const from = `${DIR}/${name}.html`;\n const asset = bundle[from];\n if (asset?.type !== 'asset' || asset.source === undefined) continue;\n delete bundle[from];\n emit({ type: 'asset', fileName: `${name}.html`, source: up(asset.source) });\n }\n}\n","import { dirname, matchesGlob, relative, resolve, sep } from 'node:path';\n\n// A port of Storybook 10.4.0's auto-title (preview-api `userOrAutoTitle`, common `normalizeStoriesEntry`)\n// for string `stories` entries, which carry no title prefix. It must agree with Storybook or ids and links diverge.\n\nconst posix = (path: string): string => path.split(sep).join('/');\n\n/** Storybook's `normalizeStoryPath`. */\nconst dotted = (path: string): string => (/^\\.{1,2}([/\\\\]|$)/.test(path) ? path : `./${path}`);\n\n/** The directory a stories glob searches from: picomatch `scan`'s `prefix + base`, or a file's directory. */\nexport function globDirectory(pattern: string): string {\n const segments = pattern.split('/');\n const magic = segments.findIndex((segment) => /^!|(^|[^\\\\])[*?[{(]/.test(segment));\n return magic === -1 ? dirname(pattern) : segments.slice(0, magic).join('/');\n}\n\n/** Storybook's `sanitize` in autoTitle: strips the extension, then collapses `Button/Button`, `index` and `stories.js`. */\nfunction titleParts(parts: string[]): string[] {\n const last = parts[parts.length - 1];\n if (last === undefined) return parts;\n const stripped = last.replace(/(?:[.](?:story|stories))?([.][^.]+)$/i, '');\n if (parts.length === 1) return [stripped];\n const nextToLast = parts[parts.length - 2];\n if (stripped && nextToLast && stripped.toLowerCase() === nextToLast.toLowerCase()) return [...parts.slice(0, -2), stripped];\n if (stripped && (/^(story|stories)([.][^.]+)$/i.test(last) || /^index$/i.test(stripped))) return parts.slice(0, -1);\n return [...parts.slice(0, -1), stripped];\n}\n\nconst titleFrom = (importPath: string, directory: string): string =>\n titleParts(importPath.replace(directory, '').split('/').filter(Boolean)).join('/');\n\n/**\n * The title Storybook gives a story file whose meta names none: its path under the directory of the first\n * `stories` glob that matches it. A file no glob matches is titled from its path under `root`.\n */\nexport function autoTitle(file: string, root: string, stories: readonly string[]): string {\n const path = posix(relative(root, file));\n const importPath = dotted(path);\n for (const pattern of stories) {\n if (!matchesGlob(path, pattern.replace(/^\\.\\//, ''))) continue;\n const directory = dotted(posix(relative(root, resolve(root, globDirectory(pattern))))).replace(/\\/$/, '');\n return titleFrom(importPath, directory);\n }\n return titleFrom(importPath, '.');\n}\n","import { type ParserPlugin, parse } from '@babel/parser';\nimport type * as t from '@babel/types';\nimport { storyId, storyNameFromExport } from '../story/ids';\nimport type { IndexEntry } from '../story/types';\n\ntype Bindings = Map<string, t.Node>;\n\n/** The stories `code` declares, in source order, without running it. `file` is absolute; `autoTitle` titles a meta that names none. */\nexport function indexFile(code: string, file: string, autoTitle: string): IndexEntry[] {\n try {\n const plugins: ParserPlugin[] = ['typescript', 'decorators-legacy', ...(/\\.[jt]sx$/.test(file) ? (['jsx'] as const) : [])];\n return indexProgram(parse(code, { sourceType: 'module', plugins }).program, file, autoTitle);\n } catch (err) {\n throw new Error(`${file}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });\n }\n}\n\nfunction indexProgram(program: t.Program, file: string, autoTitle: string): IndexEntry[] {\n const bindings: Bindings = new Map();\n const wrappers = new Set<string>();\n for (const stmt of program.body) {\n if (stmt.type === 'ImportDeclaration' && stmt.source.value === '@weasel-js/forge') {\n for (const spec of stmt.specifiers) {\n if (spec.type === 'ImportSpecifier' && ['meta', 'story'].includes(exportedName(spec.imported))) {\n wrappers.add(spec.local.name);\n }\n }\n }\n const decl = stmt.type === 'ExportNamedDeclaration' ? stmt.declaration : stmt;\n if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations) if (d.id.type === 'Identifier' && d.init) bindings.set(d.id.name, d.init);\n }\n }\n\n let metaNode: t.Node | undefined;\n let metaDoc: string | undefined;\n const exported: { name: string; node: t.Node | undefined; doc: string | undefined }[] = [];\n for (const stmt of program.body) {\n if (stmt.type === 'ExportDefaultDeclaration') {\n metaNode = stmt.declaration;\n metaDoc = docOf(stmt);\n }\n if (stmt.type !== 'ExportNamedDeclaration' || stmt.exportKind === 'type') continue;\n const doc = docOf(stmt);\n const decl = stmt.declaration;\n if (decl?.type === 'VariableDeclaration') {\n for (const d of decl.declarations) {\n if (d.id.type === 'Identifier') exported.push({ name: d.id.name, node: d.init ?? undefined, doc: docOf(d) ?? doc });\n }\n } else if (decl?.type === 'FunctionDeclaration' && decl.id) {\n exported.push({ name: decl.id.name, node: undefined, doc });\n }\n for (const spec of stmt.specifiers) {\n if (spec.type !== 'ExportSpecifier' || spec.exportKind === 'type') continue;\n const name = exportedName(spec.exported);\n const node = stmt.source ? undefined : bindings.get(spec.local.name);\n if (name === 'default') {\n metaNode = node;\n metaDoc ??= doc;\n } else exported.push({ name, node, doc });\n }\n }\n if (!metaNode && !program.body.some(isDefaultExport)) return [];\n\n const meta = objectOf(metaNode, bindings, wrappers);\n const title = stringProp(meta, 'title') ?? autoTitle;\n const include = storyFilter(meta, 'includeStories');\n const exclude = storyFilter(meta, 'excludeStories');\n const componentNode = prop(meta, 'component');\n const componentName = componentNode?.type === 'Identifier' ? componentNode.name : undefined;\n\n return exported\n .filter(({ name }) => name !== '__namedExportsOrder')\n .filter(({ name }) => (!include || include(name)) && (!exclude || !exclude(name)))\n .map(({ name, node, doc }) => {\n const spec = objectOf(node, bindings, wrappers);\n return {\n id: storyId(title, name),\n title,\n name: stringProp(spec, 'name') ?? stringProp(spec, 'storyName') ?? storyNameFromExport(name),\n exportName: name,\n file,\n ...(doc === undefined ? {} : { description: doc }),\n ...(metaDoc === undefined ? {} : { componentDescription: metaDoc }),\n ...(componentName === undefined ? {} : { componentName }),\n };\n });\n}\n\nfunction isDefaultExport(stmt: t.Statement): boolean {\n if (stmt.type === 'ExportDefaultDeclaration') return true;\n return (\n stmt.type === 'ExportNamedDeclaration' &&\n stmt.specifiers.some((s) => s.type === 'ExportSpecifier' && exportedName(s.exported) === 'default')\n );\n}\n\n/**\n * The JSDoc block immediately above `node`, as prose. A `//` comment is not\n * one: a line comment above an export is as often a note to the author as a\n * description of the story, and printing it in the dossier would be guessing.\n */\nfunction docOf(node: t.Node): string | undefined {\n const comments = node.leadingComments;\n const last = comments?.[comments.length - 1];\n if (last?.type !== 'CommentBlock' || !last.value.startsWith('*')) return undefined;\n const text = last.value\n .slice(1)\n .split('\\n')\n .map((line) => line.replace(/^\\s*\\*/, '').trim())\n .join('\\n')\n .trim();\n return text || undefined;\n}\n\nfunction exportedName(node: t.Identifier | t.StringLiteral): string {\n return node.type === 'Identifier' ? node.name : node.value;\n}\n\n/** The object literal `node` evaluates to, through casts, `meta(…)`/`story(…)` and top-level `const`s. */\nfunction objectOf(node: t.Node | undefined, bindings: Bindings, wrappers: Set<string>, depth = 0): t.ObjectExpression | null {\n if (!node || depth > 16) return null;\n switch (node.type) {\n case 'ObjectExpression':\n return node;\n case 'TSSatisfiesExpression':\n case 'TSAsExpression':\n case 'TSTypeAssertion':\n case 'TSNonNullExpression':\n case 'ParenthesizedExpression':\n return objectOf(node.expression, bindings, wrappers, depth + 1);\n case 'CallExpression':\n return node.callee.type === 'Identifier' && wrappers.has(node.callee.name)\n ? objectOf(node.arguments[0], bindings, wrappers, depth + 1)\n : null;\n case 'Identifier':\n return objectOf(bindings.get(node.name), bindings, wrappers, depth + 1);\n default:\n return null;\n }\n}\n\nfunction prop(obj: t.ObjectExpression | null, key: string): t.Node | undefined {\n for (const p of obj?.properties ?? []) {\n if (p.type !== 'ObjectProperty' || p.computed) continue;\n const name = p.key.type === 'Identifier' ? p.key.name : p.key.type === 'StringLiteral' ? p.key.value : null;\n if (name === key) return p.value;\n }\n return undefined;\n}\n\nfunction stringProp(obj: t.ObjectExpression | null, key: string): string | undefined {\n const value = prop(obj, key);\n return value?.type === 'StringLiteral' ? value.value : undefined;\n}\n\n/** `includeStories`/`excludeStories` as a predicate, when written as a string array or a regex literal. */\nfunction storyFilter(obj: t.ObjectExpression | null, key: string): ((name: string) => boolean) | null {\n const value = prop(obj, key);\n if (value?.type === 'RegExpLiteral') {\n const re = new RegExp(value.pattern, value.flags.replace(/[gy]/g, ''));\n return (name) => re.test(name);\n }\n if (value?.type === 'ArrayExpression' && value.elements.every((e) => e?.type === 'StringLiteral')) {\n const names = new Set(value.elements.map((e) => (e as t.StringLiteral).value));\n return (name) => names.has(name);\n }\n return null;\n}\n","import { fileURLToPath } from 'node:url';\nimport type { Plugin } from 'vite';\n\n/** Storybook specifiers a CSF file may import, and the forge entry each answers to. */\nconst SHIMS: readonly (readonly [RegExp, string])[] = [\n [/^@?storybook\\/preview-api$/, '@weasel-js/forge/preview-api'],\n [/^@?storybook\\/test$/, '@weasel-js/forge/play'],\n];\n\n/** Points the Storybook runtime specifiers a CSF file may carry at forge's own entries. */\nexport function storybookShims(): Plugin {\n // Resolved from forge's own location, through the app's aliases, so a monorepo reaches source and an install reaches dist.\n return {\n name: 'weaselforge:storybook-shims',\n enforce: 'pre',\n resolveId(id) {\n const hit = SHIMS.find(([pattern]) => pattern.test(id));\n if (!hit) return undefined;\n return this.resolve(hit[1], fileURLToPath(import.meta.url), { skipSelf: true });\n },\n };\n}\n","import { existsSync, globSync, readFileSync } from 'node:fs';\nimport { basename, dirname, join, matchesGlob, relative, resolve, sep } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { Logger, Plugin, ViteDevServer } from 'vite';\nimport type { IndexEntry } from '../story/types';\nimport { hoistPages, writePages } from './build';\nimport { autoTitle } from './autoTitle';\nimport { html } from './html';\nimport { indexFile } from './indexFile';\nimport { storybookShims } from './storybookShims';\n\nexport interface ForgeOptions {\n /** Globs of story files, relative to the vite root. */\n stories: string[];\n /** Path to the frame config module, relative to the vite root. Only frame documents import it. Optional. */\n frameConfig?: string;\n /** Path to the shell config module, relative to the vite root. Only the workshop page imports it. Optional. */\n shellConfig?: string;\n /** Alias Storybook's runtime modules to forge shims (Task 13). Default true. */\n storybookShims?: boolean;\n}\n\nconst PREFIX = 'virtual:forge/';\nconst MODULES = new Set(['index.js', 'importers.js', 'frame-config.js', 'shell-config.js', 'shell-entry.js', 'frame-entry.js']);\nconst PAGES: Record<string, string> = { '/': 'shell-entry.js', '/index.html': 'shell-entry.js', '/frame.html': 'frame-entry.js' };\n\n/** forge's shell and frame entry modules: source beside this file in a checkout, the built entries in an install. */\nfunction ownEntries(): string[] {\n const here = fileURLToPath(import.meta.url);\n for (let dir = dirname(here); dir !== dirname(dir); dir = dirname(dir)) {\n const manifest = join(dir, 'package.json');\n if (!existsSync(manifest) || (JSON.parse(readFileSync(manifest, 'utf8')) as { name?: string }).name !== '@weasel-js/forge') {\n continue;\n }\n const source = !relative(join(dir, 'src'), here).startsWith('..');\n return ['shell', 'frame'].map((realm) => join(dir, source ? `src/${realm}/index.ts` : `dist/${realm}/index.js`));\n }\n return [];\n}\n\nexport function forge(options: ForgeOptions): Plugin[] {\n let root = process.cwd();\n let base = '/';\n let byFile: Map<string, IndexEntry[]> | null = null;\n let logger: Logger | undefined;\n\n const glob = (): string[] => {\n const files = options.stories.flatMap((pattern) =>\n globSync(pattern, { cwd: root, exclude: (name) => basename(String(name)) === 'node_modules' })\n .map((f) => resolve(root, f))\n .sort(),\n );\n return [...new Set(files)];\n };\n const matches = (file: string): boolean => {\n const path = relative(root, file).split(sep).join('/');\n return !path.split('/').includes('node_modules') && options.stories.some((pattern) => matchesGlob(path, pattern));\n };\n const read = (file: string) => indexFile(readFileSync(file, 'utf8'), file, autoTitle(file, root, options.stories));\n const logError = (err: unknown) => logger?.error(`[forge] ${err instanceof Error ? err.message : String(err)}`);\n /** A file that fails to parse stays in the map with no entries, so an edit that fixes it re-indexes it. */\n const files = (): Map<string, IndexEntry[]> => {\n byFile ??= new Map(\n glob().map((file) => {\n try {\n return [file, read(file)];\n } catch (err) {\n logError(err);\n return [file, []];\n }\n }),\n );\n return byFile;\n };\n const index = () => [...files().values()].flat();\n\n const configModule = (path: string | undefined) =>\n path ? `export { default } from ${JSON.stringify(resolve(root, path))};\\n` : 'export default {};\\n';\n\n const modules: Record<string, () => string> = {\n 'index.js': () => `export default ${JSON.stringify(index())};\\n`,\n 'importers.js': () => {\n const lines = [...files()]\n .filter(([, entries]) => entries.length > 0)\n .map(([file]) => ` ${JSON.stringify(file)}: () => import(${JSON.stringify(file)}),`);\n return `export default {\\n${lines.join('\\n')}\\n};\\n`;\n },\n 'frame-config.js': () => configModule(options.frameConfig),\n 'shell-config.js': () => configModule(options.shellConfig),\n 'shell-entry.js': () => `import { mountWorkshop } from '@weasel-js/forge/shell';\nimport '@weasel-js/labkit/styles.css';\nimport '@weasel-js/forge/shell.css';\nimport index from 'virtual:forge/index.js';\nimport config from 'virtual:forge/shell-config.js';\n\nconst workshop = mountWorkshop({\n index,\n config,\n frameUrl: ${JSON.stringify(`${base}frame.html`)},\n stories: ${JSON.stringify(options.stories)},\n});\nimport.meta.hot?.on('forge:index', (next) => workshop.setIndex(next));\n`,\n 'frame-entry.js': () => `import { mountFrame } from '@weasel-js/forge/frame';\nimport '@weasel-js/forge/frame.css';\nimport index from 'virtual:forge/index.js';\nimport importers from 'virtual:forge/importers.js';\nimport setup from 'virtual:forge/frame-config.js';\n\nmountFrame({ index, importers, setup });\n`,\n };\n\n function reindex(server: ViteDevServer, file: string, event: 'add' | 'change' | 'unlink'): void {\n const current = files();\n if (event === 'change' && !current.has(file)) return;\n if (event === 'add' && !matches(file)) return;\n if (event === 'unlink' && !current.has(file)) return;\n\n const before = JSON.stringify(index());\n if (event === 'unlink') {\n current.delete(file);\n } else {\n try {\n current.set(file, read(file));\n } catch (err) {\n logError(err);\n return;\n }\n }\n const next = index();\n if (JSON.stringify(next) === before) return;\n\n for (const env of Object.values(server.environments)) {\n for (const name of ['index.js', 'importers.js']) {\n const mod = env.moduleGraph.getModuleById(`\\0${PREFIX}${name}`);\n if (mod) env.moduleGraph.invalidateModule(mod);\n }\n }\n server.ws.send({ type: 'custom', event: 'forge:index', data: next });\n }\n\n return [\n ...(options.storybookShims === false ? [] : [storybookShims()]),\n {\n name: 'weaselforge',\n config(config, { command }) {\n const at = resolve(config.root ?? process.cwd());\n // The pages are virtual, so vite's scan finds no entry of its own to crawl for dependencies.\n const entries = [\n ...options.stories,\n ...[options.frameConfig, options.shellConfig].flatMap((path) => (path ? [resolve(at, path)] : [])),\n ...ownEntries(),\n ];\n const optimizeDeps = { entries };\n if (command !== 'build') return { optimizeDeps };\n return { optimizeDeps, build: { rolldownOptions: { input: writePages(at) } } };\n },\n generateBundle: {\n order: 'post',\n handler(_, bundle) {\n hoistPages(bundle, (file) => this.emitFile(file));\n },\n },\n configResolved(config) {\n root = config.root;\n base = config.base;\n logger = config.logger;\n byFile = null;\n },\n resolveId(id) {\n return id.startsWith(PREFIX) && MODULES.has(id.slice(PREFIX.length)) ? `\\0${id}` : undefined;\n },\n load(id) {\n if (!id.startsWith(`\\0${PREFIX}`)) return undefined;\n return modules[id.slice(PREFIX.length + 1)]?.();\n },\n configureServer(server) {\n server.watcher.add([...files().keys()]);\n for (const event of ['add', 'change', 'unlink'] as const) {\n server.watcher.on(event, (file) => reindex(server, resolve(file), event));\n }\n server.middlewares.use((req, res, next) => {\n const url = req.url ?? '/';\n const path = url.split('?')[0] ?? '/';\n const prefix = base.endsWith('/') ? base.slice(0, -1) : base;\n const page = path === prefix ? '/' : path.startsWith(`${prefix}/`) ? path.slice(prefix.length) : null;\n const entry = req.method === 'GET' && page !== null ? PAGES[page] : undefined;\n if (!entry) return next();\n server.transformIndexHtml(url, html(entry)).then(\n (doc) => {\n res.statusCode = 200;\n res.setHeader('Content-Type', 'text/html');\n res.end(doc);\n },\n (err: unknown) => next(err),\n );\n });\n },\n },\n ];\n}\n","import { matchesGlob, relative, resolve, sep } from 'node:path';\nimport type { Plugin } from 'vite';\nimport { autoTitle } from './autoTitle';\nimport { indexFile } from './indexFile';\nimport { storybookShims } from './storybookShims';\n\nexport interface ForgeTestOptions {\n /** Globs of story files, relative to the vite root. Each matching file becomes a test file. */\n stories: string[];\n /** Path to the frame config module, relative to the vite root; it sets up every story. Optional. */\n frameConfig?: string;\n /** Alias Storybook's runtime modules to forge shims. Default true. */\n storybookShims?: boolean;\n}\n\nconst TIMEOUT_MS = 15_000;\n\n/**\n * A vite plugin for vitest browser mode: every story in a matching file runs as one test, rendered and played\n * through forge's frame in the test page itself.\n */\nexport function forgeTest(options: ForgeTestOptions): Plugin[] {\n let root = process.cwd();\n\n const matches = (id: string): boolean => {\n if (id.startsWith('\\0') || id.includes('?')) return false;\n const path = relative(root, id).split(sep).join('/');\n if (path.startsWith('../') || path.split('/').includes('node_modules')) return false;\n return options.stories.some((pattern) => matchesGlob(path, pattern));\n };\n\n return [\n ...(options.storybookShims === false ? [] : [storybookShims()]),\n {\n name: 'weaselforge:test',\n enforce: 'pre',\n configResolved(config) {\n root = config.root;\n },\n transform(code, id) {\n if (!matches(id)) return undefined;\n const title = autoTitle(id, root, options.stories);\n const entries = indexFile(code, id, title);\n if (entries.length === 0) return undefined;\n const q = (value: string) => JSON.stringify(value);\n // The module comes from its own URL at test time: vitest imports a test file with a cache-busting query,\n // so a static self-import would evaluate the file a second time and register every test twice.\n const lines = [\n '',\n `import { test as __forge_test } from \"vitest\";`,\n `import { page as __forge_page } from \"vitest/browser\";`,\n `import { runStory as __forge_runStory } from \"@weasel-js/forge/test\";`,\n `import \"@weasel-js/forge/frame.css\";`,\n ...(options.frameConfig ? [`import __forge_frame_config from ${q(resolve(root, options.frameConfig))};`] : []),\n `const __forge_file = ${q(id)};`,\n `const __forge_title = ${q(title)};`,\n `const __forge_timeout = ${TIMEOUT_MS};`,\n 'const __forge_options = {',\n ` setup: ${options.frameConfig ? '__forge_frame_config' : 'undefined'},`,\n ' viewport: (width, height) => __forge_page.viewport(width, height),',\n '};',\n 'const __forge_run = async (exportName) => __forge_runStory(await import(/* @vite-ignore */ import.meta.url), exportName, __forge_file, __forge_title, __forge_options);',\n ...entries.map(\n (entry) => `__forge_test(${q(entry.name)}, () => __forge_run(${q(entry.exportName)}), __forge_timeout);`,\n ),\n ];\n return { code: `${code}\\n${lines.join('\\n')}\\n`, map: null };\n },\n },\n ];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@weasel-js/forge",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.2",
|
|
4
4
|
"description": "A component workshop on labkit: stories in isolated frames, controls and state in lab trials.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -32,12 +32,16 @@
|
|
|
32
32
|
"types": "./dist/test/index.d.ts",
|
|
33
33
|
"import": "./dist/test/index.js"
|
|
34
34
|
},
|
|
35
|
+
"./play": {
|
|
36
|
+
"types": "./dist/test/play.d.ts",
|
|
37
|
+
"import": "./dist/test/play.js"
|
|
38
|
+
},
|
|
35
39
|
"./shell.css": "./dist/shell/index.css",
|
|
36
40
|
"./frame.css": "./dist/frame/index.css",
|
|
37
41
|
"./package.json": "./package.json"
|
|
38
42
|
},
|
|
39
43
|
"bin": {
|
|
40
|
-
"weaselforge": "
|
|
44
|
+
"weaselforge": "dist/cli.js"
|
|
41
45
|
},
|
|
42
46
|
"author": "orochi235",
|
|
43
47
|
"homepage": "https://orochi235.github.io/weasel/",
|
|
@@ -62,14 +66,19 @@
|
|
|
62
66
|
},
|
|
63
67
|
"dependencies": {
|
|
64
68
|
"@babel/parser": "^7.29.0",
|
|
65
|
-
"@
|
|
69
|
+
"@testing-library/dom": "^10.4.0",
|
|
70
|
+
"@testing-library/user-event": "^14.6.1",
|
|
71
|
+
"@vitest/expect": "^4.1.6",
|
|
72
|
+
"@weasel-js/theme": "1.5.2",
|
|
73
|
+
"axe-core": "^4.13.0",
|
|
74
|
+
"chai": "^6.2.2"
|
|
66
75
|
},
|
|
67
76
|
"devDependencies": {
|
|
68
77
|
"@babel/types": "^7.29.0"
|
|
69
78
|
},
|
|
70
79
|
"peerDependencies": {
|
|
71
|
-
"@weasel-js/core": "1.5.
|
|
72
|
-
"@weasel-js/labkit": "1.5.
|
|
80
|
+
"@weasel-js/core": "1.5.2",
|
|
81
|
+
"@weasel-js/labkit": "1.5.2",
|
|
73
82
|
"react": "^19.0.0",
|
|
74
83
|
"react-dom": "^19.0.0",
|
|
75
84
|
"vite": "^8.0.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol/messages.ts"],"names":[],"mappings":";AAEO,IAAM,gBAAA,GAAmB;AAmDzB,IAAM,YAAA,GAAe;AAGrB,SAAS,gBAAgB,KAAA,EAAwB;AACtD,EAAA,OAAO,IAAA,CAAK,SAAA;AAAA,IAAU,KAAA;AAAA,IAAO,CAAC,IAAA,EAAM,CAAA,KAClC,CAAA,IAAK,OAAO,CAAA,KAAM,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,CAAC,CAAA,GAC1C,OAAO,WAAA,CAAY,MAAA,CAAO,OAAA,CAAQ,CAAC,CAAA,CAAE,IAAA,CAAK,CAAC,CAAC,CAAC,CAAA,EAAG,CAAC,CAAC,CAAA,KAAO,CAAA,GAAI,CAAA,GAAI,EAAA,GAAK,CAAE,CAAC,CAAA,GACzE;AAAA,GACN;AACF","file":"chunk-IOBG7GZQ.js","sourcesContent":["import type { SchemaDescription } from './schema';\n\nexport const PROTOCOL_VERSION = 1;\n\nexport type Globals = Readonly<Record<string, unknown>>;\nexport type Layout = 'centered' | 'padded' | 'fullscreen';\nexport interface Viewport {\n width: number;\n height: number;\n}\nexport type FaultPhase = 'import' | 'render' | 'play' | 'protocol';\n\n/** One custom property as the frame found it. */\nexport interface CssVarReport {\n name: string;\n value: string;\n /** Whether a `vars.set` override is in force on it. */\n overridden: boolean;\n}\n\n/** Visibility and validation answers, keyed by the config they were computed for. */\nexport interface ConfigAnswers {\n /** `stableStringify(config)` of the config the frame evaluated. */\n configKey: string;\n hidden: string[];\n errors: Record<string, string[]>;\n}\n\nexport type ToFrame =\n | { type: 'init'; config: unknown; state: unknown; globals: Globals }\n | { type: 'config'; config: unknown }\n | { type: 'state'; state: unknown }\n | { type: 'globals'; globals: Globals }\n | { type: 'vars.set'; name: string; value: string | null }\n | { type: 'play' };\n\nexport type FromFrame =\n | { type: 'ready'; schema: SchemaDescription; layout: Layout; viewport: Viewport | null }\n | { type: 'answers'; answers: ConfigAnswers }\n | { type: 'setConfig'; path: string; value: unknown }\n | { type: 'setState'; state: unknown }\n | { type: 'size'; width: number; height: number }\n | { type: 'vars'; vars: CssVarReport[] }\n | { type: 'played'; ok: boolean; message?: string }\n /** `seq`, on a render fault only: how many `init`/`config`/`state`/`globals` messages the frame had received. */\n | { type: 'fault'; phase: FaultPhase; message: string; stack?: string; seq?: number };\n\nexport interface Envelope<M> {\n v: number;\n msg: M;\n}\n\n/** Posted on the frame's window with the port transferred alongside it. */\nexport const PORT_HANDOFF = 'weaselforge:port';\n\n/** JSON with object keys sorted, so two equal configs produce one key. */\nexport function stableStringify(value: unknown): string {\n return JSON.stringify(value, (_key, v) =>\n v && typeof v === 'object' && !Array.isArray(v)\n ? Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : 1)))\n : v,\n );\n}\n"]}
|