@@ -12,6 +12,7 @@ import { getJsxVariables } from "./utils/jsx-variables";
1212import { getJsxFunctions } from "./utils/jsx-functions" ;
1313import { getJsxExpressions } from "./utils/jsx-expressions" ;
1414import { collectJsxScopes , getJsxScopeAttribute } from "./utils/jsx-scope" ;
15+ import { setJsxAttributeValue } from "./utils/jsx-attribute" ;
1516
1617export const lingoJsxScopeInjectMutation = createCodeMutation ( ( payload ) => {
1718 const mode = getModuleExecutionMode ( payload . ast , payload . params . rsc ) ;
@@ -36,103 +37,81 @@ export const lingoJsxScopeInjectMutation = createCodeMutation((payload) => {
3637 continue ;
3738 }
3839
39- // Build new attributes array, preserving all original attributes
40- const originalAttributes = jsxScope . node . openingElement . attributes . slice ( ) ;
40+ // Create new JSXElement with original attributes
41+ const newNode = t . jsxElement (
42+ t . jsxOpeningElement (
43+ t . jsxIdentifier ( lingoComponentImport . importedName ) ,
44+ jsxScope . node . openingElement . attributes . slice ( ) , // original attributes
45+ true , // selfClosing
46+ ) ,
47+ null , // no closing element
48+ [ ] , // no children
49+ true , // selfClosing
50+ ) ;
51+
52+ // Create a NodePath wrapper for the new node to use setJsxAttributeValue
53+ const newNodePath = {
54+ node : newNode ,
55+ } as any ;
4156
4257 // Add $as prop
4358 const as = / ^ [ A - Z ] / . test ( originalJsxElementName )
44- ? t . jsxExpressionContainer ( t . identifier ( originalJsxElementName ) )
45- : t . stringLiteral ( originalJsxElementName ) ;
46- originalAttributes . push ( t . jsxAttribute ( t . jsxIdentifier ( "$as" ) , as ) ) ;
59+ ? t . identifier ( originalJsxElementName )
60+ : originalJsxElementName ;
61+ setJsxAttributeValue ( newNodePath , "$as" , as ) ;
62+
4763 // Add $fileKey prop
48- originalAttributes . push (
49- t . jsxAttribute (
50- t . jsxIdentifier ( "$fileKey" ) ,
51- t . stringLiteral ( payload . relativeFilePath ) ,
52- ) ,
53- ) ;
64+ setJsxAttributeValue ( newNodePath , "$fileKey" , payload . relativeFilePath ) ;
65+
5466 // Add $entryKey prop
55- originalAttributes . push (
56- t . jsxAttribute (
57- t . jsxIdentifier ( "$entryKey" ) ,
58- t . stringLiteral ( getJsxScopeAttribute ( jsxScope ) ! ) ,
59- ) ,
67+ setJsxAttributeValue (
68+ newNodePath ,
69+ "$entryKey" ,
70+ getJsxScopeAttribute ( jsxScope ) ! ,
6071 ) ;
6172
6273 // Extract $variables from original JSX scope before lingo component was inserted
6374 const $variables = getJsxVariables ( jsxScope ) ;
6475 if ( $variables . properties . length > 0 ) {
65- originalAttributes . push (
66- t . jsxAttribute (
67- t . jsxIdentifier ( "$variables" ) ,
68- t . jsxExpressionContainer ( $variables ) ,
69- ) ,
70- ) ;
76+ setJsxAttributeValue ( newNodePath , "$variables" , $variables ) ;
7177 }
78+
7279 // Extract nested JSX elements
7380 const $elements = getNestedJsxElements ( jsxScope ) ;
7481 if ( $elements . elements . length > 0 ) {
75- originalAttributes . push (
76- t . jsxAttribute (
77- t . jsxIdentifier ( "$elements" ) ,
78- t . jsxExpressionContainer ( $elements ) ,
79- ) ,
80- ) ;
82+ setJsxAttributeValue ( newNodePath , "$elements" , $elements ) ;
8183 }
84+
8285 // Extract nested functions
8386 const $functions = getJsxFunctions ( jsxScope ) ;
8487 if ( $functions . properties . length > 0 ) {
85- originalAttributes . push (
86- t . jsxAttribute (
87- t . jsxIdentifier ( "$functions" ) ,
88- t . jsxExpressionContainer ( $functions ) ,
89- ) ,
90- ) ;
88+ setJsxAttributeValue ( newNodePath , "$functions" , $functions ) ;
9189 }
90+
9291 // Extract expressions
9392 const $expressions = getJsxExpressions ( jsxScope ) ;
9493 if ( $expressions . elements . length > 0 ) {
95- originalAttributes . push (
96- t . jsxAttribute (
97- t . jsxIdentifier ( "$expressions" ) ,
98- t . jsxExpressionContainer ( $expressions ) ,
99- ) ,
100- ) ;
94+ setJsxAttributeValue ( newNodePath , "$expressions" , $expressions ) ;
10195 }
96+
10297 if ( mode === "server" ) {
10398 // Add $loadDictionary prop
10499 const loadDictionaryImport = getOrCreateImport ( payload . ast , {
105100 exportedName : "loadDictionary" ,
106101 moduleName : ModuleId . ReactRSC ,
107102 } ) ;
108- originalAttributes . push (
109- t . jsxAttribute (
110- t . jsxIdentifier ( "$loadDictionary" ) ,
111- t . jsxExpressionContainer (
112- t . arrowFunctionExpression (
113- [ t . identifier ( "locale" ) ] ,
114- t . callExpression (
115- t . identifier ( loadDictionaryImport . importedName ) ,
116- [ t . identifier ( "locale" ) ] ,
117- ) ,
118- ) ,
119- ) ,
103+ setJsxAttributeValue (
104+ newNodePath ,
105+ "$loadDictionary" ,
106+ t . arrowFunctionExpression (
107+ [ t . identifier ( "locale" ) ] ,
108+ t . callExpression ( t . identifier ( loadDictionaryImport . importedName ) , [
109+ t . identifier ( "locale" ) ,
110+ ] ) ,
120111 ) ,
121112 ) ;
122113 }
123114
124- // Create new JSXElement (self-closing)
125- const newNode = t . jsxElement (
126- t . jsxOpeningElement (
127- t . jsxIdentifier ( lingoComponentImport . importedName ) ,
128- originalAttributes ,
129- true , // selfClosing
130- ) ,
131- null , // no closing element
132- [ ] , // no children
133- true , // selfClosing
134- ) ;
135-
136115 jsxScope . replaceWith ( newNode ) ;
137116 }
138117
0 commit comments