11const path = require ( "path" ) ;
2- const crypto = require ( "crypto" ) ;
2+
33const { isInsideReactComponent } = require ( "./react-helper.cjs" ) ;
44
55/**
6- * Babel plugin that automatically injects the file path and other metadata
7- * to registerPreview() calls imported from "rozenite-preview"
6+ * Babel plugin that automatically injects file path, relative filename,
7+ * React component context, name, call site location, and other metadata
8+ * into registerPreview() calls imported from "rozenite-preview".
9+ * Also injects the Metro "module" object as the first argument.
810 */
911const ROZENITE_PREVIEW_MODULE = "rozenite-preview" ;
1012const TARGET_FUNCTION = "registerPreview" ;
1113const EXPECTED_ARGS_COUNT = 2 ;
1214
13- const cache = { } ;
14-
15- function getOrCreateId ( file , line ) {
16- const key = `${ file } :${ line } ` ;
17- if ( cache [ key ] ) return cache [ key ] ;
18-
19- const hash = crypto . createHash ( "md5" ) . update ( key ) . digest ( "hex" ) . slice ( 0 , 6 ) ;
20- const id = `${ path
21- . basename ( file , path . extname ( file ) )
22- . toLowerCase ( ) } _${ line } _${ hash } `;
23- cache [ key ] = id ;
24- return id ;
25- }
26-
2715module . exports = function ( { types : t } ) {
2816 return {
2917 visitor : {
@@ -34,12 +22,18 @@ module.exports = function ({ types: t }) {
3422 return ;
3523 }
3624
37- injectFilePathIntoRegisterPreviewCalls (
38- path ,
39- state ,
40- rozenitePreviewImports ,
41- t
42- ) ;
25+ path . traverse ( {
26+ CallExpression ( callPath ) {
27+ if (
28+ ! isTargetRegisterPreviewCall ( callPath , rozenitePreviewImports )
29+ ) {
30+ return ;
31+ }
32+
33+ injectMetadataIntoRegisterPreviewCalls ( callPath , state , t ) ;
34+ injectMetroModuleIntoRegisterPreviewCalls ( callPath , t ) ;
35+ } ,
36+ } ) ;
4337 } ,
4438 } ,
4539 } ;
@@ -94,67 +88,41 @@ function isValidImportSpecifier(specifier, t) {
9488}
9589
9690/**
97- * Traverses the AST and injects file paths into registerPreview calls
98- * @param {Object } programPath - The program AST path
91+ * Traverses the AST and injects metadata into registerPreview calls
92+ * @param {Object } callPath - The call expression AST path
9993 * @param {Object } state - Babel plugin state
100- * @param {Set } rozenitePreviewImports - Set of imported identifiers from rozenite-preview
10194 * @param {Object } t - Babel types helper
10295 */
103- function injectFilePathIntoRegisterPreviewCalls (
104- programPath ,
105- state ,
106- rozenitePreviewImports ,
107- t
108- ) {
96+ function injectMetadataIntoRegisterPreviewCalls ( callPath , state , t ) {
10997 const filename = state . file . opts . filename || "" ;
11098 const relativeFilename = path . relative ( process . cwd ( ) , filename ) ;
11199
112- programPath . traverse ( {
113- CallExpression ( callPath ) {
114- if ( isTargetRegisterPreviewCall ( callPath , rozenitePreviewImports ) ) {
115- const metadata = getMetadata ( callPath ) ;
116- const filePath = t . stringLiteral ( filename ) ;
117- const id = getOrCreateId ( relativeFilename , metadata . line ) ;
118- const argument = t . objectExpression ( [
119- t . objectProperty ( t . identifier ( "id" ) , t . stringLiteral ( id ) ) ,
120- t . objectProperty ( t . identifier ( "filePath" ) , filePath ) ,
121- t . objectProperty (
122- t . identifier ( "relativeFilename" ) ,
123- t . stringLiteral ( relativeFilename )
124- ) ,
125- t . objectProperty (
126- t . identifier ( "isInsideReactComponent" ) ,
127- t . booleanLiteral ( isInsideReactComponent ( callPath ) )
128- ) ,
129- t . objectProperty (
130- t . identifier ( "name" ) ,
131- t . stringLiteral ( metadata . name )
132- ) ,
133- t . objectProperty (
134- t . identifier ( "nameType" ) ,
135- t . stringLiteral ( metadata . nameType )
136- ) ,
137- t . objectProperty (
138- t . identifier ( "callId" ) ,
139- t . stringLiteral ( metadata . callId )
140- ) ,
141- t . objectProperty (
142- t . identifier ( "componentType" ) ,
143- t . stringLiteral ( metadata . componentType )
144- ) ,
145- t . objectProperty (
146- t . identifier ( "line" ) ,
147- t . numericLiteral ( metadata . line )
148- ) ,
149- t . objectProperty (
150- t . identifier ( "column" ) ,
151- t . numericLiteral ( metadata . column )
152- ) ,
153- ] ) ;
154- callPath . node . arguments . push ( argument ) ;
155- }
156- } ,
157- } ) ;
100+ const metadata = getMetadata ( callPath ) ;
101+ const filePath = t . stringLiteral ( filename ) ;
102+ const argument = t . objectExpression ( [
103+ t . objectProperty ( t . identifier ( "filePath" ) , filePath ) ,
104+ t . objectProperty (
105+ t . identifier ( "relativeFilename" ) ,
106+ t . stringLiteral ( relativeFilename )
107+ ) ,
108+ t . objectProperty (
109+ t . identifier ( "isInsideReactComponent" ) ,
110+ t . booleanLiteral ( isInsideReactComponent ( callPath ) )
111+ ) ,
112+ t . objectProperty ( t . identifier ( "name" ) , t . stringLiteral ( metadata . name ) ) ,
113+ t . objectProperty (
114+ t . identifier ( "nameType" ) ,
115+ t . stringLiteral ( metadata . nameType )
116+ ) ,
117+ t . objectProperty ( t . identifier ( "callId" ) , t . stringLiteral ( metadata . callId ) ) ,
118+ t . objectProperty (
119+ t . identifier ( "componentType" ) ,
120+ t . stringLiteral ( metadata . componentType )
121+ ) ,
122+ t . objectProperty ( t . identifier ( "line" ) , t . numericLiteral ( metadata . line ) ) ,
123+ t . objectProperty ( t . identifier ( "column" ) , t . numericLiteral ( metadata . column ) ) ,
124+ ] ) ;
125+ callPath . node . arguments . push ( argument ) ;
158126}
159127
160128/**
@@ -228,3 +196,13 @@ function isTargetRegisterPreviewCall(callPath, rozenitePreviewImports) {
228196 callPath . node . arguments . length === EXPECTED_ARGS_COUNT
229197 ) ;
230198}
199+
200+ /**
201+ * Injects the Metro module into all registerPreview calls as the first argument.
202+ * @param callPath - The call expression AST path
203+ * @param t
204+ */
205+ function injectMetroModuleIntoRegisterPreviewCalls ( callPath , t ) {
206+ const { node } = callPath ;
207+ node . arguments . unshift ( t . identifier ( "module" ) ) ;
208+ }
0 commit comments