| 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 |