Skip to content

Commit 9842f3e

Browse files
committed
refactor sfc-parser to handle nested template tags
1 parent e472623 commit 9842f3e

File tree

3 files changed

+31
-25
lines changed

3 files changed

+31
-25
lines changed

src/compiler/parser/html-parser.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ let IS_REGEX_CAPTURING_BROKEN = false
4040
})
4141

4242
// Special Elements (can contain anything)
43-
const special = makeMap('script,style', true)
43+
const isSpecialTag = makeMap('script,style', true)
4444

4545
const reCache = {}
4646

@@ -62,7 +62,6 @@ export function parseHTML (html, handler) {
6262
const attribute = attrForHandler(handler)
6363
const expectHTML = handler.expectHTML
6464
const isUnaryTag = handler.isUnaryTag || no
65-
const isSpecialTag = handler.isSpecialTag || special
6665
let index = 0
6766
let last, lastTag
6867
while (html) {

src/compiler/parser/sfc-parser.js

Lines changed: 21 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,18 @@ export function parseComponent (
3232
let depth = 0
3333
let currentBlock: ?SFCBlock = null
3434

35-
function start (tag: string, attrs: Array<Attribute>) {
36-
depth++
37-
if (depth > 1) {
38-
return
39-
}
40-
if (isSpecialTag(tag)) {
35+
function start (
36+
tag: string,
37+
attrs: Array<Attribute>,
38+
unary: boolean,
39+
start: number,
40+
end: number
41+
) {
42+
if (isSpecialTag(tag) && depth === 0) {
4143
currentBlock = {
4244
type: tag,
43-
content: ''
45+
content: '',
46+
start: end
4447
}
4548
checkAttrs(currentBlock, attrs)
4649
if (tag === 'style') {
@@ -49,6 +52,7 @@ export function parseComponent (
4952
sfc[tag] = currentBlock
5053
}
5154
}
55+
depth++
5256
}
5357

5458
function checkAttrs (block: SFCBlock, attrs: Array<Attribute>) {
@@ -66,26 +70,22 @@ export function parseComponent (
6670
}
6771
}
6872

69-
function end () {
70-
depth--
71-
if (options.map && currentBlock && !currentBlock.src) {
72-
addSourceMap(currentBlock)
73-
}
74-
currentBlock = null
75-
}
76-
77-
function chars (text: string) {
78-
if (currentBlock) {
79-
currentBlock.start = content.indexOf(text)
80-
currentBlock.end = currentBlock.start + text.length
81-
text = deindent(text)
73+
function end (tag: string, start: number, end: number) {
74+
if (isSpecialTag(tag) && depth === 1 && currentBlock) {
75+
currentBlock.end = start
76+
let text = deindent(content.slice(currentBlock.start, currentBlock.end))
8277
// pad content so that linters and pre-processors can output correct
8378
// line numbers in errors and warnings
8479
if (currentBlock.type !== 'template' && options.pad) {
8580
text = padContent(currentBlock) + text
8681
}
8782
currentBlock.content = text
83+
if (options.map && !currentBlock.src) {
84+
addSourceMap(currentBlock)
85+
}
86+
currentBlock = null
8887
}
88+
depth--
8989
}
9090

9191
function padContent (block: SFCBlock) {
@@ -127,10 +127,8 @@ export function parseComponent (
127127
}
128128

129129
parseHTML(content, {
130-
isSpecialTag,
131130
start,
132-
end,
133-
chars
131+
end
134132
})
135133

136134
return sfc

test/unit/modules/compiler/sfc-parser.spec.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,15 @@ describe('Single File Component parser', () => {
3030
expect(res.script.content.trim()).toBe('export default {}')
3131
})
3232

33+
it('should handle nested template', () => {
34+
const res = parseComponent(`
35+
<template>
36+
<div><template v-if="ok">hi</template></div>
37+
</template>
38+
`)
39+
expect(res.template.content.trim()).toBe('<div><template v-if="ok">hi</template></div>')
40+
})
41+
3342
it('pad content', () => {
3443
const res = parseComponent(`
3544
<template>

0 commit comments

Comments
 (0)