Skip to content

Commit e072e53

Browse files
TeagesCopilot
andauthored
pref: batch processing js snippets in template (#5)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent d30b207 commit e072e53

File tree

2 files changed

+49
-52
lines changed

2 files changed

+49
-52
lines changed

src/utils/template.ts

Lines changed: 47 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -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 = /^(wrapper_\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
}

test/template.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,8 @@ describe('transform typescript template', () => {
111111
expect(await fixture(`<div @click="" />`)).toEqual(`<div @click="" />`)
112112
})
113113

114-
it('keep error', async () => {
115-
expect(await fixture(`<div>{{ data. }}</div>`)).toEqual(
116-
`<div>{{ data. }}</div>`,
117-
)
114+
it('throw error', async () => {
115+
await expect(fixture(`<div>{{ data. }}</div>`)).rejects.toThrowError()
118116
})
119117

120118
it('quotes', async () => {

0 commit comments

Comments
 (0)