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)