@storybook-astro/framework 1.0.3 → 1.1.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-KSDXET2L.js → chunk-4HECE7IW.js} +477 -61
- package/dist/chunk-4HECE7IW.js.map +1 -0
- package/dist/{chunk-7GHEQUPV.js → chunk-POHTFYST.js} +46 -8
- package/dist/chunk-POHTFYST.js.map +1 -0
- package/dist/chunk-T7NWIO5S.js +220 -0
- package/dist/chunk-T7NWIO5S.js.map +1 -0
- package/dist/{chunk-C5OH4VBR.js → chunk-V76WSNSP.js} +124 -47
- package/dist/chunk-V76WSNSP.js.map +1 -0
- package/dist/index.d.ts +19 -9
- package/dist/index.js +10 -3
- package/dist/index.js.map +1 -1
- package/dist/middleware.js +57 -39
- package/dist/middleware.js.map +1 -1
- package/dist/node/index.d.ts +10 -0
- package/dist/node/index.js +10 -0
- package/dist/node/index.js.map +1 -0
- package/dist/preset.d.ts +1 -1
- package/dist/preset.js +3 -3
- package/dist/testing.js +12 -64
- package/dist/testing.js.map +1 -1
- package/dist/{types-CHTsRtA7.d.ts → types-Cvor6Tyi.d.ts} +21 -5
- package/dist/{viteStorybookAstroMiddlewarePlugin-NP2E52IC.js → viteStorybookAstroMiddlewarePlugin-2EFKTECT.js} +2 -2
- package/dist/vitest/global-setup.js +42 -0
- package/dist/vitest/global-setup.js.map +1 -0
- package/dist/vitest/index.js +20 -3
- package/dist/vitest/index.js.map +1 -1
- package/package.json +11 -3
- package/src/index.ts +21 -1
- package/src/lib/sanitization.ts +104 -0
- package/src/middleware.ts +76 -44
- package/src/node/index.ts +7 -0
- package/src/preset.ts +86 -16
- package/src/renderer/renderer-dev.ts +82 -0
- package/src/renderer/renderer-server.test.ts +101 -0
- package/src/renderer/renderer-server.ts +135 -0
- package/src/renderer/renderer-static.ts +62 -0
- package/src/rules.test.ts +89 -18
- package/src/rules.ts +67 -18
- package/src/server/index.ts +111 -0
- package/src/testing/renderer-daemon.ts +10 -1
- package/src/types.ts +25 -5
- package/src/virtual.d.ts +37 -0
- package/src/vite/astroFilesVirtualModulePlugin.ts +36 -0
- package/src/vite/createVirtualModulePlugin.ts +3 -3
- package/src/vite/storybookAstroRulesConfigVirtualModulePlugin.ts +37 -0
- package/src/vite/storybookAstroSanitizationConfigVirtualModulePlugin.ts +21 -0
- package/src/vite/storybookAstroServerAuthConfigVirtualModulePlugin.test.ts +71 -0
- package/src/vite/storybookAstroServerAuthConfigVirtualModulePlugin.ts +42 -0
- package/src/vitePluginAstroBuildPrerender.ts +50 -51
- package/src/vitePluginAstroBuildServer.ts +289 -0
- package/src/vitePluginAstroIntegrationOptsFallback.ts +25 -0
- package/src/vitePluginAstroToolbarFallback.ts +38 -0
- package/src/viteStorybookAstroMiddlewarePlugin.ts +40 -8
- package/src/viteStorybookAstroRendererPlugin.ts +45 -0
- package/src/vitest/config.ts +45 -4
- package/src/vitest/global-setup.ts +45 -0
- package/dist/chunk-7GHEQUPV.js.map +0 -1
- package/dist/chunk-C5OH4VBR.js.map +0 -1
- package/dist/chunk-KSDXET2L.js.map +0 -1
- package/dist/middleware.d.ts +0 -26
- package/src/msw-helpers.ts +0 -1
- package/src/msw.ts +0 -58
- /package/dist/{viteStorybookAstroMiddlewarePlugin-NP2E52IC.js.map → viteStorybookAstroMiddlewarePlugin-2EFKTECT.js.map} +0 -0
package/src/types.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompatibleString, Options } from 'storybook/internal/types';
|
|
1
|
+
import type { CompatibleString, Options, StorybookConfig as StorybookConfigBase } from 'storybook/internal/types';
|
|
2
2
|
import type { InlineConfig } from 'vite';
|
|
3
3
|
import type { Integration } from './integrations/index.ts';
|
|
4
4
|
import type { SanitizationOptions } from './lib/sanitization.ts';
|
|
@@ -7,6 +7,13 @@ import type { StoryRulesOptions } from './rules-options.ts';
|
|
|
7
7
|
type FrameworkName = CompatibleString<'@storybook-astro/framework'>;
|
|
8
8
|
|
|
9
9
|
export type { Integration, SanitizationOptions, StoryRulesOptions };
|
|
10
|
+
export type RenderMode = 'server' | 'static';
|
|
11
|
+
|
|
12
|
+
export type ServerBuildOptions = {
|
|
13
|
+
serverUrl?: string;
|
|
14
|
+
authToken?: string;
|
|
15
|
+
authHeader?: string;
|
|
16
|
+
};
|
|
10
17
|
|
|
11
18
|
export type RenderStoryInput = {
|
|
12
19
|
id: string;
|
|
@@ -14,13 +21,26 @@ export type RenderStoryInput = {
|
|
|
14
21
|
name?: string;
|
|
15
22
|
};
|
|
16
23
|
|
|
17
|
-
|
|
24
|
+
type BaseFrameworkOptions = {
|
|
18
25
|
integrations?: Integration[];
|
|
19
26
|
sanitization?: SanitizationOptions;
|
|
20
|
-
storyRules?: StoryRulesOptions;
|
|
21
27
|
resolveFrom?: string;
|
|
22
28
|
};
|
|
23
29
|
|
|
30
|
+
type ServerFrameworkOptions = BaseFrameworkOptions & {
|
|
31
|
+
renderMode?: 'server';
|
|
32
|
+
storyRules?: StoryRulesOptions;
|
|
33
|
+
server?: ServerBuildOptions;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
type StaticFrameworkOptions = BaseFrameworkOptions & {
|
|
37
|
+
renderMode: 'static';
|
|
38
|
+
storyRules?: StoryRulesOptions;
|
|
39
|
+
server?: never;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type FrameworkOptions = ServerFrameworkOptions | StaticFrameworkOptions;
|
|
43
|
+
|
|
24
44
|
type StorybookConfigFramework = {
|
|
25
45
|
framework: {
|
|
26
46
|
name: FrameworkName;
|
|
@@ -28,10 +48,10 @@ type StorybookConfigFramework = {
|
|
|
28
48
|
};
|
|
29
49
|
};
|
|
30
50
|
|
|
31
|
-
export type StorybookConfig = StorybookConfigFramework;
|
|
32
|
-
|
|
33
51
|
type ViteFinal = (config: InlineConfig, options: Options) => InlineConfig | Promise<InlineConfig>;
|
|
34
52
|
|
|
35
53
|
export type StorybookConfigVite = {
|
|
36
54
|
viteFinal?: ViteFinal;
|
|
37
55
|
};
|
|
56
|
+
|
|
57
|
+
export type StorybookConfig = Omit<StorybookConfigBase, 'framework'> & StorybookConfigFramework & StorybookConfigVite;
|
package/src/virtual.d.ts
CHANGED
|
@@ -5,4 +5,41 @@ declare module 'virtual:astro-container-renderers' {
|
|
|
5
5
|
export function resolveClientModules(specifier: string): string | undefined;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
declare module 'virtual:astro-files' {
|
|
9
|
+
const astroFiles: Record<string, unknown>;
|
|
10
|
+
|
|
11
|
+
export default astroFiles;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
declare module 'virtual:storybook-astro-renderer' {
|
|
15
|
+
import type { RenderComponentInput, RenderResponseMessage } from '@storybook-astro/renderer/types';
|
|
16
|
+
|
|
17
|
+
export function render(
|
|
18
|
+
input: RenderComponentInput,
|
|
19
|
+
timeoutMs?: number
|
|
20
|
+
): Promise<RenderResponseMessage['data']>;
|
|
21
|
+
export function init(): void;
|
|
22
|
+
export function applyStyles(): void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
declare module 'virtual:storybook-astro-sanitization-config' {
|
|
26
|
+
import type { SanitizationOptions } from './lib/sanitization.ts';
|
|
27
|
+
|
|
28
|
+
const sanitization: SanitizationOptions | undefined;
|
|
29
|
+
|
|
30
|
+
export default sanitization;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
declare module 'virtual:storybook-astro-story-rules-config' {
|
|
34
|
+
const configModule: unknown;
|
|
35
|
+
|
|
36
|
+
export default configModule;
|
|
37
|
+
export const storybookAstroStoryRulesConfigFilePath: string | undefined;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
declare module 'virtual:storybook-astro-server-auth-config' {
|
|
41
|
+
export const storybookAstroServerAuthToken: string | undefined;
|
|
42
|
+
export const storybookAstroServerAuthHeader: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
8
45
|
declare module 'virtual:storybook-renderer-fallback' {}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import { createVirtualModulePlugin } from './createVirtualModulePlugin.ts';
|
|
3
|
+
|
|
4
|
+
type ImportRecord = {
|
|
5
|
+
id: string;
|
|
6
|
+
file: string;
|
|
7
|
+
importStatement: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function astroFilesVirtualModulePlugin(astroComponents: string[]): Plugin {
|
|
11
|
+
return createVirtualModulePlugin({
|
|
12
|
+
pluginName: 'storybook-astro:virtual-astro-files',
|
|
13
|
+
virtualModuleId: 'virtual:astro-files',
|
|
14
|
+
load() {
|
|
15
|
+
const imports = astroComponents.reduce<ImportRecord[]>((records, file, index) => {
|
|
16
|
+
const moduleId = `_astroFile${index}`;
|
|
17
|
+
|
|
18
|
+
return [
|
|
19
|
+
...records,
|
|
20
|
+
{
|
|
21
|
+
id: moduleId,
|
|
22
|
+
file,
|
|
23
|
+
importStatement: `import ${moduleId} from '${file}';`
|
|
24
|
+
}
|
|
25
|
+
];
|
|
26
|
+
}, []);
|
|
27
|
+
|
|
28
|
+
return [
|
|
29
|
+
imports.map(({ importStatement }) => importStatement).join('\n'),
|
|
30
|
+
'export default {',
|
|
31
|
+
imports.map(({ file, id }) => `'${file}': ${id}`).join(',\n'),
|
|
32
|
+
'};'
|
|
33
|
+
].join('\n');
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
2
|
|
|
3
3
|
type CreateVirtualModulePluginOptions = {
|
|
4
4
|
pluginName: string;
|
|
@@ -6,7 +6,7 @@ type CreateVirtualModulePluginOptions = {
|
|
|
6
6
|
load: (id: string) => string | Promise<string> | undefined;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
export function createVirtualModulePlugin(options: CreateVirtualModulePluginOptions):
|
|
9
|
+
export function createVirtualModulePlugin(options: CreateVirtualModulePluginOptions): Plugin {
|
|
10
10
|
const resolvedVirtualModuleId = `\0${options.virtualModuleId}`;
|
|
11
11
|
|
|
12
12
|
return {
|
|
@@ -21,5 +21,5 @@ export function createVirtualModulePlugin(options: CreateVirtualModulePluginOpti
|
|
|
21
21
|
return options.load(id);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
-
} satisfies
|
|
24
|
+
} satisfies Plugin;
|
|
25
25
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import type { StoryRulesOptions } from '../rules-options.ts';
|
|
3
|
+
import { resolveRulesConfigFilePath } from '../rules-options.ts';
|
|
4
|
+
import { createVirtualModulePlugin } from './createVirtualModulePlugin.ts';
|
|
5
|
+
|
|
6
|
+
export const STORYBOOK_ASTRO_STORY_RULES_CONFIG_VIRTUAL_MODULE_ID =
|
|
7
|
+
'virtual:storybook-astro-story-rules-config';
|
|
8
|
+
|
|
9
|
+
export function storybookAstroStoryRulesConfigVirtualModulePlugin(
|
|
10
|
+
options?: StoryRulesOptions,
|
|
11
|
+
resolveFrom = process.cwd()
|
|
12
|
+
): Plugin {
|
|
13
|
+
return createVirtualModulePlugin({
|
|
14
|
+
pluginName: 'storybook-astro:virtual-story-rules-config',
|
|
15
|
+
virtualModuleId: STORYBOOK_ASTRO_STORY_RULES_CONFIG_VIRTUAL_MODULE_ID,
|
|
16
|
+
load() {
|
|
17
|
+
const configFilePath = resolveRulesConfigFilePath(options, resolveFrom);
|
|
18
|
+
|
|
19
|
+
if (!configFilePath) {
|
|
20
|
+
return [
|
|
21
|
+
'const storybookAstroStoryRulesConfig = { rules: [] };',
|
|
22
|
+
'export default storybookAstroStoryRulesConfig;',
|
|
23
|
+
'export const storybookAstroStoryRulesConfigFilePath = undefined;'
|
|
24
|
+
].join('\n');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const importPath = JSON.stringify(configFilePath.replace(/\\/g, '/'));
|
|
28
|
+
const configPath = JSON.stringify(configFilePath.replace(/\\/g, '/'));
|
|
29
|
+
|
|
30
|
+
return [
|
|
31
|
+
`import * as storybookAstroStoryRulesConfigModule from ${importPath};`,
|
|
32
|
+
'export default storybookAstroStoryRulesConfigModule;',
|
|
33
|
+
`export const storybookAstroStoryRulesConfigFilePath = ${configPath};`
|
|
34
|
+
].join('\n');
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import type { SanitizationOptions } from '../lib/sanitization.ts';
|
|
3
|
+
import { serializeSanitizationOptions } from '../lib/sanitization.ts';
|
|
4
|
+
import { createVirtualModulePlugin } from './createVirtualModulePlugin.ts';
|
|
5
|
+
|
|
6
|
+
export const STORYBOOK_ASTRO_SANITIZATION_CONFIG_VIRTUAL_MODULE_ID =
|
|
7
|
+
'virtual:storybook-astro-sanitization-config';
|
|
8
|
+
|
|
9
|
+
export function storybookAstroSanitizationConfigVirtualModulePlugin(
|
|
10
|
+
options?: SanitizationOptions
|
|
11
|
+
): Plugin {
|
|
12
|
+
return createVirtualModulePlugin({
|
|
13
|
+
pluginName: 'storybook-astro:virtual-sanitization-config',
|
|
14
|
+
virtualModuleId: STORYBOOK_ASTRO_SANITIZATION_CONFIG_VIRTUAL_MODULE_ID,
|
|
15
|
+
load() {
|
|
16
|
+
const serializedConfig = serializeSanitizationOptions(options);
|
|
17
|
+
|
|
18
|
+
return `export default ${serializedConfig};`;
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { PluginOption } from 'vite';
|
|
2
|
+
import { describe, expect, test } from 'vitest';
|
|
3
|
+
import {
|
|
4
|
+
STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID,
|
|
5
|
+
storybookAstroServerAuthConfigVirtualModulePlugin
|
|
6
|
+
} from './storybookAstroServerAuthConfigVirtualModulePlugin.ts';
|
|
7
|
+
|
|
8
|
+
function getPlugin(pluginOption: PluginOption) {
|
|
9
|
+
if (Array.isArray(pluginOption)) {
|
|
10
|
+
throw new Error('Expected a single plugin object, but got a plugin array.');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (!pluginOption || typeof pluginOption !== 'object') {
|
|
14
|
+
throw new Error('Expected plugin option to be an object.');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return pluginOption;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function getHookHandler<T extends (...args: unknown[]) => unknown>(hook: unknown): T {
|
|
21
|
+
if (typeof hook === 'function') {
|
|
22
|
+
return hook as T;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (
|
|
26
|
+
typeof hook === 'object' &&
|
|
27
|
+
hook !== null &&
|
|
28
|
+
'handler' in hook &&
|
|
29
|
+
typeof (hook as { handler?: unknown }).handler === 'function'
|
|
30
|
+
) {
|
|
31
|
+
return (hook as { handler: T }).handler;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
throw new Error('Expected hook to be a function or an object with a handler function.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
describe('storybookAstroServerAuthConfigVirtualModulePlugin', () => {
|
|
38
|
+
test('normalizes auth token and header values', async () => {
|
|
39
|
+
const plugin = getPlugin(
|
|
40
|
+
storybookAstroServerAuthConfigVirtualModulePlugin({
|
|
41
|
+
authToken: ' test-token ',
|
|
42
|
+
authHeader: ' X-Storybook-Token '
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
const resolveId = getHookHandler<(id: string) => string | undefined>(plugin.resolveId);
|
|
46
|
+
const load = getHookHandler<(id: string) => Promise<string | undefined>>(plugin.load);
|
|
47
|
+
const resolvedId = resolveId(STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID);
|
|
48
|
+
|
|
49
|
+
expect(resolvedId).toBe(`\0${STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID}`);
|
|
50
|
+
await expect(load(resolvedId!)).resolves.toBe(
|
|
51
|
+
'export const storybookAstroServerAuthToken = "test-token";\n' +
|
|
52
|
+
'export const storybookAstroServerAuthHeader = "x-storybook-token";'
|
|
53
|
+
);
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
test('falls back to authorization header and undefined token', async () => {
|
|
57
|
+
const plugin = getPlugin(
|
|
58
|
+
storybookAstroServerAuthConfigVirtualModulePlugin({
|
|
59
|
+
authToken: ' '
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
const load = getHookHandler<(id: string) => Promise<string | undefined>>(plugin.load);
|
|
63
|
+
|
|
64
|
+
await expect(
|
|
65
|
+
load(`\0${STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID}`)
|
|
66
|
+
).resolves.toBe(
|
|
67
|
+
'export const storybookAstroServerAuthToken = undefined;\n' +
|
|
68
|
+
'export const storybookAstroServerAuthHeader = "authorization";'
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { Plugin } from 'vite';
|
|
2
|
+
import type { ServerBuildOptions } from '../types.ts';
|
|
3
|
+
import { createVirtualModulePlugin } from './createVirtualModulePlugin.ts';
|
|
4
|
+
|
|
5
|
+
export const STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID =
|
|
6
|
+
'virtual:storybook-astro-server-auth-config';
|
|
7
|
+
|
|
8
|
+
export function storybookAstroServerAuthConfigVirtualModulePlugin(
|
|
9
|
+
options?: ServerBuildOptions
|
|
10
|
+
): Plugin {
|
|
11
|
+
const authToken = normalizeOptionalString(options?.authToken);
|
|
12
|
+
const authHeader = normalizeAuthHeader(options?.authHeader);
|
|
13
|
+
|
|
14
|
+
return createVirtualModulePlugin({
|
|
15
|
+
pluginName: 'storybook-astro:virtual-server-auth-config',
|
|
16
|
+
virtualModuleId: STORYBOOK_ASTRO_SERVER_AUTH_CONFIG_VIRTUAL_MODULE_ID,
|
|
17
|
+
load() {
|
|
18
|
+
return [
|
|
19
|
+
`export const storybookAstroServerAuthToken = ${
|
|
20
|
+
authToken ? JSON.stringify(authToken) : 'undefined'
|
|
21
|
+
};`,
|
|
22
|
+
`export const storybookAstroServerAuthHeader = ${JSON.stringify(authHeader)};`
|
|
23
|
+
].join('\n');
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function normalizeOptionalString(value: string | undefined) {
|
|
29
|
+
if (!value) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const normalizedValue = value.trim();
|
|
34
|
+
|
|
35
|
+
return normalizedValue || undefined;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function normalizeAuthHeader(value: string | undefined) {
|
|
39
|
+
const normalizedValue = normalizeOptionalString(value);
|
|
40
|
+
|
|
41
|
+
return (normalizedValue ?? 'authorization').toLowerCase();
|
|
42
|
+
}
|
|
@@ -9,11 +9,11 @@ import type { Integration } from './integrations/index.ts';
|
|
|
9
9
|
import { ssrLoadModuleWithFsFallback } from './lib/ssr-load-module-with-fs-fallback.ts';
|
|
10
10
|
import { resolveSanitizationOptions, sanitizeRenderPayload } from './lib/sanitization.ts';
|
|
11
11
|
import { resolveStoryModuleMock, withStoryModuleMocks } from './module-mocks.ts';
|
|
12
|
-
import { applyMswHandlers } from './msw.ts';
|
|
13
12
|
import { resolveRulesConfigFilePath } from './rules-options.ts';
|
|
14
|
-
import { selectStoryRules } from './rules.ts';
|
|
13
|
+
import { selectStoryRules, withStoryRuleCleanups } from './rules.ts';
|
|
15
14
|
import type { FrameworkOptions } from './types.ts';
|
|
16
15
|
import { vitePluginAstroFontsFallback } from './vitePluginAstroFontsFallback.ts';
|
|
16
|
+
import { vitePluginAstroIntegrationOptsFallback } from './vitePluginAstroIntegrationOptsFallback.ts';
|
|
17
17
|
import { vitePluginAstroRoutesFallback } from './vitePluginAstroRoutesFallback.ts';
|
|
18
18
|
import { vitePluginAstroVueFallback } from './vitePluginAstroVueFallback.ts';
|
|
19
19
|
|
|
@@ -218,7 +218,6 @@ async function prerenderStories(options: {
|
|
|
218
218
|
const selectedRules = await selectStoryRules({
|
|
219
219
|
configModule: rulesConfigModule,
|
|
220
220
|
configFilePath: options.storyRulesConfigFilePath,
|
|
221
|
-
mode: 'production',
|
|
222
221
|
story: {
|
|
223
222
|
id: story.id,
|
|
224
223
|
title: story.title,
|
|
@@ -226,42 +225,47 @@ async function prerenderStories(options: {
|
|
|
226
225
|
}
|
|
227
226
|
});
|
|
228
227
|
|
|
229
|
-
await applyMswHandlers(selectedRules.mswHandlers);
|
|
230
|
-
|
|
231
228
|
if (selectedRules.moduleMocks.size > 0) {
|
|
232
229
|
viteServer.moduleGraph.invalidateAll();
|
|
233
230
|
}
|
|
234
231
|
|
|
235
|
-
const html = await
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
232
|
+
const html = await withStoryRuleCleanups(selectedRules.cleanups, async () => {
|
|
233
|
+
return withStoryModuleMocks(selectedRules.moduleMocks, async () => {
|
|
234
|
+
const modulePath = resolveImportPath(story.importPath, options.resolveFrom);
|
|
235
|
+
const storyModule = await viteServer.ssrLoadModule(modulePath);
|
|
236
|
+
const meta = isRecord(storyModule.default) ? storyModule.default : {};
|
|
237
|
+
const storyExport = isRecord(storyModule[story.exportName])
|
|
238
|
+
? storyModule[story.exportName]
|
|
239
|
+
: {};
|
|
240
|
+
|
|
241
|
+
if (typeof meta.component !== 'function') {
|
|
242
|
+
throw new Error(
|
|
243
|
+
`Unable to prerender story "${story.id}". Missing default export component in ${story.importPath}.`
|
|
244
|
+
);
|
|
245
|
+
}
|
|
240
246
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
);
|
|
245
|
-
}
|
|
247
|
+
if (storyExport.component && storyExport.component !== meta.component) {
|
|
248
|
+
return undefined;
|
|
249
|
+
}
|
|
246
250
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
251
|
+
const mergedArgs = mergeStoryArgs(toRecord(meta.args), toRecord(storyExport.args));
|
|
252
|
+
const { args, slots } = separateSlots(mergedArgs);
|
|
253
|
+
const processedArgs = await processImageMetadata(args);
|
|
254
|
+
const sanitizedPayload = sanitizeRenderPayload(
|
|
255
|
+
{
|
|
256
|
+
args: processedArgs,
|
|
257
|
+
slots
|
|
258
|
+
},
|
|
259
|
+
sanitizationOptions
|
|
260
|
+
);
|
|
250
261
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
},
|
|
259
|
-
sanitizationOptions
|
|
260
|
-
);
|
|
261
|
-
|
|
262
|
-
return container.renderToString(patchCreateAstroCompat(meta.component), {
|
|
263
|
-
props: sanitizedPayload.args,
|
|
264
|
-
slots: sanitizedPayload.slots
|
|
262
|
+
return container.renderToString(
|
|
263
|
+
patchCreateAstroCompat(meta.component) as Parameters<typeof container.renderToString>[0],
|
|
264
|
+
{
|
|
265
|
+
props: sanitizedPayload.args,
|
|
266
|
+
slots: sanitizedPayload.slots
|
|
267
|
+
}
|
|
268
|
+
);
|
|
265
269
|
});
|
|
266
270
|
});
|
|
267
271
|
|
|
@@ -281,14 +285,18 @@ async function createStorySsrServer(
|
|
|
281
285
|
trackedSpecifiers: Set<string>,
|
|
282
286
|
resolveFrom: string
|
|
283
287
|
) {
|
|
284
|
-
const { getViteConfig } = await importAstroConfig(resolveFrom);
|
|
288
|
+
const { getViteConfig, passthroughImageService } = await importAstroConfig(resolveFrom);
|
|
285
289
|
const astroConfig = await getViteConfig(
|
|
286
290
|
{ root: resolveFrom },
|
|
287
291
|
{
|
|
288
292
|
configFile: false,
|
|
289
293
|
integrations: await Promise.all(
|
|
290
294
|
integrations.map((integration) => integration.loadIntegration(resolveFrom))
|
|
291
|
-
)
|
|
295
|
+
),
|
|
296
|
+
// Use the passthrough image service so nested components that use <Image>
|
|
297
|
+
// from astro:assets render as plain <img> tags without triggering image
|
|
298
|
+
// optimization (which fails in the Storybook SSR context).
|
|
299
|
+
image: { service: passthroughImageService() }
|
|
292
300
|
}
|
|
293
301
|
)({
|
|
294
302
|
mode: 'production',
|
|
@@ -303,6 +311,7 @@ async function createStorySsrServer(
|
|
|
303
311
|
plugins: [
|
|
304
312
|
createProjectAstroResolutionPlugin(resolveFrom),
|
|
305
313
|
vitePluginAstroFontsFallback(),
|
|
314
|
+
vitePluginAstroIntegrationOptsFallback(),
|
|
306
315
|
vitePluginAstroVueFallback(),
|
|
307
316
|
vitePluginAstroRoutesFallback(),
|
|
308
317
|
{
|
|
@@ -364,7 +373,7 @@ async function addContainerRenderers(
|
|
|
364
373
|
renderer: {
|
|
365
374
|
...renderer,
|
|
366
375
|
name: serverRenderer.name
|
|
367
|
-
}
|
|
376
|
+
} as Parameters<typeof container.addServerRenderer>[0]['renderer']
|
|
368
377
|
});
|
|
369
378
|
} else {
|
|
370
379
|
container.addServerRenderer({
|
|
@@ -633,7 +642,11 @@ async function processImageMetadata(
|
|
|
633
642
|
|
|
634
643
|
for (const [key, value] of Object.entries(args)) {
|
|
635
644
|
if (isImageMetadata(value)) {
|
|
636
|
-
|
|
645
|
+
// Keep ImageMetadata as a plain object — Astro's image service checks
|
|
646
|
+
// isESMImportedImage (typeof src === 'object') and skips the /@fs/ string
|
|
647
|
+
// validation that throws LocalImageUsedWrongly. Converting to a URL string
|
|
648
|
+
// causes that error when the string starts with /@fs/.
|
|
649
|
+
processed[key] = value;
|
|
637
650
|
|
|
638
651
|
continue;
|
|
639
652
|
}
|
|
@@ -642,7 +655,7 @@ async function processImageMetadata(
|
|
|
642
655
|
processed[key] = await Promise.all(
|
|
643
656
|
value.map(async (item) => {
|
|
644
657
|
if (isImageMetadata(item)) {
|
|
645
|
-
return
|
|
658
|
+
return item;
|
|
646
659
|
}
|
|
647
660
|
|
|
648
661
|
if (isRecord(item)) {
|
|
@@ -676,20 +689,6 @@ function isImageMetadata(value: unknown): value is Record<string, unknown> {
|
|
|
676
689
|
);
|
|
677
690
|
}
|
|
678
691
|
|
|
679
|
-
function convertImageMetadataToUrl(imageMetadata: Record<string, unknown>): string {
|
|
680
|
-
const src = imageMetadata.src;
|
|
681
|
-
const fsPath = imageMetadata.fsPath;
|
|
682
|
-
|
|
683
|
-
if (typeof src === 'string') {
|
|
684
|
-
return src;
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
if (typeof fsPath === 'string') {
|
|
688
|
-
return fsPath;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
|
-
return String(imageMetadata);
|
|
692
|
-
}
|
|
693
692
|
|
|
694
693
|
function createProjectAstroResolutionPlugin(resolveFrom: string): Plugin {
|
|
695
694
|
const require = createRequire(import.meta.url);
|