Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: lib/parser.dart

Issue 1312363005: Add Element.endSourceSpan (Closed) Base URL: https://github.com/dart-lang/html@master
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/dom.dart ('k') | lib/src/treebuilder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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:html/parser.dart' show parse; 4 /// import 'package:html/parser.dart' show parse;
5 /// import 'package:html/dom.dart'; 5 /// import 'package:html/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 619 matching lines...) Expand 10 before | Expand all | Expand 10 after
630 Token processStartTag(StartTagToken token) { 630 Token processStartTag(StartTagToken token) {
631 throw new UnimplementedError(); 631 throw new UnimplementedError();
632 } 632 }
633 633
634 Token startTagHtml(StartTagToken token) { 634 Token startTagHtml(StartTagToken token) {
635 if (parser.firstStartTag == false && token.name == "html") { 635 if (parser.firstStartTag == false && token.name == "html") {
636 parser.parseError(token.span, "non-html-root"); 636 parser.parseError(token.span, "non-html-root");
637 } 637 }
638 // XXX Need a check here to see if the first start tag token emitted is 638 // XXX Need a check here to see if the first start tag token emitted is
639 // this token... If it's not, invoke parser.parseError(). 639 // this token... If it's not, invoke parser.parseError().
640 tree.openElements[0].sourceSpan = token.span;
640 token.data.forEach((attr, value) { 641 token.data.forEach((attr, value) {
641 tree.openElements[0].attributes.putIfAbsent(attr, () => value); 642 tree.openElements[0].attributes.putIfAbsent(attr, () => value);
642 }); 643 });
643 parser.firstStartTag = false; 644 parser.firstStartTag = false;
644 return null; 645 return null;
645 } 646 }
646 647
647 Token processEndTag(EndTagToken token) { 648 Token processEndTag(EndTagToken token) {
648 throw new UnimplementedError(); 649 throw new UnimplementedError();
649 } 650 }
650 651
651 /// Helper method for popping openElements. 652 /// Helper method for popping openElements.
652 void popOpenElementsUntil(String name) { 653 void popOpenElementsUntil(EndTagToken token) {
654 String name = token.name;
653 var node = tree.openElements.removeLast(); 655 var node = tree.openElements.removeLast();
654 while (node.localName != name) { 656 while (node.localName != name) {
655 node = tree.openElements.removeLast(); 657 node = tree.openElements.removeLast();
656 } 658 }
659 if (node != null) {
660 node.endSourceSpan = token.span;
661 }
657 } 662 }
658 } 663 }
659 664
660 class InitialPhase extends Phase { 665 class InitialPhase extends Phase {
661 InitialPhase(parser) : super(parser); 666 InitialPhase(parser) : super(parser);
662 667
663 Token processSpaceCharacters(SpaceCharactersToken token) { 668 Token processSpaceCharacters(SpaceCharactersToken token) {
664 return null; 669 return null;
665 } 670 }
666 671
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 } 1037 }
1033 1038
1034 Token startTagOther(StartTagToken token) { 1039 Token startTagOther(StartTagToken token) {
1035 anythingElse(); 1040 anythingElse();
1036 return token; 1041 return token;
1037 } 1042 }
1038 1043
1039 void endTagHead(EndTagToken token) { 1044 void endTagHead(EndTagToken token) {
1040 var node = parser.tree.openElements.removeLast(); 1045 var node = parser.tree.openElements.removeLast();
1041 assert(node.localName == "head"); 1046 assert(node.localName == "head");
1047 node.endSourceSpan = token.span;
1042 parser.phase = parser._afterHeadPhase; 1048 parser.phase = parser._afterHeadPhase;
1043 } 1049 }
1044 1050
1045 Token endTagHtmlBodyBr(EndTagToken token) { 1051 Token endTagHtmlBodyBr(EndTagToken token) {
1046 anythingElse(); 1052 anythingElse();
1047 return token; 1053 return token;
1048 } 1054 }
1049 1055
1050 void endTagOther(EndTagToken token) { 1056 void endTagOther(EndTagToken token) {
1051 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 1057 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
(...skipping 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
1852 void endTagP(EndTagToken token) { 1858 void endTagP(EndTagToken token) {
1853 if (!tree.elementInScope("p", variant: "button")) { 1859 if (!tree.elementInScope("p", variant: "button")) {
1854 startTagCloseP(new StartTagToken("p", data: {})); 1860 startTagCloseP(new StartTagToken("p", data: {}));
1855 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); 1861 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"});
1856 endTagP(new EndTagToken("p")); 1862 endTagP(new EndTagToken("p"));
1857 } else { 1863 } else {
1858 tree.generateImpliedEndTags("p"); 1864 tree.generateImpliedEndTags("p");
1859 if (tree.openElements.last.localName != "p") { 1865 if (tree.openElements.last.localName != "p") {
1860 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); 1866 parser.parseError(token.span, "unexpected-end-tag", {"name": "p"});
1861 } 1867 }
1862 popOpenElementsUntil("p"); 1868 popOpenElementsUntil(token);
1863 } 1869 }
1864 } 1870 }
1865 1871
1866 void endTagBody(EndTagToken token) { 1872 void endTagBody(EndTagToken token) {
1867 if (!tree.elementInScope("body")) { 1873 if (!tree.elementInScope("body")) {
1868 parser.parseError(token.span, 'undefined-error'); 1874 parser.parseError(token.span, 'undefined-error');
1869 return; 1875 return;
1870 } else if (tree.openElements.last.localName != "body") { 1876 } else if (tree.openElements.last.localName == "body") {
1877 tree.openElements.last.endSourceSpan = token.span;
1878 } else {
1871 for (Element node in slice(tree.openElements, 2)) { 1879 for (Element node in slice(tree.openElements, 2)) {
1872 switch (node.localName) { 1880 switch (node.localName) {
1873 case "dd": 1881 case "dd":
1874 case "dt": 1882 case "dt":
1875 case "li": 1883 case "li":
1876 case "optgroup": 1884 case "optgroup":
1877 case "option": 1885 case "option":
1878 case "p": 1886 case "p":
1879 case "rp": 1887 case "rp":
1880 case "rt": 1888 case "rt":
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1914 dropNewline = false; 1922 dropNewline = false;
1915 } 1923 }
1916 var inScope = tree.elementInScope(token.name); 1924 var inScope = tree.elementInScope(token.name);
1917 if (inScope) { 1925 if (inScope) {
1918 tree.generateImpliedEndTags(); 1926 tree.generateImpliedEndTags();
1919 } 1927 }
1920 if (tree.openElements.last.localName != token.name) { 1928 if (tree.openElements.last.localName != token.name) {
1921 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 1929 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
1922 } 1930 }
1923 if (inScope) { 1931 if (inScope) {
1924 popOpenElementsUntil(token.name); 1932 popOpenElementsUntil(token);
1925 } 1933 }
1926 } 1934 }
1927 1935
1928 void endTagForm(EndTagToken token) { 1936 void endTagForm(EndTagToken token) {
1929 var node = tree.formPointer; 1937 var node = tree.formPointer;
1930 tree.formPointer = null; 1938 tree.formPointer = null;
1931 if (node == null || !tree.elementInScope(node)) { 1939 if (node == null || !tree.elementInScope(node)) {
1932 parser.parseError(token.span, "unexpected-end-tag", {"name": "form"}); 1940 parser.parseError(token.span, "unexpected-end-tag", {"name": "form"});
1933 } else { 1941 } else {
1934 tree.generateImpliedEndTags(); 1942 tree.generateImpliedEndTags();
1935 if (tree.openElements.last != node) { 1943 if (tree.openElements.last != node) {
1936 parser.parseError( 1944 parser.parseError(
1937 token.span, "end-tag-too-early-ignored", {"name": "form"}); 1945 token.span, "end-tag-too-early-ignored", {"name": "form"});
1938 } 1946 }
1939 tree.openElements.remove(node); 1947 tree.openElements.remove(node);
1948 node.endSourceSpan = token.span;
1940 } 1949 }
1941 } 1950 }
1942 1951
1943 void endTagListItem(EndTagToken token) { 1952 void endTagListItem(EndTagToken token) {
1944 var variant; 1953 var variant;
1945 if (token.name == "li") { 1954 if (token.name == "li") {
1946 variant = "list"; 1955 variant = "list";
1947 } else { 1956 } else {
1948 variant = null; 1957 variant = null;
1949 } 1958 }
1950 if (!tree.elementInScope(token.name, variant: variant)) { 1959 if (!tree.elementInScope(token.name, variant: variant)) {
1951 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 1960 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
1952 } else { 1961 } else {
1953 tree.generateImpliedEndTags(token.name); 1962 tree.generateImpliedEndTags(token.name);
1954 if (tree.openElements.last.localName != token.name) { 1963 if (tree.openElements.last.localName != token.name) {
1955 parser.parseError( 1964 parser.parseError(
1956 token.span, "end-tag-too-early", {"name": token.name}); 1965 token.span, "end-tag-too-early", {"name": token.name});
1957 } 1966 }
1958 popOpenElementsUntil(token.name); 1967 popOpenElementsUntil(token);
1959 } 1968 }
1960 } 1969 }
1961 1970
1962 void endTagHeading(EndTagToken token) { 1971 void endTagHeading(EndTagToken token) {
1963 for (var item in headingElements) { 1972 for (var item in headingElements) {
1964 if (tree.elementInScope(item)) { 1973 if (tree.elementInScope(item)) {
1965 tree.generateImpliedEndTags(); 1974 tree.generateImpliedEndTags();
1966 break; 1975 break;
1967 } 1976 }
1968 } 1977 }
1969 if (tree.openElements.last.localName != token.name) { 1978 if (tree.openElements.last.localName != token.name) {
1970 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 1979 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
1971 } 1980 }
1972 1981
1973 for (var item in headingElements) { 1982 for (var item in headingElements) {
1974 if (tree.elementInScope(item)) { 1983 if (tree.elementInScope(item)) {
1975 var node = tree.openElements.removeLast(); 1984 Element node = tree.openElements.removeLast();
1976 while (!headingElements.contains(node.localName)) { 1985 while (!headingElements.contains(node.localName)) {
1977 node = tree.openElements.removeLast(); 1986 node = tree.openElements.removeLast();
1978 } 1987 }
1988 if (node != null) {
1989 node.endSourceSpan = token.span;
1990 }
1979 break; 1991 break;
1980 } 1992 }
1981 } 1993 }
1982 } 1994 }
1983 1995
1984 /// The much-feared adoption agency algorithm. 1996 /// The much-feared adoption agency algorithm.
1985 endTagFormatting(EndTagToken token) { 1997 endTagFormatting(EndTagToken token) {
1986 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construc tion.html#adoptionAgency 1998 // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construc tion.html#adoptionAgency
1987 // TODO(jmesserly): the comments here don't match the numbered steps in the 1999 // TODO(jmesserly): the comments here don't match the numbered steps in the
1988 // updated spec. This needs a pass over it to verify that it still matches. 2000 // updated spec. This needs a pass over it to verify that it still matches.
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2020 var afeIndex = tree.openElements.indexOf(formattingElement); 2032 var afeIndex = tree.openElements.indexOf(formattingElement);
2021 Node furthestBlock = null; 2033 Node furthestBlock = null;
2022 for (Node element in slice(tree.openElements, afeIndex)) { 2034 for (Node element in slice(tree.openElements, afeIndex)) {
2023 if (specialElements.contains(getElementNameTuple(element))) { 2035 if (specialElements.contains(getElementNameTuple(element))) {
2024 furthestBlock = element; 2036 furthestBlock = element;
2025 break; 2037 break;
2026 } 2038 }
2027 } 2039 }
2028 // Step 3 2040 // Step 3
2029 if (furthestBlock == null) { 2041 if (furthestBlock == null) {
2030 var element = tree.openElements.removeLast(); 2042 Element element = tree.openElements.removeLast();
2031 while (element != formattingElement) { 2043 while (element != formattingElement) {
2032 element = tree.openElements.removeLast(); 2044 element = tree.openElements.removeLast();
2033 } 2045 }
2046 if (element != null) {
2047 element.endSourceSpan = token.span;
2048 }
2034 tree.activeFormattingElements.remove(element); 2049 tree.activeFormattingElements.remove(element);
2035 return; 2050 return;
2036 } 2051 }
2037 2052
2038 var commonAncestor = tree.openElements[afeIndex - 1]; 2053 var commonAncestor = tree.openElements[afeIndex - 1];
2039 2054
2040 // Step 5 2055 // Step 5
2041 // The bookmark is supposed to help us identify where to reinsert 2056 // The bookmark is supposed to help us identify where to reinsert
2042 // nodes in step 12. We have to ensure that we reinsert nodes after 2057 // nodes in step 12. We have to ensure that we reinsert nodes after
2043 // the node before the active formatting element. Note the bookmark 2058 // the node before the active formatting element. Note the bookmark
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 } 2146 }
2132 2147
2133 void endTagAppletMarqueeObject(EndTagToken token) { 2148 void endTagAppletMarqueeObject(EndTagToken token) {
2134 if (tree.elementInScope(token.name)) { 2149 if (tree.elementInScope(token.name)) {
2135 tree.generateImpliedEndTags(); 2150 tree.generateImpliedEndTags();
2136 } 2151 }
2137 if (tree.openElements.last.localName != token.name) { 2152 if (tree.openElements.last.localName != token.name) {
2138 parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); 2153 parser.parseError(token.span, "end-tag-too-early", {"name": token.name});
2139 } 2154 }
2140 if (tree.elementInScope(token.name)) { 2155 if (tree.elementInScope(token.name)) {
2141 popOpenElementsUntil(token.name); 2156 popOpenElementsUntil(token);
2142 tree.clearActiveFormattingElements(); 2157 tree.clearActiveFormattingElements();
2143 } 2158 }
2144 } 2159 }
2145 2160
2146 void endTagBr(EndTagToken token) { 2161 void endTagBr(EndTagToken token) {
2147 parser.parseError(token.span, "unexpected-end-tag-treated-as", { 2162 parser.parseError(token.span, "unexpected-end-tag-treated-as", {
2148 "originalName": "br", 2163 "originalName": "br",
2149 "newName": "br element" 2164 "newName": "br element"
2150 }); 2165 });
2151 tree.reconstructActiveFormattingElements(); 2166 tree.reconstructActiveFormattingElements();
2152 tree.insertElement(new StartTagToken("br", data: {})); 2167 tree.insertElement(new StartTagToken("br", data: {}));
2153 tree.openElements.removeLast(); 2168 tree.openElements.removeLast();
2154 } 2169 }
2155 2170
2156 void endTagOther(EndTagToken token) { 2171 void endTagOther(EndTagToken token) {
2157 for (var node in tree.openElements.reversed) { 2172 for (var node in tree.openElements.reversed) {
2158 if (node.localName == token.name) { 2173 if (node.localName == token.name) {
2159 tree.generateImpliedEndTags(token.name); 2174 tree.generateImpliedEndTags(token.name);
2160 if (tree.openElements.last.localName != token.name) { 2175 if (tree.openElements.last.localName != token.name) {
2161 parser.parseError( 2176 parser.parseError(
2162 token.span, "unexpected-end-tag", {"name": token.name}); 2177 token.span, "unexpected-end-tag", {"name": token.name});
2163 } 2178 }
2164 while (tree.openElements.removeLast() != node); 2179 while (tree.openElements.removeLast() != node);
2180 node.endSourceSpan = token.span;
2165 break; 2181 break;
2166 } else { 2182 } else {
2167 if (specialElements.contains(getElementNameTuple(node))) { 2183 if (specialElements.contains(getElementNameTuple(node))) {
2168 parser.parseError( 2184 parser.parseError(
2169 token.span, "unexpected-end-tag", {"name": token.name}); 2185 token.span, "unexpected-end-tag", {"name": token.name});
2170 break; 2186 break;
2171 } 2187 }
2172 } 2188 }
2173 } 2189 }
2174 } 2190 }
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 var last = tree.openElements.last; 2417 var last = tree.openElements.last;
2402 if (last.localName != "table") { 2418 if (last.localName != "table") {
2403 parser.parseError(token.span, "end-tag-too-early-named", { 2419 parser.parseError(token.span, "end-tag-too-early-named", {
2404 "gotName": "table", 2420 "gotName": "table",
2405 "expectedName": last.localName 2421 "expectedName": last.localName
2406 }); 2422 });
2407 } 2423 }
2408 while (tree.openElements.last.localName != "table") { 2424 while (tree.openElements.last.localName != "table") {
2409 tree.openElements.removeLast(); 2425 tree.openElements.removeLast();
2410 } 2426 }
2411 tree.openElements.removeLast(); 2427 var node = tree.openElements.removeLast();
2428 node.endSourceSpan = token.span;
2412 parser.resetInsertionMode(); 2429 parser.resetInsertionMode();
2413 } else { 2430 } else {
2414 // innerHTML case 2431 // innerHTML case
2415 assert(parser.innerHTMLMode); 2432 assert(parser.innerHTMLMode);
2416 parser.parseError(token.span, "undefined-error"); 2433 parser.parseError(token.span, "undefined-error");
2417 } 2434 }
2418 } 2435 }
2419 2436
2420 void endTagIgnore(EndTagToken token) { 2437 void endTagIgnore(EndTagToken token) {
2421 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 2438 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
2578 tree.generateImpliedEndTags(); 2595 tree.generateImpliedEndTags();
2579 if (tree.openElements.last.localName != "caption") { 2596 if (tree.openElements.last.localName != "caption") {
2580 parser.parseError(token.span, "expected-one-end-tag-but-got-another", { 2597 parser.parseError(token.span, "expected-one-end-tag-but-got-another", {
2581 "gotName": "caption", 2598 "gotName": "caption",
2582 "expectedName": tree.openElements.last.localName 2599 "expectedName": tree.openElements.last.localName
2583 }); 2600 });
2584 } 2601 }
2585 while (tree.openElements.last.localName != "caption") { 2602 while (tree.openElements.last.localName != "caption") {
2586 tree.openElements.removeLast(); 2603 tree.openElements.removeLast();
2587 } 2604 }
2588 tree.openElements.removeLast(); 2605 var node = tree.openElements.removeLast();
2606 node.endSourceSpan = token.span;
2589 tree.clearActiveFormattingElements(); 2607 tree.clearActiveFormattingElements();
2590 parser.phase = parser._inTablePhase; 2608 parser.phase = parser._inTablePhase;
2591 } else { 2609 } else {
2592 // innerHTML case 2610 // innerHTML case
2593 assert(parser.innerHTMLMode); 2611 assert(parser.innerHTMLMode);
2594 parser.parseError(token.span, "undefined-error"); 2612 parser.parseError(token.span, "undefined-error");
2595 } 2613 }
2596 } 2614 }
2597 2615
2598 Token endTagTable(EndTagToken token) { 2616 Token endTagTable(EndTagToken token) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2671 endTagColgroup(new EndTagToken("colgroup")); 2689 endTagColgroup(new EndTagToken("colgroup"));
2672 return ignoreEndTag ? null : token; 2690 return ignoreEndTag ? null : token;
2673 } 2691 }
2674 2692
2675 void endTagColgroup(EndTagToken token) { 2693 void endTagColgroup(EndTagToken token) {
2676 if (ignoreEndTagColgroup()) { 2694 if (ignoreEndTagColgroup()) {
2677 // innerHTML case 2695 // innerHTML case
2678 assert(parser.innerHTMLMode); 2696 assert(parser.innerHTMLMode);
2679 parser.parseError(token.span, "undefined-error"); 2697 parser.parseError(token.span, "undefined-error");
2680 } else { 2698 } else {
2681 tree.openElements.removeLast(); 2699 var node = tree.openElements.removeLast();
2700 node.endSourceSpan = token.span;
2682 parser.phase = parser._inTablePhase; 2701 parser.phase = parser._inTablePhase;
2683 } 2702 }
2684 } 2703 }
2685 2704
2686 void endTagCol(EndTagToken token) { 2705 void endTagCol(EndTagToken token) {
2687 parser.parseError(token.span, "no-end-tag", {"name": "col"}); 2706 parser.parseError(token.span, "no-end-tag", {"name": "col"});
2688 } 2707 }
2689 2708
2690 Token endTagOther(EndTagToken token) { 2709 Token endTagOther(EndTagToken token) {
2691 var ignoreEndTag = ignoreEndTagColgroup(); 2710 var ignoreEndTag = ignoreEndTagColgroup();
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
2783 2802
2784 Token startTagTableOther(token) => endTagTable(token); 2803 Token startTagTableOther(token) => endTagTable(token);
2785 2804
2786 Token startTagOther(StartTagToken token) { 2805 Token startTagOther(StartTagToken token) {
2787 return parser._inTablePhase.processStartTag(token); 2806 return parser._inTablePhase.processStartTag(token);
2788 } 2807 }
2789 2808
2790 void endTagTableRowGroup(EndTagToken token) { 2809 void endTagTableRowGroup(EndTagToken token) {
2791 if (tree.elementInScope(token.name, variant: "table")) { 2810 if (tree.elementInScope(token.name, variant: "table")) {
2792 clearStackToTableBodyContext(); 2811 clearStackToTableBodyContext();
2793 tree.openElements.removeLast(); 2812 var node = tree.openElements.removeLast();
2813 node.endSourceSpan = token.span;
2794 parser.phase = parser._inTablePhase; 2814 parser.phase = parser._inTablePhase;
2795 } else { 2815 } else {
2796 parser.parseError( 2816 parser.parseError(
2797 token.span, "unexpected-end-tag-in-table-body", {"name": token.name}); 2817 token.span, "unexpected-end-tag-in-table-body", {"name": token.name});
2798 } 2818 }
2799 } 2819 }
2800 2820
2801 Token endTagTable(TagToken token) { 2821 Token endTagTable(TagToken token) {
2802 // XXX AT Any ideas on how to share this with endTagTable? 2822 // XXX AT Any ideas on how to share this with endTagTable?
2803 if (tree.elementInScope("tbody", variant: "table") || 2823 if (tree.elementInScope("tbody", variant: "table") ||
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2917 return ignoreEndTag ? null : token; 2937 return ignoreEndTag ? null : token;
2918 } 2938 }
2919 2939
2920 Token startTagOther(StartTagToken token) { 2940 Token startTagOther(StartTagToken token) {
2921 return parser._inTablePhase.processStartTag(token); 2941 return parser._inTablePhase.processStartTag(token);
2922 } 2942 }
2923 2943
2924 void endTagTr(EndTagToken token) { 2944 void endTagTr(EndTagToken token) {
2925 if (!ignoreEndTagTr()) { 2945 if (!ignoreEndTagTr()) {
2926 clearStackToTableRowContext(); 2946 clearStackToTableRowContext();
2927 tree.openElements.removeLast(); 2947 var node = tree.openElements.removeLast();
2948 node.endSourceSpan = token.span;
2928 parser.phase = parser._inTableBodyPhase; 2949 parser.phase = parser._inTableBodyPhase;
2929 } else { 2950 } else {
2930 // innerHTML case 2951 // innerHTML case
2931 assert(parser.innerHTMLMode); 2952 assert(parser.innerHTMLMode);
2932 parser.parseError(token.span, "undefined-error"); 2953 parser.parseError(token.span, "undefined-error");
2933 } 2954 }
2934 } 2955 }
2935 2956
2936 Token endTagTable(EndTagToken token) { 2957 Token endTagTable(EndTagToken token) {
2937 var ignoreEndTag = ignoreEndTagTr(); 2958 var ignoreEndTag = ignoreEndTagTr();
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
3041 Token startTagOther(StartTagToken token) { 3062 Token startTagOther(StartTagToken token) {
3042 return parser._inBodyPhase.processStartTag(token); 3063 return parser._inBodyPhase.processStartTag(token);
3043 } 3064 }
3044 3065
3045 void endTagTableCell(EndTagToken token) { 3066 void endTagTableCell(EndTagToken token) {
3046 if (tree.elementInScope(token.name, variant: "table")) { 3067 if (tree.elementInScope(token.name, variant: "table")) {
3047 tree.generateImpliedEndTags(token.name); 3068 tree.generateImpliedEndTags(token.name);
3048 if (tree.openElements.last.localName != token.name) { 3069 if (tree.openElements.last.localName != token.name) {
3049 parser.parseError( 3070 parser.parseError(
3050 token.span, "unexpected-cell-end-tag", {"name": token.name}); 3071 token.span, "unexpected-cell-end-tag", {"name": token.name});
3051 popOpenElementsUntil(token.name); 3072 popOpenElementsUntil(token);
3052 } else { 3073 } else {
3053 tree.openElements.removeLast(); 3074 var node = tree.openElements.removeLast();
3075 node.endSourceSpan = token.span;
3054 } 3076 }
3055 tree.clearActiveFormattingElements(); 3077 tree.clearActiveFormattingElements();
3056 parser.phase = parser._inRowPhase; 3078 parser.phase = parser._inRowPhase;
3057 } else { 3079 } else {
3058 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 3080 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
3059 } 3081 }
3060 } 3082 }
3061 3083
3062 void endTagIgnore(EndTagToken token) { 3084 void endTagIgnore(EndTagToken token) {
3063 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); 3085 parser.parseError(token.span, "unexpected-end-tag", {"name": token.name});
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
3174 } 3196 }
3175 3197
3176 Token startTagOther(StartTagToken token) { 3198 Token startTagOther(StartTagToken token) {
3177 parser.parseError( 3199 parser.parseError(
3178 token.span, "unexpected-start-tag-in-select", {"name": token.name}); 3200 token.span, "unexpected-start-tag-in-select", {"name": token.name});
3179 return null; 3201 return null;
3180 } 3202 }
3181 3203
3182 void endTagOption(EndTagToken token) { 3204 void endTagOption(EndTagToken token) {
3183 if (tree.openElements.last.localName == "option") { 3205 if (tree.openElements.last.localName == "option") {
3184 tree.openElements.removeLast(); 3206 var node = tree.openElements.removeLast();
3207 node.endSourceSpan = token.span;
3185 } else { 3208 } else {
3186 parser.parseError( 3209 parser.parseError(
3187 token.span, "unexpected-end-tag-in-select", {"name": "option"}); 3210 token.span, "unexpected-end-tag-in-select", {"name": "option"});
3188 } 3211 }
3189 } 3212 }
3190 3213
3191 void endTagOptgroup(EndTagToken token) { 3214 void endTagOptgroup(EndTagToken token) {
3192 // </optgroup> implicitly closes <option> 3215 // </optgroup> implicitly closes <option>
3193 if (tree.openElements.last.localName == "option" && 3216 if (tree.openElements.last.localName == "option" &&
3194 tree.openElements[tree.openElements.length - 2].localName == 3217 tree.openElements[tree.openElements.length - 2].localName ==
3195 "optgroup") { 3218 "optgroup") {
3196 tree.openElements.removeLast(); 3219 tree.openElements.removeLast();
3197 } 3220 }
3198 // It also closes </optgroup> 3221 // It also closes </optgroup>
3199 if (tree.openElements.last.localName == "optgroup") { 3222 if (tree.openElements.last.localName == "optgroup") {
3200 tree.openElements.removeLast(); 3223 var node = tree.openElements.removeLast();
3224 node.endSourceSpan = token.span;
3201 // But nothing else 3225 // But nothing else
3202 } else { 3226 } else {
3203 parser.parseError( 3227 parser.parseError(
3204 token.span, "unexpected-end-tag-in-select", {"name": "optgroup"}); 3228 token.span, "unexpected-end-tag-in-select", {"name": "optgroup"});
3205 } 3229 }
3206 } 3230 }
3207 3231
3208 void endTagSelect(EndTagToken token) { 3232 void endTagSelect(EndTagToken token) {
3209 if (tree.elementInScope("select", variant: "select")) { 3233 if (tree.elementInScope("select", variant: "select")) {
3210 popOpenElementsUntil("select"); 3234 popOpenElementsUntil(token);
3211 parser.resetInsertionMode(); 3235 parser.resetInsertionMode();
3212 } else { 3236 } else {
3213 // innerHTML case 3237 // innerHTML case
3214 assert(parser.innerHTMLMode); 3238 assert(parser.innerHTMLMode);
3215 parser.parseError(token.span, "undefined-error"); 3239 parser.parseError(token.span, "undefined-error");
3216 } 3240 }
3217 } 3241 }
3218 3242
3219 void endTagOther(EndTagToken token) { 3243 void endTagOther(EndTagToken token) {
3220 parser.parseError( 3244 parser.parseError(
(...skipping 284 matching lines...) Expand 10 before | Expand all | Expand 10 after
3505 } 3529 }
3506 3530
3507 Token startTagOther(StartTagToken token) { 3531 Token startTagOther(StartTagToken token) {
3508 parser.parseError( 3532 parser.parseError(
3509 token.span, "unexpected-start-tag-after-body", {"name": token.name}); 3533 token.span, "unexpected-start-tag-after-body", {"name": token.name});
3510 parser.phase = parser._inBodyPhase; 3534 parser.phase = parser._inBodyPhase;
3511 return token; 3535 return token;
3512 } 3536 }
3513 3537
3514 void endTagHtml(Token token) { 3538 void endTagHtml(Token token) {
3539 for (var node in tree.openElements.reversed) {
3540 if (node.localName == 'html') {
3541 node.endSourceSpan = token.span;
3542 break;
3543 }
3544 }
3515 if (parser.innerHTMLMode) { 3545 if (parser.innerHTMLMode) {
3516 parser.parseError(token.span, "unexpected-end-tag-after-body-innerhtml"); 3546 parser.parseError(token.span, "unexpected-end-tag-after-body-innerhtml");
3517 } else { 3547 } else {
3518 parser.phase = parser._afterAfterBodyPhase; 3548 parser.phase = parser._afterAfterBodyPhase;
3519 } 3549 }
3520 } 3550 }
3521 3551
3522 Token endTagOther(EndTagToken token) { 3552 Token endTagOther(EndTagToken token) {
3523 parser.parseError( 3553 parser.parseError(
3524 token.span, "unexpected-end-tag-after-body", {"name": token.name}); 3554 token.span, "unexpected-end-tag-after-body", {"name": token.name});
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
3588 token.span, "unexpected-start-tag-in-frameset", {"name": token.name}); 3618 token.span, "unexpected-start-tag-in-frameset", {"name": token.name});
3589 return null; 3619 return null;
3590 } 3620 }
3591 3621
3592 void endTagFrameset(EndTagToken token) { 3622 void endTagFrameset(EndTagToken token) {
3593 if (tree.openElements.last.localName == "html") { 3623 if (tree.openElements.last.localName == "html") {
3594 // innerHTML case 3624 // innerHTML case
3595 parser.parseError( 3625 parser.parseError(
3596 token.span, "unexpected-frameset-in-frameset-innerhtml"); 3626 token.span, "unexpected-frameset-in-frameset-innerhtml");
3597 } else { 3627 } else {
3598 tree.openElements.removeLast(); 3628 var node = tree.openElements.removeLast();
3629 node.endSourceSpan = token.span;
3599 } 3630 }
3600 if (!parser.innerHTMLMode && 3631 if (!parser.innerHTMLMode &&
3601 tree.openElements.last.localName != "frameset") { 3632 tree.openElements.last.localName != "frameset") {
3602 // If we're not in innerHTML mode and the the current node is not a 3633 // If we're not in innerHTML mode and the the current node is not a
3603 // "frameset" element (anymore) then switch. 3634 // "frameset" element (anymore) then switch.
3604 parser.phase = parser._afterFramesetPhase; 3635 parser.phase = parser._afterFramesetPhase;
3605 } 3636 }
3606 } 3637 }
3607 3638
3608 void endTagOther(EndTagToken token) { 3639 void endTagOther(EndTagToken token) {
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
3782 return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; 3813 return span.sourceUrl == null ? 'ParserError on $res' : 'On $res';
3783 } 3814 }
3784 } 3815 }
3785 3816
3786 /// Convenience function to get the pair of namespace and localName. 3817 /// Convenience function to get the pair of namespace and localName.
3787 Pair<String, String> getElementNameTuple(Element e) { 3818 Pair<String, String> getElementNameTuple(Element e) {
3788 var ns = e.namespaceUri; 3819 var ns = e.namespaceUri;
3789 if (ns == null) ns = Namespaces.html; 3820 if (ns == null) ns = Namespaces.html;
3790 return new Pair(ns, e.localName); 3821 return new Pair(ns, e.localName);
3791 } 3822 }
OLDNEW
« no previous file with comments | « lib/dom.dart ('k') | lib/src/treebuilder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698