fix(parser): fix interpolation parsing in v-pre

ref: https://github.com/vuejs/docs/issues/2586
This commit is contained in:
Evan You 2023-12-04 23:06:56 +08:00
parent c3b704e446
commit 53aaa1eb28
3 changed files with 34 additions and 3 deletions

View File

@ -1733,6 +1733,35 @@ describe('compiler: parse', () => {
}) })
}) })
// https://github.com/vuejs/docs/issues/2586
test('v-pre with half-open interpolation', () => {
const ast = baseParse(
`<div v-pre>
<span>{{ number </span>
<span>}}</span>
</div>
`
)
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(`<div v-pre><span>{{ number </span></div>`)
expect((ast2.children[0] as ElementNode).children).toMatchObject([
{
type: NodeTypes.ELEMENT,
children: [{ type: NodeTypes.TEXT, content: `{{ number ` }]
}
])
})
test('self-closing v-pre', () => { test('self-closing v-pre', () => {
const ast = baseParse( const ast = baseParse(
`<div v-pre/>\n<div :id="foo"><Comp/>{{ bar }}</div>` `<div v-pre/>\n<div :id="foo"><Comp/>{{ bar }}</div>`

View File

@ -236,7 +236,7 @@ const tokenizer = new Tokenizer(stack, {
loc: getLoc(start) loc: getLoc(start)
} }
if (name === 'pre') { if (name === 'pre') {
inVPre = true inVPre = tokenizer.inVPre = true
currentVPreBoundary = currentOpenTag currentVPreBoundary = currentOpenTag
// convert dirs before this one to attributes // convert dirs before this one to attributes
const props = currentOpenTag!.props const props = currentOpenTag!.props
@ -652,7 +652,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
inPre-- inPre--
} }
if (currentVPreBoundary === el) { if (currentVPreBoundary === el) {
inVPre = false inVPre = tokenizer.inVPre = false
currentVPreBoundary = null currentVPreBoundary = null
} }
if ( if (

View File

@ -242,6 +242,8 @@ export default class Tokenizer {
public inRCDATA = false public inRCDATA = false
/** For disabling RCDATA tags handling */ /** For disabling RCDATA tags handling */
public inXML = false public inXML = false
/** For disabling interpolation parsing in v-pre */
public inVPre = false
/** Record newline positions for fast line / column calculation */ /** Record newline positions for fast line / column calculation */
private newlines: number[] = [] private newlines: number[] = []
@ -314,7 +316,7 @@ export default class Tokenizer {
this.sectionStart = this.index this.sectionStart = this.index
} else if (!__BROWSER__ && c === CharCodes.Amp) { } else if (!__BROWSER__ && c === CharCodes.Amp) {
this.startEntity() this.startEntity()
} else if (c === this.delimiterOpen[0]) { } else if (!this.inVPre && c === this.delimiterOpen[0]) {
this.state = State.InterpolationOpen this.state = State.InterpolationOpen
this.delimiterIndex = 0 this.delimiterIndex = 0
this.stateInterpolationOpen(c) this.stateInterpolationOpen(c)