@storybook-astro/framework 0.1.0-beta.9 → 1.0.1
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/README.md +38 -0
- package/dist/base-IRZo3zgK.d.ts +23 -0
- package/dist/chunk-4SWPVM6R.js +96 -0
- package/dist/chunk-4SWPVM6R.js.map +1 -0
- package/dist/chunk-5EF25G5S.js +69 -0
- package/dist/chunk-5EF25G5S.js.map +1 -0
- package/dist/chunk-7GHEQUPV.js +439 -0
- package/dist/chunk-7GHEQUPV.js.map +1 -0
- package/dist/chunk-C5OH4VBR.js +492 -0
- package/dist/chunk-C5OH4VBR.js.map +1 -0
- package/dist/chunk-DNGQBPT7.js +15 -0
- package/dist/chunk-DNGQBPT7.js.map +1 -0
- package/dist/chunk-E4LB75JN.js +89 -0
- package/dist/chunk-E4LB75JN.js.map +1 -0
- package/dist/chunk-KSDXET2L.js +660 -0
- package/dist/chunk-KSDXET2L.js.map +1 -0
- package/dist/chunk-PJEDXZVN.js +240 -0
- package/dist/chunk-PJEDXZVN.js.map +1 -0
- package/dist/dist-HJOEPVRQ.js +15574 -0
- package/dist/dist-HJOEPVRQ.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.js +13 -64
- package/dist/index.js.map +1 -1
- package/dist/integrations/index.d.ts +138 -0
- package/dist/integrations/index.js +8 -196
- package/dist/integrations/index.js.map +1 -1
- package/dist/middleware.d.ts +26 -0
- package/dist/middleware.js +179 -0
- package/dist/middleware.js.map +1 -0
- package/dist/portable-stories-BvdaQigq.d.ts +83 -0
- package/dist/preset.d.ts +14 -0
- package/dist/preset.js +5 -1
- package/dist/testing.d.ts +27 -0
- package/dist/testing.js +324 -15539
- package/dist/testing.js.map +1 -1
- package/dist/types-CHTsRtA7.d.ts +42 -0
- package/dist/viteStorybookAstroMiddlewarePlugin-NP2E52IC.js +11 -0
- package/dist/viteStorybookAstroMiddlewarePlugin-NP2E52IC.js.map +1 -0
- package/dist/vitest/index.d.ts +19 -0
- package/dist/vitest/index.js +229 -0
- package/dist/vitest/index.js.map +1 -0
- package/package.json +31 -17
- package/src/importAstroConfig.ts +11 -0
- package/src/index.ts +20 -6
- package/src/integrations/alpine.ts +5 -2
- package/src/integrations/base.ts +2 -2
- package/src/integrations/moduleResolver.ts +43 -0
- package/src/integrations/preact.ts +5 -2
- package/src/integrations/react.ts +5 -2
- package/src/integrations/solid.ts +5 -2
- package/src/integrations/svelte.ts +5 -2
- package/src/integrations/vue.ts +5 -2
- package/src/lib/sanitization.test.ts +232 -0
- package/src/lib/sanitization.ts +338 -0
- package/src/lib/ssr-load-module-with-fs-fallback.ts +29 -0
- package/src/middleware.test.ts +48 -0
- package/src/middleware.ts +204 -96
- package/src/module-mocks.ts +16 -0
- package/src/msw-helpers.ts +1 -0
- package/src/msw.ts +58 -0
- package/src/preset.ts +47 -3
- package/src/rules-options.test.ts +71 -0
- package/src/rules-options.ts +87 -0
- package/src/rules.test.ts +183 -0
- package/src/rules.ts +314 -0
- package/src/testing/astro-runtime.ts +219 -0
- package/src/testing/component-utils.ts +32 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/integration-config.ts +121 -0
- package/src/testing/project-root.ts +185 -0
- package/src/testing/renderer-daemon.ts +269 -0
- package/src/testing/story-composition.ts +33 -0
- package/src/testing/types.ts +14 -0
- package/src/testing/working-directory.ts +28 -0
- package/src/testing.ts +1 -254
- package/src/types.ts +16 -4
- package/src/virtual.d.ts +2 -1
- package/src/vite/createVirtualModulePlugin.test.ts +80 -0
- package/src/vite/createVirtualModulePlugin.ts +25 -0
- package/src/viteAstroContainerRenderersPlugin.ts +60 -26
- package/src/vitePluginAstro.ts +12 -5
- package/src/vitePluginAstroBuildPrerender.ts +665 -204
- package/src/vitePluginAstroRoutesFallback.ts +37 -0
- package/src/vitePluginAstroVueFallback.ts +47 -0
- package/src/viteStorybookAstroMiddlewarePlugin.ts +88 -12
- package/src/viteStorybookRendererFallbackPlugin.ts +13 -23
- package/src/vitest/config.ts +95 -0
- package/src/vitest/global-setup.ts +16 -0
- package/src/vitest/index.ts +2 -0
- package/src/vitest/vite-plugins.ts +187 -0
- package/dist/chunk-KTGNRGDJ.js +0 -561
- package/dist/chunk-KTGNRGDJ.js.map +0 -1
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
// src/rules.ts
|
|
2
|
+
import { dirname, isAbsolute, resolve } from "path";
|
|
3
|
+
function defineStoryRules(config) {
|
|
4
|
+
return config;
|
|
5
|
+
}
|
|
6
|
+
async function selectStoryRules(input) {
|
|
7
|
+
const config = normalizeRulesConfig(input.configModule);
|
|
8
|
+
const story = normalizeStory(input.story);
|
|
9
|
+
const selection = createEmptySelection();
|
|
10
|
+
for (const rule of config.rules) {
|
|
11
|
+
if (!isStoryRuleMatch(rule.match, story)) {
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const uses = Array.isArray(rule.use) ? rule.use : [rule.use];
|
|
15
|
+
for (const use of uses) {
|
|
16
|
+
if (typeof use !== "function") {
|
|
17
|
+
throw new Error('Each story rule "use" entry must be a function.');
|
|
18
|
+
}
|
|
19
|
+
await use({
|
|
20
|
+
mode: input.mode,
|
|
21
|
+
story,
|
|
22
|
+
msw: {
|
|
23
|
+
use: (...handlers) => {
|
|
24
|
+
selection.mswHandlers.push(...handlers);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
mock: (specifier, replacement) => {
|
|
28
|
+
const normalizedSpecifier = normalizeMockSpecifier(specifier);
|
|
29
|
+
const normalizedReplacement = normalizeMockReplacement(replacement, input.configFilePath);
|
|
30
|
+
selection.moduleMocks.set(normalizedSpecifier, normalizedReplacement);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return selection;
|
|
36
|
+
}
|
|
37
|
+
function normalizeRulesConfig(configModule) {
|
|
38
|
+
const configExport = getRulesConfigExport(configModule);
|
|
39
|
+
if (configExport === void 0 || configExport === null) {
|
|
40
|
+
return {
|
|
41
|
+
rules: []
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (!isRecord(configExport)) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
'Story rules config must export an object with a "rules" array via a default export or named export.'
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const rules = configExport.rules;
|
|
50
|
+
if (rules === void 0) {
|
|
51
|
+
return {
|
|
52
|
+
rules: []
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
if (!Array.isArray(rules)) {
|
|
56
|
+
throw new Error('Story rules config "rules" must be an array.');
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
rules
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function getRulesConfigExport(configModule) {
|
|
63
|
+
if (!isRecord(configModule)) {
|
|
64
|
+
return configModule;
|
|
65
|
+
}
|
|
66
|
+
if ("default" in configModule && configModule.default !== void 0) {
|
|
67
|
+
return configModule.default;
|
|
68
|
+
}
|
|
69
|
+
if ("rules" in configModule) {
|
|
70
|
+
return {
|
|
71
|
+
rules: configModule.rules
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
function normalizeStory(story) {
|
|
77
|
+
const id = normalizeStoryId(story?.id);
|
|
78
|
+
const title = normalizeOptionalString(story?.title);
|
|
79
|
+
const name = normalizeOptionalString(story?.name);
|
|
80
|
+
const keys = Array.from(resolveStoryKeys({ id, title, name }));
|
|
81
|
+
return {
|
|
82
|
+
id,
|
|
83
|
+
title,
|
|
84
|
+
name,
|
|
85
|
+
keys
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
function resolveStoryKeys(story) {
|
|
89
|
+
const keys = /* @__PURE__ */ new Set();
|
|
90
|
+
keys.add("");
|
|
91
|
+
const storyId = story.id;
|
|
92
|
+
const idPath = storyId ? storyId.replaceAll("--", "/") : "";
|
|
93
|
+
if (storyId) {
|
|
94
|
+
keys.add(storyId);
|
|
95
|
+
keys.add(`/story/${storyId}`);
|
|
96
|
+
}
|
|
97
|
+
if (idPath) {
|
|
98
|
+
keys.add(idPath);
|
|
99
|
+
keys.add(`/story/${idPath}`);
|
|
100
|
+
}
|
|
101
|
+
const titlePath = story.title ? story.title.split("/").map((segment) => slugify(segment)).filter(Boolean).join("/") : "";
|
|
102
|
+
const storyNamePath = story.name ? slugify(story.name) : "";
|
|
103
|
+
if (titlePath && storyNamePath) {
|
|
104
|
+
const composedPath = `${titlePath}/${storyNamePath}`;
|
|
105
|
+
keys.add(composedPath);
|
|
106
|
+
keys.add(`/story/${composedPath}`);
|
|
107
|
+
}
|
|
108
|
+
return keys;
|
|
109
|
+
}
|
|
110
|
+
function isStoryRuleMatch(match, story) {
|
|
111
|
+
const patterns = Array.isArray(match) ? match : [match];
|
|
112
|
+
return patterns.some((pattern) => {
|
|
113
|
+
if (typeof pattern !== "string") {
|
|
114
|
+
throw new Error('Story rule "match" must be a string or an array of strings.');
|
|
115
|
+
}
|
|
116
|
+
const normalizedPattern = pattern.trim();
|
|
117
|
+
if (!normalizedPattern) {
|
|
118
|
+
throw new Error('Story rule "match" cannot be empty.');
|
|
119
|
+
}
|
|
120
|
+
return story.keys.some((key) => isWildcardMatch(normalizedPattern, key));
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
function isWildcardMatch(pattern, candidate) {
|
|
124
|
+
const escapedPattern = escapeRegExp(pattern).replaceAll("*", ".*");
|
|
125
|
+
const regex = new RegExp(`^${escapedPattern}$`);
|
|
126
|
+
return regex.test(candidate);
|
|
127
|
+
}
|
|
128
|
+
function normalizeStoryId(id) {
|
|
129
|
+
const value = normalizeOptionalString(id) ?? "";
|
|
130
|
+
if (!value) {
|
|
131
|
+
return "";
|
|
132
|
+
}
|
|
133
|
+
return value.startsWith("/story/") ? value.slice("/story/".length) : value;
|
|
134
|
+
}
|
|
135
|
+
function normalizeOptionalString(value) {
|
|
136
|
+
if (typeof value !== "string") {
|
|
137
|
+
return void 0;
|
|
138
|
+
}
|
|
139
|
+
const normalizedValue = value.trim();
|
|
140
|
+
return normalizedValue || void 0;
|
|
141
|
+
}
|
|
142
|
+
function normalizeMockSpecifier(value) {
|
|
143
|
+
if (typeof value !== "string") {
|
|
144
|
+
throw new Error("Story rule mock specifier must be a string.");
|
|
145
|
+
}
|
|
146
|
+
const normalizedValue = value.trim();
|
|
147
|
+
if (!normalizedValue) {
|
|
148
|
+
throw new Error("Story rule mock specifier cannot be empty.");
|
|
149
|
+
}
|
|
150
|
+
return normalizedValue;
|
|
151
|
+
}
|
|
152
|
+
function normalizeMockReplacement(value, configFilePath) {
|
|
153
|
+
if (typeof value !== "string") {
|
|
154
|
+
throw new Error("Story rule mock replacement must be a string.");
|
|
155
|
+
}
|
|
156
|
+
const normalizedValue = value.trim();
|
|
157
|
+
if (!normalizedValue) {
|
|
158
|
+
throw new Error("Story rule mock replacement cannot be empty.");
|
|
159
|
+
}
|
|
160
|
+
if (isAbsolute(normalizedValue)) {
|
|
161
|
+
return toPosixPath(normalizedValue);
|
|
162
|
+
}
|
|
163
|
+
if (normalizedValue.startsWith(".")) {
|
|
164
|
+
if (!configFilePath) {
|
|
165
|
+
throw new Error(
|
|
166
|
+
"Story rule mock replacement uses a relative path, but rules config path is unavailable."
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
return toPosixPath(resolve(dirname(configFilePath), normalizedValue));
|
|
170
|
+
}
|
|
171
|
+
return normalizedValue;
|
|
172
|
+
}
|
|
173
|
+
function slugify(input) {
|
|
174
|
+
return input.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
175
|
+
}
|
|
176
|
+
function createEmptySelection() {
|
|
177
|
+
return {
|
|
178
|
+
moduleMocks: /* @__PURE__ */ new Map(),
|
|
179
|
+
mswHandlers: []
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function toPosixPath(input) {
|
|
183
|
+
return input.replaceAll("\\", "/");
|
|
184
|
+
}
|
|
185
|
+
function escapeRegExp(input) {
|
|
186
|
+
return input.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
|
|
187
|
+
}
|
|
188
|
+
function isRecord(value) {
|
|
189
|
+
if (typeof value !== "object" || value === null) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
return !Array.isArray(value);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// src/lib/sanitization.ts
|
|
196
|
+
import sanitizeHtml from "sanitize-html";
|
|
197
|
+
var DEFAULT_SANITIZE_HTML_OPTIONS = {
|
|
198
|
+
allowedTags: [
|
|
199
|
+
"a",
|
|
200
|
+
"abbr",
|
|
201
|
+
"b",
|
|
202
|
+
"blockquote",
|
|
203
|
+
"br",
|
|
204
|
+
"caption",
|
|
205
|
+
"cite",
|
|
206
|
+
"code",
|
|
207
|
+
"col",
|
|
208
|
+
"colgroup",
|
|
209
|
+
"dd",
|
|
210
|
+
"details",
|
|
211
|
+
"dfn",
|
|
212
|
+
"div",
|
|
213
|
+
"dl",
|
|
214
|
+
"dt",
|
|
215
|
+
"em",
|
|
216
|
+
"figcaption",
|
|
217
|
+
"figure",
|
|
218
|
+
"h1",
|
|
219
|
+
"h2",
|
|
220
|
+
"h3",
|
|
221
|
+
"h4",
|
|
222
|
+
"h5",
|
|
223
|
+
"h6",
|
|
224
|
+
"hr",
|
|
225
|
+
"i",
|
|
226
|
+
"img",
|
|
227
|
+
"kbd",
|
|
228
|
+
"li",
|
|
229
|
+
"mark",
|
|
230
|
+
"ol",
|
|
231
|
+
"p",
|
|
232
|
+
"pre",
|
|
233
|
+
"q",
|
|
234
|
+
"rp",
|
|
235
|
+
"rt",
|
|
236
|
+
"ruby",
|
|
237
|
+
"s",
|
|
238
|
+
"samp",
|
|
239
|
+
"small",
|
|
240
|
+
"span",
|
|
241
|
+
"strong",
|
|
242
|
+
"sub",
|
|
243
|
+
"summary",
|
|
244
|
+
"sup",
|
|
245
|
+
"table",
|
|
246
|
+
"tbody",
|
|
247
|
+
"td",
|
|
248
|
+
"tfoot",
|
|
249
|
+
"th",
|
|
250
|
+
"thead",
|
|
251
|
+
"time",
|
|
252
|
+
"tr",
|
|
253
|
+
"u",
|
|
254
|
+
"ul",
|
|
255
|
+
"var",
|
|
256
|
+
"wbr"
|
|
257
|
+
],
|
|
258
|
+
allowedAttributes: {
|
|
259
|
+
"*": [
|
|
260
|
+
"aria-describedby",
|
|
261
|
+
"aria-hidden",
|
|
262
|
+
"aria-label",
|
|
263
|
+
"aria-labelledby",
|
|
264
|
+
"class",
|
|
265
|
+
"id",
|
|
266
|
+
"lang",
|
|
267
|
+
"role",
|
|
268
|
+
"title"
|
|
269
|
+
],
|
|
270
|
+
a: ["href", "name", "target", "rel"],
|
|
271
|
+
img: ["src", "srcset", "alt", "title", "width", "height", "loading", "decoding"],
|
|
272
|
+
td: ["colspan", "rowspan"],
|
|
273
|
+
th: ["colspan", "rowspan", "scope"],
|
|
274
|
+
time: ["datetime"]
|
|
275
|
+
},
|
|
276
|
+
allowedSchemes: ["http", "https", "mailto", "tel", "data"],
|
|
277
|
+
allowedSchemesByTag: {
|
|
278
|
+
a: ["http", "https", "mailto", "tel"],
|
|
279
|
+
img: ["http", "https", "data"]
|
|
280
|
+
},
|
|
281
|
+
allowedSchemesAppliedToAttributes: ["href", "src", "cite", "srcset"],
|
|
282
|
+
allowProtocolRelative: false,
|
|
283
|
+
disallowedTagsMode: "discard",
|
|
284
|
+
enforceHtmlBoundary: true,
|
|
285
|
+
parseStyleAttributes: false
|
|
286
|
+
};
|
|
287
|
+
function resolveSanitizationOptions(options) {
|
|
288
|
+
if (!options) {
|
|
289
|
+
return {
|
|
290
|
+
enabled: true,
|
|
291
|
+
args: [],
|
|
292
|
+
slots: ["**"],
|
|
293
|
+
sanitizeHtml: mergeSanitizeHtmlOptions()
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
const enabled = options.enabled ?? true;
|
|
297
|
+
const args = normalizePathList(options.args, "framework.options.sanitization.args");
|
|
298
|
+
const slots = options.slots === void 0 ? ["**"] : normalizePathList(options.slots, "framework.options.sanitization.slots");
|
|
299
|
+
return {
|
|
300
|
+
enabled,
|
|
301
|
+
args,
|
|
302
|
+
slots,
|
|
303
|
+
sanitizeHtml: mergeSanitizeHtmlOptions(options.sanitizeHtml)
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
function sanitizeRenderPayload(payload, options) {
|
|
307
|
+
if (!options.enabled) {
|
|
308
|
+
return payload;
|
|
309
|
+
}
|
|
310
|
+
const sanitizedArgs = options.args.length > 0 ? sanitizeRecord(payload.args, options.args, options.sanitizeHtml) : payload.args;
|
|
311
|
+
const sanitizedSlots = options.slots.length > 0 ? sanitizeRecord(payload.slots, options.slots, options.sanitizeHtml) : payload.slots;
|
|
312
|
+
return {
|
|
313
|
+
args: sanitizedArgs,
|
|
314
|
+
slots: sanitizedSlots
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
function mergeSanitizeHtmlOptions(userOptions) {
|
|
318
|
+
const merged = {
|
|
319
|
+
...DEFAULT_SANITIZE_HTML_OPTIONS,
|
|
320
|
+
...userOptions
|
|
321
|
+
};
|
|
322
|
+
if (isRecord2(DEFAULT_SANITIZE_HTML_OPTIONS.allowedAttributes) && isRecord2(userOptions?.allowedAttributes)) {
|
|
323
|
+
merged.allowedAttributes = {
|
|
324
|
+
...DEFAULT_SANITIZE_HTML_OPTIONS.allowedAttributes,
|
|
325
|
+
...userOptions.allowedAttributes
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (isRecord2(userOptions?.allowedClasses)) {
|
|
329
|
+
merged.allowedClasses = {
|
|
330
|
+
...isRecord2(DEFAULT_SANITIZE_HTML_OPTIONS.allowedClasses) ? DEFAULT_SANITIZE_HTML_OPTIONS.allowedClasses : {},
|
|
331
|
+
...userOptions.allowedClasses
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
if (isRecord2(userOptions?.allowedStyles)) {
|
|
335
|
+
merged.allowedStyles = {
|
|
336
|
+
...isRecord2(DEFAULT_SANITIZE_HTML_OPTIONS.allowedStyles) ? DEFAULT_SANITIZE_HTML_OPTIONS.allowedStyles : {},
|
|
337
|
+
...userOptions.allowedStyles
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
return merged;
|
|
341
|
+
}
|
|
342
|
+
function normalizePathList(value, path) {
|
|
343
|
+
if (value === void 0) {
|
|
344
|
+
return [];
|
|
345
|
+
}
|
|
346
|
+
if (!Array.isArray(value)) {
|
|
347
|
+
throw new Error(`${path} must be an array of dot-path patterns.`);
|
|
348
|
+
}
|
|
349
|
+
const unique = /* @__PURE__ */ new Set();
|
|
350
|
+
value.forEach((entry, index) => {
|
|
351
|
+
if (typeof entry !== "string") {
|
|
352
|
+
throw new Error(`${path}[${index}] must be a string.`);
|
|
353
|
+
}
|
|
354
|
+
const normalized = entry.trim();
|
|
355
|
+
if (!normalized) {
|
|
356
|
+
throw new Error(`${path}[${index}] cannot be an empty string.`);
|
|
357
|
+
}
|
|
358
|
+
unique.add(normalized);
|
|
359
|
+
});
|
|
360
|
+
return Array.from(unique);
|
|
361
|
+
}
|
|
362
|
+
function sanitizeRecord(record, patterns, options) {
|
|
363
|
+
const sanitized = {};
|
|
364
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
365
|
+
sanitized[key] = sanitizeValue(value, key, patterns, options);
|
|
366
|
+
});
|
|
367
|
+
return sanitized;
|
|
368
|
+
}
|
|
369
|
+
function sanitizeValue(value, currentPath, patterns, options) {
|
|
370
|
+
if (typeof value === "string") {
|
|
371
|
+
if (shouldSanitizePath(currentPath, patterns)) {
|
|
372
|
+
return sanitizeHtml(value, options);
|
|
373
|
+
}
|
|
374
|
+
return value;
|
|
375
|
+
}
|
|
376
|
+
if (Array.isArray(value)) {
|
|
377
|
+
return value.map((item, index) => {
|
|
378
|
+
const nextPath = `${currentPath}.${index}`;
|
|
379
|
+
return sanitizeValue(item, nextPath, patterns, options);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
if (isRecord2(value)) {
|
|
383
|
+
const sanitized = {};
|
|
384
|
+
Object.entries(value).forEach(([key, nestedValue]) => {
|
|
385
|
+
const nextPath = `${currentPath}.${key}`;
|
|
386
|
+
sanitized[key] = sanitizeValue(nestedValue, nextPath, patterns, options);
|
|
387
|
+
});
|
|
388
|
+
return sanitized;
|
|
389
|
+
}
|
|
390
|
+
return value;
|
|
391
|
+
}
|
|
392
|
+
function shouldSanitizePath(path, patterns) {
|
|
393
|
+
return patterns.some((pattern) => matchesPathPattern(path, pattern));
|
|
394
|
+
}
|
|
395
|
+
function matchesPathPattern(path, pattern) {
|
|
396
|
+
const pathSegments = path.split(".");
|
|
397
|
+
const patternSegments = pattern.split(".");
|
|
398
|
+
return matchSegments(pathSegments, patternSegments);
|
|
399
|
+
}
|
|
400
|
+
function matchSegments(pathSegments, patternSegments) {
|
|
401
|
+
if (patternSegments.length === 0) {
|
|
402
|
+
return pathSegments.length === 0;
|
|
403
|
+
}
|
|
404
|
+
const [patternHead, ...patternTail] = patternSegments;
|
|
405
|
+
if (patternHead === "**") {
|
|
406
|
+
if (patternTail.length === 0) {
|
|
407
|
+
return true;
|
|
408
|
+
}
|
|
409
|
+
for (let index = 0; index <= pathSegments.length; index += 1) {
|
|
410
|
+
const remainingPath = pathSegments.slice(index);
|
|
411
|
+
if (matchSegments(remainingPath, patternTail)) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
if (pathSegments.length === 0) {
|
|
418
|
+
return false;
|
|
419
|
+
}
|
|
420
|
+
const [pathHead, ...pathTail] = pathSegments;
|
|
421
|
+
if (patternHead === "*" || patternHead === pathHead) {
|
|
422
|
+
return matchSegments(pathTail, patternTail);
|
|
423
|
+
}
|
|
424
|
+
return false;
|
|
425
|
+
}
|
|
426
|
+
function isRecord2(value) {
|
|
427
|
+
if (typeof value !== "object" || value === null) {
|
|
428
|
+
return false;
|
|
429
|
+
}
|
|
430
|
+
if (Array.isArray(value) || value instanceof RegExp) {
|
|
431
|
+
return false;
|
|
432
|
+
}
|
|
433
|
+
const prototype = Object.getPrototypeOf(value);
|
|
434
|
+
return prototype === Object.prototype || prototype === null;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// src/module-mocks.ts
|
|
438
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
439
|
+
var moduleMockStorage = new AsyncLocalStorage();
|
|
440
|
+
async function withStoryModuleMocks(moduleMocks, callback) {
|
|
441
|
+
return moduleMockStorage.run(moduleMocks, callback);
|
|
442
|
+
}
|
|
443
|
+
function resolveStoryModuleMock(specifier) {
|
|
444
|
+
return moduleMockStorage.getStore()?.get(specifier);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// src/msw.ts
|
|
448
|
+
import { setupServer } from "msw/node";
|
|
449
|
+
var defaultListenOptions = {
|
|
450
|
+
onUnhandledRequest: "bypass"
|
|
451
|
+
};
|
|
452
|
+
async function applyMswHandlers(handlers) {
|
|
453
|
+
const state = getMswState();
|
|
454
|
+
if (state.pendingUpdate) {
|
|
455
|
+
await state.pendingUpdate;
|
|
456
|
+
}
|
|
457
|
+
const updatePromise = syncMswHandlers(handlers, state);
|
|
458
|
+
state.pendingUpdate = updatePromise;
|
|
459
|
+
try {
|
|
460
|
+
await updatePromise;
|
|
461
|
+
} finally {
|
|
462
|
+
state.pendingUpdate = void 0;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
async function syncMswHandlers(handlers, state) {
|
|
466
|
+
if (!state.server) {
|
|
467
|
+
state.server = setupServer();
|
|
468
|
+
state.server.listen(defaultListenOptions);
|
|
469
|
+
}
|
|
470
|
+
state.server.resetHandlers(...handlers);
|
|
471
|
+
}
|
|
472
|
+
function getMswState() {
|
|
473
|
+
const globalState = globalThis;
|
|
474
|
+
if (!globalState.__storybookAstroMswState__) {
|
|
475
|
+
globalState.__storybookAstroMswState__ = {
|
|
476
|
+
server: void 0,
|
|
477
|
+
pendingUpdate: void 0
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
return globalState.__storybookAstroMswState__;
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export {
|
|
484
|
+
defineStoryRules,
|
|
485
|
+
selectStoryRules,
|
|
486
|
+
resolveSanitizationOptions,
|
|
487
|
+
sanitizeRenderPayload,
|
|
488
|
+
withStoryModuleMocks,
|
|
489
|
+
resolveStoryModuleMock,
|
|
490
|
+
applyMswHandlers
|
|
491
|
+
};
|
|
492
|
+
//# sourceMappingURL=chunk-C5OH4VBR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/rules.ts","../src/lib/sanitization.ts","../src/module-mocks.ts","../src/msw.ts"],"sourcesContent":["import { dirname, isAbsolute, resolve } from 'node:path';\nimport type { RequestHandler } from 'msw';\nimport type { RenderStoryInput } from './types.ts';\n\ntype StoryMode = 'development' | 'production';\ntype StoryRuleUseResult = void | Promise<void>;\n\nexport type StoryRuleUseContext = {\n mode: StoryMode;\n story: StoryRuleStory;\n msw: {\n use: (...handlers: RequestHandler[]) => void;\n };\n mock: (specifier: string, replacement: string) => void;\n};\n\nexport type StoryRuleUse = (context: StoryRuleUseContext) => StoryRuleUseResult;\n\nexport type StoryRule = {\n match: string | string[];\n use: StoryRuleUse | StoryRuleUse[];\n};\n\nexport type StoryRulesConfig = {\n rules: StoryRule[];\n};\n\nexport type StoryRuleStory = {\n id: string;\n title?: string;\n name?: string;\n keys: string[];\n};\n\nexport type StoryRuleSelectionInput = {\n configModule: unknown;\n configFilePath?: string;\n mode: StoryMode;\n story?: RenderStoryInput;\n};\n\nexport type StoryRuleSelection = {\n moduleMocks: Map<string, string>;\n mswHandlers: RequestHandler[];\n};\n\ntype MutableStoryRuleSelection = {\n moduleMocks: Map<string, string>;\n mswHandlers: RequestHandler[];\n};\n\nexport function defineStoryRules(config: StoryRulesConfig): StoryRulesConfig {\n return config;\n}\n\nexport async function selectStoryRules(\n input: StoryRuleSelectionInput\n): Promise<StoryRuleSelection> {\n const config = normalizeRulesConfig(input.configModule);\n const story = normalizeStory(input.story);\n const selection = createEmptySelection();\n\n for (const rule of config.rules) {\n if (!isStoryRuleMatch(rule.match, story)) {\n continue;\n }\n\n const uses = Array.isArray(rule.use) ? rule.use : [rule.use];\n\n for (const use of uses) {\n if (typeof use !== 'function') {\n throw new Error('Each story rule \"use\" entry must be a function.');\n }\n\n await use({\n mode: input.mode,\n story,\n msw: {\n use: (...handlers) => {\n selection.mswHandlers.push(...handlers);\n }\n },\n mock: (specifier, replacement) => {\n const normalizedSpecifier = normalizeMockSpecifier(specifier);\n const normalizedReplacement = normalizeMockReplacement(replacement, input.configFilePath);\n\n selection.moduleMocks.set(normalizedSpecifier, normalizedReplacement);\n }\n });\n }\n }\n\n return selection;\n}\n\nfunction normalizeRulesConfig(configModule: unknown): StoryRulesConfig {\n const configExport = getRulesConfigExport(configModule);\n\n if (configExport === undefined || configExport === null) {\n return {\n rules: []\n };\n }\n\n if (!isRecord(configExport)) {\n throw new Error(\n 'Story rules config must export an object with a \"rules\" array via a default export or named export.'\n );\n }\n\n const rules = configExport.rules;\n\n if (rules === undefined) {\n return {\n rules: []\n };\n }\n\n if (!Array.isArray(rules)) {\n throw new Error('Story rules config \"rules\" must be an array.');\n }\n\n return {\n rules: rules as StoryRule[]\n };\n}\n\nfunction getRulesConfigExport(configModule: unknown): unknown {\n if (!isRecord(configModule)) {\n return configModule;\n }\n\n if ('default' in configModule && configModule.default !== undefined) {\n return configModule.default;\n }\n\n if ('rules' in configModule) {\n return {\n rules: configModule.rules\n };\n }\n\n return undefined;\n}\n\nfunction normalizeStory(story?: RenderStoryInput): StoryRuleStory {\n const id = normalizeStoryId(story?.id);\n const title = normalizeOptionalString(story?.title);\n const name = normalizeOptionalString(story?.name);\n const keys = Array.from(resolveStoryKeys({ id, title, name }));\n\n return {\n id,\n title,\n name,\n keys\n };\n}\n\nfunction resolveStoryKeys(story: { id: string; title?: string; name?: string }) {\n const keys = new Set<string>();\n\n keys.add('');\n\n const storyId = story.id;\n const idPath = storyId ? storyId.replaceAll('--', '/') : '';\n\n if (storyId) {\n keys.add(storyId);\n keys.add(`/story/${storyId}`);\n }\n\n if (idPath) {\n keys.add(idPath);\n keys.add(`/story/${idPath}`);\n }\n\n const titlePath = story.title\n ? story.title\n .split('/')\n .map((segment) => slugify(segment))\n .filter(Boolean)\n .join('/')\n : '';\n\n const storyNamePath = story.name ? slugify(story.name) : '';\n\n if (titlePath && storyNamePath) {\n const composedPath = `${titlePath}/${storyNamePath}`;\n\n keys.add(composedPath);\n keys.add(`/story/${composedPath}`);\n }\n\n return keys;\n}\n\nfunction isStoryRuleMatch(match: string | string[], story: StoryRuleStory): boolean {\n const patterns = Array.isArray(match) ? match : [match];\n\n return patterns.some((pattern) => {\n if (typeof pattern !== 'string') {\n throw new Error('Story rule \"match\" must be a string or an array of strings.');\n }\n\n const normalizedPattern = pattern.trim();\n\n if (!normalizedPattern) {\n throw new Error('Story rule \"match\" cannot be empty.');\n }\n\n return story.keys.some((key) => isWildcardMatch(normalizedPattern, key));\n });\n}\n\nfunction isWildcardMatch(pattern: string, candidate: string): boolean {\n const escapedPattern = escapeRegExp(pattern).replaceAll('*', '.*');\n const regex = new RegExp(`^${escapedPattern}$`);\n\n return regex.test(candidate);\n}\n\nfunction normalizeStoryId(id?: string): string {\n const value = normalizeOptionalString(id) ?? '';\n\n if (!value) {\n return '';\n }\n\n return value.startsWith('/story/') ? value.slice('/story/'.length) : value;\n}\n\nfunction normalizeOptionalString(value: unknown): string | undefined {\n if (typeof value !== 'string') {\n return undefined;\n }\n\n const normalizedValue = value.trim();\n\n return normalizedValue || undefined;\n}\n\nfunction normalizeMockSpecifier(value: unknown): string {\n if (typeof value !== 'string') {\n throw new Error('Story rule mock specifier must be a string.');\n }\n\n const normalizedValue = value.trim();\n\n if (!normalizedValue) {\n throw new Error('Story rule mock specifier cannot be empty.');\n }\n\n return normalizedValue;\n}\n\nfunction normalizeMockReplacement(value: unknown, configFilePath?: string): string {\n if (typeof value !== 'string') {\n throw new Error('Story rule mock replacement must be a string.');\n }\n\n const normalizedValue = value.trim();\n\n if (!normalizedValue) {\n throw new Error('Story rule mock replacement cannot be empty.');\n }\n\n if (isAbsolute(normalizedValue)) {\n return toPosixPath(normalizedValue);\n }\n\n if (normalizedValue.startsWith('.')) {\n if (!configFilePath) {\n throw new Error(\n 'Story rule mock replacement uses a relative path, but rules config path is unavailable.'\n );\n }\n\n return toPosixPath(resolve(dirname(configFilePath), normalizedValue));\n }\n\n return normalizedValue;\n}\n\nfunction slugify(input: string): string {\n return input\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '');\n}\n\nfunction createEmptySelection(): MutableStoryRuleSelection {\n return {\n moduleMocks: new Map(),\n mswHandlers: []\n };\n}\n\nfunction toPosixPath(input: string): string {\n return input.replaceAll('\\\\', '/');\n}\n\nfunction escapeRegExp(input: string) {\n return input.replace(/[|\\\\{}()[\\]^$+?.]/g, '\\\\$&');\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n return !Array.isArray(value);\n}\n","import sanitizeHtml from 'sanitize-html';\nimport type { IOptions } from 'sanitize-html';\n\ntype SanitizationPayload = {\n args: Record<string, unknown>;\n slots: Record<string, unknown>;\n};\n\nexport type SanitizationOptions = {\n enabled?: boolean;\n args?: string[];\n slots?: string[];\n sanitizeHtml?: IOptions;\n};\n\nexport type ResolvedSanitizationOptions = {\n enabled: boolean;\n args: string[];\n slots: string[];\n sanitizeHtml: IOptions;\n};\n\nconst DEFAULT_SANITIZE_HTML_OPTIONS: IOptions = {\n allowedTags: [\n 'a',\n 'abbr',\n 'b',\n 'blockquote',\n 'br',\n 'caption',\n 'cite',\n 'code',\n 'col',\n 'colgroup',\n 'dd',\n 'details',\n 'dfn',\n 'div',\n 'dl',\n 'dt',\n 'em',\n 'figcaption',\n 'figure',\n 'h1',\n 'h2',\n 'h3',\n 'h4',\n 'h5',\n 'h6',\n 'hr',\n 'i',\n 'img',\n 'kbd',\n 'li',\n 'mark',\n 'ol',\n 'p',\n 'pre',\n 'q',\n 'rp',\n 'rt',\n 'ruby',\n 's',\n 'samp',\n 'small',\n 'span',\n 'strong',\n 'sub',\n 'summary',\n 'sup',\n 'table',\n 'tbody',\n 'td',\n 'tfoot',\n 'th',\n 'thead',\n 'time',\n 'tr',\n 'u',\n 'ul',\n 'var',\n 'wbr'\n ],\n allowedAttributes: {\n '*': [\n 'aria-describedby',\n 'aria-hidden',\n 'aria-label',\n 'aria-labelledby',\n 'class',\n 'id',\n 'lang',\n 'role',\n 'title'\n ],\n a: ['href', 'name', 'target', 'rel'],\n img: ['src', 'srcset', 'alt', 'title', 'width', 'height', 'loading', 'decoding'],\n td: ['colspan', 'rowspan'],\n th: ['colspan', 'rowspan', 'scope'],\n time: ['datetime']\n },\n allowedSchemes: ['http', 'https', 'mailto', 'tel', 'data'],\n allowedSchemesByTag: {\n a: ['http', 'https', 'mailto', 'tel'],\n img: ['http', 'https', 'data']\n },\n allowedSchemesAppliedToAttributes: ['href', 'src', 'cite', 'srcset'],\n allowProtocolRelative: false,\n disallowedTagsMode: 'discard',\n enforceHtmlBoundary: true,\n parseStyleAttributes: false\n};\n\nexport function resolveSanitizationOptions(options?: SanitizationOptions): ResolvedSanitizationOptions {\n if (!options) {\n return {\n enabled: true,\n args: [],\n slots: ['**'],\n sanitizeHtml: mergeSanitizeHtmlOptions()\n };\n }\n\n const enabled = options.enabled ?? true;\n const args = normalizePathList(options.args, 'framework.options.sanitization.args');\n const slots =\n options.slots === undefined\n ? ['**']\n : normalizePathList(options.slots, 'framework.options.sanitization.slots');\n\n return {\n enabled,\n args,\n slots,\n sanitizeHtml: mergeSanitizeHtmlOptions(options.sanitizeHtml)\n };\n}\n\nexport function sanitizeRenderPayload(\n payload: SanitizationPayload,\n options: ResolvedSanitizationOptions\n): SanitizationPayload {\n if (!options.enabled) {\n return payload;\n }\n\n const sanitizedArgs =\n options.args.length > 0\n ? sanitizeRecord(payload.args, options.args, options.sanitizeHtml)\n : payload.args;\n\n const sanitizedSlots =\n options.slots.length > 0\n ? sanitizeRecord(payload.slots, options.slots, options.sanitizeHtml)\n : payload.slots;\n\n return {\n args: sanitizedArgs,\n slots: sanitizedSlots\n };\n}\n\nfunction mergeSanitizeHtmlOptions(userOptions?: IOptions): IOptions {\n const merged: IOptions = {\n ...DEFAULT_SANITIZE_HTML_OPTIONS,\n ...userOptions\n };\n\n if (\n isRecord(DEFAULT_SANITIZE_HTML_OPTIONS.allowedAttributes) &&\n isRecord(userOptions?.allowedAttributes)\n ) {\n merged.allowedAttributes = {\n ...DEFAULT_SANITIZE_HTML_OPTIONS.allowedAttributes,\n ...userOptions.allowedAttributes\n };\n }\n\n if (isRecord(userOptions?.allowedClasses)) {\n merged.allowedClasses = {\n ...(isRecord(DEFAULT_SANITIZE_HTML_OPTIONS.allowedClasses)\n ? DEFAULT_SANITIZE_HTML_OPTIONS.allowedClasses\n : {}),\n ...userOptions.allowedClasses\n };\n }\n\n if (isRecord(userOptions?.allowedStyles)) {\n merged.allowedStyles = {\n ...(isRecord(DEFAULT_SANITIZE_HTML_OPTIONS.allowedStyles)\n ? DEFAULT_SANITIZE_HTML_OPTIONS.allowedStyles\n : {}),\n ...userOptions.allowedStyles\n };\n }\n\n return merged;\n}\n\nfunction normalizePathList(value: unknown, path: string): string[] {\n if (value === undefined) {\n return [];\n }\n\n if (!Array.isArray(value)) {\n throw new Error(`${path} must be an array of dot-path patterns.`);\n }\n\n const unique = new Set<string>();\n\n value.forEach((entry, index) => {\n if (typeof entry !== 'string') {\n throw new Error(`${path}[${index}] must be a string.`);\n }\n\n const normalized = entry.trim();\n\n if (!normalized) {\n throw new Error(`${path}[${index}] cannot be an empty string.`);\n }\n\n unique.add(normalized);\n });\n\n return Array.from(unique);\n}\n\nfunction sanitizeRecord(\n record: Record<string, unknown>,\n patterns: string[],\n options: IOptions\n): Record<string, unknown> {\n const sanitized: Record<string, unknown> = {};\n\n Object.entries(record).forEach(([key, value]) => {\n sanitized[key] = sanitizeValue(value, key, patterns, options);\n });\n\n return sanitized;\n}\n\nfunction sanitizeValue(\n value: unknown,\n currentPath: string,\n patterns: string[],\n options: IOptions\n): unknown {\n if (typeof value === 'string') {\n if (shouldSanitizePath(currentPath, patterns)) {\n return sanitizeHtml(value, options);\n }\n\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map((item, index) => {\n const nextPath = `${currentPath}.${index}`;\n\n return sanitizeValue(item, nextPath, patterns, options);\n });\n }\n\n if (isRecord(value)) {\n const sanitized: Record<string, unknown> = {};\n\n Object.entries(value).forEach(([key, nestedValue]) => {\n const nextPath = `${currentPath}.${key}`;\n\n sanitized[key] = sanitizeValue(nestedValue, nextPath, patterns, options);\n });\n\n return sanitized;\n }\n\n return value;\n}\n\nfunction shouldSanitizePath(path: string, patterns: string[]): boolean {\n return patterns.some((pattern) => matchesPathPattern(path, pattern));\n}\n\nfunction matchesPathPattern(path: string, pattern: string): boolean {\n const pathSegments = path.split('.');\n const patternSegments = pattern.split('.');\n\n return matchSegments(pathSegments, patternSegments);\n}\n\nfunction matchSegments(pathSegments: string[], patternSegments: string[]): boolean {\n if (patternSegments.length === 0) {\n return pathSegments.length === 0;\n }\n\n const [patternHead, ...patternTail] = patternSegments;\n\n if (patternHead === '**') {\n if (patternTail.length === 0) {\n return true;\n }\n\n for (let index = 0; index <= pathSegments.length; index += 1) {\n const remainingPath = pathSegments.slice(index);\n\n if (matchSegments(remainingPath, patternTail)) {\n return true;\n }\n }\n\n return false;\n }\n\n if (pathSegments.length === 0) {\n return false;\n }\n\n const [pathHead, ...pathTail] = pathSegments;\n\n if (patternHead === '*' || patternHead === pathHead) {\n return matchSegments(pathTail, patternTail);\n }\n\n return false;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n if (typeof value !== 'object' || value === null) {\n return false;\n }\n\n if (Array.isArray(value) || value instanceof RegExp) {\n return false;\n }\n\n const prototype = Object.getPrototypeOf(value);\n\n return prototype === Object.prototype || prototype === null;\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\n\nexport type StoryModuleMocks = Map<string, string>;\n\nconst moduleMockStorage = new AsyncLocalStorage<StoryModuleMocks>();\n\nexport async function withStoryModuleMocks<T>(\n moduleMocks: StoryModuleMocks,\n callback: () => Promise<T>\n): Promise<T> {\n return moduleMockStorage.run(moduleMocks, callback);\n}\n\nexport function resolveStoryModuleMock(specifier: string): string | undefined {\n return moduleMockStorage.getStore()?.get(specifier);\n}\n","import type { RequestHandler } from 'msw';\nimport { setupServer } from 'msw/node';\n\ntype MswServer = ReturnType<typeof setupServer>;\ntype MswServerListenOptions = Parameters<MswServer['listen']>[0];\n\ntype MswState = {\n server?: MswServer;\n pendingUpdate?: Promise<void>;\n};\n\ntype MswGlobalState = typeof globalThis & {\n __storybookAstroMswState__?: MswState;\n};\n\nconst defaultListenOptions: MswServerListenOptions = {\n onUnhandledRequest: 'bypass'\n};\n\nexport async function applyMswHandlers(handlers: RequestHandler[]): Promise<void> {\n const state = getMswState();\n\n if (state.pendingUpdate) {\n await state.pendingUpdate;\n }\n\n const updatePromise = syncMswHandlers(handlers, state);\n\n state.pendingUpdate = updatePromise;\n\n try {\n await updatePromise;\n } finally {\n state.pendingUpdate = undefined;\n }\n}\n\nasync function syncMswHandlers(handlers: RequestHandler[], state: MswState): Promise<void> {\n if (!state.server) {\n state.server = setupServer();\n state.server.listen(defaultListenOptions);\n }\n\n state.server.resetHandlers(...handlers);\n}\n\nfunction getMswState(): MswState {\n const globalState = globalThis as MswGlobalState;\n\n if (!globalState.__storybookAstroMswState__) {\n globalState.__storybookAstroMswState__ = {\n server: undefined,\n pendingUpdate: undefined\n };\n }\n\n return globalState.__storybookAstroMswState__;\n}\n"],"mappings":"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","names":["isRecord"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/importAstroConfig.ts
|
|
2
|
+
import { createRequire } from "module";
|
|
3
|
+
import { pathToFileURL } from "url";
|
|
4
|
+
async function importAstroConfig(resolveFrom) {
|
|
5
|
+
const require2 = createRequire(import.meta.url);
|
|
6
|
+
const astroConfigEntrypoint = require2.resolve("astro/config", {
|
|
7
|
+
paths: [resolveFrom]
|
|
8
|
+
});
|
|
9
|
+
return import(pathToFileURL(astroConfigEntrypoint).href);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
importAstroConfig
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-DNGQBPT7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/importAstroConfig.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\n\nexport async function importAstroConfig(resolveFrom: string) {\n const require = createRequire(import.meta.url);\n const astroConfigEntrypoint = require.resolve('astro/config', {\n paths: [resolveFrom]\n });\n\n return import(pathToFileURL(astroConfigEntrypoint).href);\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAE9B,eAAsB,kBAAkB,aAAqB;AAC3D,QAAMA,WAAU,cAAc,YAAY,GAAG;AAC7C,QAAM,wBAAwBA,SAAQ,QAAQ,gBAAgB;AAAA,IAC5D,OAAO,CAAC,WAAW;AAAA,EACrB,CAAC;AAED,SAAO,OAAO,cAAc,qBAAqB,EAAE;AACrD;","names":["require"]}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// src/vitePluginAstroComponentMarker.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
function vitePluginAstroComponentMarker() {
|
|
4
|
+
let isBuild = false;
|
|
5
|
+
return {
|
|
6
|
+
name: "storybook-astro-component-marker",
|
|
7
|
+
enforce: "post",
|
|
8
|
+
configResolved(config) {
|
|
9
|
+
isBuild = config.command === "build";
|
|
10
|
+
},
|
|
11
|
+
transform(code, id) {
|
|
12
|
+
if (!id.endsWith(".astro")) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (!code.includes("Astro components cannot be used in the browser")) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
const moduleId = id;
|
|
19
|
+
const styleCode = isBuild ? generateInlineStyles(moduleId) : generateStyleImports(moduleId);
|
|
20
|
+
return {
|
|
21
|
+
code: `
|
|
22
|
+
${styleCode}
|
|
23
|
+
const __astro_component = () => {
|
|
24
|
+
throw new Error('Astro components are rendered server-side by Storybook.');
|
|
25
|
+
};
|
|
26
|
+
__astro_component.isAstroComponentFactory = true;
|
|
27
|
+
__astro_component.moduleId = ${JSON.stringify(moduleId)};
|
|
28
|
+
export default __astro_component;
|
|
29
|
+
`,
|
|
30
|
+
map: null
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function generateStyleImports(filePath) {
|
|
36
|
+
try {
|
|
37
|
+
const source = readFileSync(filePath, "utf-8");
|
|
38
|
+
const styleCount = countStyleBlocks(source);
|
|
39
|
+
return Array.from(
|
|
40
|
+
{ length: styleCount },
|
|
41
|
+
(_, i) => `import ${JSON.stringify(`${filePath}?astro&type=style&index=${i}&lang.css`)};`
|
|
42
|
+
).join("\n");
|
|
43
|
+
} catch {
|
|
44
|
+
return "";
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function generateInlineStyles(filePath) {
|
|
48
|
+
try {
|
|
49
|
+
const source = readFileSync(filePath, "utf-8");
|
|
50
|
+
const cssBlocks = extractStyleBlocks(source);
|
|
51
|
+
if (cssBlocks.length === 0) {
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
return cssBlocks.map((css, i) => {
|
|
55
|
+
const escaped = JSON.stringify(css);
|
|
56
|
+
return `
|
|
57
|
+
(function() {
|
|
58
|
+
if (typeof document !== 'undefined') {
|
|
59
|
+
const style = document.createElement('style');
|
|
60
|
+
style.setAttribute('data-astro-build', ${JSON.stringify(filePath + ":" + i)});
|
|
61
|
+
style.textContent = ${escaped};
|
|
62
|
+
document.head.appendChild(style);
|
|
63
|
+
}
|
|
64
|
+
})();`;
|
|
65
|
+
}).join("\n");
|
|
66
|
+
} catch {
|
|
67
|
+
return "";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function extractStyleBlocks(source) {
|
|
71
|
+
const withoutFrontmatter = source.replace(/^---[\s\S]*?---/m, "");
|
|
72
|
+
const blocks = [];
|
|
73
|
+
const regex = /<style(?:\s[^>]*)?>([\s\S]*?)<\/style>/g;
|
|
74
|
+
let match;
|
|
75
|
+
while ((match = regex.exec(withoutFrontmatter)) !== null) {
|
|
76
|
+
blocks.push(match[1].trim());
|
|
77
|
+
}
|
|
78
|
+
return blocks;
|
|
79
|
+
}
|
|
80
|
+
function countStyleBlocks(source) {
|
|
81
|
+
const withoutFrontmatter = source.replace(/^---[\s\S]*?---/m, "");
|
|
82
|
+
const matches = withoutFrontmatter.match(/<style(\s|>)/g);
|
|
83
|
+
return matches ? matches.length : 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export {
|
|
87
|
+
vitePluginAstroComponentMarker
|
|
88
|
+
};
|
|
89
|
+
//# sourceMappingURL=chunk-E4LB75JN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vitePluginAstroComponentMarker.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport type { PluginOption } from 'vite';\n\n/**\n * Vite plugin that patches Astro 6's client-side .astro file transforms for Storybook.\n *\n * In Astro 6, the client-side transform of .astro files produces a stub function that\n * throws \"Astro components cannot be used in the browser\" without setting the\n * `isAstroComponentFactory` marker. Storybook's renderer relies on this marker to detect\n * Astro components and route them to server-side rendering via the Container API.\n *\n * This plugin also preserves the component's scoped CSS by importing the style sub-modules\n * that the Astro Vite plugin exposes. Without this, the client-side stub would strip all\n * CSS since Astro 6 no longer includes style imports in client-side .astro transforms.\n *\n * During builds, Astro's compile metadata cache is not populated for client-side transforms,\n * so style sub-module imports would fail. Instead, raw CSS is extracted directly from the\n * .astro source and inlined.\n */\nexport function vitePluginAstroComponentMarker(): PluginOption {\n let isBuild = false;\n\n return {\n name: 'storybook-astro-component-marker',\n enforce: 'post',\n\n configResolved(config) {\n isBuild = config.command === 'build';\n },\n\n transform(code: string, id: string) {\n // Only process main .astro modules (not sub-modules like ?astro&type=style)\n if (!id.endsWith('.astro')) {return null;}\n\n // Detect the Astro 6 client-side stub pattern\n if (!code.includes('Astro components cannot be used in the browser')) {return null;}\n\n const moduleId = id;\n\n // In dev mode, import style sub-modules via Astro's Vite plugin (which has\n // compile metadata cached from the SSR transform).\n // In build mode, Astro's compile metadata cache is not populated for client-side\n // transforms, so sub-module imports would fail. Extract raw CSS instead.\n const styleCode = isBuild\n ? generateInlineStyles(moduleId)\n : generateStyleImports(moduleId);\n\n return {\n code: `\n${styleCode}\nconst __astro_component = () => {\n throw new Error('Astro components are rendered server-side by Storybook.');\n};\n__astro_component.isAstroComponentFactory = true;\n__astro_component.moduleId = ${JSON.stringify(moduleId)};\nexport default __astro_component;\n`,\n map: null,\n };\n },\n };\n}\n\n/**\n * Reads the original .astro source file and generates import statements\n * for each <style> block, using the Astro Vite plugin's sub-module convention.\n */\nfunction generateStyleImports(filePath: string): string {\n try {\n const source = readFileSync(filePath, 'utf-8');\n const styleCount = countStyleBlocks(source);\n\n return Array.from({ length: styleCount }, (_, i) =>\n `import ${JSON.stringify(`${filePath}?astro&type=style&index=${i}&lang.css`)};`\n ).join('\\n');\n } catch {\n return '';\n }\n}\n\n/**\n * Reads the original .astro source file and generates a JS snippet that injects\n * the raw CSS from each <style> block into the document. Used during builds where\n * Astro's compile metadata cache is unavailable.\n *\n * The CSS is unscoped (no Astro scoping transforms), which is acceptable because\n * Astro components show a fallback message in static builds.\n */\nfunction generateInlineStyles(filePath: string): string {\n try {\n const source = readFileSync(filePath, 'utf-8');\n const cssBlocks = extractStyleBlocks(source);\n\n if (cssBlocks.length === 0) {return '';}\n\n // Create a side-effect that injects styles into the document\n return cssBlocks.map((css, i) => {\n const escaped = JSON.stringify(css);\n\n \nreturn `\n(function() {\n if (typeof document !== 'undefined') {\n const style = document.createElement('style');\n style.setAttribute('data-astro-build', ${JSON.stringify(filePath + ':' + i)});\n style.textContent = ${escaped};\n document.head.appendChild(style);\n }\n})();`;\n }).join('\\n');\n } catch {\n return '';\n }\n}\n\n/**\n * Extracts the content of all top-level <style> blocks from an Astro component's source.\n * Strips frontmatter before parsing.\n */\nfunction extractStyleBlocks(source: string): string[] {\n const withoutFrontmatter = source.replace(/^---[\\s\\S]*?---/m, '');\n const blocks: string[] = [];\n const regex = /<style(?:\\s[^>]*)?>([\\s\\S]*?)<\\/style>/g;\n let match;\n\n while ((match = regex.exec(withoutFrontmatter)) !== null) {\n blocks.push(match[1].trim());\n }\n\n return blocks;\n}\n\n/**\n * Counts the number of top-level <style> blocks in an Astro component's source.\n * Only counts opening tags that are NOT inside the frontmatter fence (---).\n */\nfunction countStyleBlocks(source: string): number {\n // Strip frontmatter\n const withoutFrontmatter = source.replace(/^---[\\s\\S]*?---/m, '');\n // Match <style> opening tags (with optional attributes)\n const matches = withoutFrontmatter.match(/<style(\\s|>)/g);\n\n \nreturn matches ? matches.length : 0;\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAmBtB,SAAS,iCAA+C;AAC7D,MAAI,UAAU;AAEd,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS;AAAA,IAET,eAAe,QAAQ;AACrB,gBAAU,OAAO,YAAY;AAAA,IAC/B;AAAA,IAEA,UAAU,MAAc,IAAY;AAElC,UAAI,CAAC,GAAG,SAAS,QAAQ,GAAG;AAAC,eAAO;AAAA,MAAK;AAGzC,UAAI,CAAC,KAAK,SAAS,gDAAgD,GAAG;AAAC,eAAO;AAAA,MAAK;AAEnF,YAAM,WAAW;AAMjB,YAAM,YAAY,UACd,qBAAqB,QAAQ,IAC7B,qBAAqB,QAAQ;AAEjC,aAAO;AAAA,QACL,MAAM;AAAA,EACZ,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA,+BAKoB,KAAK,UAAU,QAAQ,CAAC;AAAA;AAAA;AAAA,QAG/C,KAAK;AAAA,MACP;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,qBAAqB,UAA0B;AACtD,MAAI;AACF,UAAM,SAAS,aAAa,UAAU,OAAO;AAC7C,UAAM,aAAa,iBAAiB,MAAM;AAE1C,WAAO,MAAM;AAAA,MAAK,EAAE,QAAQ,WAAW;AAAA,MAAG,CAAC,GAAG,MAC5C,UAAU,KAAK,UAAU,GAAG,QAAQ,2BAA2B,CAAC,WAAW,CAAC;AAAA,IAC9E,EAAE,KAAK,IAAI;AAAA,EACb,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAUA,SAAS,qBAAqB,UAA0B;AACtD,MAAI;AACF,UAAM,SAAS,aAAa,UAAU,OAAO;AAC7C,UAAM,YAAY,mBAAmB,MAAM;AAE3C,QAAI,UAAU,WAAW,GAAG;AAAC,aAAO;AAAA,IAAG;AAGvC,WAAO,UAAU,IAAI,CAAC,KAAK,MAAM;AAC/B,YAAM,UAAU,KAAK,UAAU,GAAG;AAGxC,aAAO;AAAA;AAAA;AAAA;AAAA,6CAIsC,KAAK,UAAU,WAAW,MAAM,CAAC,CAAC;AAAA,0BACrD,OAAO;AAAA;AAAA;AAAA;AAAA,IAI7B,CAAC,EAAE,KAAK,IAAI;AAAA,EACd,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAMA,SAAS,mBAAmB,QAA0B;AACpD,QAAM,qBAAqB,OAAO,QAAQ,oBAAoB,EAAE;AAChE,QAAM,SAAmB,CAAC;AAC1B,QAAM,QAAQ;AACd,MAAI;AAEJ,UAAQ,QAAQ,MAAM,KAAK,kBAAkB,OAAO,MAAM;AACxD,WAAO,KAAK,MAAM,CAAC,EAAE,KAAK,CAAC;AAAA,EAC7B;AAEA,SAAO;AACT;AAMA,SAAS,iBAAiB,QAAwB;AAEhD,QAAM,qBAAqB,OAAO,QAAQ,oBAAoB,EAAE;AAEhE,QAAM,UAAU,mBAAmB,MAAM,eAAe;AAG1D,SAAO,UAAU,QAAQ,SAAS;AAClC;","names":[]}
|