@@ -63,6 +63,7 @@ export function parseHTML (html, handler) {
63
63
const expectHTML = handler . expectHTML
64
64
const isUnaryTag = handler . isUnaryTag || no
65
65
const isSpecialTag = handler . isSpecialTag || special
66
+ let index = 0
66
67
let last , lastTag
67
68
while ( html ) {
68
69
last = html
@@ -75,7 +76,7 @@ export function parseHTML (html, handler) {
75
76
const commentEnd = html . indexOf ( '-->' )
76
77
77
78
if ( commentEnd >= 0 ) {
78
- html = html . substring ( commentEnd + 3 )
79
+ advance ( commentEnd + 3 )
79
80
continue
80
81
}
81
82
}
@@ -85,7 +86,7 @@ export function parseHTML (html, handler) {
85
86
const conditionalEnd = html . indexOf ( ']>' )
86
87
87
88
if ( conditionalEnd >= 0 ) {
88
- html = html . substring ( conditionalEnd + 2 )
89
+ advance ( conditionalEnd + 2 )
89
90
continue
90
91
}
91
92
}
@@ -96,22 +97,22 @@ export function parseHTML (html, handler) {
96
97
if ( handler . doctype ) {
97
98
handler . doctype ( doctypeMatch [ 0 ] )
98
99
}
99
- html = html . substring ( doctypeMatch [ 0 ] . length )
100
+ advance ( doctypeMatch [ 0 ] . length )
100
101
continue
101
102
}
102
103
103
104
// End tag:
104
105
const endTagMatch = html . match ( endTag )
105
106
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 )
108
110
continue
109
111
}
110
112
111
113
// Start tag:
112
- const startTagMatch = parseStartTag ( html )
114
+ const startTagMatch = parseStartTag ( )
113
115
if ( startTagMatch ) {
114
- html = startTagMatch . rest
115
116
handleStartTag ( startTagMatch )
116
117
continue
117
118
}
@@ -120,7 +121,7 @@ export function parseHTML (html, handler) {
120
121
let text
121
122
if ( textEnd >= 0 ) {
122
123
text = html . substring ( 0 , textEnd )
123
- html = html . substring ( textEnd )
124
+ advance ( textEnd )
124
125
} else {
125
126
text = html
126
127
html = ''
@@ -131,9 +132,10 @@ export function parseHTML (html, handler) {
131
132
}
132
133
} else {
133
134
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
137
139
if ( stackedTag !== 'script' && stackedTag !== 'style' && stackedTag !== 'noscript' ) {
138
140
text = text
139
141
. replace ( / < ! - - ( [ \s \S ] * ?) - - > / g, '$1' )
@@ -144,36 +146,42 @@ export function parseHTML (html, handler) {
144
146
}
145
147
return ''
146
148
} )
147
-
148
- parseEndTag ( '</' + stackedTag + '>' , stackedTag )
149
+ index += html . length - rest . length
150
+ html = rest
151
+ parseEndTag ( '</' + stackedTag + '>' , stackedTag , index - endTagLength , index )
149
152
}
150
153
151
154
if ( html === last ) {
152
155
throw new Error ( 'Error parsing template:\n\n' + html )
153
156
}
154
157
}
155
158
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 )
159
165
}
160
166
161
- function parseStartTag ( input ) {
162
- const start = input . match ( startTagOpen )
167
+ function parseStartTag ( ) {
168
+ const start = html . match ( startTagOpen )
163
169
if ( start ) {
164
170
const match = {
165
171
tagName : start [ 1 ] ,
166
- attrs : [ ]
172
+ attrs : [ ] ,
173
+ start : index
167
174
}
168
- input = input . slice ( start [ 0 ] . length )
175
+ advance ( start [ 0 ] . length )
169
176
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 )
172
179
match . attrs . push ( attr )
173
180
}
174
181
if ( end ) {
175
182
match . unarySlash = end [ 1 ]
176
- match . rest = input . slice ( end [ 0 ] . length )
183
+ advance ( end [ 0 ] . length )
184
+ match . end = index
177
185
return match
178
186
}
179
187
}
@@ -217,12 +225,14 @@ export function parseHTML (html, handler) {
217
225
}
218
226
219
227
if ( handler . start ) {
220
- handler . start ( tagName , attrs , unary , unarySlash )
228
+ handler . start ( tagName , attrs , unary , match . start , match . end )
221
229
}
222
230
}
223
231
224
- function parseEndTag ( tag , tagName ) {
232
+ function parseEndTag ( tag , tagName , start , end ) {
225
233
let pos
234
+ if ( start == null ) start = index
235
+ if ( end == null ) end = index
226
236
227
237
// Find the closest opened tag of the same type
228
238
if ( tagName ) {
@@ -241,7 +251,7 @@ export function parseHTML (html, handler) {
241
251
// Close all the open elements, up the stack
242
252
for ( let i = stack . length - 1 ; i >= pos ; i -- ) {
243
253
if ( handler . end ) {
244
- handler . end ( stack [ i ] . tag , stack [ i ] . attrs , i > pos || ! tag )
254
+ handler . end ( stack [ i ] . tag , start , end )
245
255
}
246
256
}
247
257
@@ -250,14 +260,14 @@ export function parseHTML (html, handler) {
250
260
lastTag = pos && stack [ pos - 1 ] . tag
251
261
} else if ( tagName . toLowerCase ( ) === 'br' ) {
252
262
if ( handler . start ) {
253
- handler . start ( tagName , [ ] , true , '' )
263
+ handler . start ( tagName , [ ] , true , start , end )
254
264
}
255
265
} else if ( tagName . toLowerCase ( ) === 'p' ) {
256
266
if ( handler . start ) {
257
- handler . start ( tagName , [ ] , false , '' , true )
267
+ handler . start ( tagName , [ ] , false , start , end )
258
268
}
259
269
if ( handler . end ) {
260
- handler . end ( tagName , [ ] )
270
+ handler . end ( tagName , start , end )
261
271
}
262
272
}
263
273
}
0 commit comments