@@ -133,38 +133,27 @@ export async function transpileVueTemplate(content: string, root: RootNode, offs
133133 const s = new MagicString ( content )
134134
135135 handleNode ( root , ( ...items ) => expressions . push ( ...items ) )
136- await Promise . all (
137- expressions . map ( async ( item ) => {
138- if ( item . src . trim ( ) === '' ) {
139- item . replacement = item . src
140- return
141- }
142-
143- try {
144- item . replacement = await transformJsSnippet ( item . src , transform )
145-
146- const surrounding = getSurrounding (
147- content ,
148- item . loc . start . offset - offset ,
149- item . loc . end . offset - offset ,
150- )
151- if ( surrounding ) {
152- const replace = surrounding . code === `"` ? `'` : `"`
153- item . replacement = replaceQuote (
154- item . replacement ,
155- surrounding . code ,
156- replace ,
157- )
158- }
159- }
160- catch {
161- item . replacement = item . src
162- }
163- } ) ,
164- )
136+ const transformMap = await transformJsSnippets ( expressions . map ( e => e . src ) , transform )
137+ for ( const item of expressions ) {
138+ item . replacement = transformMap . get ( item . src ) ?? item . src
139+
140+ const surrounding = getSurrounding (
141+ content ,
142+ item . loc . start . offset - offset ,
143+ item . loc . end . offset - offset ,
144+ )
145+ if ( surrounding ) {
146+ const replace = surrounding . code === `"` ? `'` : `"`
147+ item . replacement = replaceQuote (
148+ item . replacement ,
149+ surrounding . code ,
150+ replace ,
151+ )
152+ }
153+ }
165154
166155 for ( const item of expressions ) {
167- if ( item . replacement ) {
156+ if ( item . replacement && item . replacement !== item . src ) {
168157 s . overwrite (
169158 item . loc . start . offset - offset ,
170159 item . loc . end . offset - offset ,
@@ -216,27 +205,37 @@ function getSurrounding(code: string, start: number, end: number) {
216205 : undefined
217206}
218207
219- async function transformJsSnippet ( code : string , transform : ( code : string ) => Promise < string > ) : Promise < string > {
220- // `{ key: val } as any` in `<div :style="{ key: val } as any" />` is a valid js snippet,
221- // but it can't be transformed.
222- // We can wrap it with `()` to make it a valid js file
208+ async function transformJsSnippets ( codes : string [ ] , transform : ( code : string ) => Promise < string > ) : Promise < Map < string , string > > {
209+ const keyMap = new Map < string , string > ( )
210+ const resMap = new Map < string , string > ( )
223211
224- let res = await transform ( `(${ code } )` )
212+ for ( const code of codes ) {
213+ keyMap . set ( `wrapper_${ keyMap . size } ` , code )
214+ }
225215
226- res = res . trim ( )
216+ // transform all snippets in a single file
217+ const batchInput = Array . from ( keyMap . entries ( ) ) . map ( ( [ wrapperName , raw ] ) => `${ wrapperName } (${ raw } );` ) . join ( '\n' )
227218
228- // result will be wrapped in `{content};\n`, we need to remove it
229- if ( res . endsWith ( ';' ) ) {
230- res = res . slice ( 0 , - 1 )
231- }
219+ try {
220+ const batchOutput = await transform ( batchInput )
232221
233- // Check if the code was a v-slot destructuring expression like "{ active, ...slotProps }"
234- // These should not be wrapped in parentheses as Vue template syntax doesn't support it
235- const isObject = / ^ \s * \{ . * \} \s * $ / . test ( code )
236- if ( isObject ) {
237- // Remove the parentheses
238- res = res . match ( / ^ \( ( . * ) \) $ / ) ?. [ 1 ] ?? res
239- }
222+ const lines = batchOutput . split ( '\n' )
223+ const wrapperRegex = / ^ ( w r a p p e r _ \d + ) \( ( . * ) \) ; $ /
224+ for ( const line of lines ) {
225+ const [ _ , wrapperName , res ] = line . match ( wrapperRegex ) ?? [ ]
226+ if ( ! wrapperName || ! res ) {
227+ continue
228+ }
240229
241- return res
230+ const raw = keyMap . get ( wrapperName )
231+ if ( raw ) {
232+ resMap . set ( raw , res )
233+ }
234+ }
235+
236+ return resMap
237+ }
238+ catch ( error ) {
239+ throw new Error ( '[vue-sfc-transform] Error parsing TypeScript expression in template' , { cause : error } )
240+ }
242241}
0 commit comments