Skip to content

Commit 1c8ab7e

Browse files
danielroeTeages
andauthored
fix: skip quote replacement in interpolation (#28)
Co-authored-by: Teages <[email protected]>
1 parent cd3d68c commit 1c8ab7e

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

src/utils/template.ts

+18
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,10 @@ export async function transpileVueTemplate(
164164
for (const item of expressions) {
165165
item.replacement = transformMap.get(item) ?? item.src
166166

167+
if (!shouldReplaceQuote(item)) {
168+
continue
169+
}
170+
167171
// the source should only have one of the quotes
168172
const sourceQuote = getSourceQuote(
169173
content,
@@ -212,6 +216,20 @@ export function replaceQuote(code: string, target: string, replace: string): str
212216
return res
213217
}
214218

219+
function shouldReplaceQuote(expression: Expression): boolean {
220+
if (!expression.src.includes(`'`) && !expression.src.includes(`"`)) {
221+
return false
222+
}
223+
224+
// skip the expression in the interpolation, it doesn't care about the quote
225+
const secondLastTrack = expression.track.at(-2)
226+
if (secondLastTrack?.type === NodeTypes.INTERPOLATION) {
227+
return false
228+
}
229+
230+
return true
231+
}
232+
215233
function getSourceQuote(code: string, start: number, end: number): string | null {
216234
const source = code.slice(start, end)
217235
const quotes = ['"', '\'']

test/template.test.ts

+26
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,32 @@ describe('transform typescript template', () => {
184184
expect(output).toBe(`'test'`)
185185
})
186186

187+
it('handles quotes in interpolations', async () => {
188+
expect(
189+
await fixture(`
190+
<template>
191+
<div>
192+
<div :class="$test('foobar', \`Foobar 'test'\`)" />
193+
<div>{{ $test('foobar', "Foobar 'test'") }}</div>
194+
<div>{{ $test('foobar', 'Foobar test') }}</div>
195+
<div>{{ $test('foobar', \`Foobar ' " ''" test\`) }}</div>
196+
</div>
197+
</template>
198+
`),
199+
).toMatchInlineSnapshot(`
200+
"
201+
<template>
202+
<div>
203+
<div :class="$test('foobar', \`Foobar \\'test\\'\`)" />
204+
<div>{{ $test("foobar", "Foobar 'test'") }}</div>
205+
<div>{{ $test("foobar", "Foobar test") }}</div>
206+
<div>{{ $test("foobar", \`Foobar ' " ''" test\`) }}</div>
207+
</div>
208+
</template>
209+
"
210+
`)
211+
})
212+
187213
async function fixture(src: string) {
188214
const requireFromVue = createRequire(resolveModulePath('vue'))
189215
const { parse } = requireFromVue('@vue/compiler-dom') as typeof import('@vue/compiler-dom')

0 commit comments

Comments
 (0)