@storybook-astro/framework 1.6.0 → 1.7.0-canary.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/dist/{chunk-RERWLIIN.js → chunk-5POAXNWB.js} +96 -107
- package/dist/chunk-5POAXNWB.js.map +1 -0
- package/dist/chunk-NOQVUQ7R.js +107 -0
- package/dist/chunk-NOQVUQ7R.js.map +1 -0
- package/dist/{chunk-6RIGYMZP.js → chunk-UIGE5653.js} +1 -1
- package/dist/chunk-UIGE5653.js.map +1 -0
- package/dist/chunk-YRG32BBU.js +15 -0
- package/dist/chunk-YRG32BBU.js.map +1 -0
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware.js +4 -2
- package/dist/middleware.js.map +1 -1
- package/dist/preset.js +78 -42
- package/dist/preset.js.map +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +39 -15
- package/dist/testing.js.map +1 -1
- package/dist/vitest/index.js +1 -1
- package/package.json +14 -13
- package/src/astroRenderHandler.ts +39 -2
- package/src/index.ts +8 -1
- package/src/lib/astro-component-marker.test.ts +48 -0
- package/src/lib/reconstruct-component-args.test.ts +97 -0
- package/src/lib/reconstruct-component-args.ts +155 -0
- package/src/lib/separate-story-slots.ts +20 -0
- package/src/preset.ts +60 -12
- package/src/productionRenderRuntime.test.ts +97 -0
- package/src/productionRenderRuntime.ts +46 -29
- package/src/storySsrVite.ts +23 -6
- package/src/testing/astro-runtime.ts +52 -21
- package/src/vitePluginAstroComponentMarker.ts +6 -1
- package/dist/chunk-6RIGYMZP.js.map +0 -1
- package/dist/chunk-RERWLIIN.js.map +0 -1
|
@@ -6,55 +6,6 @@ import {
|
|
|
6
6
|
withStoryModuleMocks
|
|
7
7
|
} from "./chunk-B5HHF6FC.js";
|
|
8
8
|
|
|
9
|
-
// src/astroImageService.ts
|
|
10
|
-
function ensureAstroPassthroughImageService() {
|
|
11
|
-
if (!globalThis.astroAsset) {
|
|
12
|
-
globalThis.astroAsset = {};
|
|
13
|
-
}
|
|
14
|
-
globalThis.astroAsset.imageService = {
|
|
15
|
-
propertiesToHash: ["src"],
|
|
16
|
-
validateOptions(options) {
|
|
17
|
-
return options;
|
|
18
|
-
},
|
|
19
|
-
getURL(options) {
|
|
20
|
-
const src = options.src;
|
|
21
|
-
if (src != null && typeof src === "object" && "src" in src && typeof src.src === "string") {
|
|
22
|
-
return src.src;
|
|
23
|
-
}
|
|
24
|
-
return typeof src === "string" ? src : "";
|
|
25
|
-
},
|
|
26
|
-
getHTMLAttributes(options) {
|
|
27
|
-
const {
|
|
28
|
-
src,
|
|
29
|
-
width,
|
|
30
|
-
height,
|
|
31
|
-
format,
|
|
32
|
-
quality,
|
|
33
|
-
densities,
|
|
34
|
-
widths,
|
|
35
|
-
formats,
|
|
36
|
-
layout,
|
|
37
|
-
priority,
|
|
38
|
-
fit,
|
|
39
|
-
position,
|
|
40
|
-
background,
|
|
41
|
-
...attrs
|
|
42
|
-
} = options;
|
|
43
|
-
const srcObject = src != null && typeof src === "object" ? src : null;
|
|
44
|
-
return {
|
|
45
|
-
...attrs,
|
|
46
|
-
width: width ?? srcObject?.width,
|
|
47
|
-
height: height ?? srcObject?.height,
|
|
48
|
-
loading: attrs.loading ?? "lazy",
|
|
49
|
-
decoding: attrs.decoding ?? "async"
|
|
50
|
-
};
|
|
51
|
-
},
|
|
52
|
-
getSrcSet() {
|
|
53
|
-
return [];
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
9
|
// src/lib/sanitization.ts
|
|
59
10
|
import sanitizeHtml from "sanitize-html";
|
|
60
11
|
var DEFAULT_SANITIZE_HTML_OPTIONS = {
|
|
@@ -369,6 +320,9 @@ function isRecord(value) {
|
|
|
369
320
|
return prototype === Object.prototype || prototype === null;
|
|
370
321
|
}
|
|
371
322
|
|
|
323
|
+
// src/astroRenderHandler.ts
|
|
324
|
+
import { markHTMLString } from "astro/runtime/server/index.js";
|
|
325
|
+
|
|
372
326
|
// src/lib/revive-dates.ts
|
|
373
327
|
var ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
374
328
|
function reviveDateStrings(args) {
|
|
@@ -398,6 +352,75 @@ function isRecord2(value) {
|
|
|
398
352
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
399
353
|
}
|
|
400
354
|
|
|
355
|
+
// src/lib/reconstruct-component-args.ts
|
|
356
|
+
import { isAstroComponentFactory, isAstroComponentMarker } from "@storybook-astro/renderer/types";
|
|
357
|
+
var MAX_DEPTH = 10;
|
|
358
|
+
async function reconstructProps(args, callbacks) {
|
|
359
|
+
return await resolvePropValue(args, callbacks, 0);
|
|
360
|
+
}
|
|
361
|
+
async function reconstructSlots(slots, callbacks) {
|
|
362
|
+
const out = {};
|
|
363
|
+
for (const [name, value] of Object.entries(slots)) {
|
|
364
|
+
out[name] = await resolveSlotValue(name, value, callbacks);
|
|
365
|
+
}
|
|
366
|
+
return out;
|
|
367
|
+
}
|
|
368
|
+
async function resolvePropValue(value, callbacks, depth) {
|
|
369
|
+
if (isAstroComponentMarker(value)) {
|
|
370
|
+
return callbacks.loadComponent(value.moduleId);
|
|
371
|
+
}
|
|
372
|
+
if (isAstroComponentFactory(value)) {
|
|
373
|
+
return value;
|
|
374
|
+
}
|
|
375
|
+
if (depth >= MAX_DEPTH) {
|
|
376
|
+
return value;
|
|
377
|
+
}
|
|
378
|
+
if (Array.isArray(value)) {
|
|
379
|
+
const resolved = await Promise.all(
|
|
380
|
+
value.map((item) => resolvePropValue(item, callbacks, depth + 1))
|
|
381
|
+
);
|
|
382
|
+
return resolved.some((item, index) => item !== value[index]) ? resolved : value;
|
|
383
|
+
}
|
|
384
|
+
if (isPlainObject(value)) {
|
|
385
|
+
let changed = false;
|
|
386
|
+
const out = {};
|
|
387
|
+
for (const [key, nested] of Object.entries(value)) {
|
|
388
|
+
const resolved = await resolvePropValue(nested, callbacks, depth + 1);
|
|
389
|
+
if (resolved !== nested) {
|
|
390
|
+
changed = true;
|
|
391
|
+
}
|
|
392
|
+
out[key] = resolved;
|
|
393
|
+
}
|
|
394
|
+
return changed ? out : value;
|
|
395
|
+
}
|
|
396
|
+
return value;
|
|
397
|
+
}
|
|
398
|
+
async function resolveSlotValue(name, value, callbacks) {
|
|
399
|
+
if (Array.isArray(value)) {
|
|
400
|
+
const parts = await Promise.all(value.map((item) => resolveSlotValue(name, item, callbacks)));
|
|
401
|
+
return parts.join("");
|
|
402
|
+
}
|
|
403
|
+
if (isAstroComponentMarker(value)) {
|
|
404
|
+
const component = await callbacks.loadComponent(value.moduleId);
|
|
405
|
+
return renderSlotComponent(name, component, callbacks);
|
|
406
|
+
}
|
|
407
|
+
if (isAstroComponentFactory(value)) {
|
|
408
|
+
return renderSlotComponent(name, value, callbacks);
|
|
409
|
+
}
|
|
410
|
+
return value;
|
|
411
|
+
}
|
|
412
|
+
async function renderSlotComponent(name, component, callbacks) {
|
|
413
|
+
try {
|
|
414
|
+
return await callbacks.renderToHtml(component);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
417
|
+
throw new Error(`Failed to render Astro component passed to slot "${name}": ${message}`);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
function isPlainObject(value) {
|
|
421
|
+
return typeof value === "object" && value !== null;
|
|
422
|
+
}
|
|
423
|
+
|
|
401
424
|
// src/storyRulesRuntime.ts
|
|
402
425
|
async function runWithStoryRules(options, callback) {
|
|
403
426
|
const rulesConfigModule = options.resolveRulesConfigModule ? await options.resolveRulesConfigModule() : void 0;
|
|
@@ -458,7 +481,10 @@ function createAstroRenderHandler(options) {
|
|
|
458
481
|
data.component,
|
|
459
482
|
selectedRules.moduleMocks.size === 0
|
|
460
483
|
);
|
|
461
|
-
const
|
|
484
|
+
const reconstructedArgs = await reconstructProps(data.args ?? {}, {
|
|
485
|
+
loadComponent: (moduleId) => loadPatchedComponent(moduleId)
|
|
486
|
+
});
|
|
487
|
+
const processedArgs = await processImageMetadata(reconstructedArgs);
|
|
462
488
|
const revivedArgs = reviveDateStrings(processedArgs);
|
|
463
489
|
const sanitizedPayload = sanitizeRenderPayload(
|
|
464
490
|
{
|
|
@@ -467,11 +493,18 @@ function createAstroRenderHandler(options) {
|
|
|
467
493
|
},
|
|
468
494
|
sanitizationOptions
|
|
469
495
|
);
|
|
496
|
+
const renderedSlots = await reconstructSlots(sanitizedPayload.slots, {
|
|
497
|
+
loadComponent: (moduleId) => loadPatchedComponent(moduleId),
|
|
498
|
+
renderToHtml: (component) => options.container.renderToString(
|
|
499
|
+
component,
|
|
500
|
+
{}
|
|
501
|
+
)
|
|
502
|
+
});
|
|
470
503
|
return options.container.renderToString(
|
|
471
504
|
patchedComponent,
|
|
472
505
|
{
|
|
473
506
|
props: sanitizedPayload.args,
|
|
474
|
-
slots:
|
|
507
|
+
slots: markRawSlots(renderedSlots)
|
|
475
508
|
}
|
|
476
509
|
);
|
|
477
510
|
}
|
|
@@ -485,6 +518,13 @@ function createAstroRenderHandler(options) {
|
|
|
485
518
|
return resultPromise;
|
|
486
519
|
};
|
|
487
520
|
}
|
|
521
|
+
function markRawSlots(slots) {
|
|
522
|
+
const marked = {};
|
|
523
|
+
for (const [name, value] of Object.entries(slots)) {
|
|
524
|
+
marked[name] = typeof value === "string" ? markHTMLString(value) : value;
|
|
525
|
+
}
|
|
526
|
+
return marked;
|
|
527
|
+
}
|
|
488
528
|
function patchCreateAstroCompat(component) {
|
|
489
529
|
if (typeof component !== "function") {
|
|
490
530
|
throw new Error("Expected Astro component factory to be a function.");
|
|
@@ -544,64 +584,13 @@ function isRecord3(value) {
|
|
|
544
584
|
return typeof value === "object" && value !== null;
|
|
545
585
|
}
|
|
546
586
|
|
|
547
|
-
// src/lib/resolve-aliased-island.ts
|
|
548
|
-
import { access } from "fs/promises";
|
|
549
|
-
import { resolve } from "path";
|
|
550
|
-
import { getTsconfig } from "get-tsconfig";
|
|
551
|
-
var ALIAS_EXTS = [".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte", ".mts", ".mjs"];
|
|
552
|
-
async function isFile(candidate) {
|
|
553
|
-
try {
|
|
554
|
-
await access(candidate);
|
|
555
|
-
return true;
|
|
556
|
-
} catch {
|
|
557
|
-
return false;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
async function resolveAliasedIsland(specifier, resolveFrom) {
|
|
561
|
-
if (!specifier || specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || specifier.startsWith("\0") || specifier.startsWith("virtual:") || specifier.startsWith("astro:") || specifier.startsWith("@astrojs/") || specifier.startsWith("@id/") || specifier.startsWith("/@fs/")) {
|
|
562
|
-
return void 0;
|
|
563
|
-
}
|
|
564
|
-
let found;
|
|
565
|
-
try {
|
|
566
|
-
found = getTsconfig(resolveFrom);
|
|
567
|
-
} catch {
|
|
568
|
-
return void 0;
|
|
569
|
-
}
|
|
570
|
-
if (!found) {
|
|
571
|
-
return void 0;
|
|
572
|
-
}
|
|
573
|
-
const compilerOptions = found.config.compilerOptions ?? {};
|
|
574
|
-
const paths = compilerOptions.paths ?? {};
|
|
575
|
-
if (Object.keys(paths).length === 0) {
|
|
576
|
-
return void 0;
|
|
577
|
-
}
|
|
578
|
-
const tsconfigDir = resolve(found.path, "..");
|
|
579
|
-
const root = compilerOptions.baseUrl ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;
|
|
580
|
-
for (const [pattern, targets] of Object.entries(paths)) {
|
|
581
|
-
const prefix = pattern.replace(/\*$/, "");
|
|
582
|
-
if (!specifier.startsWith(prefix)) {
|
|
583
|
-
continue;
|
|
584
|
-
}
|
|
585
|
-
const rest = specifier.slice(prefix.length);
|
|
586
|
-
for (const target of targets) {
|
|
587
|
-
const resolvedTarget = target.replace(/\*$/, "");
|
|
588
|
-
const base = resolve(root, resolvedTarget, rest);
|
|
589
|
-
const candidates = [base, ...ALIAS_EXTS.map((ext) => `${base}${ext}`)];
|
|
590
|
-
for (const candidate of candidates) {
|
|
591
|
-
if (await isFile(candidate)) {
|
|
592
|
-
return candidate.replace(/\\/g, "/");
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
return void 0;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
587
|
export {
|
|
601
|
-
ensureAstroPassthroughImageService,
|
|
602
588
|
resolveSanitizationOptions,
|
|
603
589
|
serializeSanitizationOptions,
|
|
590
|
+
reconstructProps,
|
|
591
|
+
reconstructSlots,
|
|
604
592
|
createAstroRenderHandler,
|
|
605
|
-
|
|
593
|
+
markRawSlots,
|
|
594
|
+
patchCreateAstroCompat
|
|
606
595
|
};
|
|
607
|
-
//# sourceMappingURL=chunk-
|
|
596
|
+
//# sourceMappingURL=chunk-5POAXNWB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/sanitization.ts","../src/astroRenderHandler.ts","../src/lib/revive-dates.ts","../src/lib/reconstruct-component-args.ts","../src/storyRulesRuntime.ts"],"sourcesContent":["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\nexport function serializeSanitizationOptions(options?: SanitizationOptions): string {\n if (!options) {\n return 'undefined';\n }\n\n assertNoFunctions(options.sanitizeHtml, 'framework.options.sanitization.sanitizeHtml');\n\n const state = {\n seen: new WeakSet<object>()\n };\n\n return serializeValue(options, 'framework.options.sanitization', state);\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 serializeValue(value: unknown, path: string, state: { seen: WeakSet<object> }): string {\n if (value === null) {\n return 'null';\n }\n\n if (value === undefined) {\n return 'undefined';\n }\n\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return JSON.stringify(value);\n }\n\n if (value instanceof RegExp) {\n return value.toString();\n }\n\n if (Array.isArray(value)) {\n const serializedItems = value.map((item, index) =>\n serializeValue(item, `${path}[${index}]`, state)\n );\n\n return `[${serializedItems.join(', ')}]`;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) {\n throw new Error(`${path} contains a circular reference.`);\n }\n\n state.seen.add(value);\n\n const serializedEntries = Object.entries(value)\n .filter(([, nestedValue]) => nestedValue !== undefined)\n .map(([key, nestedValue]) => {\n const serializedNestedValue = serializeValue(nestedValue, `${path}.${key}`, state);\n\n return `${JSON.stringify(key)}: ${serializedNestedValue}`;\n });\n\n return `{ ${serializedEntries.join(', ')} }`;\n }\n\n throw new Error(\n `${path} contains an unsupported value of type ${typeof value}. ` +\n 'Only plain objects, arrays, primitives, and regular expressions are supported.'\n );\n}\n\nfunction assertNoFunctions(value: unknown, path: string): void {\n const state = {\n seen: new WeakSet<object>()\n };\n\n assertNoFunctionsRecursive(value, path, state);\n}\n\nfunction assertNoFunctionsRecursive(\n value: unknown,\n path: string,\n state: { seen: WeakSet<object> }\n): void {\n if (typeof value === 'function') {\n throw new Error(\n `${path} cannot contain functions. ` +\n 'Function-valued sanitization hooks are not supported in framework options.'\n );\n }\n\n if (Array.isArray(value)) {\n value.forEach((item, index) => {\n assertNoFunctionsRecursive(item, `${path}[${index}]`, state);\n });\n\n return;\n }\n\n if (isRecord(value)) {\n if (state.seen.has(value)) {\n return;\n }\n\n state.seen.add(value);\n\n Object.entries(value).forEach(([key, nestedValue]) => {\n assertNoFunctionsRecursive(nestedValue, `${path}.${key}`, state);\n });\n }\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 type { experimental_AstroContainer as AstroContainer } from 'astro/container';\nimport { markHTMLString } from 'astro/runtime/server/index.js';\nimport type { SanitizationOptions } from './lib/sanitization.ts';\nimport { resolveSanitizationOptions, sanitizeRenderPayload } from './lib/sanitization.ts';\nimport { reviveDateStrings } from './lib/revive-dates.ts';\nimport { reconstructProps, reconstructSlots } from './lib/reconstruct-component-args.ts';\nimport { runWithStoryRules, type ResolveRulesConfigModule } from './storyRulesRuntime.ts';\nimport type { RenderStoryInput } from './types.ts';\n\ntype AstroCreateResult = {\n createAstro?: (...args: unknown[]) => unknown;\n};\n\ntype AstroComponentFactory = ((\n result: AstroCreateResult,\n props: unknown,\n slots: unknown\n) => unknown) & {\n isAstroComponentFactory?: boolean;\n moduleId?: string;\n propagation?: unknown;\n};\n\nexport type HandlerProps = {\n component: string;\n args?: Record<string, unknown>;\n slots?: Record<string, unknown>;\n story?: RenderStoryInput;\n};\n\ntype CreateAstroRenderHandlerOptions = {\n container: Awaited<ReturnType<typeof AstroContainer.create>>;\n sanitization?: SanitizationOptions;\n rulesConfigFilePath?: string;\n resolveRulesConfigModule?: ResolveRulesConfigModule;\n loadModule: (id: string) => Promise<{ default: unknown }>;\n invalidateModuleGraph?: () => void;\n};\n\nexport function createAstroRenderHandler(options: CreateAstroRenderHandlerOptions) {\n const sanitizationOptions = resolveSanitizationOptions(options.sanitization);\n const componentCache = new Map<string, Promise<AstroComponentFactory>>();\n let renderQueue = Promise.resolve<void>(undefined);\n\n async function loadPatchedComponent(componentId: string, useCache = true) {\n if (!useCache) {\n const { default: component } = await options.loadModule(componentId);\n\n return patchCreateAstroCompat(component);\n }\n\n if (!componentCache.has(componentId)) {\n componentCache.set(\n componentId,\n (async () => {\n const { default: component } = await options.loadModule(componentId);\n\n return patchCreateAstroCompat(component);\n })()\n );\n }\n\n const cachedComponent = componentCache.get(componentId);\n\n if (!cachedComponent) {\n throw new Error(`Failed to load Astro component: ${componentId}`);\n }\n\n try {\n return await cachedComponent;\n } catch (error) {\n componentCache.delete(componentId);\n throw error;\n }\n }\n\n return async function handler(data: HandlerProps) {\n const executeRender = async () => {\n return runWithStoryRules(\n {\n story: data.story,\n rulesConfigFilePath: options.rulesConfigFilePath,\n resolveRulesConfigModule: options.resolveRulesConfigModule,\n invalidateModuleGraph: options.invalidateModuleGraph\n },\n async (selectedRules) => {\n const patchedComponent = await loadPatchedComponent(\n data.component,\n selectedRules.moduleMocks.size === 0\n );\n // Resolve Astro components passed as props back to real factories\n // before the other arg processing (factories pass through those\n // untouched), so the parent template can render them with `<Comp />`.\n const reconstructedArgs = await reconstructProps(data.args ?? {}, {\n loadComponent: (moduleId) => loadPatchedComponent(moduleId)\n });\n const processedArgs = await processImageMetadata(reconstructedArgs);\n const revivedArgs = reviveDateStrings(processedArgs);\n const sanitizedPayload = sanitizeRenderPayload(\n {\n args: revivedArgs,\n slots: data.slots ?? {}\n },\n sanitizationOptions\n );\n\n // Render component slots to HTML *after* sanitization so a component's\n // own markup isn't stripped by the slot allowlist (string slots above\n // still are). Markers pass through sanitization untouched.\n const renderedSlots = await reconstructSlots(sanitizedPayload.slots, {\n loadComponent: (moduleId) => loadPatchedComponent(moduleId),\n renderToHtml: (component) =>\n options.container.renderToString(\n component as Parameters<typeof options.container.renderToString>[0],\n {}\n )\n });\n\n return options.container.renderToString(\n patchedComponent as Parameters<typeof options.container.renderToString>[0],\n {\n props: sanitizedPayload.args,\n slots: markRawSlots(renderedSlots)\n }\n );\n }\n );\n };\n\n const resultPromise = renderQueue.then(executeRender, executeRender);\n\n renderQueue = resultPromise.then(\n () => undefined,\n () => undefined\n );\n\n return resultPromise;\n };\n}\n\n/**\n * Marks each slot's HTML string as already-rendered so the Astro Container emits\n * it raw instead of escaping it. Astro 5 and 7 render string slots raw anyway,\n * but Astro 6 escapes an unmarked string slot — this normalizes all versions.\n * `markHTMLString` tags the string via a global symbol, so it's recognized even\n * across Astro module instances.\n */\nexport function markRawSlots(slots: Record<string, unknown>): Record<string, unknown> {\n const marked: Record<string, unknown> = {};\n\n for (const [name, value] of Object.entries(slots)) {\n marked[name] = typeof value === 'string' ? markHTMLString(value) : value;\n }\n\n return marked;\n}\n\nexport function patchCreateAstroCompat(component: unknown): AstroComponentFactory {\n if (typeof component !== 'function') {\n throw new Error('Expected Astro component factory to be a function.');\n }\n\n const originalComponent = component as AstroComponentFactory;\n const wrapped = ((result: AstroCreateResult, props: unknown, slots: unknown) => {\n if (result && typeof result.createAstro === 'function') {\n const originalCreateAstro = result.createAstro;\n const runtimeExpectsAstroGlobal = originalCreateAstro.length >= 3;\n\n result.createAstro = (...args: unknown[]) => {\n if (args.length === 3 && !runtimeExpectsAstroGlobal) {\n return originalCreateAstro(args[1], args[2]);\n }\n\n return originalCreateAstro(...args);\n };\n }\n\n return originalComponent(result, props, slots);\n }) as AstroComponentFactory;\n\n wrapped.isAstroComponentFactory = originalComponent.isAstroComponentFactory;\n wrapped.moduleId = originalComponent.moduleId;\n wrapped.propagation = originalComponent.propagation;\n\n return wrapped;\n}\n\nasync function processImageMetadata(\n args: Record<string, unknown>\n): Promise<Record<string, unknown>> {\n const processed: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(args)) {\n if (isImageMetadata(value)) {\n // Keep ImageMetadata as an object so Astro's image pipeline still\n // recognizes it as an imported image and skips local path validation.\n processed[key] = value;\n\n continue;\n }\n\n if (Array.isArray(value)) {\n processed[key] = await Promise.all(\n value.map(async (item) => {\n if (isImageMetadata(item)) {\n return item;\n }\n\n if (isRecord(item)) {\n return processImageMetadata(item);\n }\n\n return item;\n })\n );\n\n continue;\n }\n\n if (isRecord(value)) {\n processed[key] = await processImageMetadata(value);\n\n continue;\n }\n\n processed[key] = value;\n }\n\n return processed;\n}\n\nfunction isImageMetadata(value: unknown): value is Record<string, unknown> {\n return (\n isRecord(value) &&\n typeof value.src === 'string' &&\n ('width' in value || 'height' in value || 'format' in value)\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","/**\n * Revives Date objects that were lost during JSON serialization.\n *\n * When story args travel over Vite HMR (dev) or HTTP (server mode), Date\n * values are serialized by JSON.stringify into ISO 8601 strings like\n * \"2025-04-12T00:00:00.000Z\". This function walks the args tree and\n * converts those strings back into Date objects so Astro components\n * receive the types they expect.\n *\n * Only the exact format produced by Date.toJSON() is matched\n * (YYYY-MM-DDTHH:mm:ss.sssZ) to minimize false positives.\n */\n\n// Matches the exact output of Date.toJSON() / JSON.stringify(date).\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\.\\d{3}Z$/;\n\nexport function reviveDateStrings(args: Record<string, unknown>): Record<string, unknown> {\n const revived: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(args)) {\n revived[key] = reviveValue(value);\n }\n\n return revived;\n}\n\nfunction reviveValue(value: unknown): unknown {\n if (typeof value === 'string' && ISO_DATE_PATTERN.test(value)) {\n const date = new Date(value);\n\n if (!Number.isNaN(date.getTime())) {\n return date;\n }\n\n return value;\n }\n\n if (Array.isArray(value)) {\n return value.map(reviveValue);\n }\n\n if (isRecord(value)) {\n return reviveDateStrings(value);\n }\n\n return value;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n","import { isAstroComponentFactory, isAstroComponentMarker } from '@storybook-astro/renderer/types';\n\n/**\n * Resolves Astro component references that a story passed as props or slot\n * content back into something the Astro Container can render.\n *\n * A component reference arrives either as a serialized marker (the browser /\n * dev / server path, where it crossed a JSON boundary) or as a real component\n * factory (the Vitest / portable-stories path, which imports `.astro` files\n * directly). Both are handled.\n *\n * - **Props**: resolved to the real component factory and passed through, so the\n * parent template renders them with `<Comp />` (the Container supports this).\n * - **Slots**: rendered to an HTML string, because the Container only accepts\n * string slot content — a factory passed as a slot is stringified verbatim.\n *\n * Both callbacks are injected so this is reusable across the dev/server handler\n * (which loads by moduleId and renders via its container) and the testing path\n * (where factories are already in hand).\n */\ntype LoadComponent = (moduleId: string) => Promise<unknown>;\ntype RenderToHtml = (component: unknown) => Promise<string>;\n\n// Guards against pathological/cyclic arg objects. Component references are leaf\n// replacements, so real nesting is shallow; this is just insurance.\nconst MAX_DEPTH = 10;\n\n/**\n * Resolves component references in **props** back to real component factories,\n * so the parent template renders them with `<Comp />`. Run this before the\n * normal arg processing (image/date/sanitize) — factories pass through those\n * untouched, and a resolved prop must exist before the parent renders.\n */\nexport async function reconstructProps(\n args: Record<string, unknown>,\n callbacks: { loadComponent: LoadComponent }\n): Promise<Record<string, unknown>> {\n return (await resolvePropValue(args, callbacks, 0)) as Record<string, unknown>;\n}\n\n/**\n * Resolves component references in **slots** to HTML strings (the Container only\n * accepts string slots). Run this *after* sanitization so a component's rendered\n * markup — trusted, like a prop-rendered component — isn't stripped by the slot\n * HTML allowlist, while plain-string slots still are.\n */\nexport async function reconstructSlots(\n slots: Record<string, unknown>,\n callbacks: { loadComponent: LoadComponent; renderToHtml: RenderToHtml }\n): Promise<Record<string, unknown>> {\n const out: Record<string, unknown> = {};\n\n for (const [name, value] of Object.entries(slots)) {\n out[name] = await resolveSlotValue(name, value, callbacks);\n }\n\n return out;\n}\n\n/**\n * Walks a prop value, replacing component references with real factories.\n * Returns the original reference untouched when nothing changed, so unrelated\n * args keep their identity (e.g. `ImageMetadata` objects the image pipeline\n * later inspects).\n */\nasync function resolvePropValue(\n value: unknown,\n callbacks: { loadComponent: LoadComponent },\n depth: number\n): Promise<unknown> {\n if (isAstroComponentMarker(value)) {\n return callbacks.loadComponent(value.moduleId);\n }\n\n // Already a real factory (testing path) — pass it straight through as a prop.\n if (isAstroComponentFactory(value)) {\n return value;\n }\n\n if (depth >= MAX_DEPTH) {\n return value;\n }\n\n if (Array.isArray(value)) {\n const resolved = await Promise.all(\n value.map((item) => resolvePropValue(item, callbacks, depth + 1))\n );\n\n return resolved.some((item, index) => item !== value[index]) ? resolved : value;\n }\n\n if (isPlainObject(value)) {\n let changed = false;\n const out: Record<string, unknown> = {};\n\n for (const [key, nested] of Object.entries(value)) {\n const resolved = await resolvePropValue(nested, callbacks, depth + 1);\n\n if (resolved !== nested) {\n changed = true;\n }\n\n out[key] = resolved;\n }\n\n return changed ? out : value;\n }\n\n return value;\n}\n\nasync function resolveSlotValue(\n name: string,\n value: unknown,\n callbacks: { loadComponent: LoadComponent; renderToHtml: RenderToHtml }\n): Promise<unknown> {\n // An array slot (list of components and/or strings) is concatenated into one\n // HTML string, which is what the Container expects for a single slot.\n if (Array.isArray(value)) {\n const parts = await Promise.all(value.map((item) => resolveSlotValue(name, item, callbacks)));\n\n return parts.join('');\n }\n\n if (isAstroComponentMarker(value)) {\n const component = await callbacks.loadComponent(value.moduleId);\n\n return renderSlotComponent(name, component, callbacks);\n }\n\n if (isAstroComponentFactory(value)) {\n return renderSlotComponent(name, value, callbacks);\n }\n\n // Plain HTML string (or anything else) passes through unchanged.\n return value;\n}\n\nasync function renderSlotComponent(\n name: string,\n component: unknown,\n callbacks: { renderToHtml: RenderToHtml }\n): Promise<string> {\n try {\n return await callbacks.renderToHtml(component);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n\n throw new Error(`Failed to render Astro component passed to slot \"${name}\": ${message}`);\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n","import { withStoryModuleMocks } from './module-mocks.ts';\nimport { selectStoryRules, withStoryRuleCleanups, type StoryRuleSelection } from './rules.ts';\nimport type { RenderStoryInput } from './types.ts';\n\nexport type ResolveRulesConfigModule = () => unknown | Promise<unknown>;\n\ntype RunWithStoryRulesOptions = {\n story?: RenderStoryInput;\n rulesConfigFilePath?: string;\n resolveRulesConfigModule?: ResolveRulesConfigModule;\n invalidateModuleGraph?: () => void;\n};\n\nexport async function runWithStoryRules<T>(\n options: RunWithStoryRulesOptions,\n callback: (selection: StoryRuleSelection) => Promise<T>\n): Promise<T> {\n const rulesConfigModule = options.resolveRulesConfigModule\n ? await options.resolveRulesConfigModule()\n : undefined;\n const selectedRules = await selectStoryRules({\n configModule: rulesConfigModule,\n configFilePath: options.rulesConfigFilePath,\n story: options.story\n });\n\n if (selectedRules.moduleMocks.size > 0) {\n options.invalidateModuleGraph?.();\n }\n\n return withStoryRuleCleanups(selectedRules.cleanups, async () => {\n return withStoryModuleMocks(selectedRules.moduleMocks, async () => callback(selectedRules));\n });\n}\n"],"mappings":"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","names":["isRecord","isRecord"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// src/astroImageService.ts
|
|
2
|
+
function ensureAstroPassthroughImageService() {
|
|
3
|
+
if (!globalThis.astroAsset) {
|
|
4
|
+
globalThis.astroAsset = {};
|
|
5
|
+
}
|
|
6
|
+
globalThis.astroAsset.imageService = {
|
|
7
|
+
propertiesToHash: ["src"],
|
|
8
|
+
validateOptions(options) {
|
|
9
|
+
return options;
|
|
10
|
+
},
|
|
11
|
+
getURL(options) {
|
|
12
|
+
const src = options.src;
|
|
13
|
+
if (src != null && typeof src === "object" && "src" in src && typeof src.src === "string") {
|
|
14
|
+
return src.src;
|
|
15
|
+
}
|
|
16
|
+
return typeof src === "string" ? src : "";
|
|
17
|
+
},
|
|
18
|
+
getHTMLAttributes(options) {
|
|
19
|
+
const {
|
|
20
|
+
src,
|
|
21
|
+
width,
|
|
22
|
+
height,
|
|
23
|
+
format,
|
|
24
|
+
quality,
|
|
25
|
+
densities,
|
|
26
|
+
widths,
|
|
27
|
+
formats,
|
|
28
|
+
layout,
|
|
29
|
+
priority,
|
|
30
|
+
fit,
|
|
31
|
+
position,
|
|
32
|
+
background,
|
|
33
|
+
...attrs
|
|
34
|
+
} = options;
|
|
35
|
+
const srcObject = src != null && typeof src === "object" ? src : null;
|
|
36
|
+
return {
|
|
37
|
+
...attrs,
|
|
38
|
+
width: width ?? srcObject?.width,
|
|
39
|
+
height: height ?? srcObject?.height,
|
|
40
|
+
loading: attrs.loading ?? "lazy",
|
|
41
|
+
decoding: attrs.decoding ?? "async"
|
|
42
|
+
};
|
|
43
|
+
},
|
|
44
|
+
getSrcSet() {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/lib/resolve-aliased-island.ts
|
|
51
|
+
import { access } from "fs/promises";
|
|
52
|
+
import { resolve } from "path";
|
|
53
|
+
import { getTsconfig } from "get-tsconfig";
|
|
54
|
+
var ALIAS_EXTS = [".tsx", ".ts", ".jsx", ".js", ".vue", ".svelte", ".mts", ".mjs"];
|
|
55
|
+
async function isFile(candidate) {
|
|
56
|
+
try {
|
|
57
|
+
await access(candidate);
|
|
58
|
+
return true;
|
|
59
|
+
} catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
async function resolveAliasedIsland(specifier, resolveFrom) {
|
|
64
|
+
if (!specifier || specifier.startsWith("./") || specifier.startsWith("../") || specifier.startsWith("/") || specifier.startsWith("\0") || specifier.startsWith("virtual:") || specifier.startsWith("astro:") || specifier.startsWith("@astrojs/") || specifier.startsWith("@id/") || specifier.startsWith("/@fs/")) {
|
|
65
|
+
return void 0;
|
|
66
|
+
}
|
|
67
|
+
let found;
|
|
68
|
+
try {
|
|
69
|
+
found = getTsconfig(resolveFrom);
|
|
70
|
+
} catch {
|
|
71
|
+
return void 0;
|
|
72
|
+
}
|
|
73
|
+
if (!found) {
|
|
74
|
+
return void 0;
|
|
75
|
+
}
|
|
76
|
+
const compilerOptions = found.config.compilerOptions ?? {};
|
|
77
|
+
const paths = compilerOptions.paths ?? {};
|
|
78
|
+
if (Object.keys(paths).length === 0) {
|
|
79
|
+
return void 0;
|
|
80
|
+
}
|
|
81
|
+
const tsconfigDir = resolve(found.path, "..");
|
|
82
|
+
const root = compilerOptions.baseUrl ? resolve(tsconfigDir, compilerOptions.baseUrl) : tsconfigDir;
|
|
83
|
+
for (const [pattern, targets] of Object.entries(paths)) {
|
|
84
|
+
const prefix = pattern.replace(/\*$/, "");
|
|
85
|
+
if (!specifier.startsWith(prefix)) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const rest = specifier.slice(prefix.length);
|
|
89
|
+
for (const target of targets) {
|
|
90
|
+
const resolvedTarget = target.replace(/\*$/, "");
|
|
91
|
+
const base = resolve(root, resolvedTarget, rest);
|
|
92
|
+
const candidates = [base, ...ALIAS_EXTS.map((ext) => `${base}${ext}`)];
|
|
93
|
+
for (const candidate of candidates) {
|
|
94
|
+
if (await isFile(candidate)) {
|
|
95
|
+
return candidate.replace(/\\/g, "/");
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return void 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export {
|
|
104
|
+
ensureAstroPassthroughImageService,
|
|
105
|
+
resolveAliasedIsland
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=chunk-NOQVUQ7R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/astroImageService.ts","../src/lib/resolve-aliased-island.ts"],"sourcesContent":["export function ensureAstroPassthroughImageService() {\n if (!globalThis.astroAsset) {\n (globalThis as Record<string, unknown>).astroAsset = {};\n }\n\n (globalThis.astroAsset as Record<string, unknown>).imageService = {\n propertiesToHash: ['src'],\n validateOptions(options: Record<string, unknown>) {\n return options;\n },\n getURL(options: { src: unknown }) {\n const src = options.src;\n\n if (\n src != null &&\n typeof src === 'object' &&\n 'src' in src &&\n typeof (src as Record<string, unknown>).src === 'string'\n ) {\n return (src as Record<string, unknown>).src as string;\n }\n\n return typeof src === 'string' ? src : '';\n },\n getHTMLAttributes(options: Record<string, unknown>) {\n const {\n src,\n width,\n height,\n format,\n quality,\n densities,\n widths,\n formats,\n layout,\n priority,\n fit,\n position,\n background,\n ...attrs\n } = options;\n const srcObject =\n src != null && typeof src === 'object' ? (src as Record<string, unknown>) : null;\n\n return {\n ...attrs,\n width: width ?? srcObject?.width,\n height: height ?? srcObject?.height,\n loading: (attrs.loading as string | undefined) ?? 'lazy',\n decoding: (attrs.decoding as string | undefined) ?? 'async'\n };\n },\n getSrcSet() {\n return [];\n }\n };\n}\n","import { access } from 'node:fs/promises';\nimport { resolve } from 'node:path';\nimport { getTsconfig } from 'get-tsconfig';\n\n// Islands embedded in `.astro` components are frequently imported through a\n// tsconfig path alias (e.g. `@/components/Counter`). The raw aliased specifier\n// is baked into `<astro-island component-url>` and `import()`d verbatim, so it\n// must be turned into an on-disk path before it can hydrate. This helper is\n// used as a last resort after the existing resolution has already had its\n// chance.\n\nconst ALIAS_EXTS = ['.tsx', '.ts', '.jsx', '.js', '.vue', '.svelte', '.mts', '.mjs'];\n\nasync function isFile(candidate: string): Promise<boolean> {\n try {\n await access(candidate);\n\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Resolves a tsconfig-aliased island specifier (e.g. `@/components/Counter`)\n * to an absolute on-disk file path, or `undefined` when it is not a tsconfig\n * alias or no matching file exists. Already-resolvable specifiers are skipped\n * so this runs only as a genuine last resort.\n */\nexport async function resolveAliasedIsland(\n specifier: string,\n resolveFrom: string\n): Promise<string | undefined> {\n // Skip specifiers the existing resolution can already handle.\n if (\n !specifier ||\n specifier.startsWith('./') ||\n specifier.startsWith('../') ||\n specifier.startsWith('/') ||\n specifier.startsWith('\\0') ||\n specifier.startsWith('virtual:') ||\n specifier.startsWith('astro:') ||\n specifier.startsWith('@astrojs/') ||\n specifier.startsWith('@id/') ||\n specifier.startsWith('/@fs/')\n ) {\n return undefined;\n }\n\n // getTsconfig walks up from `resolveFrom` to the nearest tsconfig and merges\n // `extends` for us. We keep our own (deliberately lenient) path matching\n // below rather than its strict `createPathsMatcher`, which rejects the\n // non-relative-without-baseUrl paths that the Astro/Vite resolver accepts.\n let found;\n\n try {\n found = getTsconfig(resolveFrom);\n } catch {\n // Malformed tsconfig (bad JSON, circular extends). This is a last-resort\n // resolver, so swallow it rather than crash hydration.\n return undefined;\n }\n\n if (!found) {\n return undefined;\n }\n\n const compilerOptions = found.config.compilerOptions ?? {};\n const paths: Record<string, string[]> = compilerOptions.paths ?? {};\n\n if (Object.keys(paths).length === 0) {\n return undefined;\n }\n\n // tsconfig paths resolve relative to baseUrl when present, otherwise the\n // tsconfig directory (which get-tsconfig reports as `found.path`).\n const tsconfigDir = resolve(found.path, '..');\n const root = compilerOptions.baseUrl\n ? resolve(tsconfigDir, compilerOptions.baseUrl)\n : tsconfigDir;\n\n for (const [pattern, targets] of Object.entries(paths)) {\n const prefix = pattern.replace(/\\*$/, '');\n\n if (!specifier.startsWith(prefix)) {\n continue;\n }\n\n const rest = specifier.slice(prefix.length);\n\n for (const target of targets) {\n const resolvedTarget = target.replace(/\\*$/, '');\n const base = resolve(root, resolvedTarget, rest);\n const candidates = [base, ...ALIAS_EXTS.map((ext) => `${base}${ext}`)];\n\n for (const candidate of candidates) {\n if (await isFile(candidate)) {\n return candidate.replace(/\\\\/g, '/');\n }\n }\n }\n }\n\n return undefined;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/vitePluginAstroComponentMarker.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { dirname, resolve } from 'node:path';\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 client-side stub pattern. Astro 6's Go compiler and\n // Astro 7's Rust compiler (now the default) both emit this same error\n // string in the browser stub, so the single check covers Astro 5–7. If a\n // future compiler changes this text, components will silently miss the\n // `isAstroComponentFactory = true` marker and render blank — update the\n // string here if that happens.\n if (!code.includes('Astro components cannot be used in the browser')) {return null;}\n\n const moduleId = id;\n\n // In Storybook's Vite 6 setup with separate client/SSR environments, Astro's\n // CSS cache isn't populated for client-side transforms. CSS sub-module imports\n // fail with \"No Astro CSS at index N\", so we inline the CSS directly.\n // However, we still import child .astro components to bring them into the module\n // graph so the plugin processes them (fix for issue #114).\n const styleCode = isBuild\n ? generateInlineStyles(moduleId)\n : generateHybridStyles(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 * Hybrid approach for dev mode: inline CSS for the current component (to avoid\n * Astro's cache issues) but import child .astro components (to bring them into\n * the module graph for processing). This preserves the fix for issue #114 while\n * avoiding \"No Astro CSS at index N\" errors.\n *\n * Two caveats follow from inlining raw <style> source instead of routing it\n * through Astro's compiler:\n * - Styles are injected globally, not scoped to the component. Plain class\n * selectors still match the SSR-rendered HTML, but there is no scope isolation\n * between components in dev.\n * - `:global(...)` wrappers are unwrapped (the browser can't parse them), and\n * preprocessed blocks (`<style lang=\"scss\">` etc.) are skipped with a warning\n * since the preprocessor isn't reachable here.\n */\nfunction generateHybridStyles(filePath: string): string {\n try {\n const source = readFileSync(filePath, 'utf-8');\n\n // Inline this component's own CSS (no recursion into children).\n const inlinedCss = extractStyleBlocksWithLang(source).map((block, i) => {\n if (block.lang && block.lang !== 'css') {\n return warnUnsupportedStyleLang(filePath, block.lang);\n }\n\n return styleInjectionSnippet(\n 'data-astro-dev',\n `${filePath}:${i}`,\n unwrapGlobalSelectors(block.css)\n );\n }).join('\\n');\n\n // Import child .astro components so they enter the module graph\n const childImports = extractAstroImportSpecifiers(source).map(\n (specifier) => `import ${JSON.stringify(specifier)};`\n );\n\n return [inlinedCss, ...childImports].filter(Boolean).join('\\n');\n } catch {\n return '';\n }\n}\n\n/**\n * Astro's `:global(...)` wrapper marks a selector as un-scoped. Dev-mode styles\n * are already injected globally, so the wrapper carries no meaning here — and the\n * browser treats `:global()` as an invalid pseudo-class and drops the whole rule.\n * Unwrap it to its inner selector so the rule applies.\n */\nfunction unwrapGlobalSelectors(css: string): string {\n return css.replace(/:global\\(\\s*([^)]*?)\\s*\\)/g, '$1');\n}\n\n/**\n * Builds a snippet that warns about a preprocessed <style> block we can't inline.\n * Astro's compiler (which would turn scss/less/etc. into CSS) isn't reachable\n * from this client-side transform, and shipping the raw source would break the\n * browser's CSS parser, so we surface a clear console warning instead.\n */\nfunction warnUnsupportedStyleLang(filePath: string, lang: string): string {\n const message =\n `[storybook-astro] Skipping <style lang=\"${lang}\"> in ${filePath}: ` +\n `preprocessed styles are not supported in Storybook dev mode.`;\n\n return `\n(function() {\n if (typeof console !== 'undefined') { console.warn(${JSON.stringify(message)}); }\n})();`;\n}\n\n/**\n * Builds a self-executing snippet that injects a CSS string into <head> as a\n * <style> tag, tagged with a marker attribute. The marker also dedupes\n * re-injection (e.g. when a module re-evaluates after HMR) so styles don't\n * accumulate in the document.\n */\nfunction styleInjectionSnippet(markerAttr: string, markerValue: string, css: string): string {\n const attr = JSON.stringify(markerAttr);\n const value = JSON.stringify(markerValue);\n\n return `\n(function() {\n if (typeof document === 'undefined') { return; }\n const tagged = document.head.querySelectorAll('style[' + ${attr} + ']');\n for (const node of tagged) {\n if (node.getAttribute(${attr}) === ${value}) { return; }\n }\n const style = document.createElement('style');\n style.setAttribute(${attr}, ${value});\n style.textContent = ${JSON.stringify(css)};\n document.head.appendChild(style);\n})();`;\n}\n\n/**\n * Extracts import specifiers ending in `.astro` from a component's frontmatter.\n * Comments are stripped first so commented-out imports don't resurface as\n * broken module requests in the browser.\n */\nexport function extractAstroImportSpecifiers(source: string): string[] {\n const frontmatterMatch = source.match(/^---([\\s\\S]*?)---/m);\n\n if (!frontmatterMatch) {return [];}\n\n const frontmatter = frontmatterMatch[1]\n .replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n .replace(/\\/\\/[^\\n]*/g, '');\n\n // Matches static imports (`import Child from './Child.astro'`), side-effect\n // imports (`import './Child.astro'`), and dynamic imports (`import('./Child.astro')`).\n const importPattern = /(?:from|import)\\s*\\(?\\s*['\"]([^'\"]+\\.astro)['\"]/g;\n const specifiers = new Set<string>();\n let match;\n\n while ((match = importPattern.exec(frontmatter)) !== null) {\n specifiers.add(match[1]);\n }\n\n return [...specifiers];\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, recursing into child\n * .astro components imported via relative paths. Used during builds where\n * Astro's compile metadata cache is unavailable.\n *\n * The CSS is unscoped (no Astro scoping transforms), so `:global(...)` wrappers\n * are unwrapped here too — without that the browser drops the whole rule (e.g.\n * PageCard's `.page-card__image-wrapper :global(img)` sizing).\n */\nfunction generateInlineStyles(filePath: string): string {\n const cssBlocks = collectStyleBlocks(filePath, new Set());\n\n if (cssBlocks.length === 0) {return '';}\n\n // Create a side-effect that injects styles into the document\n return cssBlocks\n .map(({ file, css }, i) =>\n styleInjectionSnippet('data-astro-build', `${file}:${i}`, unwrapGlobalSelectors(css))\n )\n .join('\\n');\n}\n\n/**\n * Collects <style> block contents from a component and its child .astro imports.\n * Only relative specifiers are followed (aliases and packages can't be resolved\n * from disk here). The visited set guards against import cycles.\n */\nfunction collectStyleBlocks(\n filePath: string,\n visited: Set<string>\n): Array<{ file: string; css: string }> {\n if (visited.has(filePath)) {return [];}\n visited.add(filePath);\n\n let source: string;\n\n try {\n source = readFileSync(filePath, 'utf-8');\n } catch {\n return [];\n }\n\n const blocks = extractStyleBlocks(source).map((css) => ({ file: filePath, css }));\n\n for (const specifier of extractAstroImportSpecifiers(source)) {\n if (!specifier.startsWith('.')) {continue;}\n\n blocks.push(...collectStyleBlocks(resolve(dirname(filePath), specifier), visited));\n }\n\n return blocks;\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 return extractStyleBlocksWithLang(source).map((block) => block.css);\n}\n\n/**\n * Like {@link extractStyleBlocks}, but also reports each block's `lang` attribute\n * (e.g. \"scss\") so callers can tell preprocessed styles apart from plain CSS.\n * Returns `null` for the lang when no attribute is present.\n */\nfunction extractStyleBlocksWithLang(source: string): Array<{ css: string; lang: string | null }> {\n const withoutFrontmatter = source.replace(/^---[\\s\\S]*?---/m, '');\n const blocks: Array<{ css: string; lang: string | null }> = [];\n const regex = /<style((?:\\s[^>]*)?)>([\\s\\S]*?)<\\/style>/g;\n let match;\n\n while ((match = regex.exec(withoutFrontmatter)) !== null) {\n const langMatch = match[1].match(/\\blang\\s*=\\s*['\"]?([\\w-]+)/);\n\n blocks.push({ css: match[2].trim(), lang: langMatch ? langMatch[1] : null });\n }\n\n return blocks;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/lib/separate-story-slots.ts
|
|
2
|
+
function separateStorySlots(storyArgs) {
|
|
3
|
+
const componentArgs = { ...storyArgs };
|
|
4
|
+
const storySlots = componentArgs.slots;
|
|
5
|
+
delete componentArgs.slots;
|
|
6
|
+
if (typeof storySlots !== "object" || storySlots === null) {
|
|
7
|
+
return { componentArgs, storySlots: {} };
|
|
8
|
+
}
|
|
9
|
+
return { componentArgs, storySlots };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
separateStorySlots
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-YRG32BBU.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/separate-story-slots.ts"],"sourcesContent":["/**\n * Splits a story's `args` into component props and slot content. Slot content\n * lives under the reserved `slots` key (`args.slots.<name>`); everything else is\n * a prop. Returns `{}` for slots when `args.slots` is absent or not an object.\n */\nexport function separateStorySlots(storyArgs: Record<string, unknown>): {\n componentArgs: Record<string, unknown>;\n storySlots: Record<string, unknown>;\n} {\n const componentArgs = { ...storyArgs };\n const storySlots = componentArgs.slots;\n\n delete componentArgs.slots;\n\n if (typeof storySlots !== 'object' || storySlots === null) {\n return { componentArgs, storySlots: {} };\n }\n\n return { componentArgs, storySlots: storySlots as Record<string, unknown> };\n}\n"],"mappings":";AAKO,SAAS,mBAAmB,WAGjC;AACA,QAAM,gBAAgB,EAAE,GAAG,UAAU;AACrC,QAAM,aAAa,cAAc;AAEjC,SAAO,cAAc;AAErB,MAAI,OAAO,eAAe,YAAY,eAAe,MAAM;AACzD,WAAO,EAAE,eAAe,YAAY,CAAC,EAAE;AAAA,EACzC;AAEA,SAAO,EAAE,eAAe,WAAkD;AAC5E;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -31,7 +31,9 @@ var composedRenderToCanvas = async (context, canvasElement) => {
|
|
|
31
31
|
return impl.renderToCanvas(context, canvasElement);
|
|
32
32
|
};
|
|
33
33
|
function definePreview(input) {
|
|
34
|
-
|
|
34
|
+
if (typeof document !== "undefined") {
|
|
35
|
+
void loadRendererEntryPreview();
|
|
36
|
+
}
|
|
35
37
|
return definePreviewBase({
|
|
36
38
|
...input,
|
|
37
39
|
// CSF-factory stories compose only this `definePreview` chain — they never
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export types from storybook internal\nexport type {\n Args,\n ArgTypes,\n Parameters,\n ProjectAnnotations,\n StrictArgs\n} from 'storybook/internal/types';\n\nimport { definePreview as definePreviewBase, type PreviewAddon, type InferTypes, type Preview as CsfPreview } from 'storybook/internal/csf';\nimport { combineParameters } from 'storybook/internal/preview-api';\nimport type { ArgsStoryFn, ProjectAnnotations, RenderContext, Renderer } from 'storybook/internal/types';\nimport { defaultPreviewParameters } from '@storybook-astro/renderer/preview-defaults';\nimport type { AstroRenderer } from './portable-stories.ts';\n\n// CSF4 consumers reach `definePreview` from the preview iframe; Node test setup\n// files (e.g. `vitest.setup.ts`) only import the type helpers and\n// `setProjectAnnotations`. Loading `@storybook-astro/renderer/entry-preview` at\n// module scope here would pull `render.tsx`'s virtual-module chain — including\n// the configured framework integrations like Alpine.js — into the Node test\n// process, which has no `MutationObserver` etc. The dynamic import below keeps\n// that load inside `definePreview` so test setups don't pay for it.\n// Types come from src/renderer-entry-preview.d.ts; entry-preview.ts itself\n// isn't dts-built because it imports Vite virtual modules.\nimport type * as RendererEntryPreviewModule from '@storybook-astro/renderer/entry-preview';\n\ntype RendererEntryPreview = typeof RendererEntryPreviewModule;\nlet rendererImpl: RendererEntryPreview | undefined;\nlet rendererLoadPromise: Promise<RendererEntryPreview> | undefined;\n\nfunction loadRendererEntryPreview(): Promise<RendererEntryPreview> {\n rendererLoadPromise ??= import('@storybook-astro/renderer/entry-preview').then((mod) => {\n rendererImpl = mod;\n\n return mod;\n });\n\n return rendererLoadPromise;\n}\n\nconst composedRender: ArgsStoryFn<AstroRenderer> = (args, context) => {\n if (!rendererImpl) {\n throw new Error(\n '@storybook-astro: renderer not ready when `render` was called. ' +\n 'This should be reached only after `definePreview()` has kicked off the renderer load. ' +\n 'If you see this in tests, import the renderer module yourself or render via portable stories.'\n );\n }\n\n return rendererImpl.render(args, context);\n};\n\nconst composedRenderToCanvas = async (\n context: RenderContext<Renderer>,\n canvasElement: HTMLElement\n): Promise<void> => {\n const impl = await loadRendererEntryPreview();\n\n return impl.renderToCanvas(context, canvasElement);\n};\n\n/**\n * Preview configuration type for `.storybook/preview.ts` in Astro projects.\n * Reflects the full type returned by `definePreview`, including addon type extensions.\n * Use this to annotate your preview module when needed:\n *\n * ```ts\n * import type { Preview } from '@storybook-astro/framework';\n * const preview: Preview = { ... };\n * export default preview;\n * ```\n */\nexport type Preview<Addons extends PreviewAddon<never>[] = []> = CsfPreview<AstroRenderer & InferTypes<Addons>>;\n\n// Export portable stories functionality\nexport {\n composeStories,\n composeStory,\n setProjectAnnotations,\n type AstroRenderer\n} from './portable-stories.ts';\n\n// Export framework types\nexport type {\n FrameworkOptions,\n RenderMode,\n RenderStoryInput,\n ServerBuildOptions,\n SanitizationOptions,\n StoryRulesOptions,\n StorybookConfig\n} from './types.ts';\n\n// Preview configuration helper\nexport function definePreview<Addons extends PreviewAddon<never>[] = []>(\n input: ProjectAnnotations<AstroRenderer> & { addons?: Addons }\n): CsfPreview<AstroRenderer & InferTypes<Addons>> {\n // Kick off the renderer load eagerly so the impl is ready by the time\n // Storybook calls renderToCanvas — but don't await, so this stays sync.\n void loadRendererEntryPreview();\n\n return definePreviewBase<AstroRenderer, Addons>({\n ...input,\n // CSF-factory stories compose only this `definePreview` chain — they never\n // see the renderer's entry-preview annotation that carries our default\n // parameters (e.g. the Docs story height). Merge those defaults here, under\n // the user's parameters so their overrides still win.\n parameters: combineParameters(defaultPreviewParameters, {\n renderer: 'astro' as const,\n ...input.parameters\n }),\n render: input.render ?? composedRender,\n renderToCanvas: input.renderToCanvas ?? composedRenderToCanvas\n });\n}\n"],"mappings":";;;;;;;;AASA,SAAS,iBAAiB,yBAAyF;AACnH,SAAS,yBAAyB;AAElC,SAAS,gCAAgC;AAezC,IAAI;AACJ,IAAI;AAEJ,SAAS,2BAA0D;AACjE,0BAAwB,OAAO,yCAAyC,EAAE,KAAK,CAAC,QAAQ;AACtF,mBAAe;AAEf,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAEA,IAAM,iBAA6C,CAAC,MAAM,YAAY;AACpE,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAEA,SAAO,aAAa,OAAO,MAAM,OAAO;AAC1C;AAEA,IAAM,yBAAyB,OAC7B,SACA,kBACkB;AAClB,QAAM,OAAO,MAAM,yBAAyB;AAE5C,SAAO,KAAK,eAAe,SAAS,aAAa;AACnD;AAmCO,SAAS,cACd,OACgD;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export types from storybook internal\nexport type {\n Args,\n ArgTypes,\n Parameters,\n ProjectAnnotations,\n StrictArgs\n} from 'storybook/internal/types';\n\nimport { definePreview as definePreviewBase, type PreviewAddon, type InferTypes, type Preview as CsfPreview } from 'storybook/internal/csf';\nimport { combineParameters } from 'storybook/internal/preview-api';\nimport type { ArgsStoryFn, ProjectAnnotations, RenderContext, Renderer } from 'storybook/internal/types';\nimport { defaultPreviewParameters } from '@storybook-astro/renderer/preview-defaults';\nimport type { AstroRenderer } from './portable-stories.ts';\n\n// CSF4 consumers reach `definePreview` from the preview iframe; Node test setup\n// files (e.g. `vitest.setup.ts`) only import the type helpers and\n// `setProjectAnnotations`. Loading `@storybook-astro/renderer/entry-preview` at\n// module scope here would pull `render.tsx`'s virtual-module chain — including\n// the configured framework integrations like Alpine.js — into the Node test\n// process, which has no `MutationObserver` etc. The dynamic import below keeps\n// that load inside `definePreview` so test setups don't pay for it.\n// Types come from src/renderer-entry-preview.d.ts; entry-preview.ts itself\n// isn't dts-built because it imports Vite virtual modules.\nimport type * as RendererEntryPreviewModule from '@storybook-astro/renderer/entry-preview';\n\ntype RendererEntryPreview = typeof RendererEntryPreviewModule;\nlet rendererImpl: RendererEntryPreview | undefined;\nlet rendererLoadPromise: Promise<RendererEntryPreview> | undefined;\n\nfunction loadRendererEntryPreview(): Promise<RendererEntryPreview> {\n rendererLoadPromise ??= import('@storybook-astro/renderer/entry-preview').then((mod) => {\n rendererImpl = mod;\n\n return mod;\n });\n\n return rendererLoadPromise;\n}\n\nconst composedRender: ArgsStoryFn<AstroRenderer> = (args, context) => {\n if (!rendererImpl) {\n throw new Error(\n '@storybook-astro: renderer not ready when `render` was called. ' +\n 'This should be reached only after `definePreview()` has kicked off the renderer load. ' +\n 'If you see this in tests, import the renderer module yourself or render via portable stories.'\n );\n }\n\n return rendererImpl.render(args, context);\n};\n\nconst composedRenderToCanvas = async (\n context: RenderContext<Renderer>,\n canvasElement: HTMLElement\n): Promise<void> => {\n const impl = await loadRendererEntryPreview();\n\n return impl.renderToCanvas(context, canvasElement);\n};\n\n/**\n * Preview configuration type for `.storybook/preview.ts` in Astro projects.\n * Reflects the full type returned by `definePreview`, including addon type extensions.\n * Use this to annotate your preview module when needed:\n *\n * ```ts\n * import type { Preview } from '@storybook-astro/framework';\n * const preview: Preview = { ... };\n * export default preview;\n * ```\n */\nexport type Preview<Addons extends PreviewAddon<never>[] = []> = CsfPreview<AstroRenderer & InferTypes<Addons>>;\n\n// Export portable stories functionality\nexport {\n composeStories,\n composeStory,\n setProjectAnnotations,\n type AstroRenderer\n} from './portable-stories.ts';\n\n// Export framework types\nexport type {\n FrameworkOptions,\n RenderMode,\n RenderStoryInput,\n ServerBuildOptions,\n SanitizationOptions,\n StoryRulesOptions,\n StorybookConfig\n} from './types.ts';\n\n// Preview configuration helper\nexport function definePreview<Addons extends PreviewAddon<never>[] = []>(\n input: ProjectAnnotations<AstroRenderer> & { addons?: Addons }\n): CsfPreview<AstroRenderer & InferTypes<Addons>> {\n // Kick off the renderer load eagerly so the impl is ready by the time\n // Storybook calls renderToCanvas — but don't await, so this stays sync.\n // Only do this in a browser: the renderer's entry-preview imports browser-only\n // modules (and the `virtual:storybook-astro-renderer` graph) that aren't\n // available when `.storybook/preview.ts` is evaluated under Node during build\n // prerendering. renderToCanvas never runs there, and the browser path still\n // loads the renderer lazily via `composedRenderToCanvas`.\n if (typeof document !== 'undefined') {\n void loadRendererEntryPreview();\n }\n\n return definePreviewBase<AstroRenderer, Addons>({\n ...input,\n // CSF-factory stories compose only this `definePreview` chain — they never\n // see the renderer's entry-preview annotation that carries our default\n // parameters (e.g. the Docs story height). Merge those defaults here, under\n // the user's parameters so their overrides still win.\n parameters: combineParameters(defaultPreviewParameters, {\n renderer: 'astro' as const,\n ...input.parameters\n }),\n render: input.render ?? composedRender,\n renderToCanvas: input.renderToCanvas ?? composedRenderToCanvas\n });\n}\n"],"mappings":";;;;;;;;AASA,SAAS,iBAAiB,yBAAyF;AACnH,SAAS,yBAAyB;AAElC,SAAS,gCAAgC;AAezC,IAAI;AACJ,IAAI;AAEJ,SAAS,2BAA0D;AACjE,0BAAwB,OAAO,yCAAyC,EAAE,KAAK,CAAC,QAAQ;AACtF,mBAAe;AAEf,WAAO;AAAA,EACT,CAAC;AAED,SAAO;AACT;AAEA,IAAM,iBAA6C,CAAC,MAAM,YAAY;AACpE,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AAEA,SAAO,aAAa,OAAO,MAAM,OAAO;AAC1C;AAEA,IAAM,yBAAyB,OAC7B,SACA,kBACkB;AAClB,QAAM,OAAO,MAAM,yBAAyB;AAE5C,SAAO,KAAK,eAAe,SAAS,aAAa;AACnD;AAmCO,SAAS,cACd,OACgD;AAQhD,MAAI,OAAO,aAAa,aAAa;AACnC,SAAK,yBAAyB;AAAA,EAChC;AAEA,SAAO,kBAAyC;AAAA,IAC9C,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA,IAKH,YAAY,kBAAkB,0BAA0B;AAAA,MACtD,UAAU;AAAA,MACV,GAAG,MAAM;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,UAAU;AAAA,IACxB,gBAAgB,MAAM,kBAAkB;AAAA,EAC1C,CAAC;AACH;","names":[]}
|
package/dist/middleware.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
createAstroRenderHandler,
|
|
3
2
|
ensureAstroPassthroughImageService,
|
|
4
3
|
resolveAliasedIsland
|
|
5
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NOQVUQ7R.js";
|
|
5
|
+
import {
|
|
6
|
+
createAstroRenderHandler
|
|
7
|
+
} from "./chunk-5POAXNWB.js";
|
|
6
8
|
import "./chunk-ZIDMHD4S.js";
|
|
7
9
|
import {
|
|
8
10
|
resolveStoryModuleMock
|
package/dist/middleware.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["/// <reference path=\"./virtual.d.ts\" />\n\nimport { pathToFileURL } from 'node:url';\nimport { experimental_AstroContainer as AstroContainer } from 'astro/container';\nimport { ensureAstroPassthroughImageService } from './astroImageService.ts';\nimport { createAstroRenderHandler, type HandlerProps } from './astroRenderHandler.ts';\nimport type { Integration } from './integrations/index.ts';\nimport type { SanitizationOptions } from './lib/sanitization.ts';\nimport { resolveAliasedIsland } from './lib/resolve-aliased-island.ts';\nimport { resolveStoryModuleMock } from './module-mocks.ts';\nimport { addRenderers, resolveClientModules } from 'virtual:astro-container-renderers';\n\ntype ResolveRulesConfigModule = () => unknown | Promise<unknown>;\n\ntype HandlerFactoryOptions = {\n sanitization?: SanitizationOptions;\n rulesConfigFilePath?: string;\n resolveRulesConfigModule?: ResolveRulesConfigModule;\n loadModule?: (id: string) => Promise<{ default: unknown }>;\n invalidateModuleGraph?: () => void;\n resolveModule?: (specifier: string) => string | undefined;\n resolveFrom?: string;\n};\n\nexport type { HandlerProps };\n\nexport async function handlerFactory(\n _integrations: Integration[],\n options?: HandlerFactoryOptions\n) {\n ensureAstroPassthroughImageService();\n\n const container = await AstroContainer.create({\n resolve: async (specifier) => {\n const mockedModule = resolveStoryModuleMock(specifier);\n\n if (mockedModule) {\n return mockedModule;\n }\n\n const customResolution = options?.resolveModule?.(specifier);\n\n if (customResolution) {\n return customResolution;\n }\n\n if (specifier.startsWith('astro:scripts')) {\n return `/@id/${specifier}`;\n }\n\n const resolution = resolveClientModules(specifier);\n\n if (resolution) {\n return resolution;\n }\n\n // Last resort: an island imported via a tsconfig path alias (e.g. `@/...`)\n // has its raw aliased specifier baked into the island's component-url.\n // Resolve it to an on-disk file and hand back a `/@fs/` URL the dev Vite\n // server can serve so the island still hydrates.\n const aliasedIsland = await resolveAliasedIsland(\n specifier,\n options?.resolveFrom ?? process.cwd()\n );\n\n if (aliasedIsland) {\n return `/@fs/${aliasedIsland}`;\n }\n\n return specifier;\n }\n });\n\n addRenderers(container);\n\n const loadModule =\n options?.loadModule ??\n ((id: string) => {\n const normalizedId = /^[a-zA-Z]:[/\\\\]/.test(id) ? pathToFileURL(id).href : id;\n\n return import(/* @vite-ignore */ normalizedId);\n });\n\n return createAstroRenderHandler({\n container,\n sanitization: options?.sanitization,\n rulesConfigFilePath: options?.rulesConfigFilePath,\n resolveRulesConfigModule: options?.resolveRulesConfigModule,\n loadModule,\n invalidateModuleGraph: options?.invalidateModuleGraph\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["/// <reference path=\"./virtual.d.ts\" />\n\nimport { pathToFileURL } from 'node:url';\nimport { experimental_AstroContainer as AstroContainer } from 'astro/container';\nimport { ensureAstroPassthroughImageService } from './astroImageService.ts';\nimport { createAstroRenderHandler, type HandlerProps } from './astroRenderHandler.ts';\nimport type { Integration } from './integrations/index.ts';\nimport type { SanitizationOptions } from './lib/sanitization.ts';\nimport { resolveAliasedIsland } from './lib/resolve-aliased-island.ts';\nimport { resolveStoryModuleMock } from './module-mocks.ts';\nimport { addRenderers, resolveClientModules } from 'virtual:astro-container-renderers';\n\ntype ResolveRulesConfigModule = () => unknown | Promise<unknown>;\n\ntype HandlerFactoryOptions = {\n sanitization?: SanitizationOptions;\n rulesConfigFilePath?: string;\n resolveRulesConfigModule?: ResolveRulesConfigModule;\n loadModule?: (id: string) => Promise<{ default: unknown }>;\n invalidateModuleGraph?: () => void;\n resolveModule?: (specifier: string) => string | undefined;\n resolveFrom?: string;\n};\n\nexport type { HandlerProps };\n\nexport async function handlerFactory(\n _integrations: Integration[],\n options?: HandlerFactoryOptions\n) {\n ensureAstroPassthroughImageService();\n\n const container = await AstroContainer.create({\n resolve: async (specifier) => {\n const mockedModule = resolveStoryModuleMock(specifier);\n\n if (mockedModule) {\n return mockedModule;\n }\n\n const customResolution = options?.resolveModule?.(specifier);\n\n if (customResolution) {\n return customResolution;\n }\n\n if (specifier.startsWith('astro:scripts')) {\n return `/@id/${specifier}`;\n }\n\n const resolution = resolveClientModules(specifier);\n\n if (resolution) {\n return resolution;\n }\n\n // Last resort: an island imported via a tsconfig path alias (e.g. `@/...`)\n // has its raw aliased specifier baked into the island's component-url.\n // Resolve it to an on-disk file and hand back a `/@fs/` URL the dev Vite\n // server can serve so the island still hydrates.\n const aliasedIsland = await resolveAliasedIsland(\n specifier,\n options?.resolveFrom ?? process.cwd()\n );\n\n if (aliasedIsland) {\n return `/@fs/${aliasedIsland}`;\n }\n\n return specifier;\n }\n });\n\n addRenderers(container);\n\n const loadModule =\n options?.loadModule ??\n ((id: string) => {\n const normalizedId = /^[a-zA-Z]:[/\\\\]/.test(id) ? pathToFileURL(id).href : id;\n\n return import(/* @vite-ignore */ normalizedId);\n });\n\n return createAstroRenderHandler({\n container,\n sanitization: options?.sanitization,\n rulesConfigFilePath: options?.rulesConfigFilePath,\n resolveRulesConfigModule: options?.resolveRulesConfigModule,\n loadModule,\n invalidateModuleGraph: options?.invalidateModuleGraph\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AAEA,SAAS,qBAAqB;AAC9B,SAAS,+BAA+B,sBAAsB;AAO9D,SAAS,cAAc,4BAA4B;AAgBnD,eAAsB,eACpB,eACA,SACA;AACA,qCAAmC;AAEnC,QAAM,YAAY,MAAM,eAAe,OAAO;AAAA,IAC5C,SAAS,OAAO,cAAc;AAC5B,YAAM,eAAe,uBAAuB,SAAS;AAErD,UAAI,cAAc;AAChB,eAAO;AAAA,MACT;AAEA,YAAM,mBAAmB,SAAS,gBAAgB,SAAS;AAE3D,UAAI,kBAAkB;AACpB,eAAO;AAAA,MACT;AAEA,UAAI,UAAU,WAAW,eAAe,GAAG;AACzC,eAAO,QAAQ,SAAS;AAAA,MAC1B;AAEA,YAAM,aAAa,qBAAqB,SAAS;AAEjD,UAAI,YAAY;AACd,eAAO;AAAA,MACT;AAMA,YAAM,gBAAgB,MAAM;AAAA,QAC1B;AAAA,QACA,SAAS,eAAe,QAAQ,IAAI;AAAA,MACtC;AAEA,UAAI,eAAe;AACjB,eAAO,QAAQ,aAAa;AAAA,MAC9B;AAEA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,eAAa,SAAS;AAEtB,QAAM,aACJ,SAAS,eACR,CAAC,OAAe;AACf,UAAM,eAAe,kBAAkB,KAAK,EAAE,IAAI,cAAc,EAAE,EAAE,OAAO;AAE3E,WAAO;AAAA;AAAA,MAA0B;AAAA;AAAA,EACnC;AAEF,SAAO,yBAAyB;AAAA,IAC9B;AAAA,IACA,cAAc,SAAS;AAAA,IACvB,qBAAqB,SAAS;AAAA,IAC9B,0BAA0B,SAAS;AAAA,IACnC;AAAA,IACA,uBAAuB,SAAS;AAAA,EAClC,CAAC;AACH;","names":[]}
|