Skip to content

Commit e472623

Browse files
committed
add location info to html-parser
1 parent 714f793 commit e472623

File tree

1 file changed

+39
-29
lines changed

1 file changed

+39
-29
lines changed

src/compiler/parser/html-parser.js

Lines changed: 39 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export function parseHTML (html, handler) {
6363
const expectHTML = handler.expectHTML
6464
const isUnaryTag = handler.isUnaryTag || no
6565
const isSpecialTag = handler.isSpecialTag || special
66+
let index = 0
6667
let last, lastTag
6768
while (html) {
6869
last = html
@@ -75,7 +76,7 @@ export function parseHTML (html, handler) {
7576
const commentEnd = html.indexOf('-->')
7677

7778
if (commentEnd >= 0) {
78-
html = html.substring(commentEnd + 3)
79+
advance(commentEnd + 3)
7980
continue
8081
}
8182
}
@@ -85,7 +86,7 @@ export function parseHTML (html, handler) {
8586
const conditionalEnd = html.indexOf(']>')
8687

8788
if (conditionalEnd >= 0) {
88-
html = html.substring(conditionalEnd + 2)
89+
advance(conditionalEnd + 2)
8990
continue
9091
}
9192
}
@@ -96,22 +97,22 @@ export function parseHTML (html, handler) {
9697
if (handler.doctype) {
9798
handler.doctype(doctypeMatch[0])
9899
}
99-
html = html.substring(doctypeMatch[0].length)
100+
advance(doctypeMatch[0].length)
100101
continue
101102
}
102103

103104
// End tag:
104105
const endTagMatch = html.match(endTag)
105106
if (endTagMatch) {
106-
html = html.substring(endTagMatch[0].length)
107-
endTagMatch[0].replace(endTag, parseEndTag)
107+
const curIndex = index
108+
advance(endTagMatch[0].length)
109+
parseEndTag(endTagMatch[0], endTagMatch[1], curIndex, index)
108110
continue
109111
}
110112

111113
// Start tag:
112-
const startTagMatch = parseStartTag(html)
114+
const startTagMatch = parseStartTag()
113115
if (startTagMatch) {
114-
html = startTagMatch.rest
115116
handleStartTag(startTagMatch)
116117
continue
117118
}
@@ -120,7 +121,7 @@ export function parseHTML (html, handler) {
120121
let text
121122
if (textEnd >= 0) {
122123
text = html.substring(0, textEnd)
123-
html = html.substring(textEnd)
124+
advance(textEnd)
124125
} else {
125126
text = html
126127
html = ''
@@ -131,9 +132,10 @@ export function parseHTML (html, handler) {
131132
}
132133
} else {
133134
const stackedTag = lastTag.toLowerCase()
134-
const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)</' + stackedTag + '[^>]*>', 'i'))
135-
136-
html = html.replace(reStackedTag, function (all, text) {
135+
const reStackedTag = reCache[stackedTag] || (reCache[stackedTag] = new RegExp('([\\s\\S]*?)(</' + stackedTag + '[^>]*>)', 'i'))
136+
let endTagLength = 0
137+
const rest = html.replace(reStackedTag, function (all, text, endTag) {
138+
endTagLength = endTag.length
137139
if (stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript') {
138140
text = text
139141
.replace(/<!--([\s\S]*?)-->/g, '$1')
@@ -144,36 +146,42 @@ export function parseHTML (html, handler) {
144146
}
145147
return ''
146148
})
147-
148-
parseEndTag('</' + stackedTag + '>', stackedTag)
149+
index += html.length - rest.length
150+
html = rest
151+
parseEndTag('</' + stackedTag + '>', stackedTag, index - endTagLength, index)
149152
}
150153

151154
if (html === last) {
152155
throw new Error('Error parsing template:\n\n' + html)
153156
}
154157
}
155158

156-
if (!handler.partialMarkup) {
157-
// Clean up any remaining tags
158-
parseEndTag()
159+
// Clean up any remaining tags
160+
parseEndTag()
161+
162+
function advance (n) {
163+
index += n
164+
html = html.substring(n)
159165
}
160166

161-
function parseStartTag (input) {
162-
const start = input.match(startTagOpen)
167+
function parseStartTag () {
168+
const start = html.match(startTagOpen)
163169
if (start) {
164170
const match = {
165171
tagName: start[1],
166-
attrs: []
172+
attrs: [],
173+
start: index
167174
}
168-
input = input.slice(start[0].length)
175+
advance(start[0].length)
169176
let end, attr
170-
while (!(end = input.match(startTagClose)) && (attr = input.match(attribute))) {
171-
input = input.slice(attr[0].length)
177+
while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
178+
advance(attr[0].length)
172179
match.attrs.push(attr)
173180
}
174181
if (end) {
175182
match.unarySlash = end[1]
176-
match.rest = input.slice(end[0].length)
183+
advance(end[0].length)
184+
match.end = index
177185
return match
178186
}
179187
}
@@ -217,12 +225,14 @@ export function parseHTML (html, handler) {
217225
}
218226

219227
if (handler.start) {
220-
handler.start(tagName, attrs, unary, unarySlash)
228+
handler.start(tagName, attrs, unary, match.start, match.end)
221229
}
222230
}
223231

224-
function parseEndTag (tag, tagName) {
232+
function parseEndTag (tag, tagName, start, end) {
225233
let pos
234+
if (start == null) start = index
235+
if (end == null) end = index
226236

227237
// Find the closest opened tag of the same type
228238
if (tagName) {
@@ -241,7 +251,7 @@ export function parseHTML (html, handler) {
241251
// Close all the open elements, up the stack
242252
for (let i = stack.length - 1; i >= pos; i--) {
243253
if (handler.end) {
244-
handler.end(stack[i].tag, stack[i].attrs, i > pos || !tag)
254+
handler.end(stack[i].tag, start, end)
245255
}
246256
}
247257

@@ -250,14 +260,14 @@ export function parseHTML (html, handler) {
250260
lastTag = pos && stack[pos - 1].tag
251261
} else if (tagName.toLowerCase() === 'br') {
252262
if (handler.start) {
253-
handler.start(tagName, [], true, '')
263+
handler.start(tagName, [], true, start, end)
254264
}
255265
} else if (tagName.toLowerCase() === 'p') {
256266
if (handler.start) {
257-
handler.start(tagName, [], false, '', true)
267+
handler.start(tagName, [], false, start, end)
258268
}
259269
if (handler.end) {
260-
handler.end(tagName, [])
270+
handler.end(tagName, start, end)
261271
}
262272
}
263273
}

0 commit comments

Comments
 (0)