From 53aaa1eb2876baf9de16b2f2c77b2c5fd5173900 Mon Sep 17 00:00:00 2001 From: Evan You Date: Mon, 4 Dec 2023 23:06:56 +0800 Subject: [PATCH] fix(parser): fix interpolation parsing in v-pre ref: https://github.com/vuejs/docs/issues/2586 --- .../compiler-core/__tests__/parse.spec.ts | 29 +++++++++++++++++++ packages/compiler-core/src/parser.ts | 4 +-- packages/compiler-core/src/tokenizer.ts | 4 ++- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/packages/compiler-core/__tests__/parse.spec.ts b/packages/compiler-core/__tests__/parse.spec.ts index 9d84e80c2..7c6b9f463 100644 --- a/packages/compiler-core/__tests__/parse.spec.ts +++ b/packages/compiler-core/__tests__/parse.spec.ts @@ -1733,6 +1733,35 @@ describe('compiler: parse', () => { }) }) + // https://github.com/vuejs/docs/issues/2586 + test('v-pre with half-open interpolation', () => { + const ast = baseParse( + `
+ {{ number + }} +
+ ` + ) + expect((ast.children[0] as ElementNode).children).toMatchObject([ + { + type: NodeTypes.ELEMENT, + children: [{ type: NodeTypes.TEXT, content: `{{ number ` }] + }, + { + type: NodeTypes.ELEMENT, + children: [{ type: NodeTypes.TEXT, content: `}}` }] + } + ]) + + const ast2 = baseParse(`
{{ number
`) + expect((ast2.children[0] as ElementNode).children).toMatchObject([ + { + type: NodeTypes.ELEMENT, + children: [{ type: NodeTypes.TEXT, content: `{{ number ` }] + } + ]) + }) + test('self-closing v-pre', () => { const ast = baseParse( `
\n
{{ bar }}
` diff --git a/packages/compiler-core/src/parser.ts b/packages/compiler-core/src/parser.ts index f1d712b36..2250719f5 100644 --- a/packages/compiler-core/src/parser.ts +++ b/packages/compiler-core/src/parser.ts @@ -236,7 +236,7 @@ const tokenizer = new Tokenizer(stack, { loc: getLoc(start) } if (name === 'pre') { - inVPre = true + inVPre = tokenizer.inVPre = true currentVPreBoundary = currentOpenTag // convert dirs before this one to attributes const props = currentOpenTag!.props @@ -652,7 +652,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) { inPre-- } if (currentVPreBoundary === el) { - inVPre = false + inVPre = tokenizer.inVPre = false currentVPreBoundary = null } if ( diff --git a/packages/compiler-core/src/tokenizer.ts b/packages/compiler-core/src/tokenizer.ts index ca122f309..8adb1b47b 100644 --- a/packages/compiler-core/src/tokenizer.ts +++ b/packages/compiler-core/src/tokenizer.ts @@ -242,6 +242,8 @@ export default class Tokenizer { public inRCDATA = false /** For disabling RCDATA tags handling */ public inXML = false + /** For disabling interpolation parsing in v-pre */ + public inVPre = false /** Record newline positions for fast line / column calculation */ private newlines: number[] = [] @@ -314,7 +316,7 @@ export default class Tokenizer { this.sectionStart = this.index } else if (!__BROWSER__ && c === CharCodes.Amp) { this.startEntity() - } else if (c === this.delimiterOpen[0]) { + } else if (!this.inVPre && c === this.delimiterOpen[0]) { this.state = State.InterpolationOpen this.delimiterIndex = 0 this.stateInterpolationOpen(c)