1
1
import { getFrameworkName , loadPreviewOrConfigFile } from 'storybook/internal/common' ;
2
- import { isCsfFactoryPreview , readConfig } from 'storybook/internal/csf-tools' ;
3
2
import type { Options , PreviewAnnotation } from 'storybook/internal/types' ;
4
3
5
- import { genArrayFromRaw , genImport , genSafeVariableName } from 'knitwork' ;
6
- import { filename } from 'pathe/utils' ;
7
4
import { dedent } from 'ts-dedent' ;
8
5
9
6
import { processPreviewAnnotation } from './utils/process-preview-annotation' ;
@@ -14,72 +11,38 @@ export async function generateModernIframeScriptCode(options: Options, projectRo
14
11
const frameworkName = await getFrameworkName ( options ) ;
15
12
16
13
const previewOrConfigFile = loadPreviewOrConfigFile ( { configDir } ) ;
17
- const previewConfig = await readConfig ( previewOrConfigFile ! ) ;
18
- const isCsf4 = isCsfFactoryPreview ( previewConfig ) ;
19
-
20
14
const previewAnnotations = await presets . apply < PreviewAnnotation [ ] > (
21
15
'previewAnnotations' ,
22
16
[ ] ,
23
17
options
24
18
) ;
25
- return generateModernIframeScriptCodeFromPreviews ( {
26
- previewAnnotations : [ ...previewAnnotations , previewOrConfigFile ] ,
27
- projectRoot,
28
- frameworkName,
29
- isCsf4,
30
- } ) ;
31
- }
32
-
33
- export async function generateModernIframeScriptCodeFromPreviews ( options : {
34
- previewAnnotations : ( PreviewAnnotation | undefined ) [ ] ;
35
- projectRoot : string ;
36
- frameworkName : string ;
37
- isCsf4 : boolean ;
38
- } ) {
39
- const { projectRoot, frameworkName } = options ;
40
- const previewAnnotationURLs = options . previewAnnotations
41
- . filter ( ( path ) => path !== undefined )
19
+ const [ previewFileUrl , ...previewAnnotationURLs ] = [ previewOrConfigFile , ...previewAnnotations ]
20
+ . filter ( Boolean )
42
21
. map ( ( path ) => processPreviewAnnotation ( path , projectRoot ) ) ;
43
22
44
- const variables : string [ ] = [ ] ;
45
- const imports : string [ ] = [ ] ;
46
- for ( const previewAnnotation of previewAnnotationURLs ) {
47
- const variable =
48
- genSafeVariableName ( filename ( previewAnnotation ) ) . replace ( / _ ( 4 5 | 4 6 | 4 7 ) / g, '_' ) +
49
- '_' +
50
- hash ( previewAnnotation ) ;
51
- variables . push ( variable ) ;
52
- imports . push ( genImport ( previewAnnotation , { name : '*' , as : variable } ) ) ;
53
- }
54
-
55
- const previewFileURL = previewAnnotationURLs [ previewAnnotationURLs . length - 1 ] ;
56
- const previewFileVariable = variables [ variables . length - 1 ] ;
57
- const previewFileImport = imports [ imports . length - 1 ] ;
58
-
59
23
// This is pulled out to a variable because it is reused in both the initial page load
60
- // and the HMR handler.
61
- // The `hmrPreviewAnnotationModules` parameter is used to pass the updated modules from HMR.
62
- // However, only the changed modules are provided, the rest are null.
63
- const getPreviewAnnotationsFunction = options . isCsf4
64
- ? dedent `
65
- const getProjectAnnotations = (hmrPreviewAnnotationModules = []) => {
66
- const preview = hmrPreviewAnnotationModules[0] ?? ${ previewFileVariable } ;
67
- return preview.default.composed;
68
- }`
69
- : dedent `
70
- const getProjectAnnotations = (hmrPreviewAnnotationModules = []) => {
71
- const configs = ${ genArrayFromRaw (
72
- variables . map (
24
+ // and the HMR handler. We don't use the hot.accept callback params because only the changed
25
+ // modules are provided, the rest are null. We can just re-import everything again in that case.
26
+ const getPreviewAnnotationsFunction = dedent `
27
+ const getProjectAnnotations = async (hmrPreviewAnnotationModules = []) => {
28
+ const preview = await import('${ previewFileUrl } ');
29
+
30
+ if (isPreview(preview.default)) {
31
+ return preview.default.composed;
32
+ }
33
+
34
+ const configs = await Promise.all([${ previewAnnotationURLs
35
+ . map (
73
36
( previewAnnotation , index ) =>
74
- // Prefer the updated module from an HMR update, otherwise the original module
75
- `hmrPreviewAnnotationModules[${ index } ] ?? ${ previewAnnotation } `
76
- ) ,
77
- ' '
78
- ) }
79
- return composeConfigs(configs);
37
+ // Prefer the updated module from an HMR update, otherwise import the original module
38
+ `hmrPreviewAnnotationModules[${ index } ] ?? import('${ previewAnnotation } ')`
39
+ )
40
+ . join ( ',\n' ) } ])
41
+ return composeConfigs([...configs, preview]);
80
42
}` ;
81
43
82
- const generateHMRHandler = ( ) : string => {
44
+ // eslint-disable-next-line @typescript-eslint/no-shadow
45
+ const generateHMRHandler = ( frameworkName : string ) : string => {
83
46
// Web components are not compatible with HMR, so disable HMR, reload page instead.
84
47
if ( frameworkName === '@storybook/web-components-vite' ) {
85
48
return dedent `
@@ -95,7 +58,8 @@ export async function generateModernIframeScriptCodeFromPreviews(options: {
95
58
window.__STORYBOOK_PREVIEW__.onStoriesChanged({ importFn: newModule.importFn });
96
59
});
97
60
98
- import.meta.hot.accept(${ JSON . stringify ( options . isCsf4 ? [ previewFileURL ] : previewAnnotationURLs ) } , (previewAnnotationModules) => {
61
+ import.meta.hot.accept(${ JSON . stringify ( previewAnnotationURLs ) } , (previewAnnotationModules) => {
62
+ ${ getPreviewAnnotationsFunction }
99
63
// getProjectAnnotations has changed so we need to patch the new one in
100
64
window.__STORYBOOK_PREVIEW__.onGetProjectAnnotationsChanged({ getProjectAnnotations: () => getProjectAnnotations(previewAnnotationModules) });
101
65
});
@@ -112,7 +76,6 @@ export async function generateModernIframeScriptCodeFromPreviews(options: {
112
76
*/
113
77
const code = dedent `
114
78
import { setup } from 'storybook/internal/preview/runtime';
115
-
116
79
import '${ SB_VIRTUAL_FILES . VIRTUAL_ADDON_SETUP_FILE } ';
117
80
118
81
setup();
@@ -121,17 +84,12 @@ export async function generateModernIframeScriptCodeFromPreviews(options: {
121
84
import { isPreview } from 'storybook/internal/csf';
122
85
import { importFn } from '${ SB_VIRTUAL_FILES . VIRTUAL_STORIES_FILE } ';
123
86
124
- ${ options . isCsf4 ? previewFileImport : imports . join ( '\n' ) }
125
87
${ getPreviewAnnotationsFunction }
126
88
127
89
window.__STORYBOOK_PREVIEW__ = window.__STORYBOOK_PREVIEW__ || new PreviewWeb(importFn, getProjectAnnotations);
128
90
129
91
window.__STORYBOOK_STORY_STORE__ = window.__STORYBOOK_STORY_STORE__ || window.__STORYBOOK_PREVIEW__.storyStore;
130
-
131
- ${ generateHMRHandler ( ) } ;
132
- ` . trim ( ) ;
92
+
93
+ ${ generateHMRHandler ( frameworkName ) } ;` . trim ( ) ;
133
94
return code ;
134
95
}
135
- function hash ( value : string ) {
136
- return value . split ( '' ) . reduce ( ( acc , char ) => acc + char . charCodeAt ( 0 ) , 0 ) ;
137
- }
0 commit comments