OLD | NEW |
1 /// This library has a parser for HTML5 documents, that lets you parse HTML | 1 /// This library has a parser for HTML5 documents, that lets you parse HTML |
2 /// easily from a script or server side application: | 2 /// easily from a script or server side application: |
3 /// | 3 /// |
4 /// import 'package:html5lib/parser.dart' show parse; | 4 /// import 'package:html5lib/parser.dart' show parse; |
5 /// import 'package:html5lib/dom.dart'; | 5 /// import 'package:html5lib/dom.dart'; |
6 /// main() { | 6 /// main() { |
7 /// var document = parse( | 7 /// var document = parse( |
8 /// '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); | 8 /// '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); |
9 /// print(document.outerHtml); | 9 /// print(document.outerHtml); |
10 /// } | 10 /// } |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 resetInsertionMode(); | 242 resetInsertionMode(); |
243 } else { | 243 } else { |
244 phase = _initialPhase; | 244 phase = _initialPhase; |
245 } | 245 } |
246 | 246 |
247 lastPhase = null; | 247 lastPhase = null; |
248 beforeRCDataPhase = null; | 248 beforeRCDataPhase = null; |
249 framesetOK = true; | 249 framesetOK = true; |
250 } | 250 } |
251 | 251 |
252 bool isHTMLIntegrationPoint(Node element) { | 252 bool isHTMLIntegrationPoint(Element element) { |
253 if (element.tagName == "annotation-xml" && | 253 if (element.localName == "annotation-xml" && |
254 element.namespace == Namespaces.mathml) { | 254 element.namespaceUri == Namespaces.mathml) { |
255 var enc = element.attributes["encoding"]; | 255 var enc = element.attributes["encoding"]; |
256 if (enc != null) enc = asciiUpper2Lower(enc); | 256 if (enc != null) enc = asciiUpper2Lower(enc); |
257 return enc == "text/html" || enc == "application/xhtml+xml"; | 257 return enc == "text/html" || enc == "application/xhtml+xml"; |
258 } else { | 258 } else { |
259 return htmlIntegrationPointElements.contains( | 259 return htmlIntegrationPointElements.contains( |
260 new Pair(element.namespace, element.tagName)); | 260 new Pair(element.namespaceUri, element.localName)); |
261 } | 261 } |
262 } | 262 } |
263 | 263 |
264 bool isMathMLTextIntegrationPoint(Node element) { | 264 bool isMathMLTextIntegrationPoint(Element element) { |
265 return mathmlTextIntegrationPointElements.contains( | 265 return mathmlTextIntegrationPointElements.contains( |
266 new Pair(element.namespace, element.tagName)); | 266 new Pair(element.namespaceUri, element.localName)); |
267 } | 267 } |
268 | 268 |
269 bool inForeignContent(Token token, int type) { | 269 bool inForeignContent(Token token, int type) { |
270 if (tree.openElements.length == 0) return false; | 270 if (tree.openElements.length == 0) return false; |
271 | 271 |
272 var node = tree.openElements.last; | 272 var node = tree.openElements.last; |
273 if (node.namespace == tree.defaultNamespace) return false; | 273 if (node.namespaceUri == tree.defaultNamespace) return false; |
274 | 274 |
275 if (isMathMLTextIntegrationPoint(node)) { | 275 if (isMathMLTextIntegrationPoint(node)) { |
276 if (type == TokenKind.startTag && | 276 if (type == TokenKind.startTag && |
277 (token as StartTagToken).name != "mglyph" && | 277 (token as StartTagToken).name != "mglyph" && |
278 (token as StartTagToken).name != "malignmark") { | 278 (token as StartTagToken).name != "malignmark") { |
279 return false; | 279 return false; |
280 } | 280 } |
281 if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { | 281 if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { |
282 return false; | 282 return false; |
283 } | 283 } |
284 } | 284 } |
285 | 285 |
286 if (node.tagName == "annotation-xml" && type == TokenKind.startTag && | 286 if (node.localName == "annotation-xml" && type == TokenKind.startTag && |
287 (token as StartTagToken).name == "svg") { | 287 (token as StartTagToken).name == "svg") { |
288 return false; | 288 return false; |
289 } | 289 } |
290 | 290 |
291 if (isHTMLIntegrationPoint(node)) { | 291 if (isHTMLIntegrationPoint(node)) { |
292 if (type == TokenKind.startTag || | 292 if (type == TokenKind.startTag || |
293 type == TokenKind.characters || | 293 type == TokenKind.characters || |
294 type == TokenKind.spaceCharacters) { | 294 type == TokenKind.spaceCharacters) { |
295 return false; | 295 return false; |
296 } | 296 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
484 var foreignName = replacements[originalName]; | 484 var foreignName = replacements[originalName]; |
485 if (foreignName != null) { | 485 if (foreignName != null) { |
486 token.data[foreignName] = token.data.remove(originalName); | 486 token.data[foreignName] = token.data.remove(originalName); |
487 } | 487 } |
488 } | 488 } |
489 } | 489 } |
490 | 490 |
491 void resetInsertionMode() { | 491 void resetInsertionMode() { |
492 // The name of this method is mostly historical. (It's also used in the | 492 // The name of this method is mostly historical. (It's also used in the |
493 // specification.) | 493 // specification.) |
494 for (Node node in tree.openElements.reversed) { | 494 for (var node in tree.openElements.reversed) { |
495 var nodeName = node.tagName; | 495 var nodeName = node.localName; |
496 bool last = node == tree.openElements[0]; | 496 bool last = node == tree.openElements[0]; |
497 if (last) { | 497 if (last) { |
498 assert(innerHTMLMode); | 498 assert(innerHTMLMode); |
499 nodeName = innerHTML; | 499 nodeName = innerHTML; |
500 } | 500 } |
501 // Check for conditions that should only happen in the innerHTML | 501 // Check for conditions that should only happen in the innerHTML |
502 // case | 502 // case |
503 switch (nodeName) { | 503 switch (nodeName) { |
504 case "select": case "colgroup": case "head": case "html": | 504 case "select": case "colgroup": case "head": case "html": |
505 assert(innerHTMLMode); | 505 assert(innerHTMLMode); |
506 break; | 506 break; |
507 } | 507 } |
508 if (!last && node.namespace != tree.defaultNamespace) { | 508 if (!last && node.namespaceUri != tree.defaultNamespace) { |
509 continue; | 509 continue; |
510 } | 510 } |
511 switch (nodeName) { | 511 switch (nodeName) { |
512 case "select": phase = _inSelectPhase; return; | 512 case "select": phase = _inSelectPhase; return; |
513 case "td": phase = _inCellPhase; return; | 513 case "td": phase = _inCellPhase; return; |
514 case "th": phase = _inCellPhase; return; | 514 case "th": phase = _inCellPhase; return; |
515 case "tr": phase = _inRowPhase; return; | 515 case "tr": phase = _inRowPhase; return; |
516 case "tbody": phase = _inTableBodyPhase; return; | 516 case "tbody": phase = _inTableBodyPhase; return; |
517 case "thead": phase = _inTableBodyPhase; return; | 517 case "thead": phase = _inTableBodyPhase; return; |
518 case "tfoot": phase = _inTableBodyPhase; return; | 518 case "tfoot": phase = _inTableBodyPhase; return; |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 return null; | 609 return null; |
610 } | 610 } |
611 | 611 |
612 Token processEndTag(EndTagToken token) { | 612 Token processEndTag(EndTagToken token) { |
613 throw new UnimplementedError(); | 613 throw new UnimplementedError(); |
614 } | 614 } |
615 | 615 |
616 /// Helper method for popping openElements. | 616 /// Helper method for popping openElements. |
617 void popOpenElementsUntil(String name) { | 617 void popOpenElementsUntil(String name) { |
618 var node = tree.openElements.removeLast(); | 618 var node = tree.openElements.removeLast(); |
619 while (node.tagName != name) { | 619 while (node.localName != name) { |
620 node = tree.openElements.removeLast(); | 620 node = tree.openElements.removeLast(); |
621 } | 621 } |
622 } | 622 } |
623 } | 623 } |
624 | 624 |
625 class InitialPhase extends Phase { | 625 class InitialPhase extends Phase { |
626 InitialPhase(parser) : super(parser); | 626 InitialPhase(parser) : super(parser); |
627 | 627 |
628 Token processSpaceCharacters(SpaceCharactersToken token) { | 628 Token processSpaceCharacters(SpaceCharactersToken token) { |
629 return null; | 629 return null; |
(...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
964 parser.phase = parser._textPhase; | 964 parser.phase = parser._textPhase; |
965 } | 965 } |
966 | 966 |
967 Token startTagOther(StartTagToken token) { | 967 Token startTagOther(StartTagToken token) { |
968 anythingElse(); | 968 anythingElse(); |
969 return token; | 969 return token; |
970 } | 970 } |
971 | 971 |
972 void endTagHead(EndTagToken token) { | 972 void endTagHead(EndTagToken token) { |
973 var node = parser.tree.openElements.removeLast(); | 973 var node = parser.tree.openElements.removeLast(); |
974 assert(node.tagName == "head"); | 974 assert(node.localName == "head"); |
975 parser.phase = parser._afterHeadPhase; | 975 parser.phase = parser._afterHeadPhase; |
976 } | 976 } |
977 | 977 |
978 Token endTagHtmlBodyBr(EndTagToken token) { | 978 Token endTagHtmlBodyBr(EndTagToken token) { |
979 anythingElse(); | 979 anythingElse(); |
980 return token; | 980 return token; |
981 } | 981 } |
982 | 982 |
983 void endTagOther(EndTagToken token) { | 983 void endTagOther(EndTagToken token) { |
984 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); | 984 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 void startTagFrameset(StartTagToken token) { | 1042 void startTagFrameset(StartTagToken token) { |
1043 tree.insertElement(token); | 1043 tree.insertElement(token); |
1044 parser.phase = parser._inFramesetPhase; | 1044 parser.phase = parser._inFramesetPhase; |
1045 } | 1045 } |
1046 | 1046 |
1047 void startTagFromHead(StartTagToken token) { | 1047 void startTagFromHead(StartTagToken token) { |
1048 parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", | 1048 parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", |
1049 {"name": token.name}); | 1049 {"name": token.name}); |
1050 tree.openElements.add(tree.headPointer); | 1050 tree.openElements.add(tree.headPointer); |
1051 parser._inHeadPhase.processStartTag(token); | 1051 parser._inHeadPhase.processStartTag(token); |
1052 for (Node node in tree.openElements.reversed) { | 1052 for (var node in tree.openElements.reversed) { |
1053 if (node.tagName == "head") { | 1053 if (node.localName == "head") { |
1054 tree.openElements.remove(node); | 1054 tree.openElements.remove(node); |
1055 break; | 1055 break; |
1056 } | 1056 } |
1057 } | 1057 } |
1058 } | 1058 } |
1059 | 1059 |
1060 void startTagHead(StartTagToken token) { | 1060 void startTagHead(StartTagToken token) { |
1061 parser.parseError(token.span, "unexpected-start-tag", {"name": token.name}); | 1061 parser.parseError(token.span, "unexpected-start-tag", {"name": token.name}); |
1062 } | 1062 } |
1063 | 1063 |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1189 case "i": case "nobr": case "s": case "small": case "strike": | 1189 case "i": case "nobr": case "s": case "small": case "strike": |
1190 case "strong": case "tt": case "u": | 1190 case "strong": case "tt": case "u": |
1191 return endTagFormatting(token); | 1191 return endTagFormatting(token); |
1192 case "applet": case "marquee": case "object": | 1192 case "applet": case "marquee": case "object": |
1193 return endTagAppletMarqueeObject(token); | 1193 return endTagAppletMarqueeObject(token); |
1194 case "br": return endTagBr(token); | 1194 case "br": return endTagBr(token); |
1195 default: return endTagOther(token); | 1195 default: return endTagOther(token); |
1196 } | 1196 } |
1197 } | 1197 } |
1198 | 1198 |
1199 bool isMatchingFormattingElement(Node node1, Node node2) { | 1199 bool isMatchingFormattingElement(Element node1, Element node2) { |
1200 if (node1.tagName != node2.tagName || node1.namespace != node2.namespace) { | 1200 if (node1.localName != node2.localName || |
| 1201 node1.namespaceUri != node2.namespaceUri) { |
1201 return false; | 1202 return false; |
1202 } else if (node1.attributes.length != node2.attributes.length) { | 1203 } else if (node1.attributes.length != node2.attributes.length) { |
1203 return false; | 1204 return false; |
1204 } else { | 1205 } else { |
1205 for (var key in node1.attributes.keys) { | 1206 for (var key in node1.attributes.keys) { |
1206 if (node1.attributes[key] != node2.attributes[key]) { | 1207 if (node1.attributes[key] != node2.attributes[key]) { |
1207 return false; | 1208 return false; |
1208 } | 1209 } |
1209 } | 1210 } |
1210 } | 1211 } |
(...skipping 16 matching lines...) Expand all Loading... |
1227 | 1228 |
1228 assert(matchingElements.length <= 3); | 1229 assert(matchingElements.length <= 3); |
1229 if (matchingElements.length == 3) { | 1230 if (matchingElements.length == 3) { |
1230 tree.activeFormattingElements.remove(matchingElements.last); | 1231 tree.activeFormattingElements.remove(matchingElements.last); |
1231 } | 1232 } |
1232 tree.activeFormattingElements.add(element); | 1233 tree.activeFormattingElements.add(element); |
1233 } | 1234 } |
1234 | 1235 |
1235 // the real deal | 1236 // the real deal |
1236 bool processEOF() { | 1237 bool processEOF() { |
1237 for (Node node in tree.openElements.reversed) { | 1238 for (var node in tree.openElements.reversed) { |
1238 switch (node.tagName) { | 1239 switch (node.localName) { |
1239 case "dd": case "dt": case "li": case "p": case "tbody": case "td": | 1240 case "dd": case "dt": case "li": case "p": case "tbody": case "td": |
1240 case "tfoot": case "th": case "thead": case "tr": case "body": | 1241 case "tfoot": case "th": case "thead": case "tr": case "body": |
1241 case "html": | 1242 case "html": |
1242 continue; | 1243 continue; |
1243 } | 1244 } |
1244 parser.parseError(node.sourceSpan, "expected-closing-tag-but-got-eof"); | 1245 parser.parseError(node.sourceSpan, "expected-closing-tag-but-got-eof"); |
1245 break; | 1246 break; |
1246 } | 1247 } |
1247 //Stop parsing | 1248 //Stop parsing |
1248 return false; | 1249 return false; |
1249 } | 1250 } |
1250 | 1251 |
1251 void processSpaceCharactersDropNewline(StringToken token) { | 1252 void processSpaceCharactersDropNewline(StringToken token) { |
1252 // Sometimes (start of <pre>, <listing>, and <textarea> blocks) we | 1253 // Sometimes (start of <pre>, <listing>, and <textarea> blocks) we |
1253 // want to drop leading newlines | 1254 // want to drop leading newlines |
1254 var data = token.data; | 1255 var data = token.data; |
1255 dropNewline = false; | 1256 dropNewline = false; |
1256 if (data.startsWith("\n")) { | 1257 if (data.startsWith("\n")) { |
1257 var lastOpen = tree.openElements.last; | 1258 var lastOpen = tree.openElements.last; |
1258 if (const ["pre", "listing", "textarea"].contains(lastOpen.tagName) | 1259 if (const ["pre", "listing", "textarea"].contains(lastOpen.localName) |
1259 && !lastOpen.hasContent()) { | 1260 && !lastOpen.hasContent()) { |
1260 data = data.substring(1); | 1261 data = data.substring(1); |
1261 } | 1262 } |
1262 } | 1263 } |
1263 if (data.length > 0) { | 1264 if (data.length > 0) { |
1264 tree.reconstructActiveFormattingElements(); | 1265 tree.reconstructActiveFormattingElements(); |
1265 tree.insertText(data, token.span); | 1266 tree.insertText(data, token.span); |
1266 } | 1267 } |
1267 } | 1268 } |
1268 | 1269 |
(...skipping 20 matching lines...) Expand all Loading... |
1289 return null; | 1290 return null; |
1290 } | 1291 } |
1291 | 1292 |
1292 Token startTagProcessInHead(StartTagToken token) { | 1293 Token startTagProcessInHead(StartTagToken token) { |
1293 return parser._inHeadPhase.processStartTag(token); | 1294 return parser._inHeadPhase.processStartTag(token); |
1294 } | 1295 } |
1295 | 1296 |
1296 void startTagBody(StartTagToken token) { | 1297 void startTagBody(StartTagToken token) { |
1297 parser.parseError(token.span, "unexpected-start-tag", {"name": "body"}); | 1298 parser.parseError(token.span, "unexpected-start-tag", {"name": "body"}); |
1298 if (tree.openElements.length == 1 | 1299 if (tree.openElements.length == 1 |
1299 || tree.openElements[1].tagName != "body") { | 1300 || tree.openElements[1].localName != "body") { |
1300 assert(parser.innerHTMLMode); | 1301 assert(parser.innerHTMLMode); |
1301 } else { | 1302 } else { |
1302 parser.framesetOK = false; | 1303 parser.framesetOK = false; |
1303 token.data.forEach((attr, value) { | 1304 token.data.forEach((attr, value) { |
1304 tree.openElements[1].attributes.putIfAbsent(attr, () => value); | 1305 tree.openElements[1].attributes.putIfAbsent(attr, () => value); |
1305 }); | 1306 }); |
1306 } | 1307 } |
1307 } | 1308 } |
1308 | 1309 |
1309 void startTagFrameset(StartTagToken token) { | 1310 void startTagFrameset(StartTagToken token) { |
1310 parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"}); | 1311 parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"}); |
1311 if ((tree.openElements.length == 1 || | 1312 if ((tree.openElements.length == 1 || |
1312 tree.openElements[1].tagName != "body")) { | 1313 tree.openElements[1].localName != "body")) { |
1313 assert(parser.innerHTMLMode); | 1314 assert(parser.innerHTMLMode); |
1314 } else if (parser.framesetOK) { | 1315 } else if (parser.framesetOK) { |
1315 if (tree.openElements[1].parent != null) { | 1316 if (tree.openElements[1].parent != null) { |
1316 tree.openElements[1].parent.nodes.remove(tree.openElements[1]); | 1317 tree.openElements[1].parent.nodes.remove(tree.openElements[1]); |
1317 } | 1318 } |
1318 while (tree.openElements.last.tagName != "html") { | 1319 while (tree.openElements.last.localName != "html") { |
1319 tree.openElements.removeLast(); | 1320 tree.openElements.removeLast(); |
1320 } | 1321 } |
1321 tree.insertElement(token); | 1322 tree.insertElement(token); |
1322 parser.phase = parser._inFramesetPhase; | 1323 parser.phase = parser._inFramesetPhase; |
1323 } | 1324 } |
1324 } | 1325 } |
1325 | 1326 |
1326 void startTagCloseP(StartTagToken token) { | 1327 void startTagCloseP(StartTagToken token) { |
1327 if (tree.elementInScope("p", variant: "button")) { | 1328 if (tree.elementInScope("p", variant: "button")) { |
1328 endTagP(new EndTagToken("p")); | 1329 endTagP(new EndTagToken("p")); |
(...skipping 22 matching lines...) Expand all Loading... |
1351 } | 1352 } |
1352 } | 1353 } |
1353 | 1354 |
1354 void startTagListItem(StartTagToken token) { | 1355 void startTagListItem(StartTagToken token) { |
1355 parser.framesetOK = false; | 1356 parser.framesetOK = false; |
1356 | 1357 |
1357 final stopNamesMap = const {"li": const ["li"], | 1358 final stopNamesMap = const {"li": const ["li"], |
1358 "dt": const ["dt", "dd"], | 1359 "dt": const ["dt", "dd"], |
1359 "dd": const ["dt", "dd"]}; | 1360 "dd": const ["dt", "dd"]}; |
1360 var stopNames = stopNamesMap[token.name]; | 1361 var stopNames = stopNamesMap[token.name]; |
1361 for (Node node in tree.openElements.reversed) { | 1362 for (var node in tree.openElements.reversed) { |
1362 if (stopNames.contains(node.tagName)) { | 1363 if (stopNames.contains(node.localName)) { |
1363 parser.phase.processEndTag(new EndTagToken(node.tagName)); | 1364 parser.phase.processEndTag(new EndTagToken(node.localName)); |
1364 break; | 1365 break; |
1365 } | 1366 } |
1366 if (specialElements.contains(node.nameTuple) && | 1367 if (specialElements.contains(getElementNameTuple(node)) && |
1367 !const ["address", "div", "p"].contains(node.tagName)) { | 1368 !const ["address", "div", "p"].contains(node.localName)) { |
1368 break; | 1369 break; |
1369 } | 1370 } |
1370 } | 1371 } |
1371 | 1372 |
1372 if (tree.elementInScope("p", variant: "button")) { | 1373 if (tree.elementInScope("p", variant: "button")) { |
1373 parser.phase.processEndTag(new EndTagToken("p")); | 1374 parser.phase.processEndTag(new EndTagToken("p")); |
1374 } | 1375 } |
1375 | 1376 |
1376 tree.insertElement(token); | 1377 tree.insertElement(token); |
1377 } | 1378 } |
1378 | 1379 |
1379 void startTagPlaintext(StartTagToken token) { | 1380 void startTagPlaintext(StartTagToken token) { |
1380 if (tree.elementInScope("p", variant: "button")) { | 1381 if (tree.elementInScope("p", variant: "button")) { |
1381 endTagP(new EndTagToken("p")); | 1382 endTagP(new EndTagToken("p")); |
1382 } | 1383 } |
1383 tree.insertElement(token); | 1384 tree.insertElement(token); |
1384 parser.tokenizer.state = parser.tokenizer.plaintextState; | 1385 parser.tokenizer.state = parser.tokenizer.plaintextState; |
1385 } | 1386 } |
1386 | 1387 |
1387 void startTagHeading(StartTagToken token) { | 1388 void startTagHeading(StartTagToken token) { |
1388 if (tree.elementInScope("p", variant: "button")) { | 1389 if (tree.elementInScope("p", variant: "button")) { |
1389 endTagP(new EndTagToken("p")); | 1390 endTagP(new EndTagToken("p")); |
1390 } | 1391 } |
1391 if (headingElements.contains(tree.openElements.last.tagName)) { | 1392 if (headingElements.contains(tree.openElements.last.localName)) { |
1392 parser.parseError(token.span, "unexpected-start-tag", | 1393 parser.parseError(token.span, "unexpected-start-tag", |
1393 {"name": token.name}); | 1394 {"name": token.name}); |
1394 tree.openElements.removeLast(); | 1395 tree.openElements.removeLast(); |
1395 } | 1396 } |
1396 tree.insertElement(token); | 1397 tree.insertElement(token); |
1397 } | 1398 } |
1398 | 1399 |
1399 void startTagA(StartTagToken token) { | 1400 void startTagA(StartTagToken token) { |
1400 var afeAElement = tree.elementInActiveFormattingElements("a"); | 1401 var afeAElement = tree.elementInActiveFormattingElements("a"); |
1401 if (afeAElement != null) { | 1402 if (afeAElement != null) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 parser.framesetOK = false; | 1550 parser.framesetOK = false; |
1550 startTagRawtext(token); | 1551 startTagRawtext(token); |
1551 } | 1552 } |
1552 | 1553 |
1553 /// iframe, noembed noframes, noscript(if scripting enabled). | 1554 /// iframe, noembed noframes, noscript(if scripting enabled). |
1554 void startTagRawtext(StartTagToken token) { | 1555 void startTagRawtext(StartTagToken token) { |
1555 parser.parseRCDataRawtext(token, "RAWTEXT"); | 1556 parser.parseRCDataRawtext(token, "RAWTEXT"); |
1556 } | 1557 } |
1557 | 1558 |
1558 void startTagOpt(StartTagToken token) { | 1559 void startTagOpt(StartTagToken token) { |
1559 if (tree.openElements.last.tagName == "option") { | 1560 if (tree.openElements.last.localName == "option") { |
1560 parser.phase.processEndTag(new EndTagToken("option")); | 1561 parser.phase.processEndTag(new EndTagToken("option")); |
1561 } | 1562 } |
1562 tree.reconstructActiveFormattingElements(); | 1563 tree.reconstructActiveFormattingElements(); |
1563 parser.tree.insertElement(token); | 1564 parser.tree.insertElement(token); |
1564 } | 1565 } |
1565 | 1566 |
1566 void startTagSelect(StartTagToken token) { | 1567 void startTagSelect(StartTagToken token) { |
1567 tree.reconstructActiveFormattingElements(); | 1568 tree.reconstructActiveFormattingElements(); |
1568 tree.insertElement(token); | 1569 tree.insertElement(token); |
1569 parser.framesetOK = false; | 1570 parser.framesetOK = false; |
1570 | 1571 |
1571 if (parser._inTablePhase == parser.phase || | 1572 if (parser._inTablePhase == parser.phase || |
1572 parser._inCaptionPhase == parser.phase || | 1573 parser._inCaptionPhase == parser.phase || |
1573 parser._inColumnGroupPhase == parser.phase || | 1574 parser._inColumnGroupPhase == parser.phase || |
1574 parser._inTableBodyPhase == parser.phase || | 1575 parser._inTableBodyPhase == parser.phase || |
1575 parser._inRowPhase == parser.phase || | 1576 parser._inRowPhase == parser.phase || |
1576 parser._inCellPhase == parser.phase) { | 1577 parser._inCellPhase == parser.phase) { |
1577 parser.phase = parser._inSelectInTablePhase; | 1578 parser.phase = parser._inSelectInTablePhase; |
1578 } else { | 1579 } else { |
1579 parser.phase = parser._inSelectPhase; | 1580 parser.phase = parser._inSelectPhase; |
1580 } | 1581 } |
1581 } | 1582 } |
1582 | 1583 |
1583 void startTagRpRt(StartTagToken token) { | 1584 void startTagRpRt(StartTagToken token) { |
1584 if (tree.elementInScope("ruby")) { | 1585 if (tree.elementInScope("ruby")) { |
1585 tree.generateImpliedEndTags(); | 1586 tree.generateImpliedEndTags(); |
1586 var last = tree.openElements.last; | 1587 var last = tree.openElements.last; |
1587 if (last.tagName != "ruby") { | 1588 if (last.localName != "ruby") { |
1588 parser.parseError(last.sourceSpan, 'undefined-error'); | 1589 parser.parseError(last.sourceSpan, 'undefined-error'); |
1589 } | 1590 } |
1590 } | 1591 } |
1591 tree.insertElement(token); | 1592 tree.insertElement(token); |
1592 } | 1593 } |
1593 | 1594 |
1594 void startTagMath(StartTagToken token) { | 1595 void startTagMath(StartTagToken token) { |
1595 tree.reconstructActiveFormattingElements(); | 1596 tree.reconstructActiveFormattingElements(); |
1596 parser.adjustMathMLAttributes(token); | 1597 parser.adjustMathMLAttributes(token); |
1597 parser.adjustForeignAttributes(token); | 1598 parser.adjustForeignAttributes(token); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1635 return null; | 1636 return null; |
1636 } | 1637 } |
1637 | 1638 |
1638 void endTagP(EndTagToken token) { | 1639 void endTagP(EndTagToken token) { |
1639 if (!tree.elementInScope("p", variant: "button")) { | 1640 if (!tree.elementInScope("p", variant: "button")) { |
1640 startTagCloseP(new StartTagToken("p", data: {})); | 1641 startTagCloseP(new StartTagToken("p", data: {})); |
1641 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); | 1642 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); |
1642 endTagP(new EndTagToken("p")); | 1643 endTagP(new EndTagToken("p")); |
1643 } else { | 1644 } else { |
1644 tree.generateImpliedEndTags("p"); | 1645 tree.generateImpliedEndTags("p"); |
1645 if (tree.openElements.last.tagName != "p") { | 1646 if (tree.openElements.last.localName != "p") { |
1646 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); | 1647 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); |
1647 } | 1648 } |
1648 popOpenElementsUntil("p"); | 1649 popOpenElementsUntil("p"); |
1649 } | 1650 } |
1650 } | 1651 } |
1651 | 1652 |
1652 void endTagBody(EndTagToken token) { | 1653 void endTagBody(EndTagToken token) { |
1653 if (!tree.elementInScope("body")) { | 1654 if (!tree.elementInScope("body")) { |
1654 parser.parseError(token.span, 'undefined-error'); | 1655 parser.parseError(token.span, 'undefined-error'); |
1655 return; | 1656 return; |
1656 } else if (tree.openElements.last.tagName != "body") { | 1657 } else if (tree.openElements.last.localName != "body") { |
1657 for (Node node in slice(tree.openElements, 2)) { | 1658 for (Element node in slice(tree.openElements, 2)) { |
1658 switch (node.tagName) { | 1659 switch (node.localName) { |
1659 case "dd": case "dt": case "li": case "optgroup": case "option": | 1660 case "dd": case "dt": case "li": case "optgroup": case "option": |
1660 case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": | 1661 case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": |
1661 case "th": case "thead": case "tr": case "body": case "html": | 1662 case "th": case "thead": case "tr": case "body": case "html": |
1662 continue; | 1663 continue; |
1663 } | 1664 } |
1664 // Not sure this is the correct name for the parse error | 1665 // Not sure this is the correct name for the parse error |
1665 parser.parseError(token.span, "expected-one-end-tag-but-got-another", | 1666 parser.parseError(token.span, "expected-one-end-tag-but-got-another", |
1666 {"gotName": "body", "expectedName": node.tagName}); | 1667 {"gotName": "body", "expectedName": node.localName}); |
1667 break; | 1668 break; |
1668 } | 1669 } |
1669 } | 1670 } |
1670 parser.phase = parser._afterBodyPhase; | 1671 parser.phase = parser._afterBodyPhase; |
1671 } | 1672 } |
1672 | 1673 |
1673 Token endTagHtml(EndTagToken token) { | 1674 Token endTagHtml(EndTagToken token) { |
1674 //We repeat the test for the body end tag token being ignored here | 1675 //We repeat the test for the body end tag token being ignored here |
1675 if (tree.elementInScope("body")) { | 1676 if (tree.elementInScope("body")) { |
1676 endTagBody(new EndTagToken("body")); | 1677 endTagBody(new EndTagToken("body")); |
1677 return token; | 1678 return token; |
1678 } | 1679 } |
1679 return null; | 1680 return null; |
1680 } | 1681 } |
1681 | 1682 |
1682 void endTagBlock(EndTagToken token) { | 1683 void endTagBlock(EndTagToken token) { |
1683 //Put us back in the right whitespace handling mode | 1684 //Put us back in the right whitespace handling mode |
1684 if (token.name == "pre") { | 1685 if (token.name == "pre") { |
1685 dropNewline = false; | 1686 dropNewline = false; |
1686 } | 1687 } |
1687 var inScope = tree.elementInScope(token.name); | 1688 var inScope = tree.elementInScope(token.name); |
1688 if (inScope) { | 1689 if (inScope) { |
1689 tree.generateImpliedEndTags(); | 1690 tree.generateImpliedEndTags(); |
1690 } | 1691 } |
1691 if (tree.openElements.last.tagName != token.name) { | 1692 if (tree.openElements.last.localName != token.name) { |
1692 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); | 1693 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); |
1693 } | 1694 } |
1694 if (inScope) { | 1695 if (inScope) { |
1695 popOpenElementsUntil(token.name); | 1696 popOpenElementsUntil(token.name); |
1696 } | 1697 } |
1697 } | 1698 } |
1698 | 1699 |
1699 void endTagForm(EndTagToken token) { | 1700 void endTagForm(EndTagToken token) { |
1700 var node = tree.formPointer; | 1701 var node = tree.formPointer; |
1701 tree.formPointer = null; | 1702 tree.formPointer = null; |
(...skipping 12 matching lines...) Expand all Loading... |
1714 var variant; | 1715 var variant; |
1715 if (token.name == "li") { | 1716 if (token.name == "li") { |
1716 variant = "list"; | 1717 variant = "list"; |
1717 } else { | 1718 } else { |
1718 variant = null; | 1719 variant = null; |
1719 } | 1720 } |
1720 if (!tree.elementInScope(token.name, variant: variant)) { | 1721 if (!tree.elementInScope(token.name, variant: variant)) { |
1721 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); | 1722 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); |
1722 } else { | 1723 } else { |
1723 tree.generateImpliedEndTags(token.name); | 1724 tree.generateImpliedEndTags(token.name); |
1724 if (tree.openElements.last.tagName != token.name) { | 1725 if (tree.openElements.last.localName != token.name) { |
1725 parser.parseError(token.span, "end-tag-too-early", {"name": token.name})
; | 1726 parser.parseError(token.span, "end-tag-too-early", {"name": token.name})
; |
1726 } | 1727 } |
1727 popOpenElementsUntil(token.name); | 1728 popOpenElementsUntil(token.name); |
1728 } | 1729 } |
1729 } | 1730 } |
1730 | 1731 |
1731 void endTagHeading(EndTagToken token) { | 1732 void endTagHeading(EndTagToken token) { |
1732 for (var item in headingElements) { | 1733 for (var item in headingElements) { |
1733 if (tree.elementInScope(item)) { | 1734 if (tree.elementInScope(item)) { |
1734 tree.generateImpliedEndTags(); | 1735 tree.generateImpliedEndTags(); |
1735 break; | 1736 break; |
1736 } | 1737 } |
1737 } | 1738 } |
1738 if (tree.openElements.last.tagName != token.name) { | 1739 if (tree.openElements.last.localName != token.name) { |
1739 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); | 1740 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); |
1740 } | 1741 } |
1741 | 1742 |
1742 for (var item in headingElements) { | 1743 for (var item in headingElements) { |
1743 if (tree.elementInScope(item)) { | 1744 if (tree.elementInScope(item)) { |
1744 item = tree.openElements.removeLast(); | 1745 var node = tree.openElements.removeLast(); |
1745 while (!headingElements.contains(item.tagName)) { | 1746 while (!headingElements.contains(node.localName)) { |
1746 item = tree.openElements.removeLast(); | 1747 node = tree.openElements.removeLast(); |
1747 } | 1748 } |
1748 break; | 1749 break; |
1749 } | 1750 } |
1750 } | 1751 } |
1751 } | 1752 } |
1752 | 1753 |
1753 /// The much-feared adoption agency algorithm. | 1754 /// The much-feared adoption agency algorithm. |
1754 endTagFormatting(EndTagToken token) { | 1755 endTagFormatting(EndTagToken token) { |
1755 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construc
tion.html#adoptionAgency | 1756 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construc
tion.html#adoptionAgency |
1756 // TODO(jmesserly): the comments here don't match the numbered steps in the | 1757 // TODO(jmesserly): the comments here don't match the numbered steps in the |
1757 // updated spec. This needs a pass over it to verify that it still matches. | 1758 // updated spec. This needs a pass over it to verify that it still matches. |
1758 // In particular the html5lib Python code skiped "step 4", I'm not sure why. | 1759 // In particular the html5lib Python code skiped "step 4", I'm not sure why. |
1759 // XXX Better parseError messages appreciated. | 1760 // XXX Better parseError messages appreciated. |
1760 int outerLoopCounter = 0; | 1761 int outerLoopCounter = 0; |
1761 while (outerLoopCounter < 8) { | 1762 while (outerLoopCounter < 8) { |
1762 outerLoopCounter += 1; | 1763 outerLoopCounter += 1; |
1763 | 1764 |
1764 // Step 1 paragraph 1 | 1765 // Step 1 paragraph 1 |
1765 var formattingElement = tree.elementInActiveFormattingElements( | 1766 var formattingElement = tree.elementInActiveFormattingElements( |
1766 token.name); | 1767 token.name); |
1767 if (formattingElement == null || | 1768 if (formattingElement == null || |
1768 (tree.openElements.contains(formattingElement) && | 1769 (tree.openElements.contains(formattingElement) && |
1769 !tree.elementInScope(formattingElement.tagName))) { | 1770 !tree.elementInScope(formattingElement.localName))) { |
1770 parser.parseError(token.span, "adoption-agency-1.1", | 1771 parser.parseError(token.span, "adoption-agency-1.1", |
1771 {"name": token.name}); | 1772 {"name": token.name}); |
1772 return; | 1773 return; |
1773 // Step 1 paragraph 2 | 1774 // Step 1 paragraph 2 |
1774 } else if (!tree.openElements.contains(formattingElement)) { | 1775 } else if (!tree.openElements.contains(formattingElement)) { |
1775 parser.parseError(token.span, "adoption-agency-1.2", | 1776 parser.parseError(token.span, "adoption-agency-1.2", |
1776 {"name": token.name}); | 1777 {"name": token.name}); |
1777 tree.activeFormattingElements.remove(formattingElement); | 1778 tree.activeFormattingElements.remove(formattingElement); |
1778 return; | 1779 return; |
1779 } | 1780 } |
1780 | 1781 |
1781 // Step 1 paragraph 3 | 1782 // Step 1 paragraph 3 |
1782 if (formattingElement != tree.openElements.last) { | 1783 if (formattingElement != tree.openElements.last) { |
1783 parser.parseError(token.span, "adoption-agency-1.3", | 1784 parser.parseError(token.span, "adoption-agency-1.3", |
1784 {"name": token.name}); | 1785 {"name": token.name}); |
1785 } | 1786 } |
1786 | 1787 |
1787 // Step 2 | 1788 // Step 2 |
1788 // Start of the adoption agency algorithm proper | 1789 // Start of the adoption agency algorithm proper |
1789 var afeIndex = tree.openElements.indexOf(formattingElement); | 1790 var afeIndex = tree.openElements.indexOf(formattingElement); |
1790 Node furthestBlock = null; | 1791 Node furthestBlock = null; |
1791 for (Node element in slice(tree.openElements, afeIndex)) { | 1792 for (Node element in slice(tree.openElements, afeIndex)) { |
1792 if (specialElements.contains(element.nameTuple)) { | 1793 if (specialElements.contains(getElementNameTuple(element))) { |
1793 furthestBlock = element; | 1794 furthestBlock = element; |
1794 break; | 1795 break; |
1795 } | 1796 } |
1796 } | 1797 } |
1797 // Step 3 | 1798 // Step 3 |
1798 if (furthestBlock == null) { | 1799 if (furthestBlock == null) { |
1799 var element = tree.openElements.removeLast(); | 1800 var element = tree.openElements.removeLast(); |
1800 while (element != formattingElement) { | 1801 while (element != formattingElement) { |
1801 element = tree.openElements.removeLast(); | 1802 element = tree.openElements.removeLast(); |
1802 } | 1803 } |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1859 | 1860 |
1860 // Step 7 | 1861 // Step 7 |
1861 // Foster parent lastNode if commonAncestor is a | 1862 // Foster parent lastNode if commonAncestor is a |
1862 // table, tbody, tfoot, thead, or tr we need to foster parent the | 1863 // table, tbody, tfoot, thead, or tr we need to foster parent the |
1863 // lastNode | 1864 // lastNode |
1864 if (lastNode.parent != null) { | 1865 if (lastNode.parent != null) { |
1865 lastNode.parent.nodes.remove(lastNode); | 1866 lastNode.parent.nodes.remove(lastNode); |
1866 } | 1867 } |
1867 | 1868 |
1868 if (const ["table", "tbody", "tfoot", "thead", "tr"].contains( | 1869 if (const ["table", "tbody", "tfoot", "thead", "tr"].contains( |
1869 commonAncestor.tagName)) { | 1870 commonAncestor.localName)) { |
1870 var nodePos = tree.getTableMisnestedNodePosition(); | 1871 var nodePos = tree.getTableMisnestedNodePosition(); |
1871 nodePos[0].insertBefore(lastNode, nodePos[1]); | 1872 nodePos[0].insertBefore(lastNode, nodePos[1]); |
1872 } else { | 1873 } else { |
1873 commonAncestor.nodes.add(lastNode); | 1874 commonAncestor.nodes.add(lastNode); |
1874 } | 1875 } |
1875 | 1876 |
1876 // Step 8 | 1877 // Step 8 |
1877 var clone = formattingElement.clone(); | 1878 var clone = formattingElement.clone(); |
1878 | 1879 |
1879 // Step 9 | 1880 // Step 9 |
(...skipping 11 matching lines...) Expand all Loading... |
1891 tree.openElements.remove(formattingElement); | 1892 tree.openElements.remove(formattingElement); |
1892 tree.openElements.insert( | 1893 tree.openElements.insert( |
1893 tree.openElements.indexOf(furthestBlock) + 1, clone); | 1894 tree.openElements.indexOf(furthestBlock) + 1, clone); |
1894 } | 1895 } |
1895 } | 1896 } |
1896 | 1897 |
1897 void endTagAppletMarqueeObject(EndTagToken token) { | 1898 void endTagAppletMarqueeObject(EndTagToken token) { |
1898 if (tree.elementInScope(token.name)) { | 1899 if (tree.elementInScope(token.name)) { |
1899 tree.generateImpliedEndTags(); | 1900 tree.generateImpliedEndTags(); |
1900 } | 1901 } |
1901 if (tree.openElements.last.tagName != token.name) { | 1902 if (tree.openElements.last.localName != token.name) { |
1902 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); | 1903 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); |
1903 } | 1904 } |
1904 if (tree.elementInScope(token.name)) { | 1905 if (tree.elementInScope(token.name)) { |
1905 popOpenElementsUntil(token.name); | 1906 popOpenElementsUntil(token.name); |
1906 tree.clearActiveFormattingElements(); | 1907 tree.clearActiveFormattingElements(); |
1907 } | 1908 } |
1908 } | 1909 } |
1909 | 1910 |
1910 void endTagBr(EndTagToken token) { | 1911 void endTagBr(EndTagToken token) { |
1911 parser.parseError(token.span, "unexpected-end-tag-treated-as", | 1912 parser.parseError(token.span, "unexpected-end-tag-treated-as", |
1912 {"originalName": "br", "newName": "br element"}); | 1913 {"originalName": "br", "newName": "br element"}); |
1913 tree.reconstructActiveFormattingElements(); | 1914 tree.reconstructActiveFormattingElements(); |
1914 tree.insertElement(new StartTagToken("br", data: {})); | 1915 tree.insertElement(new StartTagToken("br", data: {})); |
1915 tree.openElements.removeLast(); | 1916 tree.openElements.removeLast(); |
1916 } | 1917 } |
1917 | 1918 |
1918 void endTagOther(EndTagToken token) { | 1919 void endTagOther(EndTagToken token) { |
1919 for (Node node in tree.openElements.reversed) { | 1920 for (var node in tree.openElements.reversed) { |
1920 if (node.tagName == token.name) { | 1921 if (node.localName == token.name) { |
1921 tree.generateImpliedEndTags(token.name); | 1922 tree.generateImpliedEndTags(token.name); |
1922 if (tree.openElements.last.tagName != token.name) { | 1923 if (tree.openElements.last.localName != token.name) { |
1923 parser.parseError(token.span, "unexpected-end-tag", | 1924 parser.parseError(token.span, "unexpected-end-tag", |
1924 {"name": token.name}); | 1925 {"name": token.name}); |
1925 } | 1926 } |
1926 while (tree.openElements.removeLast() != node); | 1927 while (tree.openElements.removeLast() != node); |
1927 break; | 1928 break; |
1928 } else { | 1929 } else { |
1929 if (specialElements.contains(node.nameTuple)) { | 1930 if (specialElements.contains(getElementNameTuple(node))) { |
1930 parser.parseError(token.span, "unexpected-end-tag", | 1931 parser.parseError(token.span, "unexpected-end-tag", |
1931 {"name": token.name}); | 1932 {"name": token.name}); |
1932 break; | 1933 break; |
1933 } | 1934 } |
1934 } | 1935 } |
1935 } | 1936 } |
1936 } | 1937 } |
1937 } | 1938 } |
1938 | 1939 |
1939 | 1940 |
1940 class TextPhase extends Phase { | 1941 class TextPhase extends Phase { |
1941 TextPhase(parser) : super(parser); | 1942 TextPhase(parser) : super(parser); |
1942 | 1943 |
1943 // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name | 1944 // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name |
1944 processStartTag(StartTagToken token) { assert(false); } | 1945 processStartTag(StartTagToken token) { assert(false); } |
1945 | 1946 |
1946 processEndTag(EndTagToken token) { | 1947 processEndTag(EndTagToken token) { |
1947 if (token.name == 'script') return endTagScript(token); | 1948 if (token.name == 'script') return endTagScript(token); |
1948 return endTagOther(token); | 1949 return endTagOther(token); |
1949 } | 1950 } |
1950 | 1951 |
1951 Token processCharacters(CharactersToken token) { | 1952 Token processCharacters(CharactersToken token) { |
1952 tree.insertText(token.data, token.span); | 1953 tree.insertText(token.data, token.span); |
1953 return null; | 1954 return null; |
1954 } | 1955 } |
1955 | 1956 |
1956 bool processEOF() { | 1957 bool processEOF() { |
1957 var last = tree.openElements.last; | 1958 var last = tree.openElements.last; |
1958 parser.parseError(last.sourceSpan, "expected-named-closing-tag-but-got-eof", | 1959 parser.parseError(last.sourceSpan, "expected-named-closing-tag-but-got-eof", |
1959 {'name': last.tagName}); | 1960 {'name': last.localName}); |
1960 tree.openElements.removeLast(); | 1961 tree.openElements.removeLast(); |
1961 parser.phase = parser.originalPhase; | 1962 parser.phase = parser.originalPhase; |
1962 return true; | 1963 return true; |
1963 } | 1964 } |
1964 | 1965 |
1965 void endTagScript(EndTagToken token) { | 1966 void endTagScript(EndTagToken token) { |
1966 var node = tree.openElements.removeLast(); | 1967 var node = tree.openElements.removeLast(); |
1967 assert(node.tagName == "script"); | 1968 assert(node.localName == "script"); |
1968 parser.phase = parser.originalPhase; | 1969 parser.phase = parser.originalPhase; |
1969 //The rest of this method is all stuff that only happens if | 1970 //The rest of this method is all stuff that only happens if |
1970 //document.write works | 1971 //document.write works |
1971 } | 1972 } |
1972 | 1973 |
1973 void endTagOther(EndTagToken token) { | 1974 void endTagOther(EndTagToken token) { |
1974 var node = tree.openElements.removeLast(); | 1975 var node = tree.openElements.removeLast(); |
1975 parser.phase = parser.originalPhase; | 1976 parser.phase = parser.originalPhase; |
1976 } | 1977 } |
1977 } | 1978 } |
(...skipping 24 matching lines...) Expand all Loading... |
2002 case "body": case "caption": case "col": case "colgroup": case "html": | 2003 case "body": case "caption": case "col": case "colgroup": case "html": |
2003 case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": | 2004 case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": |
2004 return endTagIgnore(token); | 2005 return endTagIgnore(token); |
2005 default: return endTagOther(token); | 2006 default: return endTagOther(token); |
2006 } | 2007 } |
2007 } | 2008 } |
2008 | 2009 |
2009 // helper methods | 2010 // helper methods |
2010 void clearStackToTableContext() { | 2011 void clearStackToTableContext() { |
2011 // "clear the stack back to a table context" | 2012 // "clear the stack back to a table context" |
2012 while (tree.openElements.last.tagName != "table" && | 2013 while (tree.openElements.last.localName != "table" && |
2013 tree.openElements.last.tagName != "html") { | 2014 tree.openElements.last.localName != "html") { |
2014 //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", | 2015 //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", |
2015 // {"name": tree.openElements.last.name}) | 2016 // {"name": tree.openElements.last.name}) |
2016 tree.openElements.removeLast(); | 2017 tree.openElements.removeLast(); |
2017 } | 2018 } |
2018 // When the current node is <html> it's an innerHTML case | 2019 // When the current node is <html> it's an innerHTML case |
2019 } | 2020 } |
2020 | 2021 |
2021 // processing methods | 2022 // processing methods |
2022 bool processEOF() { | 2023 bool processEOF() { |
2023 var last = tree.openElements.last; | 2024 var last = tree.openElements.last; |
2024 if (last.tagName != "html") { | 2025 if (last.localName != "html") { |
2025 parser.parseError(last.sourceSpan, "eof-in-table"); | 2026 parser.parseError(last.sourceSpan, "eof-in-table"); |
2026 } else { | 2027 } else { |
2027 assert(parser.innerHTMLMode); | 2028 assert(parser.innerHTMLMode); |
2028 } | 2029 } |
2029 //Stop parsing | 2030 //Stop parsing |
2030 return false; | 2031 return false; |
2031 } | 2032 } |
2032 | 2033 |
2033 Token processSpaceCharacters(SpaceCharactersToken token) { | 2034 Token processSpaceCharacters(SpaceCharactersToken token) { |
2034 var originalPhase = parser.phase; | 2035 var originalPhase = parser.phase; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2123 // Do the table magic! | 2124 // Do the table magic! |
2124 tree.insertFromTable = true; | 2125 tree.insertFromTable = true; |
2125 parser._inBodyPhase.processStartTag(token); | 2126 parser._inBodyPhase.processStartTag(token); |
2126 tree.insertFromTable = false; | 2127 tree.insertFromTable = false; |
2127 } | 2128 } |
2128 | 2129 |
2129 void endTagTable(EndTagToken token) { | 2130 void endTagTable(EndTagToken token) { |
2130 if (tree.elementInScope("table", variant: "table")) { | 2131 if (tree.elementInScope("table", variant: "table")) { |
2131 tree.generateImpliedEndTags(); | 2132 tree.generateImpliedEndTags(); |
2132 var last = tree.openElements.last; | 2133 var last = tree.openElements.last; |
2133 if (last.tagName != "table") { | 2134 if (last.localName != "table") { |
2134 parser.parseError(token.span, "end-tag-too-early-named", | 2135 parser.parseError(token.span, "end-tag-too-early-named", |
2135 {"gotName": "table", "expectedName": last.tagName}); | 2136 {"gotName": "table", "expectedName": last.localName}); |
2136 } | 2137 } |
2137 while (tree.openElements.last.tagName != "table") { | 2138 while (tree.openElements.last.localName != "table") { |
2138 tree.openElements.removeLast(); | 2139 tree.openElements.removeLast(); |
2139 } | 2140 } |
2140 tree.openElements.removeLast(); | 2141 tree.openElements.removeLast(); |
2141 parser.resetInsertionMode(); | 2142 parser.resetInsertionMode(); |
2142 } else { | 2143 } else { |
2143 // innerHTML case | 2144 // innerHTML case |
2144 assert(parser.innerHTMLMode); | 2145 assert(parser.innerHTMLMode); |
2145 parser.parseError(token.span, "undefined-error"); | 2146 parser.parseError(token.span, "undefined-error"); |
2146 } | 2147 } |
2147 } | 2148 } |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2280 } | 2281 } |
2281 | 2282 |
2282 Token startTagOther(StartTagToken token) { | 2283 Token startTagOther(StartTagToken token) { |
2283 return parser._inBodyPhase.processStartTag(token); | 2284 return parser._inBodyPhase.processStartTag(token); |
2284 } | 2285 } |
2285 | 2286 |
2286 void endTagCaption(EndTagToken token) { | 2287 void endTagCaption(EndTagToken token) { |
2287 if (!ignoreEndTagCaption()) { | 2288 if (!ignoreEndTagCaption()) { |
2288 // AT this code is quite similar to endTagTable in "InTable" | 2289 // AT this code is quite similar to endTagTable in "InTable" |
2289 tree.generateImpliedEndTags(); | 2290 tree.generateImpliedEndTags(); |
2290 if (tree.openElements.last.tagName != "caption") { | 2291 if (tree.openElements.last.localName != "caption") { |
2291 parser.parseError(token.span, "expected-one-end-tag-but-got-another", | 2292 parser.parseError(token.span, "expected-one-end-tag-but-got-another", |
2292 {"gotName": "caption", | 2293 {"gotName": "caption", |
2293 "expectedName": tree.openElements.last.tagName}); | 2294 "expectedName": tree.openElements.last.localName}); |
2294 } | 2295 } |
2295 while (tree.openElements.last.tagName != "caption") { | 2296 while (tree.openElements.last.localName != "caption") { |
2296 tree.openElements.removeLast(); | 2297 tree.openElements.removeLast(); |
2297 } | 2298 } |
2298 tree.openElements.removeLast(); | 2299 tree.openElements.removeLast(); |
2299 tree.clearActiveFormattingElements(); | 2300 tree.clearActiveFormattingElements(); |
2300 parser.phase = parser._inTablePhase; | 2301 parser.phase = parser._inTablePhase; |
2301 } else { | 2302 } else { |
2302 // innerHTML case | 2303 // innerHTML case |
2303 assert(parser.innerHTMLMode); | 2304 assert(parser.innerHTMLMode); |
2304 parser.parseError(token.span, "undefined-error"); | 2305 parser.parseError(token.span, "undefined-error"); |
2305 } | 2306 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2339 | 2340 |
2340 processEndTag(EndTagToken token) { | 2341 processEndTag(EndTagToken token) { |
2341 switch (token.name) { | 2342 switch (token.name) { |
2342 case "colgroup": return endTagColgroup(token); | 2343 case "colgroup": return endTagColgroup(token); |
2343 case "col": return endTagCol(token); | 2344 case "col": return endTagCol(token); |
2344 default: return endTagOther(token); | 2345 default: return endTagOther(token); |
2345 } | 2346 } |
2346 } | 2347 } |
2347 | 2348 |
2348 bool ignoreEndTagColgroup() { | 2349 bool ignoreEndTagColgroup() { |
2349 return tree.openElements.last.tagName == "html"; | 2350 return tree.openElements.last.localName == "html"; |
2350 } | 2351 } |
2351 | 2352 |
2352 bool processEOF() { | 2353 bool processEOF() { |
2353 var ignoreEndTag = ignoreEndTagColgroup(); | 2354 var ignoreEndTag = ignoreEndTagColgroup(); |
2354 if (ignoreEndTag) { | 2355 if (ignoreEndTag) { |
2355 assert(parser.innerHTMLMode); | 2356 assert(parser.innerHTMLMode); |
2356 return false; | 2357 return false; |
2357 } else { | 2358 } else { |
2358 endTagColgroup(new EndTagToken("colgroup")); | 2359 endTagColgroup(new EndTagToken("colgroup")); |
2359 return true; | 2360 return true; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2424 case "body": case "caption": case "col": case "colgroup": case "html": | 2425 case "body": case "caption": case "col": case "colgroup": case "html": |
2425 case "td": case "th": case "tr": | 2426 case "td": case "th": case "tr": |
2426 return endTagIgnore(token); | 2427 return endTagIgnore(token); |
2427 default: return endTagOther(token); | 2428 default: return endTagOther(token); |
2428 } | 2429 } |
2429 } | 2430 } |
2430 | 2431 |
2431 // helper methods | 2432 // helper methods |
2432 void clearStackToTableBodyContext() { | 2433 void clearStackToTableBodyContext() { |
2433 var tableTags = const ["tbody", "tfoot", "thead", "html"]; | 2434 var tableTags = const ["tbody", "tfoot", "thead", "html"]; |
2434 while (!tableTags.contains(tree.openElements.last.tagName)) { | 2435 while (!tableTags.contains(tree.openElements.last.localName)) { |
2435 //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", | 2436 //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", |
2436 // {"name": tree.openElements.last.name}) | 2437 // {"name": tree.openElements.last.name}) |
2437 tree.openElements.removeLast(); | 2438 tree.openElements.removeLast(); |
2438 } | 2439 } |
2439 if (tree.openElements.last.tagName == "html") { | 2440 if (tree.openElements.last.localName == "html") { |
2440 assert(parser.innerHTMLMode); | 2441 assert(parser.innerHTMLMode); |
2441 } | 2442 } |
2442 } | 2443 } |
2443 | 2444 |
2444 // the rest | 2445 // the rest |
2445 bool processEOF() { | 2446 bool processEOF() { |
2446 parser._inTablePhase.processEOF(); | 2447 parser._inTablePhase.processEOF(); |
2447 return false; | 2448 return false; |
2448 } | 2449 } |
2449 | 2450 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2484 {"name": token.name}); | 2485 {"name": token.name}); |
2485 } | 2486 } |
2486 } | 2487 } |
2487 | 2488 |
2488 Token endTagTable(TagToken token) { | 2489 Token endTagTable(TagToken token) { |
2489 // XXX AT Any ideas on how to share this with endTagTable? | 2490 // XXX AT Any ideas on how to share this with endTagTable? |
2490 if (tree.elementInScope("tbody", variant: "table") || | 2491 if (tree.elementInScope("tbody", variant: "table") || |
2491 tree.elementInScope("thead", variant: "table") || | 2492 tree.elementInScope("thead", variant: "table") || |
2492 tree.elementInScope("tfoot", variant: "table")) { | 2493 tree.elementInScope("tfoot", variant: "table")) { |
2493 clearStackToTableBodyContext(); | 2494 clearStackToTableBodyContext(); |
2494 endTagTableRowGroup(new EndTagToken(tree.openElements.last.tagName)); | 2495 endTagTableRowGroup(new EndTagToken(tree.openElements.last.localName)); |
2495 return token; | 2496 return token; |
2496 } else { | 2497 } else { |
2497 // innerHTML case | 2498 // innerHTML case |
2498 assert(parser.innerHTMLMode); | 2499 assert(parser.innerHTMLMode); |
2499 parser.parseError(token.span, "undefined-error"); | 2500 parser.parseError(token.span, "undefined-error"); |
2500 } | 2501 } |
2501 return null; | 2502 return null; |
2502 } | 2503 } |
2503 | 2504 |
2504 void endTagIgnore(EndTagToken token) { | 2505 void endTagIgnore(EndTagToken token) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2537 case "td": case "th": | 2538 case "td": case "th": |
2538 return endTagIgnore(token); | 2539 return endTagIgnore(token); |
2539 default: return endTagOther(token); | 2540 default: return endTagOther(token); |
2540 } | 2541 } |
2541 } | 2542 } |
2542 | 2543 |
2543 // helper methods (XXX unify this with other table helper methods) | 2544 // helper methods (XXX unify this with other table helper methods) |
2544 void clearStackToTableRowContext() { | 2545 void clearStackToTableRowContext() { |
2545 while (true) { | 2546 while (true) { |
2546 var last = tree.openElements.last; | 2547 var last = tree.openElements.last; |
2547 if (last.tagName == "tr" || last.tagName == "html") break; | 2548 if (last.localName == "tr" || last.localName == "html") break; |
2548 | 2549 |
2549 parser.parseError(last.sourceSpan, | 2550 parser.parseError(last.sourceSpan, |
2550 "unexpected-implied-end-tag-in-table-row", | 2551 "unexpected-implied-end-tag-in-table-row", |
2551 {"name": tree.openElements.last.tagName}); | 2552 {"name": tree.openElements.last.localName}); |
2552 tree.openElements.removeLast(); | 2553 tree.openElements.removeLast(); |
2553 } | 2554 } |
2554 } | 2555 } |
2555 | 2556 |
2556 bool ignoreEndTagTr() { | 2557 bool ignoreEndTagTr() { |
2557 return !tree.elementInScope("tr", variant: "table"); | 2558 return !tree.elementInScope("tr", variant: "table"); |
2558 } | 2559 } |
2559 | 2560 |
2560 // the rest | 2561 // the rest |
2561 bool processEOF() { | 2562 bool processEOF() { |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2687 } | 2688 } |
2688 } | 2689 } |
2689 | 2690 |
2690 Token startTagOther(StartTagToken token) { | 2691 Token startTagOther(StartTagToken token) { |
2691 return parser._inBodyPhase.processStartTag(token); | 2692 return parser._inBodyPhase.processStartTag(token); |
2692 } | 2693 } |
2693 | 2694 |
2694 void endTagTableCell(EndTagToken token) { | 2695 void endTagTableCell(EndTagToken token) { |
2695 if (tree.elementInScope(token.name, variant: "table")) { | 2696 if (tree.elementInScope(token.name, variant: "table")) { |
2696 tree.generateImpliedEndTags(token.name); | 2697 tree.generateImpliedEndTags(token.name); |
2697 if (tree.openElements.last.tagName != token.name) { | 2698 if (tree.openElements.last.localName != token.name) { |
2698 parser.parseError(token.span, "unexpected-cell-end-tag", | 2699 parser.parseError(token.span, "unexpected-cell-end-tag", |
2699 {"name": token.name}); | 2700 {"name": token.name}); |
2700 popOpenElementsUntil(token.name); | 2701 popOpenElementsUntil(token.name); |
2701 } else { | 2702 } else { |
2702 tree.openElements.removeLast(); | 2703 tree.openElements.removeLast(); |
2703 } | 2704 } |
2704 tree.clearActiveFormattingElements(); | 2705 tree.clearActiveFormattingElements(); |
2705 parser.phase = parser._inRowPhase; | 2706 parser.phase = parser._inRowPhase; |
2706 } else { | 2707 } else { |
2707 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); | 2708 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2749 case "option": return endTagOption(token); | 2750 case "option": return endTagOption(token); |
2750 case "optgroup": return endTagOptgroup(token); | 2751 case "optgroup": return endTagOptgroup(token); |
2751 case "select": return endTagSelect(token); | 2752 case "select": return endTagSelect(token); |
2752 default: return endTagOther(token); | 2753 default: return endTagOther(token); |
2753 } | 2754 } |
2754 } | 2755 } |
2755 | 2756 |
2756 // http://www.whatwg.org/specs/web-apps/current-work///in-select | 2757 // http://www.whatwg.org/specs/web-apps/current-work///in-select |
2757 bool processEOF() { | 2758 bool processEOF() { |
2758 var last = tree.openElements.last; | 2759 var last = tree.openElements.last; |
2759 if (last.tagName != "html") { | 2760 if (last.localName != "html") { |
2760 parser.parseError(last.sourceSpan, "eof-in-select"); | 2761 parser.parseError(last.sourceSpan, "eof-in-select"); |
2761 } else { | 2762 } else { |
2762 assert(parser.innerHTMLMode); | 2763 assert(parser.innerHTMLMode); |
2763 } | 2764 } |
2764 return false; | 2765 return false; |
2765 } | 2766 } |
2766 | 2767 |
2767 Token processCharacters(CharactersToken token) { | 2768 Token processCharacters(CharactersToken token) { |
2768 if (token.data == "\u0000") { | 2769 if (token.data == "\u0000") { |
2769 return null; | 2770 return null; |
2770 } | 2771 } |
2771 tree.insertText(token.data, token.span); | 2772 tree.insertText(token.data, token.span); |
2772 return null; | 2773 return null; |
2773 } | 2774 } |
2774 | 2775 |
2775 void startTagOption(StartTagToken token) { | 2776 void startTagOption(StartTagToken token) { |
2776 // We need to imply </option> if <option> is the current node. | 2777 // We need to imply </option> if <option> is the current node. |
2777 if (tree.openElements.last.tagName == "option") { | 2778 if (tree.openElements.last.localName == "option") { |
2778 tree.openElements.removeLast(); | 2779 tree.openElements.removeLast(); |
2779 } | 2780 } |
2780 tree.insertElement(token); | 2781 tree.insertElement(token); |
2781 } | 2782 } |
2782 | 2783 |
2783 void startTagOptgroup(StartTagToken token) { | 2784 void startTagOptgroup(StartTagToken token) { |
2784 if (tree.openElements.last.tagName == "option") { | 2785 if (tree.openElements.last.localName == "option") { |
2785 tree.openElements.removeLast(); | 2786 tree.openElements.removeLast(); |
2786 } | 2787 } |
2787 if (tree.openElements.last.tagName == "optgroup") { | 2788 if (tree.openElements.last.localName == "optgroup") { |
2788 tree.openElements.removeLast(); | 2789 tree.openElements.removeLast(); |
2789 } | 2790 } |
2790 tree.insertElement(token); | 2791 tree.insertElement(token); |
2791 } | 2792 } |
2792 | 2793 |
2793 void startTagSelect(StartTagToken token) { | 2794 void startTagSelect(StartTagToken token) { |
2794 parser.parseError(token.span, "unexpected-select-in-select"); | 2795 parser.parseError(token.span, "unexpected-select-in-select"); |
2795 endTagSelect(new EndTagToken("select")); | 2796 endTagSelect(new EndTagToken("select")); |
2796 } | 2797 } |
2797 | 2798 |
(...skipping 12 matching lines...) Expand all Loading... |
2810 return parser._inHeadPhase.processStartTag(token); | 2811 return parser._inHeadPhase.processStartTag(token); |
2811 } | 2812 } |
2812 | 2813 |
2813 Token startTagOther(StartTagToken token) { | 2814 Token startTagOther(StartTagToken token) { |
2814 parser.parseError(token.span, "unexpected-start-tag-in-select", | 2815 parser.parseError(token.span, "unexpected-start-tag-in-select", |
2815 {"name": token.name}); | 2816 {"name": token.name}); |
2816 return null; | 2817 return null; |
2817 } | 2818 } |
2818 | 2819 |
2819 void endTagOption(EndTagToken token) { | 2820 void endTagOption(EndTagToken token) { |
2820 if (tree.openElements.last.tagName == "option") { | 2821 if (tree.openElements.last.localName == "option") { |
2821 tree.openElements.removeLast(); | 2822 tree.openElements.removeLast(); |
2822 } else { | 2823 } else { |
2823 parser.parseError(token.span, "unexpected-end-tag-in-select", | 2824 parser.parseError(token.span, "unexpected-end-tag-in-select", |
2824 {"name": "option"}); | 2825 {"name": "option"}); |
2825 } | 2826 } |
2826 } | 2827 } |
2827 | 2828 |
2828 void endTagOptgroup(EndTagToken token) { | 2829 void endTagOptgroup(EndTagToken token) { |
2829 // </optgroup> implicitly closes <option> | 2830 // </optgroup> implicitly closes <option> |
2830 if (tree.openElements.last.tagName == "option" && | 2831 if (tree.openElements.last.localName == "option" && |
2831 tree.openElements[tree.openElements.length - 2].tagName == "optgroup") { | 2832 tree.openElements[tree.openElements.length - 2].localName == "optgroup") { |
2832 tree.openElements.removeLast(); | 2833 tree.openElements.removeLast(); |
2833 } | 2834 } |
2834 // It also closes </optgroup> | 2835 // It also closes </optgroup> |
2835 if (tree.openElements.last.tagName == "optgroup") { | 2836 if (tree.openElements.last.localName == "optgroup") { |
2836 tree.openElements.removeLast(); | 2837 tree.openElements.removeLast(); |
2837 // But nothing else | 2838 // But nothing else |
2838 } else { | 2839 } else { |
2839 parser.parseError(token.span, "unexpected-end-tag-in-select", | 2840 parser.parseError(token.span, "unexpected-end-tag-in-select", |
2840 {"name": "optgroup"}); | 2841 {"name": "optgroup"}); |
2841 } | 2842 } |
2842 } | 2843 } |
2843 | 2844 |
2844 void endTagSelect(EndTagToken token) { | 2845 void endTagSelect(EndTagToken token) { |
2845 if (tree.elementInScope("select", variant: "select")) { | 2846 if (tree.elementInScope("select", variant: "select")) { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2988 Token processStartTag(StartTagToken token) { | 2989 Token processStartTag(StartTagToken token) { |
2989 var currentNode = tree.openElements.last; | 2990 var currentNode = tree.openElements.last; |
2990 if (breakoutElements.contains(token.name) || | 2991 if (breakoutElements.contains(token.name) || |
2991 (token.name == "font" && | 2992 (token.name == "font" && |
2992 (token.data.containsKey("color") || | 2993 (token.data.containsKey("color") || |
2993 token.data.containsKey("face") || | 2994 token.data.containsKey("face") || |
2994 token.data.containsKey("size")))) { | 2995 token.data.containsKey("size")))) { |
2995 | 2996 |
2996 parser.parseError(token.span, | 2997 parser.parseError(token.span, |
2997 "unexpected-html-element-in-foreign-content", {'name': token.name}); | 2998 "unexpected-html-element-in-foreign-content", {'name': token.name}); |
2998 while (tree.openElements.last.namespace != | 2999 while (tree.openElements.last.namespaceUri != |
2999 tree.defaultNamespace && | 3000 tree.defaultNamespace && |
3000 !parser.isHTMLIntegrationPoint(tree.openElements.last) && | 3001 !parser.isHTMLIntegrationPoint(tree.openElements.last) && |
3001 !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { | 3002 !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { |
3002 tree.openElements.removeLast(); | 3003 tree.openElements.removeLast(); |
3003 } | 3004 } |
3004 return token; | 3005 return token; |
3005 | 3006 |
3006 } else { | 3007 } else { |
3007 if (currentNode.namespace == Namespaces.mathml) { | 3008 if (currentNode.namespaceUri == Namespaces.mathml) { |
3008 parser.adjustMathMLAttributes(token); | 3009 parser.adjustMathMLAttributes(token); |
3009 } else if (currentNode.namespace == Namespaces.svg) { | 3010 } else if (currentNode.namespaceUri == Namespaces.svg) { |
3010 adjustSVGTagNames(token); | 3011 adjustSVGTagNames(token); |
3011 parser.adjustSVGAttributes(token); | 3012 parser.adjustSVGAttributes(token); |
3012 } | 3013 } |
3013 parser.adjustForeignAttributes(token); | 3014 parser.adjustForeignAttributes(token); |
3014 token.namespace = currentNode.namespace; | 3015 token.namespace = currentNode.namespaceUri; |
3015 tree.insertElement(token); | 3016 tree.insertElement(token); |
3016 if (token.selfClosing) { | 3017 if (token.selfClosing) { |
3017 tree.openElements.removeLast(); | 3018 tree.openElements.removeLast(); |
3018 token.selfClosingAcknowledged = true; | 3019 token.selfClosingAcknowledged = true; |
3019 } | 3020 } |
3020 return null; | 3021 return null; |
3021 } | 3022 } |
3022 } | 3023 } |
3023 | 3024 |
3024 Token processEndTag(EndTagToken token) { | 3025 Token processEndTag(EndTagToken token) { |
3025 var nodeIndex = tree.openElements.length - 1; | 3026 var nodeIndex = tree.openElements.length - 1; |
3026 var node = tree.openElements.last; | 3027 var node = tree.openElements.last; |
3027 if (node.tagName != token.name) { | 3028 if (node.localName != token.name) { |
3028 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); | 3029 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); |
3029 } | 3030 } |
3030 | 3031 |
3031 var newToken = null; | 3032 var newToken = null; |
3032 while (true) { | 3033 while (true) { |
3033 if (asciiUpper2Lower(node.tagName) == token.name) { | 3034 if (asciiUpper2Lower(node.localName) == token.name) { |
3034 //XXX this isn't in the spec but it seems necessary | 3035 //XXX this isn't in the spec but it seems necessary |
3035 if (parser.phase == parser._inTableTextPhase) { | 3036 if (parser.phase == parser._inTableTextPhase) { |
3036 InTableTextPhase inTableText = parser.phase; | 3037 InTableTextPhase inTableText = parser.phase; |
3037 inTableText.flushCharacters(); | 3038 inTableText.flushCharacters(); |
3038 parser.phase = inTableText.originalPhase; | 3039 parser.phase = inTableText.originalPhase; |
3039 } | 3040 } |
3040 while (tree.openElements.removeLast() != node) { | 3041 while (tree.openElements.removeLast() != node) { |
3041 assert(tree.openElements.length > 0); | 3042 assert(tree.openElements.length > 0); |
3042 } | 3043 } |
3043 newToken = null; | 3044 newToken = null; |
3044 break; | 3045 break; |
3045 } | 3046 } |
3046 nodeIndex -= 1; | 3047 nodeIndex -= 1; |
3047 | 3048 |
3048 node = tree.openElements[nodeIndex]; | 3049 node = tree.openElements[nodeIndex]; |
3049 if (node.namespace != tree.defaultNamespace) { | 3050 if (node.namespaceUri != tree.defaultNamespace) { |
3050 continue; | 3051 continue; |
3051 } else { | 3052 } else { |
3052 newToken = parser.phase.processEndTag(token); | 3053 newToken = parser.phase.processEndTag(token); |
3053 break; | 3054 break; |
3054 } | 3055 } |
3055 } | 3056 } |
3056 return newToken; | 3057 return newToken; |
3057 } | 3058 } |
3058 } | 3059 } |
3059 | 3060 |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3130 | 3131 |
3131 processEndTag(EndTagToken token) { | 3132 processEndTag(EndTagToken token) { |
3132 switch (token.name) { | 3133 switch (token.name) { |
3133 case "frameset": return endTagFrameset(token); | 3134 case "frameset": return endTagFrameset(token); |
3134 default: return endTagOther(token); | 3135 default: return endTagOther(token); |
3135 } | 3136 } |
3136 } | 3137 } |
3137 | 3138 |
3138 bool processEOF() { | 3139 bool processEOF() { |
3139 var last = tree.openElements.last; | 3140 var last = tree.openElements.last; |
3140 if (last.tagName != "html") { | 3141 if (last.localName != "html") { |
3141 parser.parseError(last.sourceSpan, "eof-in-frameset"); | 3142 parser.parseError(last.sourceSpan, "eof-in-frameset"); |
3142 } else { | 3143 } else { |
3143 assert(parser.innerHTMLMode); | 3144 assert(parser.innerHTMLMode); |
3144 } | 3145 } |
3145 return false; | 3146 return false; |
3146 } | 3147 } |
3147 | 3148 |
3148 Token processCharacters(CharactersToken token) { | 3149 Token processCharacters(CharactersToken token) { |
3149 parser.parseError(token.span, "unexpected-char-in-frameset"); | 3150 parser.parseError(token.span, "unexpected-char-in-frameset"); |
3150 return null; | 3151 return null; |
(...skipping 12 matching lines...) Expand all Loading... |
3163 return parser._inBodyPhase.processStartTag(token); | 3164 return parser._inBodyPhase.processStartTag(token); |
3164 } | 3165 } |
3165 | 3166 |
3166 Token startTagOther(StartTagToken token) { | 3167 Token startTagOther(StartTagToken token) { |
3167 parser.parseError(token.span, "unexpected-start-tag-in-frameset", | 3168 parser.parseError(token.span, "unexpected-start-tag-in-frameset", |
3168 {"name": token.name}); | 3169 {"name": token.name}); |
3169 return null; | 3170 return null; |
3170 } | 3171 } |
3171 | 3172 |
3172 void endTagFrameset(EndTagToken token) { | 3173 void endTagFrameset(EndTagToken token) { |
3173 if (tree.openElements.last.tagName == "html") { | 3174 if (tree.openElements.last.localName == "html") { |
3174 // innerHTML case | 3175 // innerHTML case |
3175 parser.parseError(token.span, | 3176 parser.parseError(token.span, |
3176 "unexpected-frameset-in-frameset-innerhtml"); | 3177 "unexpected-frameset-in-frameset-innerhtml"); |
3177 } else { | 3178 } else { |
3178 tree.openElements.removeLast(); | 3179 tree.openElements.removeLast(); |
3179 } | 3180 } |
3180 if (!parser.innerHTMLMode && tree.openElements.last.tagName != "frameset") { | 3181 if (!parser.innerHTMLMode && |
| 3182 tree.openElements.last.localName != "frameset") { |
3181 // If we're not in innerHTML mode and the the current node is not a | 3183 // If we're not in innerHTML mode and the the current node is not a |
3182 // "frameset" element (anymore) then switch. | 3184 // "frameset" element (anymore) then switch. |
3183 parser.phase = parser._afterFramesetPhase; | 3185 parser.phase = parser._afterFramesetPhase; |
3184 } | 3186 } |
3185 } | 3187 } |
3186 | 3188 |
3187 void endTagOther(EndTagToken token) { | 3189 void endTagOther(EndTagToken token) { |
3188 parser.parseError(token.span, "unexpected-end-tag-in-frameset", | 3190 parser.parseError(token.span, "unexpected-end-tag-in-frameset", |
3189 {"name": token.name}); | 3191 {"name": token.name}); |
3190 } | 3192 } |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3348 /// [span.getLocationMessage] and [toString] are equivalent. Otherwise, | 3350 /// [span.getLocationMessage] and [toString] are equivalent. Otherwise, |
3349 /// [span.getLocationMessage] will not show any source url information, but | 3351 /// [span.getLocationMessage] will not show any source url information, but |
3350 /// [toString] will include 'ParserError:' as a prefix. | 3352 /// [toString] will include 'ParserError:' as a prefix. |
3351 String get message => formatStr(errorMessages[errorCode], data); | 3353 String get message => formatStr(errorMessages[errorCode], data); |
3352 | 3354 |
3353 String toString() { | 3355 String toString() { |
3354 var res = span.getLocationMessage(message); | 3356 var res = span.getLocationMessage(message); |
3355 return span.sourceUrl == null ? 'ParserError$res' : res; | 3357 return span.sourceUrl == null ? 'ParserError$res' : res; |
3356 } | 3358 } |
3357 } | 3359 } |
| 3360 |
| 3361 |
| 3362 /// Convenience function to get the pair of namespace and localName. |
| 3363 Pair<String, String> getElementNameTuple(Element e) { |
| 3364 var ns = e.namespaceUri; |
| 3365 if (ns == null) ns = Namespaces.html; |
| 3366 return new Pair(ns, e.localName); |
| 3367 } |
OLD | NEW |