From f0096cb2ccaadfd5ee265149f7e29323d7b722d7 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" Date: Wed, 14 Aug 2013 20:59:46 +0000 Subject: [PATCH 001/212] move html5lib code into dart svn repo also gets the tests running Changes to scripts: * pkg/pkg.gyp: add 'third_party' to list of folders to search * tools/publish_pkg.py: update copyright year * tools/publish_all_pkgs.py: also include pkg/third_party Changes to html5lib: * pubspec.yaml -- removed versions * README.md -- removed some historical notes * added html5lib.status * test/browser -- rename browser_tests to browser_test so test framework finds it * test/parser_test.dart, test/parser_feature_test.dart -- moved dart:io test into parser_test so parser_feature_test can work in browser * test/support.dart -- now finds the data folder relative to entry point script * test/support.dart -- rename "pathos" import to "path" Not changed: * ./test/run.sh still works for testing, in addition to ./tools/test.dart R=dgrove@google.com, ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//22375011 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@26152 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/LICENSE | 23 + pkgs/html/README.md | 56 + pkgs/html/lib/dom.dart | 871 + pkgs/html/lib/dom_parsing.dart | 176 + pkgs/html/lib/parser.dart | 3345 ++ pkgs/html/lib/parser_console.dart | 46 + pkgs/html/lib/src/char_encodings.dart | 212 + pkgs/html/lib/src/constants.dart | 3129 ++ pkgs/html/lib/src/encoding_parser.dart | 385 + pkgs/html/lib/src/inputstream.dart | 310 + pkgs/html/lib/src/list_proxy.dart | 88 + pkgs/html/lib/src/token.dart | 122 + pkgs/html/lib/src/tokenizer.dart | 1900 + pkgs/html/lib/src/treebuilder.dart | 400 + pkgs/html/lib/src/utils.dart | 124 + pkgs/html/pubspec.yaml | 10 + pkgs/html/test/browser/browser_test.dart | 14 + pkgs/html/test/browser/browser_test.html | 28 + .../test/data/parser_feature/raw_file.html | 6 + .../data/tokenizer/contentModelFlags.test | 75 + pkgs/html/test/data/tokenizer/domjs.test | 90 + pkgs/html/test/data/tokenizer/entities.test | 283 + pkgs/html/test/data/tokenizer/escapeFlag.test | 33 + .../test/data/tokenizer/namedEntities.test | 44189 ++++++++++++++++ .../test/data/tokenizer/numericEntities.test | 1313 + .../data/tokenizer/pendingSpecChanges.test | 7 + pkgs/html/test/data/tokenizer/test1.test | 196 + pkgs/html/test/data/tokenizer/test2.test | 179 + pkgs/html/test/data/tokenizer/test3.test | 6047 +++ pkgs/html/test/data/tokenizer/test4.test | 344 + .../test/data/tokenizer/unicodeChars.test | 1295 + .../tokenizer/unicodeCharsProblematic.test | 27 + .../test/data/tokenizer/xmlViolation.test | 22 + .../data/tree-construction/adoption01.dat | 194 + .../data/tree-construction/adoption02.dat | 31 + .../data/tree-construction/comments01.dat | 135 + .../test/data/tree-construction/doctype01.dat | 370 + .../data/tree-construction/domjs-unsafe.dat | Bin 0 -> 6639 bytes .../data/tree-construction/entities01.dat | 603 + .../data/tree-construction/entities02.dat | 249 + .../data/tree-construction/html5test-com.dat | 246 + .../test/data/tree-construction/inbody01.dat | 43 + .../test/data/tree-construction/isindex.dat | 40 + ...pending-spec-changes-plain-text-unsafe.dat | Bin 0 -> 115 bytes .../pending-spec-changes.dat | 52 + .../tree-construction/plain-text-unsafe.dat | Bin 0 -> 4166 bytes .../data/tree-construction/scriptdata01.dat | 308 + .../tree-construction/scripted/adoption01.dat | 15 + .../data/tree-construction/scripted/ark.dat | 26 + .../tree-construction/scripted/webkit01.dat | 28 + .../test/data/tree-construction/tables01.dat | 212 + .../test/data/tree-construction/tests1.dat | 1952 + .../test/data/tree-construction/tests10.dat | 799 + .../test/data/tree-construction/tests11.dat | 482 + .../test/data/tree-construction/tests12.dat | 62 + .../test/data/tree-construction/tests14.dat | 74 + .../test/data/tree-construction/tests15.dat | 208 + .../test/data/tree-construction/tests16.dat | 2299 + .../test/data/tree-construction/tests17.dat | 153 + .../test/data/tree-construction/tests18.dat | 269 + .../test/data/tree-construction/tests19.dat | 1237 + .../test/data/tree-construction/tests2.dat | 763 + .../test/data/tree-construction/tests20.dat | 455 + .../test/data/tree-construction/tests21.dat | 221 + .../test/data/tree-construction/tests22.dat | 157 + .../test/data/tree-construction/tests23.dat | 155 + .../test/data/tree-construction/tests24.dat | 79 + .../test/data/tree-construction/tests25.dat | 219 + .../test/data/tree-construction/tests26.dat | 313 + .../test/data/tree-construction/tests3.dat | 305 + .../test/data/tree-construction/tests4.dat | 59 + .../test/data/tree-construction/tests5.dat | 191 + .../test/data/tree-construction/tests6.dat | 663 + .../test/data/tree-construction/tests7.dat | 390 + .../test/data/tree-construction/tests8.dat | 148 + .../test/data/tree-construction/tests9.dat | 457 + .../tree-construction/tests_innerHTML_1.dat | 741 + .../test/data/tree-construction/tricky01.dat | 261 + .../test/data/tree-construction/webkit01.dat | 594 + .../test/data/tree-construction/webkit02.dat | 94 + pkgs/html/test/dom_compat_test.dart | 31 + .../test/dom_compat_test_definitions.dart | 10 + pkgs/html/test/dom_test.dart | 34 + pkgs/html/test/parser_feature_test.dart | 251 + pkgs/html/test/parser_test.dart | 124 + pkgs/html/test/run.sh | 22 + pkgs/html/test/run_all.dart | 34 + pkgs/html/test/support.dart | 168 + pkgs/html/test/tokenizer_test.dart | 270 + 89 files changed, 82641 insertions(+) create mode 100644 pkgs/html/LICENSE create mode 100644 pkgs/html/README.md create mode 100644 pkgs/html/lib/dom.dart create mode 100644 pkgs/html/lib/dom_parsing.dart create mode 100644 pkgs/html/lib/parser.dart create mode 100644 pkgs/html/lib/parser_console.dart create mode 100644 pkgs/html/lib/src/char_encodings.dart create mode 100644 pkgs/html/lib/src/constants.dart create mode 100644 pkgs/html/lib/src/encoding_parser.dart create mode 100644 pkgs/html/lib/src/inputstream.dart create mode 100644 pkgs/html/lib/src/list_proxy.dart create mode 100644 pkgs/html/lib/src/token.dart create mode 100644 pkgs/html/lib/src/tokenizer.dart create mode 100644 pkgs/html/lib/src/treebuilder.dart create mode 100644 pkgs/html/lib/src/utils.dart create mode 100644 pkgs/html/pubspec.yaml create mode 100644 pkgs/html/test/browser/browser_test.dart create mode 100644 pkgs/html/test/browser/browser_test.html create mode 100644 pkgs/html/test/data/parser_feature/raw_file.html create mode 100644 pkgs/html/test/data/tokenizer/contentModelFlags.test create mode 100644 pkgs/html/test/data/tokenizer/domjs.test create mode 100644 pkgs/html/test/data/tokenizer/entities.test create mode 100644 pkgs/html/test/data/tokenizer/escapeFlag.test create mode 100644 pkgs/html/test/data/tokenizer/namedEntities.test create mode 100644 pkgs/html/test/data/tokenizer/numericEntities.test create mode 100644 pkgs/html/test/data/tokenizer/pendingSpecChanges.test create mode 100644 pkgs/html/test/data/tokenizer/test1.test create mode 100644 pkgs/html/test/data/tokenizer/test2.test create mode 100644 pkgs/html/test/data/tokenizer/test3.test create mode 100644 pkgs/html/test/data/tokenizer/test4.test create mode 100644 pkgs/html/test/data/tokenizer/unicodeChars.test create mode 100644 pkgs/html/test/data/tokenizer/unicodeCharsProblematic.test create mode 100644 pkgs/html/test/data/tokenizer/xmlViolation.test create mode 100644 pkgs/html/test/data/tree-construction/adoption01.dat create mode 100644 pkgs/html/test/data/tree-construction/adoption02.dat create mode 100644 pkgs/html/test/data/tree-construction/comments01.dat create mode 100644 pkgs/html/test/data/tree-construction/doctype01.dat create mode 100644 pkgs/html/test/data/tree-construction/domjs-unsafe.dat create mode 100644 pkgs/html/test/data/tree-construction/entities01.dat create mode 100644 pkgs/html/test/data/tree-construction/entities02.dat create mode 100644 pkgs/html/test/data/tree-construction/html5test-com.dat create mode 100644 pkgs/html/test/data/tree-construction/inbody01.dat create mode 100644 pkgs/html/test/data/tree-construction/isindex.dat create mode 100644 pkgs/html/test/data/tree-construction/pending-spec-changes-plain-text-unsafe.dat create mode 100644 pkgs/html/test/data/tree-construction/pending-spec-changes.dat create mode 100644 pkgs/html/test/data/tree-construction/plain-text-unsafe.dat create mode 100644 pkgs/html/test/data/tree-construction/scriptdata01.dat create mode 100644 pkgs/html/test/data/tree-construction/scripted/adoption01.dat create mode 100644 pkgs/html/test/data/tree-construction/scripted/ark.dat create mode 100644 pkgs/html/test/data/tree-construction/scripted/webkit01.dat create mode 100644 pkgs/html/test/data/tree-construction/tables01.dat create mode 100644 pkgs/html/test/data/tree-construction/tests1.dat create mode 100644 pkgs/html/test/data/tree-construction/tests10.dat create mode 100644 pkgs/html/test/data/tree-construction/tests11.dat create mode 100644 pkgs/html/test/data/tree-construction/tests12.dat create mode 100644 pkgs/html/test/data/tree-construction/tests14.dat create mode 100644 pkgs/html/test/data/tree-construction/tests15.dat create mode 100644 pkgs/html/test/data/tree-construction/tests16.dat create mode 100644 pkgs/html/test/data/tree-construction/tests17.dat create mode 100644 pkgs/html/test/data/tree-construction/tests18.dat create mode 100644 pkgs/html/test/data/tree-construction/tests19.dat create mode 100644 pkgs/html/test/data/tree-construction/tests2.dat create mode 100644 pkgs/html/test/data/tree-construction/tests20.dat create mode 100644 pkgs/html/test/data/tree-construction/tests21.dat create mode 100644 pkgs/html/test/data/tree-construction/tests22.dat create mode 100644 pkgs/html/test/data/tree-construction/tests23.dat create mode 100644 pkgs/html/test/data/tree-construction/tests24.dat create mode 100644 pkgs/html/test/data/tree-construction/tests25.dat create mode 100644 pkgs/html/test/data/tree-construction/tests26.dat create mode 100644 pkgs/html/test/data/tree-construction/tests3.dat create mode 100644 pkgs/html/test/data/tree-construction/tests4.dat create mode 100644 pkgs/html/test/data/tree-construction/tests5.dat create mode 100644 pkgs/html/test/data/tree-construction/tests6.dat create mode 100644 pkgs/html/test/data/tree-construction/tests7.dat create mode 100644 pkgs/html/test/data/tree-construction/tests8.dat create mode 100644 pkgs/html/test/data/tree-construction/tests9.dat create mode 100644 pkgs/html/test/data/tree-construction/tests_innerHTML_1.dat create mode 100644 pkgs/html/test/data/tree-construction/tricky01.dat create mode 100644 pkgs/html/test/data/tree-construction/webkit01.dat create mode 100644 pkgs/html/test/data/tree-construction/webkit02.dat create mode 100644 pkgs/html/test/dom_compat_test.dart create mode 100644 pkgs/html/test/dom_compat_test_definitions.dart create mode 100644 pkgs/html/test/dom_test.dart create mode 100644 pkgs/html/test/parser_feature_test.dart create mode 100644 pkgs/html/test/parser_test.dart create mode 100755 pkgs/html/test/run.sh create mode 100644 pkgs/html/test/run_all.dart create mode 100644 pkgs/html/test/support.dart create mode 100644 pkgs/html/test/tokenizer_test.dart diff --git a/pkgs/html/LICENSE b/pkgs/html/LICENSE new file mode 100644 index 000000000..d5ee6416d --- /dev/null +++ b/pkgs/html/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2006-2012 The Authors + +Contributors: +James Graham - jg307@cam.ac.uk +Anne van Kesteren - annevankesteren@gmail.com +Lachlan Hunt - lachlan.hunt@lachy.id.au +Matt McDonald - kanashii@kanashii.ca +Sam Ruby - rubys@intertwingly.net +Ian Hickson (Google) - ian@hixie.ch +Thomas Broyer - t.broyer@ltgt.net +Jacques Distler - distler@golem.ph.utexas.edu +Henri Sivonen - hsivonen@iki.fi +Adam Barth - abarth@webkit.org +Eric Seidel - eric@webkit.org +The Mozilla Foundation (contributions from Henri Sivonen since 2008) +David Flanagan (Mozilla) - dflanagan@mozilla.com +Google Inc. (contributed the Dart port) - misc@dartlang.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/pkgs/html/README.md b/pkgs/html/README.md new file mode 100644 index 000000000..4a8319c7b --- /dev/null +++ b/pkgs/html/README.md @@ -0,0 +1,56 @@ +html5lib in Pure Dart +===================== + +This is a pure [Dart][dart] [html5 parser][html5parse]. It's a port of +[html5lib](http://code.google.com/p/html5lib/) from Python. Since it's 100% +Dart you can use it safely from a script or server side app. + +Eventually the parse tree API will be compatible with [dart:html][d_html], so +the same code will work on the client and the server. + +Installation +------------ + +Add this to your `pubspec.yaml` (or create it): +```yaml +dependencies: + html5lib: any +``` +Then run the [Pub Package Manager][pub] (comes with the Dart SDK): + + pub install + +Usage +----- + +Parsing HTML is easy! +```dart +import 'package:html5lib/parser.dart' show parse; +import 'package:html5lib/dom.dart'; + +main() { + var document = parse( + 'Hello world! HTML5 rocks!'); + print(document.outerHtml); +} +``` + +You can pass a String or list of bytes to `parse`. +There's also `parseFragment` for parsing a document fragment, and `HtmlParser` +if you want more low level control. + +Running Tests +------------- + +```bash +# From Dart SVN checkout +./tools/build.py -m release +./tools/test.py -m release html5lib +./tools/test.py -m release -r drt html5lib +``` + +[dart]: http://www.dartlang.org/ +[html5parse]: http://dev.w3.org/html5/spec/parsing.html +[d_html]: http://api.dartlang.org/docs/continuous/dart_html.html +[files]: http://html5lib.googlecode.com/hg/python/html5lib/ +[pub]: http://www.dartlang.org/docs/pub-package-manager/ diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart new file mode 100644 index 000000000..d73edaac3 --- /dev/null +++ b/pkgs/html/lib/dom.dart @@ -0,0 +1,871 @@ +/** + * A simple tree API that results from parsing html. Intended to be compatible + * with dart:html, but right now it resembles the classic JS DOM. + */ +library dom; + +import 'dart:collection'; +import 'package:source_maps/span.dart' show FileSpan; + +import 'src/constants.dart'; +import 'src/list_proxy.dart'; +import 'src/token.dart'; +import 'src/tokenizer.dart'; +import 'src/treebuilder.dart'; +import 'src/utils.dart'; +import 'dom_parsing.dart'; +import 'parser.dart'; + +// TODO(jmesserly): this needs to be replaced by an AttributeMap for attributes +// that exposes namespace info. +class AttributeName implements Comparable { + /** The namespace prefix, e.g. `xlink`. */ + final String prefix; + + /** The attribute name, e.g. `title`. */ + final String name; + + /** The namespace url, e.g. `http://www.w3.org/1999/xlink` */ + final String namespace; + + const AttributeName(this.prefix, this.name, this.namespace); + + String toString() { + // Implement: + // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments + // If we get here we know we are xml, xmlns, or xlink, because of + // [HtmlParser.adjustForeignAttriubtes] is the only place we create + // an AttributeName. + return prefix != null ? '$prefix:$name' : name; + } + + int get hashCode { + int h = prefix.hashCode; + h = 37 * (h & 0x1FFFFF) + name.hashCode; + h = 37 * (h & 0x1FFFFF) + namespace.hashCode; + return h & 0x3FFFFFFF; + } + + int compareTo(other) { + // Not sure about this sort order + if (other is! AttributeName) return 1; + int cmp = (prefix != null ? prefix : "").compareTo( + (other.prefix != null ? other.prefix : "")); + if (cmp != 0) return cmp; + cmp = name.compareTo(other.name); + if (cmp != 0) return cmp; + return namespace.compareTo(other.namespace); + } + + bool operator ==(x) { + if (x is! AttributeName) return false; + return prefix == x.prefix && name == x.name && namespace == x.namespace; + } +} + +/** Really basic implementation of a DOM-core like Node. */ +abstract class Node { + static const int ATTRIBUTE_NODE = 2; + static const int CDATA_SECTION_NODE = 4; + static const int COMMENT_NODE = 8; + static const int DOCUMENT_FRAGMENT_NODE = 11; + static const int DOCUMENT_NODE = 9; + static const int DOCUMENT_TYPE_NODE = 10; + static const int ELEMENT_NODE = 1; + static const int ENTITY_NODE = 6; + static const int ENTITY_REFERENCE_NODE = 5; + static const int NOTATION_NODE = 12; + static const int PROCESSING_INSTRUCTION_NODE = 7; + static const int TEXT_NODE = 3; + + // TODO(jmesserly): this should be on Element + /** The tag name associated with the node. */ + final String tagName; + + /** The parent of the current node (or null for the document node). */ + Node parent; + + // TODO(jmesserly): should move to Element. + /** + * A map holding name, value pairs for attributes of the node. + * + * Note that attribute order needs to be stable for serialization, so we use a + * LinkedHashMap. Each key is a [String] or [AttributeName]. + */ + LinkedHashMap attributes = new LinkedHashMap(); + + /** + * A list of child nodes of the current node. This must + * include all elements but not necessarily other node types. + */ + final NodeList nodes = new NodeList._(); + + List _elements; + + // TODO(jmesserly): consider using an Expando for this, and put it in + // dom_parsing. Need to check the performance affect. + /** The source span of this node, if it was created by the [HtmlParser]. */ + FileSpan sourceSpan; + + /** The attribute spans if requested. Otherwise null. */ + LinkedHashMap _attributeSpans; + LinkedHashMap _attributeValueSpans; + + Node(this.tagName) { + nodes._parent = this; + } + + /** + * If [sourceSpan] is available, this contains the spans of each attribute. + * The span of an attribute is the entire attribute, including the name and + * quotes (if any). For example, the span of "attr" in `` + * would be the text `attr="value"`. + */ + LinkedHashMap get attributeSpans { + _ensureAttributeSpans(); + return _attributeSpans; + } + + /** + * If [sourceSpan] is available, this contains the spans of each attribute's + * value. Unlike [attributeSpans], this span will inlcude only the value. + * For example, the value span of "attr" in `` would be the + * text `value`. + */ + LinkedHashMap get attributeValueSpans { + _ensureAttributeSpans(); + return _attributeValueSpans; + } + + List get children { + if (_elements == null) { + _elements = new FilteredElementList(this); + } + return _elements; + } + + // TODO(jmesserly): needs to support deep clone. + /** + * Return a shallow copy of the current node i.e. a node with the same + * name and attributes but with no parent or child nodes. + */ + Node clone(); + + String get namespace => null; + + // TODO(jmesserly): do we need this here? + /** The value of the current node (applies to text nodes and comments). */ + String get value => null; + + // TODO(jmesserly): this is a workaround for http://dartbug.com/4754 + int get $dom_nodeType => nodeType; + + int get nodeType; + + String get outerHtml { + var str = new StringBuffer(); + _addOuterHtml(str); + return str.toString(); + } + + String get innerHtml { + var str = new StringBuffer(); + _addInnerHtml(str); + return str.toString(); + } + + set innerHtml(String value) { + nodes.clear(); + // TODO(jmesserly): should be able to get the same effect by adding the + // fragment directly. + nodes.addAll(parseFragment(value, container: tagName).nodes); + } + + void _addOuterHtml(StringBuffer str); + + void _addInnerHtml(StringBuffer str) { + for (Node child in nodes) child._addOuterHtml(str); + } + + String toString() => tagName; + + Node remove() { + // TODO(jmesserly): is parent == null an error? + if (parent != null) { + parent.nodes.remove(this); + } + return this; + } + + /** + * Insert [node] as a child of the current node, before [refNode] in the + * list of child nodes. Raises [UnsupportedOperationException] if [refNode] + * is not a child of the current node. If refNode is null, this adds to the + * end of the list. + */ + void insertBefore(Node node, Node refNode) { + if (refNode == null) { + nodes.add(node); + } else { + nodes.insert(nodes.indexOf(refNode), node); + } + } + + /** Replaces this node with another node. */ + Node replaceWith(Node otherNode) { + if (parent == null) { + throw new UnsupportedError('Node must have a parent to replace it.'); + } + parent.nodes[parent.nodes.indexOf(this)] = otherNode; + return this; + } + + // TODO(jmesserly): should this be a property or remove? + /** Return true if the node has children or text. */ + bool hasContent() => nodes.length > 0; + + Pair get nameTuple { + var ns = namespace != null ? namespace : Namespaces.html; + return new Pair(ns, tagName); + } + + /** + * Move all the children of the current node to [newParent]. + * This is needed so that trees that don't store text as nodes move the + * text in the correct way. + */ + void reparentChildren(Node newParent) { + newParent.nodes.addAll(nodes); + nodes.clear(); + } + + /** + * Seaches for the first descendant node matching the given selectors, using a + * preorder traversal. NOTE: right now, this supports only a single type + * selectors, e.g. `node.query('div')`. + */ + Element query(String selectors) => _queryType(_typeSelector(selectors)); + + /** + * Returns all descendant nodes matching the given selectors, using a + * preorder traversal. NOTE: right now, this supports only a single type + * selectors, e.g. `node.queryAll('div')`. + */ + List queryAll(String selectors) { + var results = new List(); + _queryAllType(_typeSelector(selectors), results); + return results; + } + + bool hasChildNodes() => !nodes.isEmpty; + + bool contains(Node node) => nodes.contains(node); + + String _typeSelector(String selectors) { + selectors = selectors.trim(); + if (!_isTypeSelector(selectors)) { + throw new UnimplementedError('only type selectors are implemented'); + } + return selectors; + } + + /** + * Checks if this is a type selector. + * See . + * Note: this doesn't support '*', the universal selector, non-ascii chars or + * escape chars. + */ + bool _isTypeSelector(String selector) { + // Parser: + + // element_name + // : IDENT | '*' + // ; + + // Lexer: + + // nmstart [_a-z]|{nonascii}|{escape} + // nmchar [_a-z0-9-]|{nonascii}|{escape} + // ident -?{nmstart}{nmchar}* + // nonascii [\240-\377] + // unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])? + // escape {unicode}|\\[^\r\n\f0-9a-f] + + // As mentioned above, no nonascii or escape support yet. + int len = selector.length; + if (len == 0) return false; + + int i = 0; + const int DASH = 45; + if (selector.codeUnitAt(i) == DASH) i++; + + if (i >= len || !isLetter(selector[i])) return false; + i++; + + for (; i < len; i++) { + if (!isLetterOrDigit(selector[i]) && selector.codeUnitAt(i) != DASH) { + return false; + } + } + + return true; + } + + Element _queryType(String tag) { + for (var node in nodes) { + if (node is! Element) continue; + if (node.tagName == tag) return node; + var result = node._queryType(tag); + if (result != null) return result; + } + return null; + } + + void _queryAllType(String tag, List results) { + for (var node in nodes) { + if (node is! Element) continue; + if (node.tagName == tag) results.add(node); + node._queryAllType(tag, results); + } + } + + /** Initialize [attributeSpans] using [sourceSpan]. */ + void _ensureAttributeSpans() { + if (_attributeSpans != null) return; + + _attributeSpans = new LinkedHashMap(); + _attributeValueSpans = new LinkedHashMap(); + + if (sourceSpan == null) return; + + var tokenizer = new HtmlTokenizer(sourceSpan.text, generateSpans: true, + attributeSpans: true); + + tokenizer.moveNext(); + var token = tokenizer.current as StartTagToken; + + if (token.attributeSpans == null) return; // no attributes + + for (var attr in token.attributeSpans) { + var offset = sourceSpan.start.offset; + _attributeSpans[attr.name] = sourceSpan.file.span( + offset + attr.start, offset + attr.end); + if (attr.startValue != null) { + _attributeValueSpans[attr.name] = sourceSpan.file.span( + offset + attr.startValue, offset + attr.endValue); + } + } + } +} + +class Document extends Node { + Document() : super(null); + factory Document.html(String html) => parse(html); + + int get nodeType => Node.DOCUMENT_NODE; + + // TODO(jmesserly): optmize this if needed + Element get head => query('html').query('head'); + Element get body => query('html').query('body'); + + String toString() => "#document"; + + void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); + + Document clone() => new Document(); +} + +class DocumentFragment extends Document { + DocumentFragment(); + factory DocumentFragment.html(String html) => parseFragment(html); + + int get nodeType => Node.DOCUMENT_FRAGMENT_NODE; + + String toString() => "#document-fragment"; + + DocumentFragment clone() => new DocumentFragment(); +} + +class DocumentType extends Node { + final String publicId; + final String systemId; + + DocumentType(String name, this.publicId, this.systemId) : super(name); + + int get nodeType => Node.DOCUMENT_TYPE_NODE; + + String toString() { + if (publicId != null || systemId != null) { + // TODO(jmesserly): the html5 serialization spec does not add these. But + // it seems useful, and the parser can handle it, so for now keeping it. + var pid = publicId != null ? publicId : ''; + var sid = systemId != null ? systemId : ''; + return ''; + } else { + return ''; + } + } + + + void _addOuterHtml(StringBuffer str) { + str.write(toString()); + } + + DocumentType clone() => new DocumentType(tagName, publicId, systemId); +} + +class Text extends Node { + // TODO(jmesserly): this should be text? + String value; + + Text(this.value) : super(null); + + int get nodeType => Node.TEXT_NODE; + + String toString() => '"$value"'; + + void _addOuterHtml(StringBuffer str) { + // Don't escape text for certain elements, notably + + + + diff --git a/pkgs/html/test/data/parser_feature/raw_file.html b/pkgs/html/test/data/parser_feature/raw_file.html new file mode 100644 index 000000000..bcdbf76f9 --- /dev/null +++ b/pkgs/html/test/data/parser_feature/raw_file.html @@ -0,0 +1,6 @@ + + + +Hello world! + + diff --git a/pkgs/html/test/data/tokenizer/contentModelFlags.test b/pkgs/html/test/data/tokenizer/contentModelFlags.test new file mode 100644 index 000000000..a8b169586 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/contentModelFlags.test @@ -0,0 +1,75 @@ +{"tests": [ + +{"description":"PLAINTEXT content model flag", +"initialStates":["PLAINTEXT state"], +"lastStartTag":"plaintext", +"input":"&body;", +"output":[["Character", "&body;"]]}, + +{"description":"End tag closing RCDATA or RAWTEXT", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foo", +"output":[["Character", "foo"], ["EndTag", "xmp"]]}, + +{"description":"End tag closing RCDATA or RAWTEXT (case-insensitivity)", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foo", +"output":[["Character", "foo"], ["EndTag", "xmp"]]}, + +{"description":"End tag closing RCDATA or RAWTEXT (ending with space)", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foobar", +"output":[["Character", "bar"], ["EndTag", "xmp"]]}, + +{"description":"End tag with incorrect name in RCDATA or RAWTEXT (starting like correct name)", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"bar", +"output":[["Character", "bar"]]}, + +{"description":"End tag closing RCDATA or RAWTEXT, switching back to PCDATA", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foo", +"output":[["Character", "foo"], ["EndTag", "xmp"], ["EndTag", "baz"]]}, + +{"description":"RAWTEXT w/ something looking like an entity", +"initialStates":["RAWTEXT state"], +"lastStartTag":"xmp", +"input":"&foo;", +"output":[["Character", "&foo;"]]}, + +{"description":"RCDATA w/ an entity", +"initialStates":["RCDATA state"], +"lastStartTag":"textarea", +"input":"<", +"output":[["Character", "<"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/domjs.test b/pkgs/html/test/data/tokenizer/domjs.test new file mode 100644 index 000000000..74771e230 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/domjs.test @@ -0,0 +1,90 @@ +{ + "tests": [ + { + "description":"CR in bogus comment state", + "input":"", + "output":[["EndTag","xmp"]] + }, + { + "description":"bad endtag in RCDATA and RAWTEXT", + "initialStates":["RCDATA state", "RAWTEXT state"], + "lastStartTag":"xmp", + "input":"", + "output":[["Character",""]] + }, + { + "description":"bad endtag in RCDATA and RAWTEXT", + "initialStates":["RCDATA state", "RAWTEXT state"], + "lastStartTag":"xmp", + "input":"", + "output":[["Character",""]] + }, + { + "description":"bad endtag in RCDATA and RAWTEXT", + "initialStates":["RCDATA state", "RAWTEXT state"], + "lastStartTag":"xmp", + "input":"", + "output":[["StartTag", "p", {"id":"\u2242\u0338"}]] + }, + { + "description":"--!NUL in comment ", + "doubleEscaped":true, + "input":"", + "output":["ParseError", ["Comment", "--!\\uFFFD"]] + }, + { + "description":"space EOF after doctype ", + "input":"", +"output": ["ParseError", ["StartTag", "h", {"a": "¬i;"}]]}, + +{"description": "Entity name followed by the equals sign in an attribute value.", +"input":"", +"output": ["ParseError", ["StartTag", "h", {"a": "&lang="}]]}, + +{"description": "CR as numeric entity", +"input":" ", +"output": ["ParseError", ["Character", "\r"]]}, + +{"description": "CR as hexadecimal numeric entity", +"input":" ", +"output": ["ParseError", ["Character", "\r"]]}, + +{"description": "Windows-1252 EURO SIGN numeric entity.", +"input":"€", +"output": ["ParseError", ["Character", "\u20AC"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u0081"]]}, + +{"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK numeric entity.", +"input":"‚", +"output": ["ParseError", ["Character", "\u201A"]]}, + +{"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK numeric entity.", +"input":"ƒ", +"output": ["ParseError", ["Character", "\u0192"]]}, + +{"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK numeric entity.", +"input":"„", +"output": ["ParseError", ["Character", "\u201E"]]}, + +{"description": "Windows-1252 HORIZONTAL ELLIPSIS numeric entity.", +"input":"…", +"output": ["ParseError", ["Character", "\u2026"]]}, + +{"description": "Windows-1252 DAGGER numeric entity.", +"input":"†", +"output": ["ParseError", ["Character", "\u2020"]]}, + +{"description": "Windows-1252 DOUBLE DAGGER numeric entity.", +"input":"‡", +"output": ["ParseError", ["Character", "\u2021"]]}, + +{"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT numeric entity.", +"input":"ˆ", +"output": ["ParseError", ["Character", "\u02C6"]]}, + +{"description": "Windows-1252 PER MILLE SIGN numeric entity.", +"input":"‰", +"output": ["ParseError", ["Character", "\u2030"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON numeric entity.", +"input":"Š", +"output": ["ParseError", ["Character", "\u0160"]]}, + +{"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK numeric entity.", +"input":"‹", +"output": ["ParseError", ["Character", "\u2039"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LIGATURE OE numeric entity.", +"input":"Œ", +"output": ["ParseError", ["Character", "\u0152"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u008D"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON numeric entity.", +"input":"Ž", +"output": ["ParseError", ["Character", "\u017D"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u008F"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u0090"]]}, + +{"description": "Windows-1252 LEFT SINGLE QUOTATION MARK numeric entity.", +"input":"‘", +"output": ["ParseError", ["Character", "\u2018"]]}, + +{"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK numeric entity.", +"input":"’", +"output": ["ParseError", ["Character", "\u2019"]]}, + +{"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK numeric entity.", +"input":"“", +"output": ["ParseError", ["Character", "\u201C"]]}, + +{"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK numeric entity.", +"input":"”", +"output": ["ParseError", ["Character", "\u201D"]]}, + +{"description": "Windows-1252 BULLET numeric entity.", +"input":"•", +"output": ["ParseError", ["Character", "\u2022"]]}, + +{"description": "Windows-1252 EN DASH numeric entity.", +"input":"–", +"output": ["ParseError", ["Character", "\u2013"]]}, + +{"description": "Windows-1252 EM DASH numeric entity.", +"input":"—", +"output": ["ParseError", ["Character", "\u2014"]]}, + +{"description": "Windows-1252 SMALL TILDE numeric entity.", +"input":"˜", +"output": ["ParseError", ["Character", "\u02DC"]]}, + +{"description": "Windows-1252 TRADE MARK SIGN numeric entity.", +"input":"™", +"output": ["ParseError", ["Character", "\u2122"]]}, + +{"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON numeric entity.", +"input":"š", +"output": ["ParseError", ["Character", "\u0161"]]}, + +{"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK numeric entity.", +"input":"›", +"output": ["ParseError", ["Character", "\u203A"]]}, + +{"description": "Windows-1252 LATIN SMALL LIGATURE OE numeric entity.", +"input":"œ", +"output": ["ParseError", ["Character", "\u0153"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u009D"]]}, + +{"description": "Windows-1252 EURO SIGN hexadecimal numeric entity.", +"input":"€", +"output": ["ParseError", ["Character", "\u20AC"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u0081"]]}, + +{"description": "Windows-1252 SINGLE LOW-9 QUOTATION MARK hexadecimal numeric entity.", +"input":"‚", +"output": ["ParseError", ["Character", "\u201A"]]}, + +{"description": "Windows-1252 LATIN SMALL LETTER F WITH HOOK hexadecimal numeric entity.", +"input":"ƒ", +"output": ["ParseError", ["Character", "\u0192"]]}, + +{"description": "Windows-1252 DOUBLE LOW-9 QUOTATION MARK hexadecimal numeric entity.", +"input":"„", +"output": ["ParseError", ["Character", "\u201E"]]}, + +{"description": "Windows-1252 HORIZONTAL ELLIPSIS hexadecimal numeric entity.", +"input":"…", +"output": ["ParseError", ["Character", "\u2026"]]}, + +{"description": "Windows-1252 DAGGER hexadecimal numeric entity.", +"input":"†", +"output": ["ParseError", ["Character", "\u2020"]]}, + +{"description": "Windows-1252 DOUBLE DAGGER hexadecimal numeric entity.", +"input":"‡", +"output": ["ParseError", ["Character", "\u2021"]]}, + +{"description": "Windows-1252 MODIFIER LETTER CIRCUMFLEX ACCENT hexadecimal numeric entity.", +"input":"ˆ", +"output": ["ParseError", ["Character", "\u02C6"]]}, + +{"description": "Windows-1252 PER MILLE SIGN hexadecimal numeric entity.", +"input":"‰", +"output": ["ParseError", ["Character", "\u2030"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LETTER S WITH CARON hexadecimal numeric entity.", +"input":"Š", +"output": ["ParseError", ["Character", "\u0160"]]}, + +{"description": "Windows-1252 SINGLE LEFT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.", +"input":"‹", +"output": ["ParseError", ["Character", "\u2039"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LIGATURE OE hexadecimal numeric entity.", +"input":"Œ", +"output": ["ParseError", ["Character", "\u0152"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u008D"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LETTER Z WITH CARON hexadecimal numeric entity.", +"input":"Ž", +"output": ["ParseError", ["Character", "\u017D"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u008F"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u0090"]]}, + +{"description": "Windows-1252 LEFT SINGLE QUOTATION MARK hexadecimal numeric entity.", +"input":"‘", +"output": ["ParseError", ["Character", "\u2018"]]}, + +{"description": "Windows-1252 RIGHT SINGLE QUOTATION MARK hexadecimal numeric entity.", +"input":"’", +"output": ["ParseError", ["Character", "\u2019"]]}, + +{"description": "Windows-1252 LEFT DOUBLE QUOTATION MARK hexadecimal numeric entity.", +"input":"“", +"output": ["ParseError", ["Character", "\u201C"]]}, + +{"description": "Windows-1252 RIGHT DOUBLE QUOTATION MARK hexadecimal numeric entity.", +"input":"”", +"output": ["ParseError", ["Character", "\u201D"]]}, + +{"description": "Windows-1252 BULLET hexadecimal numeric entity.", +"input":"•", +"output": ["ParseError", ["Character", "\u2022"]]}, + +{"description": "Windows-1252 EN DASH hexadecimal numeric entity.", +"input":"–", +"output": ["ParseError", ["Character", "\u2013"]]}, + +{"description": "Windows-1252 EM DASH hexadecimal numeric entity.", +"input":"—", +"output": ["ParseError", ["Character", "\u2014"]]}, + +{"description": "Windows-1252 SMALL TILDE hexadecimal numeric entity.", +"input":"˜", +"output": ["ParseError", ["Character", "\u02DC"]]}, + +{"description": "Windows-1252 TRADE MARK SIGN hexadecimal numeric entity.", +"input":"™", +"output": ["ParseError", ["Character", "\u2122"]]}, + +{"description": "Windows-1252 LATIN SMALL LETTER S WITH CARON hexadecimal numeric entity.", +"input":"š", +"output": ["ParseError", ["Character", "\u0161"]]}, + +{"description": "Windows-1252 SINGLE RIGHT-POINTING ANGLE QUOTATION MARK hexadecimal numeric entity.", +"input":"›", +"output": ["ParseError", ["Character", "\u203A"]]}, + +{"description": "Windows-1252 LATIN SMALL LIGATURE OE hexadecimal numeric entity.", +"input":"œ", +"output": ["ParseError", ["Character", "\u0153"]]}, + +{"description": "Windows-1252 REPLACEMENT CHAR hexadecimal numeric entity.", +"input":"", +"output": ["ParseError", ["Character", "\u009D"]]}, + +{"description": "Windows-1252 LATIN SMALL LETTER Z WITH CARON hexadecimal numeric entity.", +"input":"ž", +"output": ["ParseError", ["Character", "\u017E"]]}, + +{"description": "Windows-1252 LATIN CAPITAL LETTER Y WITH DIAERESIS hexadecimal numeric entity.", +"input":"Ÿ", +"output": ["ParseError", ["Character", "\u0178"]]}, + +{"description": "Decimal numeric entity followed by hex character a.", +"input":"aa", +"output": ["ParseError", ["Character", "aa"]]}, + +{"description": "Decimal numeric entity followed by hex character A.", +"input":"aA", +"output": ["ParseError", ["Character", "aA"]]}, + +{"description": "Decimal numeric entity followed by hex character f.", +"input":"af", +"output": ["ParseError", ["Character", "af"]]}, + +{"description": "Decimal numeric entity followed by hex character A.", +"input":"aF", +"output": ["ParseError", ["Character", "aF"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/escapeFlag.test b/pkgs/html/test/data/tokenizer/escapeFlag.test new file mode 100644 index 000000000..18cb4309e --- /dev/null +++ b/pkgs/html/test/data/tokenizer/escapeFlag.test @@ -0,0 +1,33 @@ +{"tests": [ + +{"description":"Commented close tag in RCDATA or RAWTEXT", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foo", +"output":[["Character", "foo"], ["EndTag", "xmp"]]}, + +{"description":"Bogus comment in RCDATA or RAWTEXT", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foobaz", +"output":[["Character", "foobaz"], ["EndTag", "xmp"]]}, + +{"description":"End tag surrounded by bogus comment in RCDATA or RAWTEXT", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foobaz", +"output":[["Character", "foo"], ["EndTag", "xmp"], "ParseError", ["Comment", ""], ["Character", "baz"], ["EndTag", "xmp"]]}, + +{"description":"Commented entities in RCDATA", +"initialStates":["RCDATA state"], +"lastStartTag":"xmp", +"input":" & & ", +"output":[["Character", " & & "], ["EndTag", "xmp"]]}, + +{"description":"Incorrect comment ending sequences in RCDATA or RAWTEXT", +"initialStates":["RCDATA state", "RAWTEXT state"], +"lastStartTag":"xmp", +"input":"foox--<>", +"output":[["Character", "foox--<>"], ["EndTag", "xmp"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/namedEntities.test b/pkgs/html/test/data/tokenizer/namedEntities.test new file mode 100644 index 000000000..4a51c9c1a --- /dev/null +++ b/pkgs/html/test/data/tokenizer/namedEntities.test @@ -0,0 +1,44189 @@ +{ + "tests": [ + { + "input": "Æ", + "description": "Named entity: AElig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c6" + ] + ] + }, + { + "input": "Æ", + "description": "Named entity: AElig; with a semi-colon", + "output": [ + [ + "Character", + "\u00c6" + ] + ] + }, + { + "input": "&", + "description": "Named entity: AMP without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&" + ] + ] + }, + { + "input": "&", + "description": "Named entity: AMP; with a semi-colon", + "output": [ + [ + "Character", + "&" + ] + ] + }, + { + "input": "Á", + "description": "Named entity: Aacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c1" + ] + ] + }, + { + "input": "Á", + "description": "Named entity: Aacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00c1" + ] + ] + }, + { + "input": "&Abreve", + "description": "Bad named entity: Abreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Abreve" + ] + ] + }, + { + "input": "Ă", + "description": "Named entity: Abreve; with a semi-colon", + "output": [ + [ + "Character", + "\u0102" + ] + ] + }, + { + "input": "Â", + "description": "Named entity: Acirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c2" + ] + ] + }, + { + "input": "Â", + "description": "Named entity: Acirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00c2" + ] + ] + }, + { + "input": "&Acy", + "description": "Bad named entity: Acy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Acy" + ] + ] + }, + { + "input": "А", + "description": "Named entity: Acy; with a semi-colon", + "output": [ + [ + "Character", + "\u0410" + ] + ] + }, + { + "input": "&Afr", + "description": "Bad named entity: Afr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Afr" + ] + ] + }, + { + "input": "𝔄", + "description": "Named entity: Afr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd04" + ] + ] + }, + { + "input": "À", + "description": "Named entity: Agrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c0" + ] + ] + }, + { + "input": "À", + "description": "Named entity: Agrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00c0" + ] + ] + }, + { + "input": "&Alpha", + "description": "Bad named entity: Alpha without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Alpha" + ] + ] + }, + { + "input": "Α", + "description": "Named entity: Alpha; with a semi-colon", + "output": [ + [ + "Character", + "\u0391" + ] + ] + }, + { + "input": "&Amacr", + "description": "Bad named entity: Amacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Amacr" + ] + ] + }, + { + "input": "Ā", + "description": "Named entity: Amacr; with a semi-colon", + "output": [ + [ + "Character", + "\u0100" + ] + ] + }, + { + "input": "&And", + "description": "Bad named entity: And without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&And" + ] + ] + }, + { + "input": "⩓", + "description": "Named entity: And; with a semi-colon", + "output": [ + [ + "Character", + "\u2a53" + ] + ] + }, + { + "input": "&Aogon", + "description": "Bad named entity: Aogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Aogon" + ] + ] + }, + { + "input": "Ą", + "description": "Named entity: Aogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0104" + ] + ] + }, + { + "input": "&Aopf", + "description": "Bad named entity: Aopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Aopf" + ] + ] + }, + { + "input": "𝔸", + "description": "Named entity: Aopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd38" + ] + ] + }, + { + "input": "&ApplyFunction", + "description": "Bad named entity: ApplyFunction without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ApplyFunction" + ] + ] + }, + { + "input": "⁡", + "description": "Named entity: ApplyFunction; with a semi-colon", + "output": [ + [ + "Character", + "\u2061" + ] + ] + }, + { + "input": "Å", + "description": "Named entity: Aring without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c5" + ] + ] + }, + { + "input": "Å", + "description": "Named entity: Aring; with a semi-colon", + "output": [ + [ + "Character", + "\u00c5" + ] + ] + }, + { + "input": "&Ascr", + "description": "Bad named entity: Ascr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ascr" + ] + ] + }, + { + "input": "𝒜", + "description": "Named entity: Ascr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udc9c" + ] + ] + }, + { + "input": "&Assign", + "description": "Bad named entity: Assign without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Assign" + ] + ] + }, + { + "input": "≔", + "description": "Named entity: Assign; with a semi-colon", + "output": [ + [ + "Character", + "\u2254" + ] + ] + }, + { + "input": "Ã", + "description": "Named entity: Atilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c3" + ] + ] + }, + { + "input": "Ã", + "description": "Named entity: Atilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00c3" + ] + ] + }, + { + "input": "Ä", + "description": "Named entity: Auml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c4" + ] + ] + }, + { + "input": "Ä", + "description": "Named entity: Auml; with a semi-colon", + "output": [ + [ + "Character", + "\u00c4" + ] + ] + }, + { + "input": "&Backslash", + "description": "Bad named entity: Backslash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Backslash" + ] + ] + }, + { + "input": "∖", + "description": "Named entity: Backslash; with a semi-colon", + "output": [ + [ + "Character", + "\u2216" + ] + ] + }, + { + "input": "&Barv", + "description": "Bad named entity: Barv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Barv" + ] + ] + }, + { + "input": "⫧", + "description": "Named entity: Barv; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae7" + ] + ] + }, + { + "input": "&Barwed", + "description": "Bad named entity: Barwed without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Barwed" + ] + ] + }, + { + "input": "⌆", + "description": "Named entity: Barwed; with a semi-colon", + "output": [ + [ + "Character", + "\u2306" + ] + ] + }, + { + "input": "&Bcy", + "description": "Bad named entity: Bcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bcy" + ] + ] + }, + { + "input": "Б", + "description": "Named entity: Bcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0411" + ] + ] + }, + { + "input": "&Because", + "description": "Bad named entity: Because without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Because" + ] + ] + }, + { + "input": "∵", + "description": "Named entity: Because; with a semi-colon", + "output": [ + [ + "Character", + "\u2235" + ] + ] + }, + { + "input": "&Bernoullis", + "description": "Bad named entity: Bernoullis without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bernoullis" + ] + ] + }, + { + "input": "ℬ", + "description": "Named entity: Bernoullis; with a semi-colon", + "output": [ + [ + "Character", + "\u212c" + ] + ] + }, + { + "input": "&Beta", + "description": "Bad named entity: Beta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Beta" + ] + ] + }, + { + "input": "Β", + "description": "Named entity: Beta; with a semi-colon", + "output": [ + [ + "Character", + "\u0392" + ] + ] + }, + { + "input": "&Bfr", + "description": "Bad named entity: Bfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bfr" + ] + ] + }, + { + "input": "𝔅", + "description": "Named entity: Bfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd05" + ] + ] + }, + { + "input": "&Bopf", + "description": "Bad named entity: Bopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bopf" + ] + ] + }, + { + "input": "𝔹", + "description": "Named entity: Bopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd39" + ] + ] + }, + { + "input": "&Breve", + "description": "Bad named entity: Breve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Breve" + ] + ] + }, + { + "input": "˘", + "description": "Named entity: Breve; with a semi-colon", + "output": [ + [ + "Character", + "\u02d8" + ] + ] + }, + { + "input": "&Bscr", + "description": "Bad named entity: Bscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bscr" + ] + ] + }, + { + "input": "ℬ", + "description": "Named entity: Bscr; with a semi-colon", + "output": [ + [ + "Character", + "\u212c" + ] + ] + }, + { + "input": "&Bumpeq", + "description": "Bad named entity: Bumpeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Bumpeq" + ] + ] + }, + { + "input": "≎", + "description": "Named entity: Bumpeq; with a semi-colon", + "output": [ + [ + "Character", + "\u224e" + ] + ] + }, + { + "input": "&CHcy", + "description": "Bad named entity: CHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CHcy" + ] + ] + }, + { + "input": "Ч", + "description": "Named entity: CHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0427" + ] + ] + }, + { + "input": "©", + "description": "Named entity: COPY without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a9" + ] + ] + }, + { + "input": "©", + "description": "Named entity: COPY; with a semi-colon", + "output": [ + [ + "Character", + "\u00a9" + ] + ] + }, + { + "input": "&Cacute", + "description": "Bad named entity: Cacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cacute" + ] + ] + }, + { + "input": "Ć", + "description": "Named entity: Cacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0106" + ] + ] + }, + { + "input": "&Cap", + "description": "Bad named entity: Cap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cap" + ] + ] + }, + { + "input": "⋒", + "description": "Named entity: Cap; with a semi-colon", + "output": [ + [ + "Character", + "\u22d2" + ] + ] + }, + { + "input": "&CapitalDifferentialD", + "description": "Bad named entity: CapitalDifferentialD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CapitalDifferentialD" + ] + ] + }, + { + "input": "ⅅ", + "description": "Named entity: CapitalDifferentialD; with a semi-colon", + "output": [ + [ + "Character", + "\u2145" + ] + ] + }, + { + "input": "&Cayleys", + "description": "Bad named entity: Cayleys without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cayleys" + ] + ] + }, + { + "input": "ℭ", + "description": "Named entity: Cayleys; with a semi-colon", + "output": [ + [ + "Character", + "\u212d" + ] + ] + }, + { + "input": "&Ccaron", + "description": "Bad named entity: Ccaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ccaron" + ] + ] + }, + { + "input": "Č", + "description": "Named entity: Ccaron; with a semi-colon", + "output": [ + [ + "Character", + "\u010c" + ] + ] + }, + { + "input": "Ç", + "description": "Named entity: Ccedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c7" + ] + ] + }, + { + "input": "Ç", + "description": "Named entity: Ccedil; with a semi-colon", + "output": [ + [ + "Character", + "\u00c7" + ] + ] + }, + { + "input": "&Ccirc", + "description": "Bad named entity: Ccirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ccirc" + ] + ] + }, + { + "input": "Ĉ", + "description": "Named entity: Ccirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0108" + ] + ] + }, + { + "input": "&Cconint", + "description": "Bad named entity: Cconint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cconint" + ] + ] + }, + { + "input": "∰", + "description": "Named entity: Cconint; with a semi-colon", + "output": [ + [ + "Character", + "\u2230" + ] + ] + }, + { + "input": "&Cdot", + "description": "Bad named entity: Cdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cdot" + ] + ] + }, + { + "input": "Ċ", + "description": "Named entity: Cdot; with a semi-colon", + "output": [ + [ + "Character", + "\u010a" + ] + ] + }, + { + "input": "&Cedilla", + "description": "Bad named entity: Cedilla without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cedilla" + ] + ] + }, + { + "input": "¸", + "description": "Named entity: Cedilla; with a semi-colon", + "output": [ + [ + "Character", + "\u00b8" + ] + ] + }, + { + "input": "&CenterDot", + "description": "Bad named entity: CenterDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CenterDot" + ] + ] + }, + { + "input": "·", + "description": "Named entity: CenterDot; with a semi-colon", + "output": [ + [ + "Character", + "\u00b7" + ] + ] + }, + { + "input": "&Cfr", + "description": "Bad named entity: Cfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cfr" + ] + ] + }, + { + "input": "ℭ", + "description": "Named entity: Cfr; with a semi-colon", + "output": [ + [ + "Character", + "\u212d" + ] + ] + }, + { + "input": "&Chi", + "description": "Bad named entity: Chi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Chi" + ] + ] + }, + { + "input": "Χ", + "description": "Named entity: Chi; with a semi-colon", + "output": [ + [ + "Character", + "\u03a7" + ] + ] + }, + { + "input": "&CircleDot", + "description": "Bad named entity: CircleDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CircleDot" + ] + ] + }, + { + "input": "⊙", + "description": "Named entity: CircleDot; with a semi-colon", + "output": [ + [ + "Character", + "\u2299" + ] + ] + }, + { + "input": "&CircleMinus", + "description": "Bad named entity: CircleMinus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CircleMinus" + ] + ] + }, + { + "input": "⊖", + "description": "Named entity: CircleMinus; with a semi-colon", + "output": [ + [ + "Character", + "\u2296" + ] + ] + }, + { + "input": "&CirclePlus", + "description": "Bad named entity: CirclePlus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CirclePlus" + ] + ] + }, + { + "input": "⊕", + "description": "Named entity: CirclePlus; with a semi-colon", + "output": [ + [ + "Character", + "\u2295" + ] + ] + }, + { + "input": "&CircleTimes", + "description": "Bad named entity: CircleTimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CircleTimes" + ] + ] + }, + { + "input": "⊗", + "description": "Named entity: CircleTimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2297" + ] + ] + }, + { + "input": "&ClockwiseContourIntegral", + "description": "Bad named entity: ClockwiseContourIntegral without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ClockwiseContourIntegral" + ] + ] + }, + { + "input": "∲", + "description": "Named entity: ClockwiseContourIntegral; with a semi-colon", + "output": [ + [ + "Character", + "\u2232" + ] + ] + }, + { + "input": "&CloseCurlyDoubleQuote", + "description": "Bad named entity: CloseCurlyDoubleQuote without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CloseCurlyDoubleQuote" + ] + ] + }, + { + "input": "”", + "description": "Named entity: CloseCurlyDoubleQuote; with a semi-colon", + "output": [ + [ + "Character", + "\u201d" + ] + ] + }, + { + "input": "&CloseCurlyQuote", + "description": "Bad named entity: CloseCurlyQuote without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CloseCurlyQuote" + ] + ] + }, + { + "input": "’", + "description": "Named entity: CloseCurlyQuote; with a semi-colon", + "output": [ + [ + "Character", + "\u2019" + ] + ] + }, + { + "input": "&Colon", + "description": "Bad named entity: Colon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Colon" + ] + ] + }, + { + "input": "∷", + "description": "Named entity: Colon; with a semi-colon", + "output": [ + [ + "Character", + "\u2237" + ] + ] + }, + { + "input": "&Colone", + "description": "Bad named entity: Colone without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Colone" + ] + ] + }, + { + "input": "⩴", + "description": "Named entity: Colone; with a semi-colon", + "output": [ + [ + "Character", + "\u2a74" + ] + ] + }, + { + "input": "&Congruent", + "description": "Bad named entity: Congruent without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Congruent" + ] + ] + }, + { + "input": "≡", + "description": "Named entity: Congruent; with a semi-colon", + "output": [ + [ + "Character", + "\u2261" + ] + ] + }, + { + "input": "&Conint", + "description": "Bad named entity: Conint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Conint" + ] + ] + }, + { + "input": "∯", + "description": "Named entity: Conint; with a semi-colon", + "output": [ + [ + "Character", + "\u222f" + ] + ] + }, + { + "input": "&ContourIntegral", + "description": "Bad named entity: ContourIntegral without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ContourIntegral" + ] + ] + }, + { + "input": "∮", + "description": "Named entity: ContourIntegral; with a semi-colon", + "output": [ + [ + "Character", + "\u222e" + ] + ] + }, + { + "input": "&Copf", + "description": "Bad named entity: Copf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Copf" + ] + ] + }, + { + "input": "ℂ", + "description": "Named entity: Copf; with a semi-colon", + "output": [ + [ + "Character", + "\u2102" + ] + ] + }, + { + "input": "&Coproduct", + "description": "Bad named entity: Coproduct without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Coproduct" + ] + ] + }, + { + "input": "∐", + "description": "Named entity: Coproduct; with a semi-colon", + "output": [ + [ + "Character", + "\u2210" + ] + ] + }, + { + "input": "&CounterClockwiseContourIntegral", + "description": "Bad named entity: CounterClockwiseContourIntegral without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CounterClockwiseContourIntegral" + ] + ] + }, + { + "input": "∳", + "description": "Named entity: CounterClockwiseContourIntegral; with a semi-colon", + "output": [ + [ + "Character", + "\u2233" + ] + ] + }, + { + "input": "&Cross", + "description": "Bad named entity: Cross without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cross" + ] + ] + }, + { + "input": "⨯", + "description": "Named entity: Cross; with a semi-colon", + "output": [ + [ + "Character", + "\u2a2f" + ] + ] + }, + { + "input": "&Cscr", + "description": "Bad named entity: Cscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cscr" + ] + ] + }, + { + "input": "𝒞", + "description": "Named entity: Cscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udc9e" + ] + ] + }, + { + "input": "&Cup", + "description": "Bad named entity: Cup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Cup" + ] + ] + }, + { + "input": "⋓", + "description": "Named entity: Cup; with a semi-colon", + "output": [ + [ + "Character", + "\u22d3" + ] + ] + }, + { + "input": "&CupCap", + "description": "Bad named entity: CupCap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&CupCap" + ] + ] + }, + { + "input": "≍", + "description": "Named entity: CupCap; with a semi-colon", + "output": [ + [ + "Character", + "\u224d" + ] + ] + }, + { + "input": "&DD", + "description": "Bad named entity: DD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DD" + ] + ] + }, + { + "input": "ⅅ", + "description": "Named entity: DD; with a semi-colon", + "output": [ + [ + "Character", + "\u2145" + ] + ] + }, + { + "input": "&DDotrahd", + "description": "Bad named entity: DDotrahd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DDotrahd" + ] + ] + }, + { + "input": "⤑", + "description": "Named entity: DDotrahd; with a semi-colon", + "output": [ + [ + "Character", + "\u2911" + ] + ] + }, + { + "input": "&DJcy", + "description": "Bad named entity: DJcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DJcy" + ] + ] + }, + { + "input": "Ђ", + "description": "Named entity: DJcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0402" + ] + ] + }, + { + "input": "&DScy", + "description": "Bad named entity: DScy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DScy" + ] + ] + }, + { + "input": "Ѕ", + "description": "Named entity: DScy; with a semi-colon", + "output": [ + [ + "Character", + "\u0405" + ] + ] + }, + { + "input": "&DZcy", + "description": "Bad named entity: DZcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DZcy" + ] + ] + }, + { + "input": "Џ", + "description": "Named entity: DZcy; with a semi-colon", + "output": [ + [ + "Character", + "\u040f" + ] + ] + }, + { + "input": "&Dagger", + "description": "Bad named entity: Dagger without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dagger" + ] + ] + }, + { + "input": "‡", + "description": "Named entity: Dagger; with a semi-colon", + "output": [ + [ + "Character", + "\u2021" + ] + ] + }, + { + "input": "&Darr", + "description": "Bad named entity: Darr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Darr" + ] + ] + }, + { + "input": "↡", + "description": "Named entity: Darr; with a semi-colon", + "output": [ + [ + "Character", + "\u21a1" + ] + ] + }, + { + "input": "&Dashv", + "description": "Bad named entity: Dashv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dashv" + ] + ] + }, + { + "input": "⫤", + "description": "Named entity: Dashv; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae4" + ] + ] + }, + { + "input": "&Dcaron", + "description": "Bad named entity: Dcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dcaron" + ] + ] + }, + { + "input": "Ď", + "description": "Named entity: Dcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u010e" + ] + ] + }, + { + "input": "&Dcy", + "description": "Bad named entity: Dcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dcy" + ] + ] + }, + { + "input": "Д", + "description": "Named entity: Dcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0414" + ] + ] + }, + { + "input": "&Del", + "description": "Bad named entity: Del without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Del" + ] + ] + }, + { + "input": "∇", + "description": "Named entity: Del; with a semi-colon", + "output": [ + [ + "Character", + "\u2207" + ] + ] + }, + { + "input": "&Delta", + "description": "Bad named entity: Delta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Delta" + ] + ] + }, + { + "input": "Δ", + "description": "Named entity: Delta; with a semi-colon", + "output": [ + [ + "Character", + "\u0394" + ] + ] + }, + { + "input": "&Dfr", + "description": "Bad named entity: Dfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dfr" + ] + ] + }, + { + "input": "𝔇", + "description": "Named entity: Dfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd07" + ] + ] + }, + { + "input": "&DiacriticalAcute", + "description": "Bad named entity: DiacriticalAcute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DiacriticalAcute" + ] + ] + }, + { + "input": "´", + "description": "Named entity: DiacriticalAcute; with a semi-colon", + "output": [ + [ + "Character", + "\u00b4" + ] + ] + }, + { + "input": "&DiacriticalDot", + "description": "Bad named entity: DiacriticalDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DiacriticalDot" + ] + ] + }, + { + "input": "˙", + "description": "Named entity: DiacriticalDot; with a semi-colon", + "output": [ + [ + "Character", + "\u02d9" + ] + ] + }, + { + "input": "&DiacriticalDoubleAcute", + "description": "Bad named entity: DiacriticalDoubleAcute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DiacriticalDoubleAcute" + ] + ] + }, + { + "input": "˝", + "description": "Named entity: DiacriticalDoubleAcute; with a semi-colon", + "output": [ + [ + "Character", + "\u02dd" + ] + ] + }, + { + "input": "&DiacriticalGrave", + "description": "Bad named entity: DiacriticalGrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DiacriticalGrave" + ] + ] + }, + { + "input": "`", + "description": "Named entity: DiacriticalGrave; with a semi-colon", + "output": [ + [ + "Character", + "`" + ] + ] + }, + { + "input": "&DiacriticalTilde", + "description": "Bad named entity: DiacriticalTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DiacriticalTilde" + ] + ] + }, + { + "input": "˜", + "description": "Named entity: DiacriticalTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u02dc" + ] + ] + }, + { + "input": "&Diamond", + "description": "Bad named entity: Diamond without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Diamond" + ] + ] + }, + { + "input": "⋄", + "description": "Named entity: Diamond; with a semi-colon", + "output": [ + [ + "Character", + "\u22c4" + ] + ] + }, + { + "input": "&DifferentialD", + "description": "Bad named entity: DifferentialD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DifferentialD" + ] + ] + }, + { + "input": "ⅆ", + "description": "Named entity: DifferentialD; with a semi-colon", + "output": [ + [ + "Character", + "\u2146" + ] + ] + }, + { + "input": "&Dopf", + "description": "Bad named entity: Dopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dopf" + ] + ] + }, + { + "input": "𝔻", + "description": "Named entity: Dopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd3b" + ] + ] + }, + { + "input": "&Dot", + "description": "Bad named entity: Dot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dot" + ] + ] + }, + { + "input": "¨", + "description": "Named entity: Dot; with a semi-colon", + "output": [ + [ + "Character", + "\u00a8" + ] + ] + }, + { + "input": "&DotDot", + "description": "Bad named entity: DotDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DotDot" + ] + ] + }, + { + "input": "⃜", + "description": "Named entity: DotDot; with a semi-colon", + "output": [ + [ + "Character", + "\u20dc" + ] + ] + }, + { + "input": "&DotEqual", + "description": "Bad named entity: DotEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DotEqual" + ] + ] + }, + { + "input": "≐", + "description": "Named entity: DotEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2250" + ] + ] + }, + { + "input": "&DoubleContourIntegral", + "description": "Bad named entity: DoubleContourIntegral without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleContourIntegral" + ] + ] + }, + { + "input": "∯", + "description": "Named entity: DoubleContourIntegral; with a semi-colon", + "output": [ + [ + "Character", + "\u222f" + ] + ] + }, + { + "input": "&DoubleDot", + "description": "Bad named entity: DoubleDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleDot" + ] + ] + }, + { + "input": "¨", + "description": "Named entity: DoubleDot; with a semi-colon", + "output": [ + [ + "Character", + "\u00a8" + ] + ] + }, + { + "input": "&DoubleDownArrow", + "description": "Bad named entity: DoubleDownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleDownArrow" + ] + ] + }, + { + "input": "⇓", + "description": "Named entity: DoubleDownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d3" + ] + ] + }, + { + "input": "&DoubleLeftArrow", + "description": "Bad named entity: DoubleLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLeftArrow" + ] + ] + }, + { + "input": "⇐", + "description": "Named entity: DoubleLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d0" + ] + ] + }, + { + "input": "&DoubleLeftRightArrow", + "description": "Bad named entity: DoubleLeftRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLeftRightArrow" + ] + ] + }, + { + "input": "⇔", + "description": "Named entity: DoubleLeftRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d4" + ] + ] + }, + { + "input": "&DoubleLeftTee", + "description": "Bad named entity: DoubleLeftTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLeftTee" + ] + ] + }, + { + "input": "⫤", + "description": "Named entity: DoubleLeftTee; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae4" + ] + ] + }, + { + "input": "&DoubleLongLeftArrow", + "description": "Bad named entity: DoubleLongLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLongLeftArrow" + ] + ] + }, + { + "input": "⟸", + "description": "Named entity: DoubleLongLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f8" + ] + ] + }, + { + "input": "&DoubleLongLeftRightArrow", + "description": "Bad named entity: DoubleLongLeftRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLongLeftRightArrow" + ] + ] + }, + { + "input": "⟺", + "description": "Named entity: DoubleLongLeftRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27fa" + ] + ] + }, + { + "input": "&DoubleLongRightArrow", + "description": "Bad named entity: DoubleLongRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleLongRightArrow" + ] + ] + }, + { + "input": "⟹", + "description": "Named entity: DoubleLongRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f9" + ] + ] + }, + { + "input": "&DoubleRightArrow", + "description": "Bad named entity: DoubleRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleRightArrow" + ] + ] + }, + { + "input": "⇒", + "description": "Named entity: DoubleRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d2" + ] + ] + }, + { + "input": "&DoubleRightTee", + "description": "Bad named entity: DoubleRightTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleRightTee" + ] + ] + }, + { + "input": "⊨", + "description": "Named entity: DoubleRightTee; with a semi-colon", + "output": [ + [ + "Character", + "\u22a8" + ] + ] + }, + { + "input": "&DoubleUpArrow", + "description": "Bad named entity: DoubleUpArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleUpArrow" + ] + ] + }, + { + "input": "⇑", + "description": "Named entity: DoubleUpArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d1" + ] + ] + }, + { + "input": "&DoubleUpDownArrow", + "description": "Bad named entity: DoubleUpDownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleUpDownArrow" + ] + ] + }, + { + "input": "⇕", + "description": "Named entity: DoubleUpDownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d5" + ] + ] + }, + { + "input": "&DoubleVerticalBar", + "description": "Bad named entity: DoubleVerticalBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DoubleVerticalBar" + ] + ] + }, + { + "input": "∥", + "description": "Named entity: DoubleVerticalBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2225" + ] + ] + }, + { + "input": "&DownArrow", + "description": "Bad named entity: DownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownArrow" + ] + ] + }, + { + "input": "↓", + "description": "Named entity: DownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2193" + ] + ] + }, + { + "input": "&DownArrowBar", + "description": "Bad named entity: DownArrowBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownArrowBar" + ] + ] + }, + { + "input": "⤓", + "description": "Named entity: DownArrowBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2913" + ] + ] + }, + { + "input": "&DownArrowUpArrow", + "description": "Bad named entity: DownArrowUpArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownArrowUpArrow" + ] + ] + }, + { + "input": "⇵", + "description": "Named entity: DownArrowUpArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21f5" + ] + ] + }, + { + "input": "&DownBreve", + "description": "Bad named entity: DownBreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownBreve" + ] + ] + }, + { + "input": "̑", + "description": "Named entity: DownBreve; with a semi-colon", + "output": [ + [ + "Character", + "\u0311" + ] + ] + }, + { + "input": "&DownLeftRightVector", + "description": "Bad named entity: DownLeftRightVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownLeftRightVector" + ] + ] + }, + { + "input": "⥐", + "description": "Named entity: DownLeftRightVector; with a semi-colon", + "output": [ + [ + "Character", + "\u2950" + ] + ] + }, + { + "input": "&DownLeftTeeVector", + "description": "Bad named entity: DownLeftTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownLeftTeeVector" + ] + ] + }, + { + "input": "⥞", + "description": "Named entity: DownLeftTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295e" + ] + ] + }, + { + "input": "&DownLeftVector", + "description": "Bad named entity: DownLeftVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownLeftVector" + ] + ] + }, + { + "input": "↽", + "description": "Named entity: DownLeftVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21bd" + ] + ] + }, + { + "input": "&DownLeftVectorBar", + "description": "Bad named entity: DownLeftVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownLeftVectorBar" + ] + ] + }, + { + "input": "⥖", + "description": "Named entity: DownLeftVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2956" + ] + ] + }, + { + "input": "&DownRightTeeVector", + "description": "Bad named entity: DownRightTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownRightTeeVector" + ] + ] + }, + { + "input": "⥟", + "description": "Named entity: DownRightTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295f" + ] + ] + }, + { + "input": "&DownRightVector", + "description": "Bad named entity: DownRightVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownRightVector" + ] + ] + }, + { + "input": "⇁", + "description": "Named entity: DownRightVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21c1" + ] + ] + }, + { + "input": "&DownRightVectorBar", + "description": "Bad named entity: DownRightVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownRightVectorBar" + ] + ] + }, + { + "input": "⥗", + "description": "Named entity: DownRightVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2957" + ] + ] + }, + { + "input": "&DownTee", + "description": "Bad named entity: DownTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownTee" + ] + ] + }, + { + "input": "⊤", + "description": "Named entity: DownTee; with a semi-colon", + "output": [ + [ + "Character", + "\u22a4" + ] + ] + }, + { + "input": "&DownTeeArrow", + "description": "Bad named entity: DownTeeArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&DownTeeArrow" + ] + ] + }, + { + "input": "↧", + "description": "Named entity: DownTeeArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a7" + ] + ] + }, + { + "input": "&Downarrow", + "description": "Bad named entity: Downarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Downarrow" + ] + ] + }, + { + "input": "⇓", + "description": "Named entity: Downarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d3" + ] + ] + }, + { + "input": "&Dscr", + "description": "Bad named entity: Dscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dscr" + ] + ] + }, + { + "input": "𝒟", + "description": "Named entity: Dscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udc9f" + ] + ] + }, + { + "input": "&Dstrok", + "description": "Bad named entity: Dstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Dstrok" + ] + ] + }, + { + "input": "Đ", + "description": "Named entity: Dstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0110" + ] + ] + }, + { + "input": "&ENG", + "description": "Bad named entity: ENG without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ENG" + ] + ] + }, + { + "input": "Ŋ", + "description": "Named entity: ENG; with a semi-colon", + "output": [ + [ + "Character", + "\u014a" + ] + ] + }, + { + "input": "Ð", + "description": "Named entity: ETH without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d0" + ] + ] + }, + { + "input": "Ð", + "description": "Named entity: ETH; with a semi-colon", + "output": [ + [ + "Character", + "\u00d0" + ] + ] + }, + { + "input": "É", + "description": "Named entity: Eacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c9" + ] + ] + }, + { + "input": "É", + "description": "Named entity: Eacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00c9" + ] + ] + }, + { + "input": "&Ecaron", + "description": "Bad named entity: Ecaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ecaron" + ] + ] + }, + { + "input": "Ě", + "description": "Named entity: Ecaron; with a semi-colon", + "output": [ + [ + "Character", + "\u011a" + ] + ] + }, + { + "input": "Ê", + "description": "Named entity: Ecirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ca" + ] + ] + }, + { + "input": "Ê", + "description": "Named entity: Ecirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00ca" + ] + ] + }, + { + "input": "&Ecy", + "description": "Bad named entity: Ecy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ecy" + ] + ] + }, + { + "input": "Э", + "description": "Named entity: Ecy; with a semi-colon", + "output": [ + [ + "Character", + "\u042d" + ] + ] + }, + { + "input": "&Edot", + "description": "Bad named entity: Edot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Edot" + ] + ] + }, + { + "input": "Ė", + "description": "Named entity: Edot; with a semi-colon", + "output": [ + [ + "Character", + "\u0116" + ] + ] + }, + { + "input": "&Efr", + "description": "Bad named entity: Efr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Efr" + ] + ] + }, + { + "input": "𝔈", + "description": "Named entity: Efr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd08" + ] + ] + }, + { + "input": "È", + "description": "Named entity: Egrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00c8" + ] + ] + }, + { + "input": "È", + "description": "Named entity: Egrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00c8" + ] + ] + }, + { + "input": "&Element", + "description": "Bad named entity: Element without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Element" + ] + ] + }, + { + "input": "∈", + "description": "Named entity: Element; with a semi-colon", + "output": [ + [ + "Character", + "\u2208" + ] + ] + }, + { + "input": "&Emacr", + "description": "Bad named entity: Emacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Emacr" + ] + ] + }, + { + "input": "Ē", + "description": "Named entity: Emacr; with a semi-colon", + "output": [ + [ + "Character", + "\u0112" + ] + ] + }, + { + "input": "&EmptySmallSquare", + "description": "Bad named entity: EmptySmallSquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&EmptySmallSquare" + ] + ] + }, + { + "input": "◻", + "description": "Named entity: EmptySmallSquare; with a semi-colon", + "output": [ + [ + "Character", + "\u25fb" + ] + ] + }, + { + "input": "&EmptyVerySmallSquare", + "description": "Bad named entity: EmptyVerySmallSquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&EmptyVerySmallSquare" + ] + ] + }, + { + "input": "▫", + "description": "Named entity: EmptyVerySmallSquare; with a semi-colon", + "output": [ + [ + "Character", + "\u25ab" + ] + ] + }, + { + "input": "&Eogon", + "description": "Bad named entity: Eogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Eogon" + ] + ] + }, + { + "input": "Ę", + "description": "Named entity: Eogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0118" + ] + ] + }, + { + "input": "&Eopf", + "description": "Bad named entity: Eopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Eopf" + ] + ] + }, + { + "input": "𝔼", + "description": "Named entity: Eopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd3c" + ] + ] + }, + { + "input": "&Epsilon", + "description": "Bad named entity: Epsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Epsilon" + ] + ] + }, + { + "input": "Ε", + "description": "Named entity: Epsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u0395" + ] + ] + }, + { + "input": "&Equal", + "description": "Bad named entity: Equal without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Equal" + ] + ] + }, + { + "input": "⩵", + "description": "Named entity: Equal; with a semi-colon", + "output": [ + [ + "Character", + "\u2a75" + ] + ] + }, + { + "input": "&EqualTilde", + "description": "Bad named entity: EqualTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&EqualTilde" + ] + ] + }, + { + "input": "≂", + "description": "Named entity: EqualTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2242" + ] + ] + }, + { + "input": "&Equilibrium", + "description": "Bad named entity: Equilibrium without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Equilibrium" + ] + ] + }, + { + "input": "⇌", + "description": "Named entity: Equilibrium; with a semi-colon", + "output": [ + [ + "Character", + "\u21cc" + ] + ] + }, + { + "input": "&Escr", + "description": "Bad named entity: Escr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Escr" + ] + ] + }, + { + "input": "ℰ", + "description": "Named entity: Escr; with a semi-colon", + "output": [ + [ + "Character", + "\u2130" + ] + ] + }, + { + "input": "&Esim", + "description": "Bad named entity: Esim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Esim" + ] + ] + }, + { + "input": "⩳", + "description": "Named entity: Esim; with a semi-colon", + "output": [ + [ + "Character", + "\u2a73" + ] + ] + }, + { + "input": "&Eta", + "description": "Bad named entity: Eta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Eta" + ] + ] + }, + { + "input": "Η", + "description": "Named entity: Eta; with a semi-colon", + "output": [ + [ + "Character", + "\u0397" + ] + ] + }, + { + "input": "Ë", + "description": "Named entity: Euml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00cb" + ] + ] + }, + { + "input": "Ë", + "description": "Named entity: Euml; with a semi-colon", + "output": [ + [ + "Character", + "\u00cb" + ] + ] + }, + { + "input": "&Exists", + "description": "Bad named entity: Exists without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Exists" + ] + ] + }, + { + "input": "∃", + "description": "Named entity: Exists; with a semi-colon", + "output": [ + [ + "Character", + "\u2203" + ] + ] + }, + { + "input": "&ExponentialE", + "description": "Bad named entity: ExponentialE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ExponentialE" + ] + ] + }, + { + "input": "ⅇ", + "description": "Named entity: ExponentialE; with a semi-colon", + "output": [ + [ + "Character", + "\u2147" + ] + ] + }, + { + "input": "&Fcy", + "description": "Bad named entity: Fcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Fcy" + ] + ] + }, + { + "input": "Ф", + "description": "Named entity: Fcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0424" + ] + ] + }, + { + "input": "&Ffr", + "description": "Bad named entity: Ffr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ffr" + ] + ] + }, + { + "input": "𝔉", + "description": "Named entity: Ffr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd09" + ] + ] + }, + { + "input": "&FilledSmallSquare", + "description": "Bad named entity: FilledSmallSquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&FilledSmallSquare" + ] + ] + }, + { + "input": "◼", + "description": "Named entity: FilledSmallSquare; with a semi-colon", + "output": [ + [ + "Character", + "\u25fc" + ] + ] + }, + { + "input": "&FilledVerySmallSquare", + "description": "Bad named entity: FilledVerySmallSquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&FilledVerySmallSquare" + ] + ] + }, + { + "input": "▪", + "description": "Named entity: FilledVerySmallSquare; with a semi-colon", + "output": [ + [ + "Character", + "\u25aa" + ] + ] + }, + { + "input": "&Fopf", + "description": "Bad named entity: Fopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Fopf" + ] + ] + }, + { + "input": "𝔽", + "description": "Named entity: Fopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd3d" + ] + ] + }, + { + "input": "&ForAll", + "description": "Bad named entity: ForAll without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ForAll" + ] + ] + }, + { + "input": "∀", + "description": "Named entity: ForAll; with a semi-colon", + "output": [ + [ + "Character", + "\u2200" + ] + ] + }, + { + "input": "&Fouriertrf", + "description": "Bad named entity: Fouriertrf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Fouriertrf" + ] + ] + }, + { + "input": "ℱ", + "description": "Named entity: Fouriertrf; with a semi-colon", + "output": [ + [ + "Character", + "\u2131" + ] + ] + }, + { + "input": "&Fscr", + "description": "Bad named entity: Fscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Fscr" + ] + ] + }, + { + "input": "ℱ", + "description": "Named entity: Fscr; with a semi-colon", + "output": [ + [ + "Character", + "\u2131" + ] + ] + }, + { + "input": "&GJcy", + "description": "Bad named entity: GJcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GJcy" + ] + ] + }, + { + "input": "Ѓ", + "description": "Named entity: GJcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0403" + ] + ] + }, + { + "input": ">", + "description": "Named entity: GT without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + ">" + ] + ] + }, + { + "input": ">", + "description": "Named entity: GT; with a semi-colon", + "output": [ + [ + "Character", + ">" + ] + ] + }, + { + "input": "&Gamma", + "description": "Bad named entity: Gamma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gamma" + ] + ] + }, + { + "input": "Γ", + "description": "Named entity: Gamma; with a semi-colon", + "output": [ + [ + "Character", + "\u0393" + ] + ] + }, + { + "input": "&Gammad", + "description": "Bad named entity: Gammad without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gammad" + ] + ] + }, + { + "input": "Ϝ", + "description": "Named entity: Gammad; with a semi-colon", + "output": [ + [ + "Character", + "\u03dc" + ] + ] + }, + { + "input": "&Gbreve", + "description": "Bad named entity: Gbreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gbreve" + ] + ] + }, + { + "input": "Ğ", + "description": "Named entity: Gbreve; with a semi-colon", + "output": [ + [ + "Character", + "\u011e" + ] + ] + }, + { + "input": "&Gcedil", + "description": "Bad named entity: Gcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gcedil" + ] + ] + }, + { + "input": "Ģ", + "description": "Named entity: Gcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0122" + ] + ] + }, + { + "input": "&Gcirc", + "description": "Bad named entity: Gcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gcirc" + ] + ] + }, + { + "input": "Ĝ", + "description": "Named entity: Gcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u011c" + ] + ] + }, + { + "input": "&Gcy", + "description": "Bad named entity: Gcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gcy" + ] + ] + }, + { + "input": "Г", + "description": "Named entity: Gcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0413" + ] + ] + }, + { + "input": "&Gdot", + "description": "Bad named entity: Gdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gdot" + ] + ] + }, + { + "input": "Ġ", + "description": "Named entity: Gdot; with a semi-colon", + "output": [ + [ + "Character", + "\u0120" + ] + ] + }, + { + "input": "&Gfr", + "description": "Bad named entity: Gfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gfr" + ] + ] + }, + { + "input": "𝔊", + "description": "Named entity: Gfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd0a" + ] + ] + }, + { + "input": "&Gg", + "description": "Bad named entity: Gg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gg" + ] + ] + }, + { + "input": "⋙", + "description": "Named entity: Gg; with a semi-colon", + "output": [ + [ + "Character", + "\u22d9" + ] + ] + }, + { + "input": "&Gopf", + "description": "Bad named entity: Gopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gopf" + ] + ] + }, + { + "input": "𝔾", + "description": "Named entity: Gopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd3e" + ] + ] + }, + { + "input": "&GreaterEqual", + "description": "Bad named entity: GreaterEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterEqual" + ] + ] + }, + { + "input": "≥", + "description": "Named entity: GreaterEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2265" + ] + ] + }, + { + "input": "&GreaterEqualLess", + "description": "Bad named entity: GreaterEqualLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterEqualLess" + ] + ] + }, + { + "input": "⋛", + "description": "Named entity: GreaterEqualLess; with a semi-colon", + "output": [ + [ + "Character", + "\u22db" + ] + ] + }, + { + "input": "&GreaterFullEqual", + "description": "Bad named entity: GreaterFullEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterFullEqual" + ] + ] + }, + { + "input": "≧", + "description": "Named entity: GreaterFullEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2267" + ] + ] + }, + { + "input": "&GreaterGreater", + "description": "Bad named entity: GreaterGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterGreater" + ] + ] + }, + { + "input": "⪢", + "description": "Named entity: GreaterGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa2" + ] + ] + }, + { + "input": "&GreaterLess", + "description": "Bad named entity: GreaterLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterLess" + ] + ] + }, + { + "input": "≷", + "description": "Named entity: GreaterLess; with a semi-colon", + "output": [ + [ + "Character", + "\u2277" + ] + ] + }, + { + "input": "&GreaterSlantEqual", + "description": "Bad named entity: GreaterSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterSlantEqual" + ] + ] + }, + { + "input": "⩾", + "description": "Named entity: GreaterSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e" + ] + ] + }, + { + "input": "&GreaterTilde", + "description": "Bad named entity: GreaterTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&GreaterTilde" + ] + ] + }, + { + "input": "≳", + "description": "Named entity: GreaterTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2273" + ] + ] + }, + { + "input": "&Gscr", + "description": "Bad named entity: Gscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gscr" + ] + ] + }, + { + "input": "𝒢", + "description": "Named entity: Gscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udca2" + ] + ] + }, + { + "input": "&Gt", + "description": "Bad named entity: Gt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Gt" + ] + ] + }, + { + "input": "≫", + "description": "Named entity: Gt; with a semi-colon", + "output": [ + [ + "Character", + "\u226b" + ] + ] + }, + { + "input": "&HARDcy", + "description": "Bad named entity: HARDcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&HARDcy" + ] + ] + }, + { + "input": "Ъ", + "description": "Named entity: HARDcy; with a semi-colon", + "output": [ + [ + "Character", + "\u042a" + ] + ] + }, + { + "input": "&Hacek", + "description": "Bad named entity: Hacek without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hacek" + ] + ] + }, + { + "input": "ˇ", + "description": "Named entity: Hacek; with a semi-colon", + "output": [ + [ + "Character", + "\u02c7" + ] + ] + }, + { + "input": "&Hat", + "description": "Bad named entity: Hat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hat" + ] + ] + }, + { + "input": "^", + "description": "Named entity: Hat; with a semi-colon", + "output": [ + [ + "Character", + "^" + ] + ] + }, + { + "input": "&Hcirc", + "description": "Bad named entity: Hcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hcirc" + ] + ] + }, + { + "input": "Ĥ", + "description": "Named entity: Hcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0124" + ] + ] + }, + { + "input": "&Hfr", + "description": "Bad named entity: Hfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hfr" + ] + ] + }, + { + "input": "ℌ", + "description": "Named entity: Hfr; with a semi-colon", + "output": [ + [ + "Character", + "\u210c" + ] + ] + }, + { + "input": "&HilbertSpace", + "description": "Bad named entity: HilbertSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&HilbertSpace" + ] + ] + }, + { + "input": "ℋ", + "description": "Named entity: HilbertSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u210b" + ] + ] + }, + { + "input": "&Hopf", + "description": "Bad named entity: Hopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hopf" + ] + ] + }, + { + "input": "ℍ", + "description": "Named entity: Hopf; with a semi-colon", + "output": [ + [ + "Character", + "\u210d" + ] + ] + }, + { + "input": "&HorizontalLine", + "description": "Bad named entity: HorizontalLine without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&HorizontalLine" + ] + ] + }, + { + "input": "─", + "description": "Named entity: HorizontalLine; with a semi-colon", + "output": [ + [ + "Character", + "\u2500" + ] + ] + }, + { + "input": "&Hscr", + "description": "Bad named entity: Hscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hscr" + ] + ] + }, + { + "input": "ℋ", + "description": "Named entity: Hscr; with a semi-colon", + "output": [ + [ + "Character", + "\u210b" + ] + ] + }, + { + "input": "&Hstrok", + "description": "Bad named entity: Hstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Hstrok" + ] + ] + }, + { + "input": "Ħ", + "description": "Named entity: Hstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0126" + ] + ] + }, + { + "input": "&HumpDownHump", + "description": "Bad named entity: HumpDownHump without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&HumpDownHump" + ] + ] + }, + { + "input": "≎", + "description": "Named entity: HumpDownHump; with a semi-colon", + "output": [ + [ + "Character", + "\u224e" + ] + ] + }, + { + "input": "&HumpEqual", + "description": "Bad named entity: HumpEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&HumpEqual" + ] + ] + }, + { + "input": "≏", + "description": "Named entity: HumpEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u224f" + ] + ] + }, + { + "input": "&IEcy", + "description": "Bad named entity: IEcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&IEcy" + ] + ] + }, + { + "input": "Е", + "description": "Named entity: IEcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0415" + ] + ] + }, + { + "input": "&IJlig", + "description": "Bad named entity: IJlig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&IJlig" + ] + ] + }, + { + "input": "IJ", + "description": "Named entity: IJlig; with a semi-colon", + "output": [ + [ + "Character", + "\u0132" + ] + ] + }, + { + "input": "&IOcy", + "description": "Bad named entity: IOcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&IOcy" + ] + ] + }, + { + "input": "Ё", + "description": "Named entity: IOcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0401" + ] + ] + }, + { + "input": "Í", + "description": "Named entity: Iacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00cd" + ] + ] + }, + { + "input": "Í", + "description": "Named entity: Iacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00cd" + ] + ] + }, + { + "input": "Î", + "description": "Named entity: Icirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ce" + ] + ] + }, + { + "input": "Î", + "description": "Named entity: Icirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00ce" + ] + ] + }, + { + "input": "&Icy", + "description": "Bad named entity: Icy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Icy" + ] + ] + }, + { + "input": "И", + "description": "Named entity: Icy; with a semi-colon", + "output": [ + [ + "Character", + "\u0418" + ] + ] + }, + { + "input": "&Idot", + "description": "Bad named entity: Idot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Idot" + ] + ] + }, + { + "input": "İ", + "description": "Named entity: Idot; with a semi-colon", + "output": [ + [ + "Character", + "\u0130" + ] + ] + }, + { + "input": "&Ifr", + "description": "Bad named entity: Ifr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ifr" + ] + ] + }, + { + "input": "ℑ", + "description": "Named entity: Ifr; with a semi-colon", + "output": [ + [ + "Character", + "\u2111" + ] + ] + }, + { + "input": "Ì", + "description": "Named entity: Igrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00cc" + ] + ] + }, + { + "input": "Ì", + "description": "Named entity: Igrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00cc" + ] + ] + }, + { + "input": "&Im", + "description": "Bad named entity: Im without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Im" + ] + ] + }, + { + "input": "ℑ", + "description": "Named entity: Im; with a semi-colon", + "output": [ + [ + "Character", + "\u2111" + ] + ] + }, + { + "input": "&Imacr", + "description": "Bad named entity: Imacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Imacr" + ] + ] + }, + { + "input": "Ī", + "description": "Named entity: Imacr; with a semi-colon", + "output": [ + [ + "Character", + "\u012a" + ] + ] + }, + { + "input": "&ImaginaryI", + "description": "Bad named entity: ImaginaryI without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ImaginaryI" + ] + ] + }, + { + "input": "ⅈ", + "description": "Named entity: ImaginaryI; with a semi-colon", + "output": [ + [ + "Character", + "\u2148" + ] + ] + }, + { + "input": "&Implies", + "description": "Bad named entity: Implies without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Implies" + ] + ] + }, + { + "input": "⇒", + "description": "Named entity: Implies; with a semi-colon", + "output": [ + [ + "Character", + "\u21d2" + ] + ] + }, + { + "input": "&Int", + "description": "Bad named entity: Int without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Int" + ] + ] + }, + { + "input": "∬", + "description": "Named entity: Int; with a semi-colon", + "output": [ + [ + "Character", + "\u222c" + ] + ] + }, + { + "input": "&Integral", + "description": "Bad named entity: Integral without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Integral" + ] + ] + }, + { + "input": "∫", + "description": "Named entity: Integral; with a semi-colon", + "output": [ + [ + "Character", + "\u222b" + ] + ] + }, + { + "input": "&Intersection", + "description": "Bad named entity: Intersection without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Intersection" + ] + ] + }, + { + "input": "⋂", + "description": "Named entity: Intersection; with a semi-colon", + "output": [ + [ + "Character", + "\u22c2" + ] + ] + }, + { + "input": "&InvisibleComma", + "description": "Bad named entity: InvisibleComma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&InvisibleComma" + ] + ] + }, + { + "input": "⁣", + "description": "Named entity: InvisibleComma; with a semi-colon", + "output": [ + [ + "Character", + "\u2063" + ] + ] + }, + { + "input": "&InvisibleTimes", + "description": "Bad named entity: InvisibleTimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&InvisibleTimes" + ] + ] + }, + { + "input": "⁢", + "description": "Named entity: InvisibleTimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2062" + ] + ] + }, + { + "input": "&Iogon", + "description": "Bad named entity: Iogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Iogon" + ] + ] + }, + { + "input": "Į", + "description": "Named entity: Iogon; with a semi-colon", + "output": [ + [ + "Character", + "\u012e" + ] + ] + }, + { + "input": "&Iopf", + "description": "Bad named entity: Iopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Iopf" + ] + ] + }, + { + "input": "𝕀", + "description": "Named entity: Iopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd40" + ] + ] + }, + { + "input": "&Iota", + "description": "Bad named entity: Iota without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Iota" + ] + ] + }, + { + "input": "Ι", + "description": "Named entity: Iota; with a semi-colon", + "output": [ + [ + "Character", + "\u0399" + ] + ] + }, + { + "input": "&Iscr", + "description": "Bad named entity: Iscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Iscr" + ] + ] + }, + { + "input": "ℐ", + "description": "Named entity: Iscr; with a semi-colon", + "output": [ + [ + "Character", + "\u2110" + ] + ] + }, + { + "input": "&Itilde", + "description": "Bad named entity: Itilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Itilde" + ] + ] + }, + { + "input": "Ĩ", + "description": "Named entity: Itilde; with a semi-colon", + "output": [ + [ + "Character", + "\u0128" + ] + ] + }, + { + "input": "&Iukcy", + "description": "Bad named entity: Iukcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Iukcy" + ] + ] + }, + { + "input": "І", + "description": "Named entity: Iukcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0406" + ] + ] + }, + { + "input": "Ï", + "description": "Named entity: Iuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00cf" + ] + ] + }, + { + "input": "Ï", + "description": "Named entity: Iuml; with a semi-colon", + "output": [ + [ + "Character", + "\u00cf" + ] + ] + }, + { + "input": "&Jcirc", + "description": "Bad named entity: Jcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jcirc" + ] + ] + }, + { + "input": "Ĵ", + "description": "Named entity: Jcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0134" + ] + ] + }, + { + "input": "&Jcy", + "description": "Bad named entity: Jcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jcy" + ] + ] + }, + { + "input": "Й", + "description": "Named entity: Jcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0419" + ] + ] + }, + { + "input": "&Jfr", + "description": "Bad named entity: Jfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jfr" + ] + ] + }, + { + "input": "𝔍", + "description": "Named entity: Jfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd0d" + ] + ] + }, + { + "input": "&Jopf", + "description": "Bad named entity: Jopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jopf" + ] + ] + }, + { + "input": "𝕁", + "description": "Named entity: Jopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd41" + ] + ] + }, + { + "input": "&Jscr", + "description": "Bad named entity: Jscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jscr" + ] + ] + }, + { + "input": "𝒥", + "description": "Named entity: Jscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udca5" + ] + ] + }, + { + "input": "&Jsercy", + "description": "Bad named entity: Jsercy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jsercy" + ] + ] + }, + { + "input": "Ј", + "description": "Named entity: Jsercy; with a semi-colon", + "output": [ + [ + "Character", + "\u0408" + ] + ] + }, + { + "input": "&Jukcy", + "description": "Bad named entity: Jukcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Jukcy" + ] + ] + }, + { + "input": "Є", + "description": "Named entity: Jukcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0404" + ] + ] + }, + { + "input": "&KHcy", + "description": "Bad named entity: KHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&KHcy" + ] + ] + }, + { + "input": "Х", + "description": "Named entity: KHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0425" + ] + ] + }, + { + "input": "&KJcy", + "description": "Bad named entity: KJcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&KJcy" + ] + ] + }, + { + "input": "Ќ", + "description": "Named entity: KJcy; with a semi-colon", + "output": [ + [ + "Character", + "\u040c" + ] + ] + }, + { + "input": "&Kappa", + "description": "Bad named entity: Kappa without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kappa" + ] + ] + }, + { + "input": "Κ", + "description": "Named entity: Kappa; with a semi-colon", + "output": [ + [ + "Character", + "\u039a" + ] + ] + }, + { + "input": "&Kcedil", + "description": "Bad named entity: Kcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kcedil" + ] + ] + }, + { + "input": "Ķ", + "description": "Named entity: Kcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0136" + ] + ] + }, + { + "input": "&Kcy", + "description": "Bad named entity: Kcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kcy" + ] + ] + }, + { + "input": "К", + "description": "Named entity: Kcy; with a semi-colon", + "output": [ + [ + "Character", + "\u041a" + ] + ] + }, + { + "input": "&Kfr", + "description": "Bad named entity: Kfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kfr" + ] + ] + }, + { + "input": "𝔎", + "description": "Named entity: Kfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd0e" + ] + ] + }, + { + "input": "&Kopf", + "description": "Bad named entity: Kopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kopf" + ] + ] + }, + { + "input": "𝕂", + "description": "Named entity: Kopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd42" + ] + ] + }, + { + "input": "&Kscr", + "description": "Bad named entity: Kscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Kscr" + ] + ] + }, + { + "input": "𝒦", + "description": "Named entity: Kscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udca6" + ] + ] + }, + { + "input": "&LJcy", + "description": "Bad named entity: LJcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LJcy" + ] + ] + }, + { + "input": "Љ", + "description": "Named entity: LJcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0409" + ] + ] + }, + { + "input": "<", + "description": "Named entity: LT without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "<" + ] + ] + }, + { + "input": "<", + "description": "Named entity: LT; with a semi-colon", + "output": [ + [ + "Character", + "<" + ] + ] + }, + { + "input": "&Lacute", + "description": "Bad named entity: Lacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lacute" + ] + ] + }, + { + "input": "Ĺ", + "description": "Named entity: Lacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0139" + ] + ] + }, + { + "input": "&Lambda", + "description": "Bad named entity: Lambda without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lambda" + ] + ] + }, + { + "input": "Λ", + "description": "Named entity: Lambda; with a semi-colon", + "output": [ + [ + "Character", + "\u039b" + ] + ] + }, + { + "input": "&Lang", + "description": "Bad named entity: Lang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lang" + ] + ] + }, + { + "input": "⟪", + "description": "Named entity: Lang; with a semi-colon", + "output": [ + [ + "Character", + "\u27ea" + ] + ] + }, + { + "input": "&Laplacetrf", + "description": "Bad named entity: Laplacetrf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Laplacetrf" + ] + ] + }, + { + "input": "ℒ", + "description": "Named entity: Laplacetrf; with a semi-colon", + "output": [ + [ + "Character", + "\u2112" + ] + ] + }, + { + "input": "&Larr", + "description": "Bad named entity: Larr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Larr" + ] + ] + }, + { + "input": "↞", + "description": "Named entity: Larr; with a semi-colon", + "output": [ + [ + "Character", + "\u219e" + ] + ] + }, + { + "input": "&Lcaron", + "description": "Bad named entity: Lcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lcaron" + ] + ] + }, + { + "input": "Ľ", + "description": "Named entity: Lcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u013d" + ] + ] + }, + { + "input": "&Lcedil", + "description": "Bad named entity: Lcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lcedil" + ] + ] + }, + { + "input": "Ļ", + "description": "Named entity: Lcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u013b" + ] + ] + }, + { + "input": "&Lcy", + "description": "Bad named entity: Lcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lcy" + ] + ] + }, + { + "input": "Л", + "description": "Named entity: Lcy; with a semi-colon", + "output": [ + [ + "Character", + "\u041b" + ] + ] + }, + { + "input": "&LeftAngleBracket", + "description": "Bad named entity: LeftAngleBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftAngleBracket" + ] + ] + }, + { + "input": "⟨", + "description": "Named entity: LeftAngleBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u27e8" + ] + ] + }, + { + "input": "&LeftArrow", + "description": "Bad named entity: LeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftArrow" + ] + ] + }, + { + "input": "←", + "description": "Named entity: LeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2190" + ] + ] + }, + { + "input": "&LeftArrowBar", + "description": "Bad named entity: LeftArrowBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftArrowBar" + ] + ] + }, + { + "input": "⇤", + "description": "Named entity: LeftArrowBar; with a semi-colon", + "output": [ + [ + "Character", + "\u21e4" + ] + ] + }, + { + "input": "&LeftArrowRightArrow", + "description": "Bad named entity: LeftArrowRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftArrowRightArrow" + ] + ] + }, + { + "input": "⇆", + "description": "Named entity: LeftArrowRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21c6" + ] + ] + }, + { + "input": "&LeftCeiling", + "description": "Bad named entity: LeftCeiling without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftCeiling" + ] + ] + }, + { + "input": "⌈", + "description": "Named entity: LeftCeiling; with a semi-colon", + "output": [ + [ + "Character", + "\u2308" + ] + ] + }, + { + "input": "&LeftDoubleBracket", + "description": "Bad named entity: LeftDoubleBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftDoubleBracket" + ] + ] + }, + { + "input": "⟦", + "description": "Named entity: LeftDoubleBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u27e6" + ] + ] + }, + { + "input": "&LeftDownTeeVector", + "description": "Bad named entity: LeftDownTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftDownTeeVector" + ] + ] + }, + { + "input": "⥡", + "description": "Named entity: LeftDownTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u2961" + ] + ] + }, + { + "input": "&LeftDownVector", + "description": "Bad named entity: LeftDownVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftDownVector" + ] + ] + }, + { + "input": "⇃", + "description": "Named entity: LeftDownVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21c3" + ] + ] + }, + { + "input": "&LeftDownVectorBar", + "description": "Bad named entity: LeftDownVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftDownVectorBar" + ] + ] + }, + { + "input": "⥙", + "description": "Named entity: LeftDownVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2959" + ] + ] + }, + { + "input": "&LeftFloor", + "description": "Bad named entity: LeftFloor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftFloor" + ] + ] + }, + { + "input": "⌊", + "description": "Named entity: LeftFloor; with a semi-colon", + "output": [ + [ + "Character", + "\u230a" + ] + ] + }, + { + "input": "&LeftRightArrow", + "description": "Bad named entity: LeftRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftRightArrow" + ] + ] + }, + { + "input": "↔", + "description": "Named entity: LeftRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2194" + ] + ] + }, + { + "input": "&LeftRightVector", + "description": "Bad named entity: LeftRightVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftRightVector" + ] + ] + }, + { + "input": "⥎", + "description": "Named entity: LeftRightVector; with a semi-colon", + "output": [ + [ + "Character", + "\u294e" + ] + ] + }, + { + "input": "&LeftTee", + "description": "Bad named entity: LeftTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTee" + ] + ] + }, + { + "input": "⊣", + "description": "Named entity: LeftTee; with a semi-colon", + "output": [ + [ + "Character", + "\u22a3" + ] + ] + }, + { + "input": "&LeftTeeArrow", + "description": "Bad named entity: LeftTeeArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTeeArrow" + ] + ] + }, + { + "input": "↤", + "description": "Named entity: LeftTeeArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a4" + ] + ] + }, + { + "input": "&LeftTeeVector", + "description": "Bad named entity: LeftTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTeeVector" + ] + ] + }, + { + "input": "⥚", + "description": "Named entity: LeftTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295a" + ] + ] + }, + { + "input": "&LeftTriangle", + "description": "Bad named entity: LeftTriangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTriangle" + ] + ] + }, + { + "input": "⊲", + "description": "Named entity: LeftTriangle; with a semi-colon", + "output": [ + [ + "Character", + "\u22b2" + ] + ] + }, + { + "input": "&LeftTriangleBar", + "description": "Bad named entity: LeftTriangleBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTriangleBar" + ] + ] + }, + { + "input": "⧏", + "description": "Named entity: LeftTriangleBar; with a semi-colon", + "output": [ + [ + "Character", + "\u29cf" + ] + ] + }, + { + "input": "&LeftTriangleEqual", + "description": "Bad named entity: LeftTriangleEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftTriangleEqual" + ] + ] + }, + { + "input": "⊴", + "description": "Named entity: LeftTriangleEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22b4" + ] + ] + }, + { + "input": "&LeftUpDownVector", + "description": "Bad named entity: LeftUpDownVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftUpDownVector" + ] + ] + }, + { + "input": "⥑", + "description": "Named entity: LeftUpDownVector; with a semi-colon", + "output": [ + [ + "Character", + "\u2951" + ] + ] + }, + { + "input": "&LeftUpTeeVector", + "description": "Bad named entity: LeftUpTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftUpTeeVector" + ] + ] + }, + { + "input": "⥠", + "description": "Named entity: LeftUpTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u2960" + ] + ] + }, + { + "input": "&LeftUpVector", + "description": "Bad named entity: LeftUpVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftUpVector" + ] + ] + }, + { + "input": "↿", + "description": "Named entity: LeftUpVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21bf" + ] + ] + }, + { + "input": "&LeftUpVectorBar", + "description": "Bad named entity: LeftUpVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftUpVectorBar" + ] + ] + }, + { + "input": "⥘", + "description": "Named entity: LeftUpVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2958" + ] + ] + }, + { + "input": "&LeftVector", + "description": "Bad named entity: LeftVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftVector" + ] + ] + }, + { + "input": "↼", + "description": "Named entity: LeftVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21bc" + ] + ] + }, + { + "input": "&LeftVectorBar", + "description": "Bad named entity: LeftVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LeftVectorBar" + ] + ] + }, + { + "input": "⥒", + "description": "Named entity: LeftVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2952" + ] + ] + }, + { + "input": "&Leftarrow", + "description": "Bad named entity: Leftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Leftarrow" + ] + ] + }, + { + "input": "⇐", + "description": "Named entity: Leftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d0" + ] + ] + }, + { + "input": "&Leftrightarrow", + "description": "Bad named entity: Leftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Leftrightarrow" + ] + ] + }, + { + "input": "⇔", + "description": "Named entity: Leftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d4" + ] + ] + }, + { + "input": "&LessEqualGreater", + "description": "Bad named entity: LessEqualGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessEqualGreater" + ] + ] + }, + { + "input": "⋚", + "description": "Named entity: LessEqualGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u22da" + ] + ] + }, + { + "input": "&LessFullEqual", + "description": "Bad named entity: LessFullEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessFullEqual" + ] + ] + }, + { + "input": "≦", + "description": "Named entity: LessFullEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2266" + ] + ] + }, + { + "input": "&LessGreater", + "description": "Bad named entity: LessGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessGreater" + ] + ] + }, + { + "input": "≶", + "description": "Named entity: LessGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u2276" + ] + ] + }, + { + "input": "&LessLess", + "description": "Bad named entity: LessLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessLess" + ] + ] + }, + { + "input": "⪡", + "description": "Named entity: LessLess; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa1" + ] + ] + }, + { + "input": "&LessSlantEqual", + "description": "Bad named entity: LessSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessSlantEqual" + ] + ] + }, + { + "input": "⩽", + "description": "Named entity: LessSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d" + ] + ] + }, + { + "input": "&LessTilde", + "description": "Bad named entity: LessTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LessTilde" + ] + ] + }, + { + "input": "≲", + "description": "Named entity: LessTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2272" + ] + ] + }, + { + "input": "&Lfr", + "description": "Bad named entity: Lfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lfr" + ] + ] + }, + { + "input": "𝔏", + "description": "Named entity: Lfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd0f" + ] + ] + }, + { + "input": "&Ll", + "description": "Bad named entity: Ll without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ll" + ] + ] + }, + { + "input": "⋘", + "description": "Named entity: Ll; with a semi-colon", + "output": [ + [ + "Character", + "\u22d8" + ] + ] + }, + { + "input": "&Lleftarrow", + "description": "Bad named entity: Lleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lleftarrow" + ] + ] + }, + { + "input": "⇚", + "description": "Named entity: Lleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21da" + ] + ] + }, + { + "input": "&Lmidot", + "description": "Bad named entity: Lmidot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lmidot" + ] + ] + }, + { + "input": "Ŀ", + "description": "Named entity: Lmidot; with a semi-colon", + "output": [ + [ + "Character", + "\u013f" + ] + ] + }, + { + "input": "&LongLeftArrow", + "description": "Bad named entity: LongLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LongLeftArrow" + ] + ] + }, + { + "input": "⟵", + "description": "Named entity: LongLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f5" + ] + ] + }, + { + "input": "&LongLeftRightArrow", + "description": "Bad named entity: LongLeftRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LongLeftRightArrow" + ] + ] + }, + { + "input": "⟷", + "description": "Named entity: LongLeftRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f7" + ] + ] + }, + { + "input": "&LongRightArrow", + "description": "Bad named entity: LongRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LongRightArrow" + ] + ] + }, + { + "input": "⟶", + "description": "Named entity: LongRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f6" + ] + ] + }, + { + "input": "&Longleftarrow", + "description": "Bad named entity: Longleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Longleftarrow" + ] + ] + }, + { + "input": "⟸", + "description": "Named entity: Longleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f8" + ] + ] + }, + { + "input": "&Longleftrightarrow", + "description": "Bad named entity: Longleftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Longleftrightarrow" + ] + ] + }, + { + "input": "⟺", + "description": "Named entity: Longleftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27fa" + ] + ] + }, + { + "input": "&Longrightarrow", + "description": "Bad named entity: Longrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Longrightarrow" + ] + ] + }, + { + "input": "⟹", + "description": "Named entity: Longrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f9" + ] + ] + }, + { + "input": "&Lopf", + "description": "Bad named entity: Lopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lopf" + ] + ] + }, + { + "input": "𝕃", + "description": "Named entity: Lopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd43" + ] + ] + }, + { + "input": "&LowerLeftArrow", + "description": "Bad named entity: LowerLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LowerLeftArrow" + ] + ] + }, + { + "input": "↙", + "description": "Named entity: LowerLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2199" + ] + ] + }, + { + "input": "&LowerRightArrow", + "description": "Bad named entity: LowerRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&LowerRightArrow" + ] + ] + }, + { + "input": "↘", + "description": "Named entity: LowerRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2198" + ] + ] + }, + { + "input": "&Lscr", + "description": "Bad named entity: Lscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lscr" + ] + ] + }, + { + "input": "ℒ", + "description": "Named entity: Lscr; with a semi-colon", + "output": [ + [ + "Character", + "\u2112" + ] + ] + }, + { + "input": "&Lsh", + "description": "Bad named entity: Lsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lsh" + ] + ] + }, + { + "input": "↰", + "description": "Named entity: Lsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b0" + ] + ] + }, + { + "input": "&Lstrok", + "description": "Bad named entity: Lstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lstrok" + ] + ] + }, + { + "input": "Ł", + "description": "Named entity: Lstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0141" + ] + ] + }, + { + "input": "&Lt", + "description": "Bad named entity: Lt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Lt" + ] + ] + }, + { + "input": "≪", + "description": "Named entity: Lt; with a semi-colon", + "output": [ + [ + "Character", + "\u226a" + ] + ] + }, + { + "input": "&Map", + "description": "Bad named entity: Map without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Map" + ] + ] + }, + { + "input": "⤅", + "description": "Named entity: Map; with a semi-colon", + "output": [ + [ + "Character", + "\u2905" + ] + ] + }, + { + "input": "&Mcy", + "description": "Bad named entity: Mcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mcy" + ] + ] + }, + { + "input": "М", + "description": "Named entity: Mcy; with a semi-colon", + "output": [ + [ + "Character", + "\u041c" + ] + ] + }, + { + "input": "&MediumSpace", + "description": "Bad named entity: MediumSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&MediumSpace" + ] + ] + }, + { + "input": " ", + "description": "Named entity: MediumSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u205f" + ] + ] + }, + { + "input": "&Mellintrf", + "description": "Bad named entity: Mellintrf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mellintrf" + ] + ] + }, + { + "input": "ℳ", + "description": "Named entity: Mellintrf; with a semi-colon", + "output": [ + [ + "Character", + "\u2133" + ] + ] + }, + { + "input": "&Mfr", + "description": "Bad named entity: Mfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mfr" + ] + ] + }, + { + "input": "𝔐", + "description": "Named entity: Mfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd10" + ] + ] + }, + { + "input": "&MinusPlus", + "description": "Bad named entity: MinusPlus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&MinusPlus" + ] + ] + }, + { + "input": "∓", + "description": "Named entity: MinusPlus; with a semi-colon", + "output": [ + [ + "Character", + "\u2213" + ] + ] + }, + { + "input": "&Mopf", + "description": "Bad named entity: Mopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mopf" + ] + ] + }, + { + "input": "𝕄", + "description": "Named entity: Mopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd44" + ] + ] + }, + { + "input": "&Mscr", + "description": "Bad named entity: Mscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mscr" + ] + ] + }, + { + "input": "ℳ", + "description": "Named entity: Mscr; with a semi-colon", + "output": [ + [ + "Character", + "\u2133" + ] + ] + }, + { + "input": "&Mu", + "description": "Bad named entity: Mu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Mu" + ] + ] + }, + { + "input": "Μ", + "description": "Named entity: Mu; with a semi-colon", + "output": [ + [ + "Character", + "\u039c" + ] + ] + }, + { + "input": "&NJcy", + "description": "Bad named entity: NJcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NJcy" + ] + ] + }, + { + "input": "Њ", + "description": "Named entity: NJcy; with a semi-colon", + "output": [ + [ + "Character", + "\u040a" + ] + ] + }, + { + "input": "&Nacute", + "description": "Bad named entity: Nacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Nacute" + ] + ] + }, + { + "input": "Ń", + "description": "Named entity: Nacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0143" + ] + ] + }, + { + "input": "&Ncaron", + "description": "Bad named entity: Ncaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ncaron" + ] + ] + }, + { + "input": "Ň", + "description": "Named entity: Ncaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0147" + ] + ] + }, + { + "input": "&Ncedil", + "description": "Bad named entity: Ncedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ncedil" + ] + ] + }, + { + "input": "Ņ", + "description": "Named entity: Ncedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0145" + ] + ] + }, + { + "input": "&Ncy", + "description": "Bad named entity: Ncy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ncy" + ] + ] + }, + { + "input": "Н", + "description": "Named entity: Ncy; with a semi-colon", + "output": [ + [ + "Character", + "\u041d" + ] + ] + }, + { + "input": "&NegativeMediumSpace", + "description": "Bad named entity: NegativeMediumSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NegativeMediumSpace" + ] + ] + }, + { + "input": "​", + "description": "Named entity: NegativeMediumSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200b" + ] + ] + }, + { + "input": "&NegativeThickSpace", + "description": "Bad named entity: NegativeThickSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NegativeThickSpace" + ] + ] + }, + { + "input": "​", + "description": "Named entity: NegativeThickSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200b" + ] + ] + }, + { + "input": "&NegativeThinSpace", + "description": "Bad named entity: NegativeThinSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NegativeThinSpace" + ] + ] + }, + { + "input": "​", + "description": "Named entity: NegativeThinSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200b" + ] + ] + }, + { + "input": "&NegativeVeryThinSpace", + "description": "Bad named entity: NegativeVeryThinSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NegativeVeryThinSpace" + ] + ] + }, + { + "input": "​", + "description": "Named entity: NegativeVeryThinSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200b" + ] + ] + }, + { + "input": "&NestedGreaterGreater", + "description": "Bad named entity: NestedGreaterGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NestedGreaterGreater" + ] + ] + }, + { + "input": "≫", + "description": "Named entity: NestedGreaterGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u226b" + ] + ] + }, + { + "input": "&NestedLessLess", + "description": "Bad named entity: NestedLessLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NestedLessLess" + ] + ] + }, + { + "input": "≪", + "description": "Named entity: NestedLessLess; with a semi-colon", + "output": [ + [ + "Character", + "\u226a" + ] + ] + }, + { + "input": "&NewLine", + "description": "Bad named entity: NewLine without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NewLine" + ] + ] + }, + { + "input": " ", + "description": "Named entity: NewLine; with a semi-colon", + "output": [ + [ + "Character", + "\n" + ] + ] + }, + { + "input": "&Nfr", + "description": "Bad named entity: Nfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Nfr" + ] + ] + }, + { + "input": "𝔑", + "description": "Named entity: Nfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd11" + ] + ] + }, + { + "input": "&NoBreak", + "description": "Bad named entity: NoBreak without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NoBreak" + ] + ] + }, + { + "input": "⁠", + "description": "Named entity: NoBreak; with a semi-colon", + "output": [ + [ + "Character", + "\u2060" + ] + ] + }, + { + "input": "&NonBreakingSpace", + "description": "Bad named entity: NonBreakingSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NonBreakingSpace" + ] + ] + }, + { + "input": " ", + "description": "Named entity: NonBreakingSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u00a0" + ] + ] + }, + { + "input": "&Nopf", + "description": "Bad named entity: Nopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Nopf" + ] + ] + }, + { + "input": "ℕ", + "description": "Named entity: Nopf; with a semi-colon", + "output": [ + [ + "Character", + "\u2115" + ] + ] + }, + { + "input": "&Not", + "description": "Bad named entity: Not without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Not" + ] + ] + }, + { + "input": "⫬", + "description": "Named entity: Not; with a semi-colon", + "output": [ + [ + "Character", + "\u2aec" + ] + ] + }, + { + "input": "&NotCongruent", + "description": "Bad named entity: NotCongruent without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotCongruent" + ] + ] + }, + { + "input": "≢", + "description": "Named entity: NotCongruent; with a semi-colon", + "output": [ + [ + "Character", + "\u2262" + ] + ] + }, + { + "input": "&NotCupCap", + "description": "Bad named entity: NotCupCap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotCupCap" + ] + ] + }, + { + "input": "≭", + "description": "Named entity: NotCupCap; with a semi-colon", + "output": [ + [ + "Character", + "\u226d" + ] + ] + }, + { + "input": "&NotDoubleVerticalBar", + "description": "Bad named entity: NotDoubleVerticalBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotDoubleVerticalBar" + ] + ] + }, + { + "input": "∦", + "description": "Named entity: NotDoubleVerticalBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2226" + ] + ] + }, + { + "input": "&NotElement", + "description": "Bad named entity: NotElement without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotElement" + ] + ] + }, + { + "input": "∉", + "description": "Named entity: NotElement; with a semi-colon", + "output": [ + [ + "Character", + "\u2209" + ] + ] + }, + { + "input": "&NotEqual", + "description": "Bad named entity: NotEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotEqual" + ] + ] + }, + { + "input": "≠", + "description": "Named entity: NotEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2260" + ] + ] + }, + { + "input": "&NotEqualTilde", + "description": "Bad named entity: NotEqualTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotEqualTilde" + ] + ] + }, + { + "input": "≂̸", + "description": "Named entity: NotEqualTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2242\u0338" + ] + ] + }, + { + "input": "&NotExists", + "description": "Bad named entity: NotExists without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotExists" + ] + ] + }, + { + "input": "∄", + "description": "Named entity: NotExists; with a semi-colon", + "output": [ + [ + "Character", + "\u2204" + ] + ] + }, + { + "input": "&NotGreater", + "description": "Bad named entity: NotGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreater" + ] + ] + }, + { + "input": "≯", + "description": "Named entity: NotGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u226f" + ] + ] + }, + { + "input": "&NotGreaterEqual", + "description": "Bad named entity: NotGreaterEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterEqual" + ] + ] + }, + { + "input": "≱", + "description": "Named entity: NotGreaterEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2271" + ] + ] + }, + { + "input": "&NotGreaterFullEqual", + "description": "Bad named entity: NotGreaterFullEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterFullEqual" + ] + ] + }, + { + "input": "≧̸", + "description": "Named entity: NotGreaterFullEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2267\u0338" + ] + ] + }, + { + "input": "&NotGreaterGreater", + "description": "Bad named entity: NotGreaterGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterGreater" + ] + ] + }, + { + "input": "≫̸", + "description": "Named entity: NotGreaterGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u226b\u0338" + ] + ] + }, + { + "input": "&NotGreaterLess", + "description": "Bad named entity: NotGreaterLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterLess" + ] + ] + }, + { + "input": "≹", + "description": "Named entity: NotGreaterLess; with a semi-colon", + "output": [ + [ + "Character", + "\u2279" + ] + ] + }, + { + "input": "&NotGreaterSlantEqual", + "description": "Bad named entity: NotGreaterSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterSlantEqual" + ] + ] + }, + { + "input": "⩾̸", + "description": "Named entity: NotGreaterSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e\u0338" + ] + ] + }, + { + "input": "&NotGreaterTilde", + "description": "Bad named entity: NotGreaterTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotGreaterTilde" + ] + ] + }, + { + "input": "≵", + "description": "Named entity: NotGreaterTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2275" + ] + ] + }, + { + "input": "&NotHumpDownHump", + "description": "Bad named entity: NotHumpDownHump without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotHumpDownHump" + ] + ] + }, + { + "input": "≎̸", + "description": "Named entity: NotHumpDownHump; with a semi-colon", + "output": [ + [ + "Character", + "\u224e\u0338" + ] + ] + }, + { + "input": "&NotHumpEqual", + "description": "Bad named entity: NotHumpEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotHumpEqual" + ] + ] + }, + { + "input": "≏̸", + "description": "Named entity: NotHumpEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u224f\u0338" + ] + ] + }, + { + "input": "&NotLeftTriangle", + "description": "Bad named entity: NotLeftTriangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLeftTriangle" + ] + ] + }, + { + "input": "⋪", + "description": "Named entity: NotLeftTriangle; with a semi-colon", + "output": [ + [ + "Character", + "\u22ea" + ] + ] + }, + { + "input": "&NotLeftTriangleBar", + "description": "Bad named entity: NotLeftTriangleBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLeftTriangleBar" + ] + ] + }, + { + "input": "⧏̸", + "description": "Named entity: NotLeftTriangleBar; with a semi-colon", + "output": [ + [ + "Character", + "\u29cf\u0338" + ] + ] + }, + { + "input": "&NotLeftTriangleEqual", + "description": "Bad named entity: NotLeftTriangleEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLeftTriangleEqual" + ] + ] + }, + { + "input": "⋬", + "description": "Named entity: NotLeftTriangleEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22ec" + ] + ] + }, + { + "input": "&NotLess", + "description": "Bad named entity: NotLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLess" + ] + ] + }, + { + "input": "≮", + "description": "Named entity: NotLess; with a semi-colon", + "output": [ + [ + "Character", + "\u226e" + ] + ] + }, + { + "input": "&NotLessEqual", + "description": "Bad named entity: NotLessEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLessEqual" + ] + ] + }, + { + "input": "≰", + "description": "Named entity: NotLessEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2270" + ] + ] + }, + { + "input": "&NotLessGreater", + "description": "Bad named entity: NotLessGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLessGreater" + ] + ] + }, + { + "input": "≸", + "description": "Named entity: NotLessGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u2278" + ] + ] + }, + { + "input": "&NotLessLess", + "description": "Bad named entity: NotLessLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLessLess" + ] + ] + }, + { + "input": "≪̸", + "description": "Named entity: NotLessLess; with a semi-colon", + "output": [ + [ + "Character", + "\u226a\u0338" + ] + ] + }, + { + "input": "&NotLessSlantEqual", + "description": "Bad named entity: NotLessSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLessSlantEqual" + ] + ] + }, + { + "input": "⩽̸", + "description": "Named entity: NotLessSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d\u0338" + ] + ] + }, + { + "input": "&NotLessTilde", + "description": "Bad named entity: NotLessTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotLessTilde" + ] + ] + }, + { + "input": "≴", + "description": "Named entity: NotLessTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2274" + ] + ] + }, + { + "input": "&NotNestedGreaterGreater", + "description": "Bad named entity: NotNestedGreaterGreater without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotNestedGreaterGreater" + ] + ] + }, + { + "input": "⪢̸", + "description": "Named entity: NotNestedGreaterGreater; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa2\u0338" + ] + ] + }, + { + "input": "&NotNestedLessLess", + "description": "Bad named entity: NotNestedLessLess without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotNestedLessLess" + ] + ] + }, + { + "input": "⪡̸", + "description": "Named entity: NotNestedLessLess; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa1\u0338" + ] + ] + }, + { + "input": "&NotPrecedes", + "description": "Bad named entity: NotPrecedes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotPrecedes" + ] + ] + }, + { + "input": "⊀", + "description": "Named entity: NotPrecedes; with a semi-colon", + "output": [ + [ + "Character", + "\u2280" + ] + ] + }, + { + "input": "&NotPrecedesEqual", + "description": "Bad named entity: NotPrecedesEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotPrecedesEqual" + ] + ] + }, + { + "input": "⪯̸", + "description": "Named entity: NotPrecedesEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf\u0338" + ] + ] + }, + { + "input": "&NotPrecedesSlantEqual", + "description": "Bad named entity: NotPrecedesSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotPrecedesSlantEqual" + ] + ] + }, + { + "input": "⋠", + "description": "Named entity: NotPrecedesSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22e0" + ] + ] + }, + { + "input": "&NotReverseElement", + "description": "Bad named entity: NotReverseElement without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotReverseElement" + ] + ] + }, + { + "input": "∌", + "description": "Named entity: NotReverseElement; with a semi-colon", + "output": [ + [ + "Character", + "\u220c" + ] + ] + }, + { + "input": "&NotRightTriangle", + "description": "Bad named entity: NotRightTriangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotRightTriangle" + ] + ] + }, + { + "input": "⋫", + "description": "Named entity: NotRightTriangle; with a semi-colon", + "output": [ + [ + "Character", + "\u22eb" + ] + ] + }, + { + "input": "&NotRightTriangleBar", + "description": "Bad named entity: NotRightTriangleBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotRightTriangleBar" + ] + ] + }, + { + "input": "⧐̸", + "description": "Named entity: NotRightTriangleBar; with a semi-colon", + "output": [ + [ + "Character", + "\u29d0\u0338" + ] + ] + }, + { + "input": "&NotRightTriangleEqual", + "description": "Bad named entity: NotRightTriangleEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotRightTriangleEqual" + ] + ] + }, + { + "input": "⋭", + "description": "Named entity: NotRightTriangleEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22ed" + ] + ] + }, + { + "input": "&NotSquareSubset", + "description": "Bad named entity: NotSquareSubset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSquareSubset" + ] + ] + }, + { + "input": "⊏̸", + "description": "Named entity: NotSquareSubset; with a semi-colon", + "output": [ + [ + "Character", + "\u228f\u0338" + ] + ] + }, + { + "input": "&NotSquareSubsetEqual", + "description": "Bad named entity: NotSquareSubsetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSquareSubsetEqual" + ] + ] + }, + { + "input": "⋢", + "description": "Named entity: NotSquareSubsetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22e2" + ] + ] + }, + { + "input": "&NotSquareSuperset", + "description": "Bad named entity: NotSquareSuperset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSquareSuperset" + ] + ] + }, + { + "input": "⊐̸", + "description": "Named entity: NotSquareSuperset; with a semi-colon", + "output": [ + [ + "Character", + "\u2290\u0338" + ] + ] + }, + { + "input": "&NotSquareSupersetEqual", + "description": "Bad named entity: NotSquareSupersetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSquareSupersetEqual" + ] + ] + }, + { + "input": "⋣", + "description": "Named entity: NotSquareSupersetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22e3" + ] + ] + }, + { + "input": "&NotSubset", + "description": "Bad named entity: NotSubset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSubset" + ] + ] + }, + { + "input": "⊂⃒", + "description": "Named entity: NotSubset; with a semi-colon", + "output": [ + [ + "Character", + "\u2282\u20d2" + ] + ] + }, + { + "input": "&NotSubsetEqual", + "description": "Bad named entity: NotSubsetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSubsetEqual" + ] + ] + }, + { + "input": "⊈", + "description": "Named entity: NotSubsetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2288" + ] + ] + }, + { + "input": "&NotSucceeds", + "description": "Bad named entity: NotSucceeds without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSucceeds" + ] + ] + }, + { + "input": "⊁", + "description": "Named entity: NotSucceeds; with a semi-colon", + "output": [ + [ + "Character", + "\u2281" + ] + ] + }, + { + "input": "&NotSucceedsEqual", + "description": "Bad named entity: NotSucceedsEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSucceedsEqual" + ] + ] + }, + { + "input": "⪰̸", + "description": "Named entity: NotSucceedsEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0\u0338" + ] + ] + }, + { + "input": "&NotSucceedsSlantEqual", + "description": "Bad named entity: NotSucceedsSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSucceedsSlantEqual" + ] + ] + }, + { + "input": "⋡", + "description": "Named entity: NotSucceedsSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22e1" + ] + ] + }, + { + "input": "&NotSucceedsTilde", + "description": "Bad named entity: NotSucceedsTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSucceedsTilde" + ] + ] + }, + { + "input": "≿̸", + "description": "Named entity: NotSucceedsTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u227f\u0338" + ] + ] + }, + { + "input": "&NotSuperset", + "description": "Bad named entity: NotSuperset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSuperset" + ] + ] + }, + { + "input": "⊃⃒", + "description": "Named entity: NotSuperset; with a semi-colon", + "output": [ + [ + "Character", + "\u2283\u20d2" + ] + ] + }, + { + "input": "&NotSupersetEqual", + "description": "Bad named entity: NotSupersetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotSupersetEqual" + ] + ] + }, + { + "input": "⊉", + "description": "Named entity: NotSupersetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2289" + ] + ] + }, + { + "input": "&NotTilde", + "description": "Bad named entity: NotTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotTilde" + ] + ] + }, + { + "input": "≁", + "description": "Named entity: NotTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2241" + ] + ] + }, + { + "input": "&NotTildeEqual", + "description": "Bad named entity: NotTildeEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotTildeEqual" + ] + ] + }, + { + "input": "≄", + "description": "Named entity: NotTildeEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2244" + ] + ] + }, + { + "input": "&NotTildeFullEqual", + "description": "Bad named entity: NotTildeFullEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotTildeFullEqual" + ] + ] + }, + { + "input": "≇", + "description": "Named entity: NotTildeFullEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2247" + ] + ] + }, + { + "input": "&NotTildeTilde", + "description": "Bad named entity: NotTildeTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotTildeTilde" + ] + ] + }, + { + "input": "≉", + "description": "Named entity: NotTildeTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2249" + ] + ] + }, + { + "input": "&NotVerticalBar", + "description": "Bad named entity: NotVerticalBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&NotVerticalBar" + ] + ] + }, + { + "input": "∤", + "description": "Named entity: NotVerticalBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2224" + ] + ] + }, + { + "input": "&Nscr", + "description": "Bad named entity: Nscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Nscr" + ] + ] + }, + { + "input": "𝒩", + "description": "Named entity: Nscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udca9" + ] + ] + }, + { + "input": "Ñ", + "description": "Named entity: Ntilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d1" + ] + ] + }, + { + "input": "Ñ", + "description": "Named entity: Ntilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00d1" + ] + ] + }, + { + "input": "&Nu", + "description": "Bad named entity: Nu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Nu" + ] + ] + }, + { + "input": "Ν", + "description": "Named entity: Nu; with a semi-colon", + "output": [ + [ + "Character", + "\u039d" + ] + ] + }, + { + "input": "&OElig", + "description": "Bad named entity: OElig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OElig" + ] + ] + }, + { + "input": "Œ", + "description": "Named entity: OElig; with a semi-colon", + "output": [ + [ + "Character", + "\u0152" + ] + ] + }, + { + "input": "Ó", + "description": "Named entity: Oacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d3" + ] + ] + }, + { + "input": "Ó", + "description": "Named entity: Oacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00d3" + ] + ] + }, + { + "input": "Ô", + "description": "Named entity: Ocirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d4" + ] + ] + }, + { + "input": "Ô", + "description": "Named entity: Ocirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00d4" + ] + ] + }, + { + "input": "&Ocy", + "description": "Bad named entity: Ocy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ocy" + ] + ] + }, + { + "input": "О", + "description": "Named entity: Ocy; with a semi-colon", + "output": [ + [ + "Character", + "\u041e" + ] + ] + }, + { + "input": "&Odblac", + "description": "Bad named entity: Odblac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Odblac" + ] + ] + }, + { + "input": "Ő", + "description": "Named entity: Odblac; with a semi-colon", + "output": [ + [ + "Character", + "\u0150" + ] + ] + }, + { + "input": "&Ofr", + "description": "Bad named entity: Ofr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ofr" + ] + ] + }, + { + "input": "𝔒", + "description": "Named entity: Ofr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd12" + ] + ] + }, + { + "input": "Ò", + "description": "Named entity: Ograve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d2" + ] + ] + }, + { + "input": "Ò", + "description": "Named entity: Ograve; with a semi-colon", + "output": [ + [ + "Character", + "\u00d2" + ] + ] + }, + { + "input": "&Omacr", + "description": "Bad named entity: Omacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Omacr" + ] + ] + }, + { + "input": "Ō", + "description": "Named entity: Omacr; with a semi-colon", + "output": [ + [ + "Character", + "\u014c" + ] + ] + }, + { + "input": "&Omega", + "description": "Bad named entity: Omega without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Omega" + ] + ] + }, + { + "input": "Ω", + "description": "Named entity: Omega; with a semi-colon", + "output": [ + [ + "Character", + "\u03a9" + ] + ] + }, + { + "input": "&Omicron", + "description": "Bad named entity: Omicron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Omicron" + ] + ] + }, + { + "input": "Ο", + "description": "Named entity: Omicron; with a semi-colon", + "output": [ + [ + "Character", + "\u039f" + ] + ] + }, + { + "input": "&Oopf", + "description": "Bad named entity: Oopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Oopf" + ] + ] + }, + { + "input": "𝕆", + "description": "Named entity: Oopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd46" + ] + ] + }, + { + "input": "&OpenCurlyDoubleQuote", + "description": "Bad named entity: OpenCurlyDoubleQuote without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OpenCurlyDoubleQuote" + ] + ] + }, + { + "input": "“", + "description": "Named entity: OpenCurlyDoubleQuote; with a semi-colon", + "output": [ + [ + "Character", + "\u201c" + ] + ] + }, + { + "input": "&OpenCurlyQuote", + "description": "Bad named entity: OpenCurlyQuote without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OpenCurlyQuote" + ] + ] + }, + { + "input": "‘", + "description": "Named entity: OpenCurlyQuote; with a semi-colon", + "output": [ + [ + "Character", + "\u2018" + ] + ] + }, + { + "input": "&Or", + "description": "Bad named entity: Or without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Or" + ] + ] + }, + { + "input": "⩔", + "description": "Named entity: Or; with a semi-colon", + "output": [ + [ + "Character", + "\u2a54" + ] + ] + }, + { + "input": "&Oscr", + "description": "Bad named entity: Oscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Oscr" + ] + ] + }, + { + "input": "𝒪", + "description": "Named entity: Oscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcaa" + ] + ] + }, + { + "input": "Ø", + "description": "Named entity: Oslash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d8" + ] + ] + }, + { + "input": "Ø", + "description": "Named entity: Oslash; with a semi-colon", + "output": [ + [ + "Character", + "\u00d8" + ] + ] + }, + { + "input": "Õ", + "description": "Named entity: Otilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d5" + ] + ] + }, + { + "input": "Õ", + "description": "Named entity: Otilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00d5" + ] + ] + }, + { + "input": "&Otimes", + "description": "Bad named entity: Otimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Otimes" + ] + ] + }, + { + "input": "⨷", + "description": "Named entity: Otimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2a37" + ] + ] + }, + { + "input": "Ö", + "description": "Named entity: Ouml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d6" + ] + ] + }, + { + "input": "Ö", + "description": "Named entity: Ouml; with a semi-colon", + "output": [ + [ + "Character", + "\u00d6" + ] + ] + }, + { + "input": "&OverBar", + "description": "Bad named entity: OverBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OverBar" + ] + ] + }, + { + "input": "‾", + "description": "Named entity: OverBar; with a semi-colon", + "output": [ + [ + "Character", + "\u203e" + ] + ] + }, + { + "input": "&OverBrace", + "description": "Bad named entity: OverBrace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OverBrace" + ] + ] + }, + { + "input": "⏞", + "description": "Named entity: OverBrace; with a semi-colon", + "output": [ + [ + "Character", + "\u23de" + ] + ] + }, + { + "input": "&OverBracket", + "description": "Bad named entity: OverBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OverBracket" + ] + ] + }, + { + "input": "⎴", + "description": "Named entity: OverBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u23b4" + ] + ] + }, + { + "input": "&OverParenthesis", + "description": "Bad named entity: OverParenthesis without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&OverParenthesis" + ] + ] + }, + { + "input": "⏜", + "description": "Named entity: OverParenthesis; with a semi-colon", + "output": [ + [ + "Character", + "\u23dc" + ] + ] + }, + { + "input": "&PartialD", + "description": "Bad named entity: PartialD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&PartialD" + ] + ] + }, + { + "input": "∂", + "description": "Named entity: PartialD; with a semi-colon", + "output": [ + [ + "Character", + "\u2202" + ] + ] + }, + { + "input": "&Pcy", + "description": "Bad named entity: Pcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Pcy" + ] + ] + }, + { + "input": "П", + "description": "Named entity: Pcy; with a semi-colon", + "output": [ + [ + "Character", + "\u041f" + ] + ] + }, + { + "input": "&Pfr", + "description": "Bad named entity: Pfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Pfr" + ] + ] + }, + { + "input": "𝔓", + "description": "Named entity: Pfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd13" + ] + ] + }, + { + "input": "&Phi", + "description": "Bad named entity: Phi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Phi" + ] + ] + }, + { + "input": "Φ", + "description": "Named entity: Phi; with a semi-colon", + "output": [ + [ + "Character", + "\u03a6" + ] + ] + }, + { + "input": "&Pi", + "description": "Bad named entity: Pi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Pi" + ] + ] + }, + { + "input": "Π", + "description": "Named entity: Pi; with a semi-colon", + "output": [ + [ + "Character", + "\u03a0" + ] + ] + }, + { + "input": "&PlusMinus", + "description": "Bad named entity: PlusMinus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&PlusMinus" + ] + ] + }, + { + "input": "±", + "description": "Named entity: PlusMinus; with a semi-colon", + "output": [ + [ + "Character", + "\u00b1" + ] + ] + }, + { + "input": "&Poincareplane", + "description": "Bad named entity: Poincareplane without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Poincareplane" + ] + ] + }, + { + "input": "ℌ", + "description": "Named entity: Poincareplane; with a semi-colon", + "output": [ + [ + "Character", + "\u210c" + ] + ] + }, + { + "input": "&Popf", + "description": "Bad named entity: Popf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Popf" + ] + ] + }, + { + "input": "ℙ", + "description": "Named entity: Popf; with a semi-colon", + "output": [ + [ + "Character", + "\u2119" + ] + ] + }, + { + "input": "&Pr", + "description": "Bad named entity: Pr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Pr" + ] + ] + }, + { + "input": "⪻", + "description": "Named entity: Pr; with a semi-colon", + "output": [ + [ + "Character", + "\u2abb" + ] + ] + }, + { + "input": "&Precedes", + "description": "Bad named entity: Precedes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Precedes" + ] + ] + }, + { + "input": "≺", + "description": "Named entity: Precedes; with a semi-colon", + "output": [ + [ + "Character", + "\u227a" + ] + ] + }, + { + "input": "&PrecedesEqual", + "description": "Bad named entity: PrecedesEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&PrecedesEqual" + ] + ] + }, + { + "input": "⪯", + "description": "Named entity: PrecedesEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf" + ] + ] + }, + { + "input": "&PrecedesSlantEqual", + "description": "Bad named entity: PrecedesSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&PrecedesSlantEqual" + ] + ] + }, + { + "input": "≼", + "description": "Named entity: PrecedesSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u227c" + ] + ] + }, + { + "input": "&PrecedesTilde", + "description": "Bad named entity: PrecedesTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&PrecedesTilde" + ] + ] + }, + { + "input": "≾", + "description": "Named entity: PrecedesTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u227e" + ] + ] + }, + { + "input": "&Prime", + "description": "Bad named entity: Prime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Prime" + ] + ] + }, + { + "input": "″", + "description": "Named entity: Prime; with a semi-colon", + "output": [ + [ + "Character", + "\u2033" + ] + ] + }, + { + "input": "&Product", + "description": "Bad named entity: Product without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Product" + ] + ] + }, + { + "input": "∏", + "description": "Named entity: Product; with a semi-colon", + "output": [ + [ + "Character", + "\u220f" + ] + ] + }, + { + "input": "&Proportion", + "description": "Bad named entity: Proportion without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Proportion" + ] + ] + }, + { + "input": "∷", + "description": "Named entity: Proportion; with a semi-colon", + "output": [ + [ + "Character", + "\u2237" + ] + ] + }, + { + "input": "&Proportional", + "description": "Bad named entity: Proportional without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Proportional" + ] + ] + }, + { + "input": "∝", + "description": "Named entity: Proportional; with a semi-colon", + "output": [ + [ + "Character", + "\u221d" + ] + ] + }, + { + "input": "&Pscr", + "description": "Bad named entity: Pscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Pscr" + ] + ] + }, + { + "input": "𝒫", + "description": "Named entity: Pscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcab" + ] + ] + }, + { + "input": "&Psi", + "description": "Bad named entity: Psi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Psi" + ] + ] + }, + { + "input": "Ψ", + "description": "Named entity: Psi; with a semi-colon", + "output": [ + [ + "Character", + "\u03a8" + ] + ] + }, + { + "input": """, + "description": "Named entity: QUOT without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\"" + ] + ] + }, + { + "input": """, + "description": "Named entity: QUOT; with a semi-colon", + "output": [ + [ + "Character", + "\"" + ] + ] + }, + { + "input": "&Qfr", + "description": "Bad named entity: Qfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Qfr" + ] + ] + }, + { + "input": "𝔔", + "description": "Named entity: Qfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd14" + ] + ] + }, + { + "input": "&Qopf", + "description": "Bad named entity: Qopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Qopf" + ] + ] + }, + { + "input": "ℚ", + "description": "Named entity: Qopf; with a semi-colon", + "output": [ + [ + "Character", + "\u211a" + ] + ] + }, + { + "input": "&Qscr", + "description": "Bad named entity: Qscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Qscr" + ] + ] + }, + { + "input": "𝒬", + "description": "Named entity: Qscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcac" + ] + ] + }, + { + "input": "&RBarr", + "description": "Bad named entity: RBarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RBarr" + ] + ] + }, + { + "input": "⤐", + "description": "Named entity: RBarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2910" + ] + ] + }, + { + "input": "®", + "description": "Named entity: REG without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ae" + ] + ] + }, + { + "input": "®", + "description": "Named entity: REG; with a semi-colon", + "output": [ + [ + "Character", + "\u00ae" + ] + ] + }, + { + "input": "&Racute", + "description": "Bad named entity: Racute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Racute" + ] + ] + }, + { + "input": "Ŕ", + "description": "Named entity: Racute; with a semi-colon", + "output": [ + [ + "Character", + "\u0154" + ] + ] + }, + { + "input": "&Rang", + "description": "Bad named entity: Rang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rang" + ] + ] + }, + { + "input": "⟫", + "description": "Named entity: Rang; with a semi-colon", + "output": [ + [ + "Character", + "\u27eb" + ] + ] + }, + { + "input": "&Rarr", + "description": "Bad named entity: Rarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rarr" + ] + ] + }, + { + "input": "↠", + "description": "Named entity: Rarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21a0" + ] + ] + }, + { + "input": "&Rarrtl", + "description": "Bad named entity: Rarrtl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rarrtl" + ] + ] + }, + { + "input": "⤖", + "description": "Named entity: Rarrtl; with a semi-colon", + "output": [ + [ + "Character", + "\u2916" + ] + ] + }, + { + "input": "&Rcaron", + "description": "Bad named entity: Rcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rcaron" + ] + ] + }, + { + "input": "Ř", + "description": "Named entity: Rcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0158" + ] + ] + }, + { + "input": "&Rcedil", + "description": "Bad named entity: Rcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rcedil" + ] + ] + }, + { + "input": "Ŗ", + "description": "Named entity: Rcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0156" + ] + ] + }, + { + "input": "&Rcy", + "description": "Bad named entity: Rcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rcy" + ] + ] + }, + { + "input": "Р", + "description": "Named entity: Rcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0420" + ] + ] + }, + { + "input": "&Re", + "description": "Bad named entity: Re without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Re" + ] + ] + }, + { + "input": "ℜ", + "description": "Named entity: Re; with a semi-colon", + "output": [ + [ + "Character", + "\u211c" + ] + ] + }, + { + "input": "&ReverseElement", + "description": "Bad named entity: ReverseElement without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ReverseElement" + ] + ] + }, + { + "input": "∋", + "description": "Named entity: ReverseElement; with a semi-colon", + "output": [ + [ + "Character", + "\u220b" + ] + ] + }, + { + "input": "&ReverseEquilibrium", + "description": "Bad named entity: ReverseEquilibrium without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ReverseEquilibrium" + ] + ] + }, + { + "input": "⇋", + "description": "Named entity: ReverseEquilibrium; with a semi-colon", + "output": [ + [ + "Character", + "\u21cb" + ] + ] + }, + { + "input": "&ReverseUpEquilibrium", + "description": "Bad named entity: ReverseUpEquilibrium without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ReverseUpEquilibrium" + ] + ] + }, + { + "input": "⥯", + "description": "Named entity: ReverseUpEquilibrium; with a semi-colon", + "output": [ + [ + "Character", + "\u296f" + ] + ] + }, + { + "input": "&Rfr", + "description": "Bad named entity: Rfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rfr" + ] + ] + }, + { + "input": "ℜ", + "description": "Named entity: Rfr; with a semi-colon", + "output": [ + [ + "Character", + "\u211c" + ] + ] + }, + { + "input": "&Rho", + "description": "Bad named entity: Rho without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rho" + ] + ] + }, + { + "input": "Ρ", + "description": "Named entity: Rho; with a semi-colon", + "output": [ + [ + "Character", + "\u03a1" + ] + ] + }, + { + "input": "&RightAngleBracket", + "description": "Bad named entity: RightAngleBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightAngleBracket" + ] + ] + }, + { + "input": "⟩", + "description": "Named entity: RightAngleBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u27e9" + ] + ] + }, + { + "input": "&RightArrow", + "description": "Bad named entity: RightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightArrow" + ] + ] + }, + { + "input": "→", + "description": "Named entity: RightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2192" + ] + ] + }, + { + "input": "&RightArrowBar", + "description": "Bad named entity: RightArrowBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightArrowBar" + ] + ] + }, + { + "input": "⇥", + "description": "Named entity: RightArrowBar; with a semi-colon", + "output": [ + [ + "Character", + "\u21e5" + ] + ] + }, + { + "input": "&RightArrowLeftArrow", + "description": "Bad named entity: RightArrowLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightArrowLeftArrow" + ] + ] + }, + { + "input": "⇄", + "description": "Named entity: RightArrowLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21c4" + ] + ] + }, + { + "input": "&RightCeiling", + "description": "Bad named entity: RightCeiling without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightCeiling" + ] + ] + }, + { + "input": "⌉", + "description": "Named entity: RightCeiling; with a semi-colon", + "output": [ + [ + "Character", + "\u2309" + ] + ] + }, + { + "input": "&RightDoubleBracket", + "description": "Bad named entity: RightDoubleBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightDoubleBracket" + ] + ] + }, + { + "input": "⟧", + "description": "Named entity: RightDoubleBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u27e7" + ] + ] + }, + { + "input": "&RightDownTeeVector", + "description": "Bad named entity: RightDownTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightDownTeeVector" + ] + ] + }, + { + "input": "⥝", + "description": "Named entity: RightDownTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295d" + ] + ] + }, + { + "input": "&RightDownVector", + "description": "Bad named entity: RightDownVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightDownVector" + ] + ] + }, + { + "input": "⇂", + "description": "Named entity: RightDownVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21c2" + ] + ] + }, + { + "input": "&RightDownVectorBar", + "description": "Bad named entity: RightDownVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightDownVectorBar" + ] + ] + }, + { + "input": "⥕", + "description": "Named entity: RightDownVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2955" + ] + ] + }, + { + "input": "&RightFloor", + "description": "Bad named entity: RightFloor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightFloor" + ] + ] + }, + { + "input": "⌋", + "description": "Named entity: RightFloor; with a semi-colon", + "output": [ + [ + "Character", + "\u230b" + ] + ] + }, + { + "input": "&RightTee", + "description": "Bad named entity: RightTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTee" + ] + ] + }, + { + "input": "⊢", + "description": "Named entity: RightTee; with a semi-colon", + "output": [ + [ + "Character", + "\u22a2" + ] + ] + }, + { + "input": "&RightTeeArrow", + "description": "Bad named entity: RightTeeArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTeeArrow" + ] + ] + }, + { + "input": "↦", + "description": "Named entity: RightTeeArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a6" + ] + ] + }, + { + "input": "&RightTeeVector", + "description": "Bad named entity: RightTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTeeVector" + ] + ] + }, + { + "input": "⥛", + "description": "Named entity: RightTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295b" + ] + ] + }, + { + "input": "&RightTriangle", + "description": "Bad named entity: RightTriangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTriangle" + ] + ] + }, + { + "input": "⊳", + "description": "Named entity: RightTriangle; with a semi-colon", + "output": [ + [ + "Character", + "\u22b3" + ] + ] + }, + { + "input": "&RightTriangleBar", + "description": "Bad named entity: RightTriangleBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTriangleBar" + ] + ] + }, + { + "input": "⧐", + "description": "Named entity: RightTriangleBar; with a semi-colon", + "output": [ + [ + "Character", + "\u29d0" + ] + ] + }, + { + "input": "&RightTriangleEqual", + "description": "Bad named entity: RightTriangleEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightTriangleEqual" + ] + ] + }, + { + "input": "⊵", + "description": "Named entity: RightTriangleEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u22b5" + ] + ] + }, + { + "input": "&RightUpDownVector", + "description": "Bad named entity: RightUpDownVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightUpDownVector" + ] + ] + }, + { + "input": "⥏", + "description": "Named entity: RightUpDownVector; with a semi-colon", + "output": [ + [ + "Character", + "\u294f" + ] + ] + }, + { + "input": "&RightUpTeeVector", + "description": "Bad named entity: RightUpTeeVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightUpTeeVector" + ] + ] + }, + { + "input": "⥜", + "description": "Named entity: RightUpTeeVector; with a semi-colon", + "output": [ + [ + "Character", + "\u295c" + ] + ] + }, + { + "input": "&RightUpVector", + "description": "Bad named entity: RightUpVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightUpVector" + ] + ] + }, + { + "input": "↾", + "description": "Named entity: RightUpVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21be" + ] + ] + }, + { + "input": "&RightUpVectorBar", + "description": "Bad named entity: RightUpVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightUpVectorBar" + ] + ] + }, + { + "input": "⥔", + "description": "Named entity: RightUpVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2954" + ] + ] + }, + { + "input": "&RightVector", + "description": "Bad named entity: RightVector without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightVector" + ] + ] + }, + { + "input": "⇀", + "description": "Named entity: RightVector; with a semi-colon", + "output": [ + [ + "Character", + "\u21c0" + ] + ] + }, + { + "input": "&RightVectorBar", + "description": "Bad named entity: RightVectorBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RightVectorBar" + ] + ] + }, + { + "input": "⥓", + "description": "Named entity: RightVectorBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2953" + ] + ] + }, + { + "input": "&Rightarrow", + "description": "Bad named entity: Rightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rightarrow" + ] + ] + }, + { + "input": "⇒", + "description": "Named entity: Rightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d2" + ] + ] + }, + { + "input": "&Ropf", + "description": "Bad named entity: Ropf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ropf" + ] + ] + }, + { + "input": "ℝ", + "description": "Named entity: Ropf; with a semi-colon", + "output": [ + [ + "Character", + "\u211d" + ] + ] + }, + { + "input": "&RoundImplies", + "description": "Bad named entity: RoundImplies without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RoundImplies" + ] + ] + }, + { + "input": "⥰", + "description": "Named entity: RoundImplies; with a semi-colon", + "output": [ + [ + "Character", + "\u2970" + ] + ] + }, + { + "input": "&Rrightarrow", + "description": "Bad named entity: Rrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rrightarrow" + ] + ] + }, + { + "input": "⇛", + "description": "Named entity: Rrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21db" + ] + ] + }, + { + "input": "&Rscr", + "description": "Bad named entity: Rscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rscr" + ] + ] + }, + { + "input": "ℛ", + "description": "Named entity: Rscr; with a semi-colon", + "output": [ + [ + "Character", + "\u211b" + ] + ] + }, + { + "input": "&Rsh", + "description": "Bad named entity: Rsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Rsh" + ] + ] + }, + { + "input": "↱", + "description": "Named entity: Rsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b1" + ] + ] + }, + { + "input": "&RuleDelayed", + "description": "Bad named entity: RuleDelayed without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&RuleDelayed" + ] + ] + }, + { + "input": "⧴", + "description": "Named entity: RuleDelayed; with a semi-colon", + "output": [ + [ + "Character", + "\u29f4" + ] + ] + }, + { + "input": "&SHCHcy", + "description": "Bad named entity: SHCHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SHCHcy" + ] + ] + }, + { + "input": "Щ", + "description": "Named entity: SHCHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0429" + ] + ] + }, + { + "input": "&SHcy", + "description": "Bad named entity: SHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SHcy" + ] + ] + }, + { + "input": "Ш", + "description": "Named entity: SHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0428" + ] + ] + }, + { + "input": "&SOFTcy", + "description": "Bad named entity: SOFTcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SOFTcy" + ] + ] + }, + { + "input": "Ь", + "description": "Named entity: SOFTcy; with a semi-colon", + "output": [ + [ + "Character", + "\u042c" + ] + ] + }, + { + "input": "&Sacute", + "description": "Bad named entity: Sacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sacute" + ] + ] + }, + { + "input": "Ś", + "description": "Named entity: Sacute; with a semi-colon", + "output": [ + [ + "Character", + "\u015a" + ] + ] + }, + { + "input": "&Sc", + "description": "Bad named entity: Sc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sc" + ] + ] + }, + { + "input": "⪼", + "description": "Named entity: Sc; with a semi-colon", + "output": [ + [ + "Character", + "\u2abc" + ] + ] + }, + { + "input": "&Scaron", + "description": "Bad named entity: Scaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Scaron" + ] + ] + }, + { + "input": "Š", + "description": "Named entity: Scaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0160" + ] + ] + }, + { + "input": "&Scedil", + "description": "Bad named entity: Scedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Scedil" + ] + ] + }, + { + "input": "Ş", + "description": "Named entity: Scedil; with a semi-colon", + "output": [ + [ + "Character", + "\u015e" + ] + ] + }, + { + "input": "&Scirc", + "description": "Bad named entity: Scirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Scirc" + ] + ] + }, + { + "input": "Ŝ", + "description": "Named entity: Scirc; with a semi-colon", + "output": [ + [ + "Character", + "\u015c" + ] + ] + }, + { + "input": "&Scy", + "description": "Bad named entity: Scy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Scy" + ] + ] + }, + { + "input": "С", + "description": "Named entity: Scy; with a semi-colon", + "output": [ + [ + "Character", + "\u0421" + ] + ] + }, + { + "input": "&Sfr", + "description": "Bad named entity: Sfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sfr" + ] + ] + }, + { + "input": "𝔖", + "description": "Named entity: Sfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd16" + ] + ] + }, + { + "input": "&ShortDownArrow", + "description": "Bad named entity: ShortDownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ShortDownArrow" + ] + ] + }, + { + "input": "↓", + "description": "Named entity: ShortDownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2193" + ] + ] + }, + { + "input": "&ShortLeftArrow", + "description": "Bad named entity: ShortLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ShortLeftArrow" + ] + ] + }, + { + "input": "←", + "description": "Named entity: ShortLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2190" + ] + ] + }, + { + "input": "&ShortRightArrow", + "description": "Bad named entity: ShortRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ShortRightArrow" + ] + ] + }, + { + "input": "→", + "description": "Named entity: ShortRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2192" + ] + ] + }, + { + "input": "&ShortUpArrow", + "description": "Bad named entity: ShortUpArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ShortUpArrow" + ] + ] + }, + { + "input": "↑", + "description": "Named entity: ShortUpArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2191" + ] + ] + }, + { + "input": "&Sigma", + "description": "Bad named entity: Sigma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sigma" + ] + ] + }, + { + "input": "Σ", + "description": "Named entity: Sigma; with a semi-colon", + "output": [ + [ + "Character", + "\u03a3" + ] + ] + }, + { + "input": "&SmallCircle", + "description": "Bad named entity: SmallCircle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SmallCircle" + ] + ] + }, + { + "input": "∘", + "description": "Named entity: SmallCircle; with a semi-colon", + "output": [ + [ + "Character", + "\u2218" + ] + ] + }, + { + "input": "&Sopf", + "description": "Bad named entity: Sopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sopf" + ] + ] + }, + { + "input": "𝕊", + "description": "Named entity: Sopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4a" + ] + ] + }, + { + "input": "&Sqrt", + "description": "Bad named entity: Sqrt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sqrt" + ] + ] + }, + { + "input": "√", + "description": "Named entity: Sqrt; with a semi-colon", + "output": [ + [ + "Character", + "\u221a" + ] + ] + }, + { + "input": "&Square", + "description": "Bad named entity: Square without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Square" + ] + ] + }, + { + "input": "□", + "description": "Named entity: Square; with a semi-colon", + "output": [ + [ + "Character", + "\u25a1" + ] + ] + }, + { + "input": "&SquareIntersection", + "description": "Bad named entity: SquareIntersection without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareIntersection" + ] + ] + }, + { + "input": "⊓", + "description": "Named entity: SquareIntersection; with a semi-colon", + "output": [ + [ + "Character", + "\u2293" + ] + ] + }, + { + "input": "&SquareSubset", + "description": "Bad named entity: SquareSubset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareSubset" + ] + ] + }, + { + "input": "⊏", + "description": "Named entity: SquareSubset; with a semi-colon", + "output": [ + [ + "Character", + "\u228f" + ] + ] + }, + { + "input": "&SquareSubsetEqual", + "description": "Bad named entity: SquareSubsetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareSubsetEqual" + ] + ] + }, + { + "input": "⊑", + "description": "Named entity: SquareSubsetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2291" + ] + ] + }, + { + "input": "&SquareSuperset", + "description": "Bad named entity: SquareSuperset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareSuperset" + ] + ] + }, + { + "input": "⊐", + "description": "Named entity: SquareSuperset; with a semi-colon", + "output": [ + [ + "Character", + "\u2290" + ] + ] + }, + { + "input": "&SquareSupersetEqual", + "description": "Bad named entity: SquareSupersetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareSupersetEqual" + ] + ] + }, + { + "input": "⊒", + "description": "Named entity: SquareSupersetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2292" + ] + ] + }, + { + "input": "&SquareUnion", + "description": "Bad named entity: SquareUnion without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SquareUnion" + ] + ] + }, + { + "input": "⊔", + "description": "Named entity: SquareUnion; with a semi-colon", + "output": [ + [ + "Character", + "\u2294" + ] + ] + }, + { + "input": "&Sscr", + "description": "Bad named entity: Sscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sscr" + ] + ] + }, + { + "input": "𝒮", + "description": "Named entity: Sscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcae" + ] + ] + }, + { + "input": "&Star", + "description": "Bad named entity: Star without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Star" + ] + ] + }, + { + "input": "⋆", + "description": "Named entity: Star; with a semi-colon", + "output": [ + [ + "Character", + "\u22c6" + ] + ] + }, + { + "input": "&Sub", + "description": "Bad named entity: Sub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sub" + ] + ] + }, + { + "input": "⋐", + "description": "Named entity: Sub; with a semi-colon", + "output": [ + [ + "Character", + "\u22d0" + ] + ] + }, + { + "input": "&Subset", + "description": "Bad named entity: Subset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Subset" + ] + ] + }, + { + "input": "⋐", + "description": "Named entity: Subset; with a semi-colon", + "output": [ + [ + "Character", + "\u22d0" + ] + ] + }, + { + "input": "&SubsetEqual", + "description": "Bad named entity: SubsetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SubsetEqual" + ] + ] + }, + { + "input": "⊆", + "description": "Named entity: SubsetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2286" + ] + ] + }, + { + "input": "&Succeeds", + "description": "Bad named entity: Succeeds without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Succeeds" + ] + ] + }, + { + "input": "≻", + "description": "Named entity: Succeeds; with a semi-colon", + "output": [ + [ + "Character", + "\u227b" + ] + ] + }, + { + "input": "&SucceedsEqual", + "description": "Bad named entity: SucceedsEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SucceedsEqual" + ] + ] + }, + { + "input": "⪰", + "description": "Named entity: SucceedsEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0" + ] + ] + }, + { + "input": "&SucceedsSlantEqual", + "description": "Bad named entity: SucceedsSlantEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SucceedsSlantEqual" + ] + ] + }, + { + "input": "≽", + "description": "Named entity: SucceedsSlantEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u227d" + ] + ] + }, + { + "input": "&SucceedsTilde", + "description": "Bad named entity: SucceedsTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SucceedsTilde" + ] + ] + }, + { + "input": "≿", + "description": "Named entity: SucceedsTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u227f" + ] + ] + }, + { + "input": "&SuchThat", + "description": "Bad named entity: SuchThat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SuchThat" + ] + ] + }, + { + "input": "∋", + "description": "Named entity: SuchThat; with a semi-colon", + "output": [ + [ + "Character", + "\u220b" + ] + ] + }, + { + "input": "&Sum", + "description": "Bad named entity: Sum without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sum" + ] + ] + }, + { + "input": "∑", + "description": "Named entity: Sum; with a semi-colon", + "output": [ + [ + "Character", + "\u2211" + ] + ] + }, + { + "input": "&Sup", + "description": "Bad named entity: Sup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Sup" + ] + ] + }, + { + "input": "⋑", + "description": "Named entity: Sup; with a semi-colon", + "output": [ + [ + "Character", + "\u22d1" + ] + ] + }, + { + "input": "&Superset", + "description": "Bad named entity: Superset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Superset" + ] + ] + }, + { + "input": "⊃", + "description": "Named entity: Superset; with a semi-colon", + "output": [ + [ + "Character", + "\u2283" + ] + ] + }, + { + "input": "&SupersetEqual", + "description": "Bad named entity: SupersetEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&SupersetEqual" + ] + ] + }, + { + "input": "⊇", + "description": "Named entity: SupersetEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2287" + ] + ] + }, + { + "input": "&Supset", + "description": "Bad named entity: Supset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Supset" + ] + ] + }, + { + "input": "⋑", + "description": "Named entity: Supset; with a semi-colon", + "output": [ + [ + "Character", + "\u22d1" + ] + ] + }, + { + "input": "Þ", + "description": "Named entity: THORN without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00de" + ] + ] + }, + { + "input": "Þ", + "description": "Named entity: THORN; with a semi-colon", + "output": [ + [ + "Character", + "\u00de" + ] + ] + }, + { + "input": "&TRADE", + "description": "Bad named entity: TRADE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TRADE" + ] + ] + }, + { + "input": "™", + "description": "Named entity: TRADE; with a semi-colon", + "output": [ + [ + "Character", + "\u2122" + ] + ] + }, + { + "input": "&TSHcy", + "description": "Bad named entity: TSHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TSHcy" + ] + ] + }, + { + "input": "Ћ", + "description": "Named entity: TSHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u040b" + ] + ] + }, + { + "input": "&TScy", + "description": "Bad named entity: TScy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TScy" + ] + ] + }, + { + "input": "Ц", + "description": "Named entity: TScy; with a semi-colon", + "output": [ + [ + "Character", + "\u0426" + ] + ] + }, + { + "input": "&Tab", + "description": "Bad named entity: Tab without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tab" + ] + ] + }, + { + "input": " ", + "description": "Named entity: Tab; with a semi-colon", + "output": [ + [ + "Character", + "\t" + ] + ] + }, + { + "input": "&Tau", + "description": "Bad named entity: Tau without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tau" + ] + ] + }, + { + "input": "Τ", + "description": "Named entity: Tau; with a semi-colon", + "output": [ + [ + "Character", + "\u03a4" + ] + ] + }, + { + "input": "&Tcaron", + "description": "Bad named entity: Tcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tcaron" + ] + ] + }, + { + "input": "Ť", + "description": "Named entity: Tcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0164" + ] + ] + }, + { + "input": "&Tcedil", + "description": "Bad named entity: Tcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tcedil" + ] + ] + }, + { + "input": "Ţ", + "description": "Named entity: Tcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0162" + ] + ] + }, + { + "input": "&Tcy", + "description": "Bad named entity: Tcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tcy" + ] + ] + }, + { + "input": "Т", + "description": "Named entity: Tcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0422" + ] + ] + }, + { + "input": "&Tfr", + "description": "Bad named entity: Tfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tfr" + ] + ] + }, + { + "input": "𝔗", + "description": "Named entity: Tfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd17" + ] + ] + }, + { + "input": "&Therefore", + "description": "Bad named entity: Therefore without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Therefore" + ] + ] + }, + { + "input": "∴", + "description": "Named entity: Therefore; with a semi-colon", + "output": [ + [ + "Character", + "\u2234" + ] + ] + }, + { + "input": "&Theta", + "description": "Bad named entity: Theta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Theta" + ] + ] + }, + { + "input": "Θ", + "description": "Named entity: Theta; with a semi-colon", + "output": [ + [ + "Character", + "\u0398" + ] + ] + }, + { + "input": "&ThickSpace", + "description": "Bad named entity: ThickSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ThickSpace" + ] + ] + }, + { + "input": "  ", + "description": "Named entity: ThickSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u205f\u200a" + ] + ] + }, + { + "input": "&ThinSpace", + "description": "Bad named entity: ThinSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ThinSpace" + ] + ] + }, + { + "input": " ", + "description": "Named entity: ThinSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u2009" + ] + ] + }, + { + "input": "&Tilde", + "description": "Bad named entity: Tilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tilde" + ] + ] + }, + { + "input": "∼", + "description": "Named entity: Tilde; with a semi-colon", + "output": [ + [ + "Character", + "\u223c" + ] + ] + }, + { + "input": "&TildeEqual", + "description": "Bad named entity: TildeEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TildeEqual" + ] + ] + }, + { + "input": "≃", + "description": "Named entity: TildeEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2243" + ] + ] + }, + { + "input": "&TildeFullEqual", + "description": "Bad named entity: TildeFullEqual without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TildeFullEqual" + ] + ] + }, + { + "input": "≅", + "description": "Named entity: TildeFullEqual; with a semi-colon", + "output": [ + [ + "Character", + "\u2245" + ] + ] + }, + { + "input": "&TildeTilde", + "description": "Bad named entity: TildeTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TildeTilde" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: TildeTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&Topf", + "description": "Bad named entity: Topf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Topf" + ] + ] + }, + { + "input": "𝕋", + "description": "Named entity: Topf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4b" + ] + ] + }, + { + "input": "&TripleDot", + "description": "Bad named entity: TripleDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&TripleDot" + ] + ] + }, + { + "input": "⃛", + "description": "Named entity: TripleDot; with a semi-colon", + "output": [ + [ + "Character", + "\u20db" + ] + ] + }, + { + "input": "&Tscr", + "description": "Bad named entity: Tscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tscr" + ] + ] + }, + { + "input": "𝒯", + "description": "Named entity: Tscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcaf" + ] + ] + }, + { + "input": "&Tstrok", + "description": "Bad named entity: Tstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Tstrok" + ] + ] + }, + { + "input": "Ŧ", + "description": "Named entity: Tstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0166" + ] + ] + }, + { + "input": "Ú", + "description": "Named entity: Uacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00da" + ] + ] + }, + { + "input": "Ú", + "description": "Named entity: Uacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00da" + ] + ] + }, + { + "input": "&Uarr", + "description": "Bad named entity: Uarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uarr" + ] + ] + }, + { + "input": "↟", + "description": "Named entity: Uarr; with a semi-colon", + "output": [ + [ + "Character", + "\u219f" + ] + ] + }, + { + "input": "&Uarrocir", + "description": "Bad named entity: Uarrocir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uarrocir" + ] + ] + }, + { + "input": "⥉", + "description": "Named entity: Uarrocir; with a semi-colon", + "output": [ + [ + "Character", + "\u2949" + ] + ] + }, + { + "input": "&Ubrcy", + "description": "Bad named entity: Ubrcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ubrcy" + ] + ] + }, + { + "input": "Ў", + "description": "Named entity: Ubrcy; with a semi-colon", + "output": [ + [ + "Character", + "\u040e" + ] + ] + }, + { + "input": "&Ubreve", + "description": "Bad named entity: Ubreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ubreve" + ] + ] + }, + { + "input": "Ŭ", + "description": "Named entity: Ubreve; with a semi-colon", + "output": [ + [ + "Character", + "\u016c" + ] + ] + }, + { + "input": "Û", + "description": "Named entity: Ucirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00db" + ] + ] + }, + { + "input": "Û", + "description": "Named entity: Ucirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00db" + ] + ] + }, + { + "input": "&Ucy", + "description": "Bad named entity: Ucy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ucy" + ] + ] + }, + { + "input": "У", + "description": "Named entity: Ucy; with a semi-colon", + "output": [ + [ + "Character", + "\u0423" + ] + ] + }, + { + "input": "&Udblac", + "description": "Bad named entity: Udblac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Udblac" + ] + ] + }, + { + "input": "Ű", + "description": "Named entity: Udblac; with a semi-colon", + "output": [ + [ + "Character", + "\u0170" + ] + ] + }, + { + "input": "&Ufr", + "description": "Bad named entity: Ufr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ufr" + ] + ] + }, + { + "input": "𝔘", + "description": "Named entity: Ufr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd18" + ] + ] + }, + { + "input": "Ù", + "description": "Named entity: Ugrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d9" + ] + ] + }, + { + "input": "Ù", + "description": "Named entity: Ugrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00d9" + ] + ] + }, + { + "input": "&Umacr", + "description": "Bad named entity: Umacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Umacr" + ] + ] + }, + { + "input": "Ū", + "description": "Named entity: Umacr; with a semi-colon", + "output": [ + [ + "Character", + "\u016a" + ] + ] + }, + { + "input": "&UnderBar", + "description": "Bad named entity: UnderBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UnderBar" + ] + ] + }, + { + "input": "_", + "description": "Named entity: UnderBar; with a semi-colon", + "output": [ + [ + "Character", + "_" + ] + ] + }, + { + "input": "&UnderBrace", + "description": "Bad named entity: UnderBrace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UnderBrace" + ] + ] + }, + { + "input": "⏟", + "description": "Named entity: UnderBrace; with a semi-colon", + "output": [ + [ + "Character", + "\u23df" + ] + ] + }, + { + "input": "&UnderBracket", + "description": "Bad named entity: UnderBracket without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UnderBracket" + ] + ] + }, + { + "input": "⎵", + "description": "Named entity: UnderBracket; with a semi-colon", + "output": [ + [ + "Character", + "\u23b5" + ] + ] + }, + { + "input": "&UnderParenthesis", + "description": "Bad named entity: UnderParenthesis without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UnderParenthesis" + ] + ] + }, + { + "input": "⏝", + "description": "Named entity: UnderParenthesis; with a semi-colon", + "output": [ + [ + "Character", + "\u23dd" + ] + ] + }, + { + "input": "&Union", + "description": "Bad named entity: Union without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Union" + ] + ] + }, + { + "input": "⋃", + "description": "Named entity: Union; with a semi-colon", + "output": [ + [ + "Character", + "\u22c3" + ] + ] + }, + { + "input": "&UnionPlus", + "description": "Bad named entity: UnionPlus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UnionPlus" + ] + ] + }, + { + "input": "⊎", + "description": "Named entity: UnionPlus; with a semi-colon", + "output": [ + [ + "Character", + "\u228e" + ] + ] + }, + { + "input": "&Uogon", + "description": "Bad named entity: Uogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uogon" + ] + ] + }, + { + "input": "Ų", + "description": "Named entity: Uogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0172" + ] + ] + }, + { + "input": "&Uopf", + "description": "Bad named entity: Uopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uopf" + ] + ] + }, + { + "input": "𝕌", + "description": "Named entity: Uopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4c" + ] + ] + }, + { + "input": "&UpArrow", + "description": "Bad named entity: UpArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpArrow" + ] + ] + }, + { + "input": "↑", + "description": "Named entity: UpArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2191" + ] + ] + }, + { + "input": "&UpArrowBar", + "description": "Bad named entity: UpArrowBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpArrowBar" + ] + ] + }, + { + "input": "⤒", + "description": "Named entity: UpArrowBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2912" + ] + ] + }, + { + "input": "&UpArrowDownArrow", + "description": "Bad named entity: UpArrowDownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpArrowDownArrow" + ] + ] + }, + { + "input": "⇅", + "description": "Named entity: UpArrowDownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21c5" + ] + ] + }, + { + "input": "&UpDownArrow", + "description": "Bad named entity: UpDownArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpDownArrow" + ] + ] + }, + { + "input": "↕", + "description": "Named entity: UpDownArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2195" + ] + ] + }, + { + "input": "&UpEquilibrium", + "description": "Bad named entity: UpEquilibrium without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpEquilibrium" + ] + ] + }, + { + "input": "⥮", + "description": "Named entity: UpEquilibrium; with a semi-colon", + "output": [ + [ + "Character", + "\u296e" + ] + ] + }, + { + "input": "&UpTee", + "description": "Bad named entity: UpTee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpTee" + ] + ] + }, + { + "input": "⊥", + "description": "Named entity: UpTee; with a semi-colon", + "output": [ + [ + "Character", + "\u22a5" + ] + ] + }, + { + "input": "&UpTeeArrow", + "description": "Bad named entity: UpTeeArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpTeeArrow" + ] + ] + }, + { + "input": "↥", + "description": "Named entity: UpTeeArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a5" + ] + ] + }, + { + "input": "&Uparrow", + "description": "Bad named entity: Uparrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uparrow" + ] + ] + }, + { + "input": "⇑", + "description": "Named entity: Uparrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d1" + ] + ] + }, + { + "input": "&Updownarrow", + "description": "Bad named entity: Updownarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Updownarrow" + ] + ] + }, + { + "input": "⇕", + "description": "Named entity: Updownarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21d5" + ] + ] + }, + { + "input": "&UpperLeftArrow", + "description": "Bad named entity: UpperLeftArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpperLeftArrow" + ] + ] + }, + { + "input": "↖", + "description": "Named entity: UpperLeftArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2196" + ] + ] + }, + { + "input": "&UpperRightArrow", + "description": "Bad named entity: UpperRightArrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&UpperRightArrow" + ] + ] + }, + { + "input": "↗", + "description": "Named entity: UpperRightArrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2197" + ] + ] + }, + { + "input": "&Upsi", + "description": "Bad named entity: Upsi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Upsi" + ] + ] + }, + { + "input": "ϒ", + "description": "Named entity: Upsi; with a semi-colon", + "output": [ + [ + "Character", + "\u03d2" + ] + ] + }, + { + "input": "&Upsilon", + "description": "Bad named entity: Upsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Upsilon" + ] + ] + }, + { + "input": "Υ", + "description": "Named entity: Upsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03a5" + ] + ] + }, + { + "input": "&Uring", + "description": "Bad named entity: Uring without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uring" + ] + ] + }, + { + "input": "Ů", + "description": "Named entity: Uring; with a semi-colon", + "output": [ + [ + "Character", + "\u016e" + ] + ] + }, + { + "input": "&Uscr", + "description": "Bad named entity: Uscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Uscr" + ] + ] + }, + { + "input": "𝒰", + "description": "Named entity: Uscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb0" + ] + ] + }, + { + "input": "&Utilde", + "description": "Bad named entity: Utilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Utilde" + ] + ] + }, + { + "input": "Ũ", + "description": "Named entity: Utilde; with a semi-colon", + "output": [ + [ + "Character", + "\u0168" + ] + ] + }, + { + "input": "Ü", + "description": "Named entity: Uuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00dc" + ] + ] + }, + { + "input": "Ü", + "description": "Named entity: Uuml; with a semi-colon", + "output": [ + [ + "Character", + "\u00dc" + ] + ] + }, + { + "input": "&VDash", + "description": "Bad named entity: VDash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VDash" + ] + ] + }, + { + "input": "⊫", + "description": "Named entity: VDash; with a semi-colon", + "output": [ + [ + "Character", + "\u22ab" + ] + ] + }, + { + "input": "&Vbar", + "description": "Bad named entity: Vbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vbar" + ] + ] + }, + { + "input": "⫫", + "description": "Named entity: Vbar; with a semi-colon", + "output": [ + [ + "Character", + "\u2aeb" + ] + ] + }, + { + "input": "&Vcy", + "description": "Bad named entity: Vcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vcy" + ] + ] + }, + { + "input": "В", + "description": "Named entity: Vcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0412" + ] + ] + }, + { + "input": "&Vdash", + "description": "Bad named entity: Vdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vdash" + ] + ] + }, + { + "input": "⊩", + "description": "Named entity: Vdash; with a semi-colon", + "output": [ + [ + "Character", + "\u22a9" + ] + ] + }, + { + "input": "&Vdashl", + "description": "Bad named entity: Vdashl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vdashl" + ] + ] + }, + { + "input": "⫦", + "description": "Named entity: Vdashl; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae6" + ] + ] + }, + { + "input": "&Vee", + "description": "Bad named entity: Vee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vee" + ] + ] + }, + { + "input": "⋁", + "description": "Named entity: Vee; with a semi-colon", + "output": [ + [ + "Character", + "\u22c1" + ] + ] + }, + { + "input": "&Verbar", + "description": "Bad named entity: Verbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Verbar" + ] + ] + }, + { + "input": "‖", + "description": "Named entity: Verbar; with a semi-colon", + "output": [ + [ + "Character", + "\u2016" + ] + ] + }, + { + "input": "&Vert", + "description": "Bad named entity: Vert without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vert" + ] + ] + }, + { + "input": "‖", + "description": "Named entity: Vert; with a semi-colon", + "output": [ + [ + "Character", + "\u2016" + ] + ] + }, + { + "input": "&VerticalBar", + "description": "Bad named entity: VerticalBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VerticalBar" + ] + ] + }, + { + "input": "∣", + "description": "Named entity: VerticalBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2223" + ] + ] + }, + { + "input": "&VerticalLine", + "description": "Bad named entity: VerticalLine without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VerticalLine" + ] + ] + }, + { + "input": "|", + "description": "Named entity: VerticalLine; with a semi-colon", + "output": [ + [ + "Character", + "|" + ] + ] + }, + { + "input": "&VerticalSeparator", + "description": "Bad named entity: VerticalSeparator without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VerticalSeparator" + ] + ] + }, + { + "input": "❘", + "description": "Named entity: VerticalSeparator; with a semi-colon", + "output": [ + [ + "Character", + "\u2758" + ] + ] + }, + { + "input": "&VerticalTilde", + "description": "Bad named entity: VerticalTilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VerticalTilde" + ] + ] + }, + { + "input": "≀", + "description": "Named entity: VerticalTilde; with a semi-colon", + "output": [ + [ + "Character", + "\u2240" + ] + ] + }, + { + "input": "&VeryThinSpace", + "description": "Bad named entity: VeryThinSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&VeryThinSpace" + ] + ] + }, + { + "input": " ", + "description": "Named entity: VeryThinSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200a" + ] + ] + }, + { + "input": "&Vfr", + "description": "Bad named entity: Vfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vfr" + ] + ] + }, + { + "input": "𝔙", + "description": "Named entity: Vfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd19" + ] + ] + }, + { + "input": "&Vopf", + "description": "Bad named entity: Vopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vopf" + ] + ] + }, + { + "input": "𝕍", + "description": "Named entity: Vopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4d" + ] + ] + }, + { + "input": "&Vscr", + "description": "Bad named entity: Vscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vscr" + ] + ] + }, + { + "input": "𝒱", + "description": "Named entity: Vscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb1" + ] + ] + }, + { + "input": "&Vvdash", + "description": "Bad named entity: Vvdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Vvdash" + ] + ] + }, + { + "input": "⊪", + "description": "Named entity: Vvdash; with a semi-colon", + "output": [ + [ + "Character", + "\u22aa" + ] + ] + }, + { + "input": "&Wcirc", + "description": "Bad named entity: Wcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Wcirc" + ] + ] + }, + { + "input": "Ŵ", + "description": "Named entity: Wcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0174" + ] + ] + }, + { + "input": "&Wedge", + "description": "Bad named entity: Wedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Wedge" + ] + ] + }, + { + "input": "⋀", + "description": "Named entity: Wedge; with a semi-colon", + "output": [ + [ + "Character", + "\u22c0" + ] + ] + }, + { + "input": "&Wfr", + "description": "Bad named entity: Wfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Wfr" + ] + ] + }, + { + "input": "𝔚", + "description": "Named entity: Wfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd1a" + ] + ] + }, + { + "input": "&Wopf", + "description": "Bad named entity: Wopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Wopf" + ] + ] + }, + { + "input": "𝕎", + "description": "Named entity: Wopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4e" + ] + ] + }, + { + "input": "&Wscr", + "description": "Bad named entity: Wscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Wscr" + ] + ] + }, + { + "input": "𝒲", + "description": "Named entity: Wscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb2" + ] + ] + }, + { + "input": "&Xfr", + "description": "Bad named entity: Xfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Xfr" + ] + ] + }, + { + "input": "𝔛", + "description": "Named entity: Xfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd1b" + ] + ] + }, + { + "input": "&Xi", + "description": "Bad named entity: Xi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Xi" + ] + ] + }, + { + "input": "Ξ", + "description": "Named entity: Xi; with a semi-colon", + "output": [ + [ + "Character", + "\u039e" + ] + ] + }, + { + "input": "&Xopf", + "description": "Bad named entity: Xopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Xopf" + ] + ] + }, + { + "input": "𝕏", + "description": "Named entity: Xopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd4f" + ] + ] + }, + { + "input": "&Xscr", + "description": "Bad named entity: Xscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Xscr" + ] + ] + }, + { + "input": "𝒳", + "description": "Named entity: Xscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb3" + ] + ] + }, + { + "input": "&YAcy", + "description": "Bad named entity: YAcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&YAcy" + ] + ] + }, + { + "input": "Я", + "description": "Named entity: YAcy; with a semi-colon", + "output": [ + [ + "Character", + "\u042f" + ] + ] + }, + { + "input": "&YIcy", + "description": "Bad named entity: YIcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&YIcy" + ] + ] + }, + { + "input": "Ї", + "description": "Named entity: YIcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0407" + ] + ] + }, + { + "input": "&YUcy", + "description": "Bad named entity: YUcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&YUcy" + ] + ] + }, + { + "input": "Ю", + "description": "Named entity: YUcy; with a semi-colon", + "output": [ + [ + "Character", + "\u042e" + ] + ] + }, + { + "input": "Ý", + "description": "Named entity: Yacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00dd" + ] + ] + }, + { + "input": "Ý", + "description": "Named entity: Yacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00dd" + ] + ] + }, + { + "input": "&Ycirc", + "description": "Bad named entity: Ycirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ycirc" + ] + ] + }, + { + "input": "Ŷ", + "description": "Named entity: Ycirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0176" + ] + ] + }, + { + "input": "&Ycy", + "description": "Bad named entity: Ycy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Ycy" + ] + ] + }, + { + "input": "Ы", + "description": "Named entity: Ycy; with a semi-colon", + "output": [ + [ + "Character", + "\u042b" + ] + ] + }, + { + "input": "&Yfr", + "description": "Bad named entity: Yfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Yfr" + ] + ] + }, + { + "input": "𝔜", + "description": "Named entity: Yfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd1c" + ] + ] + }, + { + "input": "&Yopf", + "description": "Bad named entity: Yopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Yopf" + ] + ] + }, + { + "input": "𝕐", + "description": "Named entity: Yopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd50" + ] + ] + }, + { + "input": "&Yscr", + "description": "Bad named entity: Yscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Yscr" + ] + ] + }, + { + "input": "𝒴", + "description": "Named entity: Yscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb4" + ] + ] + }, + { + "input": "&Yuml", + "description": "Bad named entity: Yuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Yuml" + ] + ] + }, + { + "input": "Ÿ", + "description": "Named entity: Yuml; with a semi-colon", + "output": [ + [ + "Character", + "\u0178" + ] + ] + }, + { + "input": "&ZHcy", + "description": "Bad named entity: ZHcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ZHcy" + ] + ] + }, + { + "input": "Ж", + "description": "Named entity: ZHcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0416" + ] + ] + }, + { + "input": "&Zacute", + "description": "Bad named entity: Zacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zacute" + ] + ] + }, + { + "input": "Ź", + "description": "Named entity: Zacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0179" + ] + ] + }, + { + "input": "&Zcaron", + "description": "Bad named entity: Zcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zcaron" + ] + ] + }, + { + "input": "Ž", + "description": "Named entity: Zcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u017d" + ] + ] + }, + { + "input": "&Zcy", + "description": "Bad named entity: Zcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zcy" + ] + ] + }, + { + "input": "З", + "description": "Named entity: Zcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0417" + ] + ] + }, + { + "input": "&Zdot", + "description": "Bad named entity: Zdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zdot" + ] + ] + }, + { + "input": "Ż", + "description": "Named entity: Zdot; with a semi-colon", + "output": [ + [ + "Character", + "\u017b" + ] + ] + }, + { + "input": "&ZeroWidthSpace", + "description": "Bad named entity: ZeroWidthSpace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ZeroWidthSpace" + ] + ] + }, + { + "input": "​", + "description": "Named entity: ZeroWidthSpace; with a semi-colon", + "output": [ + [ + "Character", + "\u200b" + ] + ] + }, + { + "input": "&Zeta", + "description": "Bad named entity: Zeta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zeta" + ] + ] + }, + { + "input": "Ζ", + "description": "Named entity: Zeta; with a semi-colon", + "output": [ + [ + "Character", + "\u0396" + ] + ] + }, + { + "input": "&Zfr", + "description": "Bad named entity: Zfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zfr" + ] + ] + }, + { + "input": "ℨ", + "description": "Named entity: Zfr; with a semi-colon", + "output": [ + [ + "Character", + "\u2128" + ] + ] + }, + { + "input": "&Zopf", + "description": "Bad named entity: Zopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zopf" + ] + ] + }, + { + "input": "ℤ", + "description": "Named entity: Zopf; with a semi-colon", + "output": [ + [ + "Character", + "\u2124" + ] + ] + }, + { + "input": "&Zscr", + "description": "Bad named entity: Zscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&Zscr" + ] + ] + }, + { + "input": "𝒵", + "description": "Named entity: Zscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb5" + ] + ] + }, + { + "input": "á", + "description": "Named entity: aacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e1" + ] + ] + }, + { + "input": "á", + "description": "Named entity: aacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00e1" + ] + ] + }, + { + "input": "&abreve", + "description": "Bad named entity: abreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&abreve" + ] + ] + }, + { + "input": "ă", + "description": "Named entity: abreve; with a semi-colon", + "output": [ + [ + "Character", + "\u0103" + ] + ] + }, + { + "input": "&ac", + "description": "Bad named entity: ac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ac" + ] + ] + }, + { + "input": "∾", + "description": "Named entity: ac; with a semi-colon", + "output": [ + [ + "Character", + "\u223e" + ] + ] + }, + { + "input": "&acE", + "description": "Bad named entity: acE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&acE" + ] + ] + }, + { + "input": "∾̳", + "description": "Named entity: acE; with a semi-colon", + "output": [ + [ + "Character", + "\u223e\u0333" + ] + ] + }, + { + "input": "&acd", + "description": "Bad named entity: acd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&acd" + ] + ] + }, + { + "input": "∿", + "description": "Named entity: acd; with a semi-colon", + "output": [ + [ + "Character", + "\u223f" + ] + ] + }, + { + "input": "â", + "description": "Named entity: acirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e2" + ] + ] + }, + { + "input": "â", + "description": "Named entity: acirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00e2" + ] + ] + }, + { + "input": "´", + "description": "Named entity: acute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b4" + ] + ] + }, + { + "input": "´", + "description": "Named entity: acute; with a semi-colon", + "output": [ + [ + "Character", + "\u00b4" + ] + ] + }, + { + "input": "&acy", + "description": "Bad named entity: acy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&acy" + ] + ] + }, + { + "input": "а", + "description": "Named entity: acy; with a semi-colon", + "output": [ + [ + "Character", + "\u0430" + ] + ] + }, + { + "input": "æ", + "description": "Named entity: aelig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e6" + ] + ] + }, + { + "input": "æ", + "description": "Named entity: aelig; with a semi-colon", + "output": [ + [ + "Character", + "\u00e6" + ] + ] + }, + { + "input": "&af", + "description": "Bad named entity: af without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&af" + ] + ] + }, + { + "input": "⁡", + "description": "Named entity: af; with a semi-colon", + "output": [ + [ + "Character", + "\u2061" + ] + ] + }, + { + "input": "&afr", + "description": "Bad named entity: afr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&afr" + ] + ] + }, + { + "input": "𝔞", + "description": "Named entity: afr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd1e" + ] + ] + }, + { + "input": "à", + "description": "Named entity: agrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e0" + ] + ] + }, + { + "input": "à", + "description": "Named entity: agrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00e0" + ] + ] + }, + { + "input": "&alefsym", + "description": "Bad named entity: alefsym without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&alefsym" + ] + ] + }, + { + "input": "ℵ", + "description": "Named entity: alefsym; with a semi-colon", + "output": [ + [ + "Character", + "\u2135" + ] + ] + }, + { + "input": "&aleph", + "description": "Bad named entity: aleph without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&aleph" + ] + ] + }, + { + "input": "ℵ", + "description": "Named entity: aleph; with a semi-colon", + "output": [ + [ + "Character", + "\u2135" + ] + ] + }, + { + "input": "&alpha", + "description": "Bad named entity: alpha without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&alpha" + ] + ] + }, + { + "input": "α", + "description": "Named entity: alpha; with a semi-colon", + "output": [ + [ + "Character", + "\u03b1" + ] + ] + }, + { + "input": "&amacr", + "description": "Bad named entity: amacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&amacr" + ] + ] + }, + { + "input": "ā", + "description": "Named entity: amacr; with a semi-colon", + "output": [ + [ + "Character", + "\u0101" + ] + ] + }, + { + "input": "&amalg", + "description": "Bad named entity: amalg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&amalg" + ] + ] + }, + { + "input": "⨿", + "description": "Named entity: amalg; with a semi-colon", + "output": [ + [ + "Character", + "\u2a3f" + ] + ] + }, + { + "input": "&", + "description": "Named entity: amp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&" + ] + ] + }, + { + "input": "&", + "description": "Named entity: amp; with a semi-colon", + "output": [ + [ + "Character", + "&" + ] + ] + }, + { + "input": "&and", + "description": "Bad named entity: and without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&and" + ] + ] + }, + { + "input": "∧", + "description": "Named entity: and; with a semi-colon", + "output": [ + [ + "Character", + "\u2227" + ] + ] + }, + { + "input": "&andand", + "description": "Bad named entity: andand without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&andand" + ] + ] + }, + { + "input": "⩕", + "description": "Named entity: andand; with a semi-colon", + "output": [ + [ + "Character", + "\u2a55" + ] + ] + }, + { + "input": "&andd", + "description": "Bad named entity: andd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&andd" + ] + ] + }, + { + "input": "⩜", + "description": "Named entity: andd; with a semi-colon", + "output": [ + [ + "Character", + "\u2a5c" + ] + ] + }, + { + "input": "&andslope", + "description": "Bad named entity: andslope without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&andslope" + ] + ] + }, + { + "input": "⩘", + "description": "Named entity: andslope; with a semi-colon", + "output": [ + [ + "Character", + "\u2a58" + ] + ] + }, + { + "input": "&andv", + "description": "Bad named entity: andv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&andv" + ] + ] + }, + { + "input": "⩚", + "description": "Named entity: andv; with a semi-colon", + "output": [ + [ + "Character", + "\u2a5a" + ] + ] + }, + { + "input": "&ang", + "description": "Bad named entity: ang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ang" + ] + ] + }, + { + "input": "∠", + "description": "Named entity: ang; with a semi-colon", + "output": [ + [ + "Character", + "\u2220" + ] + ] + }, + { + "input": "&ange", + "description": "Bad named entity: ange without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ange" + ] + ] + }, + { + "input": "⦤", + "description": "Named entity: ange; with a semi-colon", + "output": [ + [ + "Character", + "\u29a4" + ] + ] + }, + { + "input": "&angle", + "description": "Bad named entity: angle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angle" + ] + ] + }, + { + "input": "∠", + "description": "Named entity: angle; with a semi-colon", + "output": [ + [ + "Character", + "\u2220" + ] + ] + }, + { + "input": "&angmsd", + "description": "Bad named entity: angmsd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsd" + ] + ] + }, + { + "input": "∡", + "description": "Named entity: angmsd; with a semi-colon", + "output": [ + [ + "Character", + "\u2221" + ] + ] + }, + { + "input": "&angmsdaa", + "description": "Bad named entity: angmsdaa without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdaa" + ] + ] + }, + { + "input": "⦨", + "description": "Named entity: angmsdaa; with a semi-colon", + "output": [ + [ + "Character", + "\u29a8" + ] + ] + }, + { + "input": "&angmsdab", + "description": "Bad named entity: angmsdab without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdab" + ] + ] + }, + { + "input": "⦩", + "description": "Named entity: angmsdab; with a semi-colon", + "output": [ + [ + "Character", + "\u29a9" + ] + ] + }, + { + "input": "&angmsdac", + "description": "Bad named entity: angmsdac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdac" + ] + ] + }, + { + "input": "⦪", + "description": "Named entity: angmsdac; with a semi-colon", + "output": [ + [ + "Character", + "\u29aa" + ] + ] + }, + { + "input": "&angmsdad", + "description": "Bad named entity: angmsdad without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdad" + ] + ] + }, + { + "input": "⦫", + "description": "Named entity: angmsdad; with a semi-colon", + "output": [ + [ + "Character", + "\u29ab" + ] + ] + }, + { + "input": "&angmsdae", + "description": "Bad named entity: angmsdae without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdae" + ] + ] + }, + { + "input": "⦬", + "description": "Named entity: angmsdae; with a semi-colon", + "output": [ + [ + "Character", + "\u29ac" + ] + ] + }, + { + "input": "&angmsdaf", + "description": "Bad named entity: angmsdaf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdaf" + ] + ] + }, + { + "input": "⦭", + "description": "Named entity: angmsdaf; with a semi-colon", + "output": [ + [ + "Character", + "\u29ad" + ] + ] + }, + { + "input": "&angmsdag", + "description": "Bad named entity: angmsdag without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdag" + ] + ] + }, + { + "input": "⦮", + "description": "Named entity: angmsdag; with a semi-colon", + "output": [ + [ + "Character", + "\u29ae" + ] + ] + }, + { + "input": "&angmsdah", + "description": "Bad named entity: angmsdah without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angmsdah" + ] + ] + }, + { + "input": "⦯", + "description": "Named entity: angmsdah; with a semi-colon", + "output": [ + [ + "Character", + "\u29af" + ] + ] + }, + { + "input": "&angrt", + "description": "Bad named entity: angrt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angrt" + ] + ] + }, + { + "input": "∟", + "description": "Named entity: angrt; with a semi-colon", + "output": [ + [ + "Character", + "\u221f" + ] + ] + }, + { + "input": "&angrtvb", + "description": "Bad named entity: angrtvb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angrtvb" + ] + ] + }, + { + "input": "⊾", + "description": "Named entity: angrtvb; with a semi-colon", + "output": [ + [ + "Character", + "\u22be" + ] + ] + }, + { + "input": "&angrtvbd", + "description": "Bad named entity: angrtvbd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angrtvbd" + ] + ] + }, + { + "input": "⦝", + "description": "Named entity: angrtvbd; with a semi-colon", + "output": [ + [ + "Character", + "\u299d" + ] + ] + }, + { + "input": "&angsph", + "description": "Bad named entity: angsph without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angsph" + ] + ] + }, + { + "input": "∢", + "description": "Named entity: angsph; with a semi-colon", + "output": [ + [ + "Character", + "\u2222" + ] + ] + }, + { + "input": "&angst", + "description": "Bad named entity: angst without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angst" + ] + ] + }, + { + "input": "Å", + "description": "Named entity: angst; with a semi-colon", + "output": [ + [ + "Character", + "\u00c5" + ] + ] + }, + { + "input": "&angzarr", + "description": "Bad named entity: angzarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&angzarr" + ] + ] + }, + { + "input": "⍼", + "description": "Named entity: angzarr; with a semi-colon", + "output": [ + [ + "Character", + "\u237c" + ] + ] + }, + { + "input": "&aogon", + "description": "Bad named entity: aogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&aogon" + ] + ] + }, + { + "input": "ą", + "description": "Named entity: aogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0105" + ] + ] + }, + { + "input": "&aopf", + "description": "Bad named entity: aopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&aopf" + ] + ] + }, + { + "input": "𝕒", + "description": "Named entity: aopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd52" + ] + ] + }, + { + "input": "&ap", + "description": "Bad named entity: ap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ap" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: ap; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&apE", + "description": "Bad named entity: apE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&apE" + ] + ] + }, + { + "input": "⩰", + "description": "Named entity: apE; with a semi-colon", + "output": [ + [ + "Character", + "\u2a70" + ] + ] + }, + { + "input": "&apacir", + "description": "Bad named entity: apacir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&apacir" + ] + ] + }, + { + "input": "⩯", + "description": "Named entity: apacir; with a semi-colon", + "output": [ + [ + "Character", + "\u2a6f" + ] + ] + }, + { + "input": "&ape", + "description": "Bad named entity: ape without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ape" + ] + ] + }, + { + "input": "≊", + "description": "Named entity: ape; with a semi-colon", + "output": [ + [ + "Character", + "\u224a" + ] + ] + }, + { + "input": "&apid", + "description": "Bad named entity: apid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&apid" + ] + ] + }, + { + "input": "≋", + "description": "Named entity: apid; with a semi-colon", + "output": [ + [ + "Character", + "\u224b" + ] + ] + }, + { + "input": "&apos", + "description": "Bad named entity: apos without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&apos" + ] + ] + }, + { + "input": "'", + "description": "Named entity: apos; with a semi-colon", + "output": [ + [ + "Character", + "'" + ] + ] + }, + { + "input": "&approx", + "description": "Bad named entity: approx without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&approx" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: approx; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&approxeq", + "description": "Bad named entity: approxeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&approxeq" + ] + ] + }, + { + "input": "≊", + "description": "Named entity: approxeq; with a semi-colon", + "output": [ + [ + "Character", + "\u224a" + ] + ] + }, + { + "input": "å", + "description": "Named entity: aring without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e5" + ] + ] + }, + { + "input": "å", + "description": "Named entity: aring; with a semi-colon", + "output": [ + [ + "Character", + "\u00e5" + ] + ] + }, + { + "input": "&ascr", + "description": "Bad named entity: ascr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ascr" + ] + ] + }, + { + "input": "𝒶", + "description": "Named entity: ascr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb6" + ] + ] + }, + { + "input": "&ast", + "description": "Bad named entity: ast without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ast" + ] + ] + }, + { + "input": "*", + "description": "Named entity: ast; with a semi-colon", + "output": [ + [ + "Character", + "*" + ] + ] + }, + { + "input": "&asymp", + "description": "Bad named entity: asymp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&asymp" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: asymp; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&asympeq", + "description": "Bad named entity: asympeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&asympeq" + ] + ] + }, + { + "input": "≍", + "description": "Named entity: asympeq; with a semi-colon", + "output": [ + [ + "Character", + "\u224d" + ] + ] + }, + { + "input": "ã", + "description": "Named entity: atilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e3" + ] + ] + }, + { + "input": "ã", + "description": "Named entity: atilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00e3" + ] + ] + }, + { + "input": "ä", + "description": "Named entity: auml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e4" + ] + ] + }, + { + "input": "ä", + "description": "Named entity: auml; with a semi-colon", + "output": [ + [ + "Character", + "\u00e4" + ] + ] + }, + { + "input": "&awconint", + "description": "Bad named entity: awconint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&awconint" + ] + ] + }, + { + "input": "∳", + "description": "Named entity: awconint; with a semi-colon", + "output": [ + [ + "Character", + "\u2233" + ] + ] + }, + { + "input": "&awint", + "description": "Bad named entity: awint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&awint" + ] + ] + }, + { + "input": "⨑", + "description": "Named entity: awint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a11" + ] + ] + }, + { + "input": "&bNot", + "description": "Bad named entity: bNot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bNot" + ] + ] + }, + { + "input": "⫭", + "description": "Named entity: bNot; with a semi-colon", + "output": [ + [ + "Character", + "\u2aed" + ] + ] + }, + { + "input": "&backcong", + "description": "Bad named entity: backcong without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&backcong" + ] + ] + }, + { + "input": "≌", + "description": "Named entity: backcong; with a semi-colon", + "output": [ + [ + "Character", + "\u224c" + ] + ] + }, + { + "input": "&backepsilon", + "description": "Bad named entity: backepsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&backepsilon" + ] + ] + }, + { + "input": "϶", + "description": "Named entity: backepsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03f6" + ] + ] + }, + { + "input": "&backprime", + "description": "Bad named entity: backprime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&backprime" + ] + ] + }, + { + "input": "‵", + "description": "Named entity: backprime; with a semi-colon", + "output": [ + [ + "Character", + "\u2035" + ] + ] + }, + { + "input": "&backsim", + "description": "Bad named entity: backsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&backsim" + ] + ] + }, + { + "input": "∽", + "description": "Named entity: backsim; with a semi-colon", + "output": [ + [ + "Character", + "\u223d" + ] + ] + }, + { + "input": "&backsimeq", + "description": "Bad named entity: backsimeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&backsimeq" + ] + ] + }, + { + "input": "⋍", + "description": "Named entity: backsimeq; with a semi-colon", + "output": [ + [ + "Character", + "\u22cd" + ] + ] + }, + { + "input": "&barvee", + "description": "Bad named entity: barvee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&barvee" + ] + ] + }, + { + "input": "⊽", + "description": "Named entity: barvee; with a semi-colon", + "output": [ + [ + "Character", + "\u22bd" + ] + ] + }, + { + "input": "&barwed", + "description": "Bad named entity: barwed without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&barwed" + ] + ] + }, + { + "input": "⌅", + "description": "Named entity: barwed; with a semi-colon", + "output": [ + [ + "Character", + "\u2305" + ] + ] + }, + { + "input": "&barwedge", + "description": "Bad named entity: barwedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&barwedge" + ] + ] + }, + { + "input": "⌅", + "description": "Named entity: barwedge; with a semi-colon", + "output": [ + [ + "Character", + "\u2305" + ] + ] + }, + { + "input": "&bbrk", + "description": "Bad named entity: bbrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bbrk" + ] + ] + }, + { + "input": "⎵", + "description": "Named entity: bbrk; with a semi-colon", + "output": [ + [ + "Character", + "\u23b5" + ] + ] + }, + { + "input": "&bbrktbrk", + "description": "Bad named entity: bbrktbrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bbrktbrk" + ] + ] + }, + { + "input": "⎶", + "description": "Named entity: bbrktbrk; with a semi-colon", + "output": [ + [ + "Character", + "\u23b6" + ] + ] + }, + { + "input": "&bcong", + "description": "Bad named entity: bcong without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bcong" + ] + ] + }, + { + "input": "≌", + "description": "Named entity: bcong; with a semi-colon", + "output": [ + [ + "Character", + "\u224c" + ] + ] + }, + { + "input": "&bcy", + "description": "Bad named entity: bcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bcy" + ] + ] + }, + { + "input": "б", + "description": "Named entity: bcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0431" + ] + ] + }, + { + "input": "&bdquo", + "description": "Bad named entity: bdquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bdquo" + ] + ] + }, + { + "input": "„", + "description": "Named entity: bdquo; with a semi-colon", + "output": [ + [ + "Character", + "\u201e" + ] + ] + }, + { + "input": "&becaus", + "description": "Bad named entity: becaus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&becaus" + ] + ] + }, + { + "input": "∵", + "description": "Named entity: becaus; with a semi-colon", + "output": [ + [ + "Character", + "\u2235" + ] + ] + }, + { + "input": "&because", + "description": "Bad named entity: because without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&because" + ] + ] + }, + { + "input": "∵", + "description": "Named entity: because; with a semi-colon", + "output": [ + [ + "Character", + "\u2235" + ] + ] + }, + { + "input": "&bemptyv", + "description": "Bad named entity: bemptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bemptyv" + ] + ] + }, + { + "input": "⦰", + "description": "Named entity: bemptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u29b0" + ] + ] + }, + { + "input": "&bepsi", + "description": "Bad named entity: bepsi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bepsi" + ] + ] + }, + { + "input": "϶", + "description": "Named entity: bepsi; with a semi-colon", + "output": [ + [ + "Character", + "\u03f6" + ] + ] + }, + { + "input": "&bernou", + "description": "Bad named entity: bernou without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bernou" + ] + ] + }, + { + "input": "ℬ", + "description": "Named entity: bernou; with a semi-colon", + "output": [ + [ + "Character", + "\u212c" + ] + ] + }, + { + "input": "&beta", + "description": "Bad named entity: beta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&beta" + ] + ] + }, + { + "input": "β", + "description": "Named entity: beta; with a semi-colon", + "output": [ + [ + "Character", + "\u03b2" + ] + ] + }, + { + "input": "&beth", + "description": "Bad named entity: beth without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&beth" + ] + ] + }, + { + "input": "ℶ", + "description": "Named entity: beth; with a semi-colon", + "output": [ + [ + "Character", + "\u2136" + ] + ] + }, + { + "input": "&between", + "description": "Bad named entity: between without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&between" + ] + ] + }, + { + "input": "≬", + "description": "Named entity: between; with a semi-colon", + "output": [ + [ + "Character", + "\u226c" + ] + ] + }, + { + "input": "&bfr", + "description": "Bad named entity: bfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bfr" + ] + ] + }, + { + "input": "𝔟", + "description": "Named entity: bfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd1f" + ] + ] + }, + { + "input": "&bigcap", + "description": "Bad named entity: bigcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigcap" + ] + ] + }, + { + "input": "⋂", + "description": "Named entity: bigcap; with a semi-colon", + "output": [ + [ + "Character", + "\u22c2" + ] + ] + }, + { + "input": "&bigcirc", + "description": "Bad named entity: bigcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigcirc" + ] + ] + }, + { + "input": "◯", + "description": "Named entity: bigcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u25ef" + ] + ] + }, + { + "input": "&bigcup", + "description": "Bad named entity: bigcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigcup" + ] + ] + }, + { + "input": "⋃", + "description": "Named entity: bigcup; with a semi-colon", + "output": [ + [ + "Character", + "\u22c3" + ] + ] + }, + { + "input": "&bigodot", + "description": "Bad named entity: bigodot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigodot" + ] + ] + }, + { + "input": "⨀", + "description": "Named entity: bigodot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a00" + ] + ] + }, + { + "input": "&bigoplus", + "description": "Bad named entity: bigoplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigoplus" + ] + ] + }, + { + "input": "⨁", + "description": "Named entity: bigoplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a01" + ] + ] + }, + { + "input": "&bigotimes", + "description": "Bad named entity: bigotimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigotimes" + ] + ] + }, + { + "input": "⨂", + "description": "Named entity: bigotimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2a02" + ] + ] + }, + { + "input": "&bigsqcup", + "description": "Bad named entity: bigsqcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigsqcup" + ] + ] + }, + { + "input": "⨆", + "description": "Named entity: bigsqcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a06" + ] + ] + }, + { + "input": "&bigstar", + "description": "Bad named entity: bigstar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigstar" + ] + ] + }, + { + "input": "★", + "description": "Named entity: bigstar; with a semi-colon", + "output": [ + [ + "Character", + "\u2605" + ] + ] + }, + { + "input": "&bigtriangledown", + "description": "Bad named entity: bigtriangledown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigtriangledown" + ] + ] + }, + { + "input": "▽", + "description": "Named entity: bigtriangledown; with a semi-colon", + "output": [ + [ + "Character", + "\u25bd" + ] + ] + }, + { + "input": "&bigtriangleup", + "description": "Bad named entity: bigtriangleup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigtriangleup" + ] + ] + }, + { + "input": "△", + "description": "Named entity: bigtriangleup; with a semi-colon", + "output": [ + [ + "Character", + "\u25b3" + ] + ] + }, + { + "input": "&biguplus", + "description": "Bad named entity: biguplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&biguplus" + ] + ] + }, + { + "input": "⨄", + "description": "Named entity: biguplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a04" + ] + ] + }, + { + "input": "&bigvee", + "description": "Bad named entity: bigvee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigvee" + ] + ] + }, + { + "input": "⋁", + "description": "Named entity: bigvee; with a semi-colon", + "output": [ + [ + "Character", + "\u22c1" + ] + ] + }, + { + "input": "&bigwedge", + "description": "Bad named entity: bigwedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bigwedge" + ] + ] + }, + { + "input": "⋀", + "description": "Named entity: bigwedge; with a semi-colon", + "output": [ + [ + "Character", + "\u22c0" + ] + ] + }, + { + "input": "&bkarow", + "description": "Bad named entity: bkarow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bkarow" + ] + ] + }, + { + "input": "⤍", + "description": "Named entity: bkarow; with a semi-colon", + "output": [ + [ + "Character", + "\u290d" + ] + ] + }, + { + "input": "&blacklozenge", + "description": "Bad named entity: blacklozenge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacklozenge" + ] + ] + }, + { + "input": "⧫", + "description": "Named entity: blacklozenge; with a semi-colon", + "output": [ + [ + "Character", + "\u29eb" + ] + ] + }, + { + "input": "&blacksquare", + "description": "Bad named entity: blacksquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacksquare" + ] + ] + }, + { + "input": "▪", + "description": "Named entity: blacksquare; with a semi-colon", + "output": [ + [ + "Character", + "\u25aa" + ] + ] + }, + { + "input": "&blacktriangle", + "description": "Bad named entity: blacktriangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacktriangle" + ] + ] + }, + { + "input": "▴", + "description": "Named entity: blacktriangle; with a semi-colon", + "output": [ + [ + "Character", + "\u25b4" + ] + ] + }, + { + "input": "&blacktriangledown", + "description": "Bad named entity: blacktriangledown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacktriangledown" + ] + ] + }, + { + "input": "▾", + "description": "Named entity: blacktriangledown; with a semi-colon", + "output": [ + [ + "Character", + "\u25be" + ] + ] + }, + { + "input": "&blacktriangleleft", + "description": "Bad named entity: blacktriangleleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacktriangleleft" + ] + ] + }, + { + "input": "◂", + "description": "Named entity: blacktriangleleft; with a semi-colon", + "output": [ + [ + "Character", + "\u25c2" + ] + ] + }, + { + "input": "&blacktriangleright", + "description": "Bad named entity: blacktriangleright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blacktriangleright" + ] + ] + }, + { + "input": "▸", + "description": "Named entity: blacktriangleright; with a semi-colon", + "output": [ + [ + "Character", + "\u25b8" + ] + ] + }, + { + "input": "&blank", + "description": "Bad named entity: blank without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blank" + ] + ] + }, + { + "input": "␣", + "description": "Named entity: blank; with a semi-colon", + "output": [ + [ + "Character", + "\u2423" + ] + ] + }, + { + "input": "&blk12", + "description": "Bad named entity: blk12 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blk12" + ] + ] + }, + { + "input": "▒", + "description": "Named entity: blk12; with a semi-colon", + "output": [ + [ + "Character", + "\u2592" + ] + ] + }, + { + "input": "&blk14", + "description": "Bad named entity: blk14 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blk14" + ] + ] + }, + { + "input": "░", + "description": "Named entity: blk14; with a semi-colon", + "output": [ + [ + "Character", + "\u2591" + ] + ] + }, + { + "input": "&blk34", + "description": "Bad named entity: blk34 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&blk34" + ] + ] + }, + { + "input": "▓", + "description": "Named entity: blk34; with a semi-colon", + "output": [ + [ + "Character", + "\u2593" + ] + ] + }, + { + "input": "&block", + "description": "Bad named entity: block without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&block" + ] + ] + }, + { + "input": "█", + "description": "Named entity: block; with a semi-colon", + "output": [ + [ + "Character", + "\u2588" + ] + ] + }, + { + "input": "&bne", + "description": "Bad named entity: bne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bne" + ] + ] + }, + { + "input": "=⃥", + "description": "Named entity: bne; with a semi-colon", + "output": [ + [ + "Character", + "=\u20e5" + ] + ] + }, + { + "input": "&bnequiv", + "description": "Bad named entity: bnequiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bnequiv" + ] + ] + }, + { + "input": "≡⃥", + "description": "Named entity: bnequiv; with a semi-colon", + "output": [ + [ + "Character", + "\u2261\u20e5" + ] + ] + }, + { + "input": "&bnot", + "description": "Bad named entity: bnot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bnot" + ] + ] + }, + { + "input": "⌐", + "description": "Named entity: bnot; with a semi-colon", + "output": [ + [ + "Character", + "\u2310" + ] + ] + }, + { + "input": "&bopf", + "description": "Bad named entity: bopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bopf" + ] + ] + }, + { + "input": "𝕓", + "description": "Named entity: bopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd53" + ] + ] + }, + { + "input": "&bot", + "description": "Bad named entity: bot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bot" + ] + ] + }, + { + "input": "⊥", + "description": "Named entity: bot; with a semi-colon", + "output": [ + [ + "Character", + "\u22a5" + ] + ] + }, + { + "input": "&bottom", + "description": "Bad named entity: bottom without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bottom" + ] + ] + }, + { + "input": "⊥", + "description": "Named entity: bottom; with a semi-colon", + "output": [ + [ + "Character", + "\u22a5" + ] + ] + }, + { + "input": "&bowtie", + "description": "Bad named entity: bowtie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bowtie" + ] + ] + }, + { + "input": "⋈", + "description": "Named entity: bowtie; with a semi-colon", + "output": [ + [ + "Character", + "\u22c8" + ] + ] + }, + { + "input": "&boxDL", + "description": "Bad named entity: boxDL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxDL" + ] + ] + }, + { + "input": "╗", + "description": "Named entity: boxDL; with a semi-colon", + "output": [ + [ + "Character", + "\u2557" + ] + ] + }, + { + "input": "&boxDR", + "description": "Bad named entity: boxDR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxDR" + ] + ] + }, + { + "input": "╔", + "description": "Named entity: boxDR; with a semi-colon", + "output": [ + [ + "Character", + "\u2554" + ] + ] + }, + { + "input": "&boxDl", + "description": "Bad named entity: boxDl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxDl" + ] + ] + }, + { + "input": "╖", + "description": "Named entity: boxDl; with a semi-colon", + "output": [ + [ + "Character", + "\u2556" + ] + ] + }, + { + "input": "&boxDr", + "description": "Bad named entity: boxDr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxDr" + ] + ] + }, + { + "input": "╓", + "description": "Named entity: boxDr; with a semi-colon", + "output": [ + [ + "Character", + "\u2553" + ] + ] + }, + { + "input": "&boxH", + "description": "Bad named entity: boxH without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxH" + ] + ] + }, + { + "input": "═", + "description": "Named entity: boxH; with a semi-colon", + "output": [ + [ + "Character", + "\u2550" + ] + ] + }, + { + "input": "&boxHD", + "description": "Bad named entity: boxHD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxHD" + ] + ] + }, + { + "input": "╦", + "description": "Named entity: boxHD; with a semi-colon", + "output": [ + [ + "Character", + "\u2566" + ] + ] + }, + { + "input": "&boxHU", + "description": "Bad named entity: boxHU without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxHU" + ] + ] + }, + { + "input": "╩", + "description": "Named entity: boxHU; with a semi-colon", + "output": [ + [ + "Character", + "\u2569" + ] + ] + }, + { + "input": "&boxHd", + "description": "Bad named entity: boxHd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxHd" + ] + ] + }, + { + "input": "╤", + "description": "Named entity: boxHd; with a semi-colon", + "output": [ + [ + "Character", + "\u2564" + ] + ] + }, + { + "input": "&boxHu", + "description": "Bad named entity: boxHu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxHu" + ] + ] + }, + { + "input": "╧", + "description": "Named entity: boxHu; with a semi-colon", + "output": [ + [ + "Character", + "\u2567" + ] + ] + }, + { + "input": "&boxUL", + "description": "Bad named entity: boxUL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxUL" + ] + ] + }, + { + "input": "╝", + "description": "Named entity: boxUL; with a semi-colon", + "output": [ + [ + "Character", + "\u255d" + ] + ] + }, + { + "input": "&boxUR", + "description": "Bad named entity: boxUR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxUR" + ] + ] + }, + { + "input": "╚", + "description": "Named entity: boxUR; with a semi-colon", + "output": [ + [ + "Character", + "\u255a" + ] + ] + }, + { + "input": "&boxUl", + "description": "Bad named entity: boxUl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxUl" + ] + ] + }, + { + "input": "╜", + "description": "Named entity: boxUl; with a semi-colon", + "output": [ + [ + "Character", + "\u255c" + ] + ] + }, + { + "input": "&boxUr", + "description": "Bad named entity: boxUr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxUr" + ] + ] + }, + { + "input": "╙", + "description": "Named entity: boxUr; with a semi-colon", + "output": [ + [ + "Character", + "\u2559" + ] + ] + }, + { + "input": "&boxV", + "description": "Bad named entity: boxV without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxV" + ] + ] + }, + { + "input": "║", + "description": "Named entity: boxV; with a semi-colon", + "output": [ + [ + "Character", + "\u2551" + ] + ] + }, + { + "input": "&boxVH", + "description": "Bad named entity: boxVH without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVH" + ] + ] + }, + { + "input": "╬", + "description": "Named entity: boxVH; with a semi-colon", + "output": [ + [ + "Character", + "\u256c" + ] + ] + }, + { + "input": "&boxVL", + "description": "Bad named entity: boxVL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVL" + ] + ] + }, + { + "input": "╣", + "description": "Named entity: boxVL; with a semi-colon", + "output": [ + [ + "Character", + "\u2563" + ] + ] + }, + { + "input": "&boxVR", + "description": "Bad named entity: boxVR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVR" + ] + ] + }, + { + "input": "╠", + "description": "Named entity: boxVR; with a semi-colon", + "output": [ + [ + "Character", + "\u2560" + ] + ] + }, + { + "input": "&boxVh", + "description": "Bad named entity: boxVh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVh" + ] + ] + }, + { + "input": "╫", + "description": "Named entity: boxVh; with a semi-colon", + "output": [ + [ + "Character", + "\u256b" + ] + ] + }, + { + "input": "&boxVl", + "description": "Bad named entity: boxVl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVl" + ] + ] + }, + { + "input": "╢", + "description": "Named entity: boxVl; with a semi-colon", + "output": [ + [ + "Character", + "\u2562" + ] + ] + }, + { + "input": "&boxVr", + "description": "Bad named entity: boxVr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxVr" + ] + ] + }, + { + "input": "╟", + "description": "Named entity: boxVr; with a semi-colon", + "output": [ + [ + "Character", + "\u255f" + ] + ] + }, + { + "input": "&boxbox", + "description": "Bad named entity: boxbox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxbox" + ] + ] + }, + { + "input": "⧉", + "description": "Named entity: boxbox; with a semi-colon", + "output": [ + [ + "Character", + "\u29c9" + ] + ] + }, + { + "input": "&boxdL", + "description": "Bad named entity: boxdL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxdL" + ] + ] + }, + { + "input": "╕", + "description": "Named entity: boxdL; with a semi-colon", + "output": [ + [ + "Character", + "\u2555" + ] + ] + }, + { + "input": "&boxdR", + "description": "Bad named entity: boxdR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxdR" + ] + ] + }, + { + "input": "╒", + "description": "Named entity: boxdR; with a semi-colon", + "output": [ + [ + "Character", + "\u2552" + ] + ] + }, + { + "input": "&boxdl", + "description": "Bad named entity: boxdl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxdl" + ] + ] + }, + { + "input": "┐", + "description": "Named entity: boxdl; with a semi-colon", + "output": [ + [ + "Character", + "\u2510" + ] + ] + }, + { + "input": "&boxdr", + "description": "Bad named entity: boxdr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxdr" + ] + ] + }, + { + "input": "┌", + "description": "Named entity: boxdr; with a semi-colon", + "output": [ + [ + "Character", + "\u250c" + ] + ] + }, + { + "input": "&boxh", + "description": "Bad named entity: boxh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxh" + ] + ] + }, + { + "input": "─", + "description": "Named entity: boxh; with a semi-colon", + "output": [ + [ + "Character", + "\u2500" + ] + ] + }, + { + "input": "&boxhD", + "description": "Bad named entity: boxhD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxhD" + ] + ] + }, + { + "input": "╥", + "description": "Named entity: boxhD; with a semi-colon", + "output": [ + [ + "Character", + "\u2565" + ] + ] + }, + { + "input": "&boxhU", + "description": "Bad named entity: boxhU without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxhU" + ] + ] + }, + { + "input": "╨", + "description": "Named entity: boxhU; with a semi-colon", + "output": [ + [ + "Character", + "\u2568" + ] + ] + }, + { + "input": "&boxhd", + "description": "Bad named entity: boxhd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxhd" + ] + ] + }, + { + "input": "┬", + "description": "Named entity: boxhd; with a semi-colon", + "output": [ + [ + "Character", + "\u252c" + ] + ] + }, + { + "input": "&boxhu", + "description": "Bad named entity: boxhu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxhu" + ] + ] + }, + { + "input": "┴", + "description": "Named entity: boxhu; with a semi-colon", + "output": [ + [ + "Character", + "\u2534" + ] + ] + }, + { + "input": "&boxminus", + "description": "Bad named entity: boxminus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxminus" + ] + ] + }, + { + "input": "⊟", + "description": "Named entity: boxminus; with a semi-colon", + "output": [ + [ + "Character", + "\u229f" + ] + ] + }, + { + "input": "&boxplus", + "description": "Bad named entity: boxplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxplus" + ] + ] + }, + { + "input": "⊞", + "description": "Named entity: boxplus; with a semi-colon", + "output": [ + [ + "Character", + "\u229e" + ] + ] + }, + { + "input": "&boxtimes", + "description": "Bad named entity: boxtimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxtimes" + ] + ] + }, + { + "input": "⊠", + "description": "Named entity: boxtimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22a0" + ] + ] + }, + { + "input": "&boxuL", + "description": "Bad named entity: boxuL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxuL" + ] + ] + }, + { + "input": "╛", + "description": "Named entity: boxuL; with a semi-colon", + "output": [ + [ + "Character", + "\u255b" + ] + ] + }, + { + "input": "&boxuR", + "description": "Bad named entity: boxuR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxuR" + ] + ] + }, + { + "input": "╘", + "description": "Named entity: boxuR; with a semi-colon", + "output": [ + [ + "Character", + "\u2558" + ] + ] + }, + { + "input": "&boxul", + "description": "Bad named entity: boxul without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxul" + ] + ] + }, + { + "input": "┘", + "description": "Named entity: boxul; with a semi-colon", + "output": [ + [ + "Character", + "\u2518" + ] + ] + }, + { + "input": "&boxur", + "description": "Bad named entity: boxur without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxur" + ] + ] + }, + { + "input": "└", + "description": "Named entity: boxur; with a semi-colon", + "output": [ + [ + "Character", + "\u2514" + ] + ] + }, + { + "input": "&boxv", + "description": "Bad named entity: boxv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxv" + ] + ] + }, + { + "input": "│", + "description": "Named entity: boxv; with a semi-colon", + "output": [ + [ + "Character", + "\u2502" + ] + ] + }, + { + "input": "&boxvH", + "description": "Bad named entity: boxvH without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvH" + ] + ] + }, + { + "input": "╪", + "description": "Named entity: boxvH; with a semi-colon", + "output": [ + [ + "Character", + "\u256a" + ] + ] + }, + { + "input": "&boxvL", + "description": "Bad named entity: boxvL without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvL" + ] + ] + }, + { + "input": "╡", + "description": "Named entity: boxvL; with a semi-colon", + "output": [ + [ + "Character", + "\u2561" + ] + ] + }, + { + "input": "&boxvR", + "description": "Bad named entity: boxvR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvR" + ] + ] + }, + { + "input": "╞", + "description": "Named entity: boxvR; with a semi-colon", + "output": [ + [ + "Character", + "\u255e" + ] + ] + }, + { + "input": "&boxvh", + "description": "Bad named entity: boxvh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvh" + ] + ] + }, + { + "input": "┼", + "description": "Named entity: boxvh; with a semi-colon", + "output": [ + [ + "Character", + "\u253c" + ] + ] + }, + { + "input": "&boxvl", + "description": "Bad named entity: boxvl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvl" + ] + ] + }, + { + "input": "┤", + "description": "Named entity: boxvl; with a semi-colon", + "output": [ + [ + "Character", + "\u2524" + ] + ] + }, + { + "input": "&boxvr", + "description": "Bad named entity: boxvr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&boxvr" + ] + ] + }, + { + "input": "├", + "description": "Named entity: boxvr; with a semi-colon", + "output": [ + [ + "Character", + "\u251c" + ] + ] + }, + { + "input": "&bprime", + "description": "Bad named entity: bprime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bprime" + ] + ] + }, + { + "input": "‵", + "description": "Named entity: bprime; with a semi-colon", + "output": [ + [ + "Character", + "\u2035" + ] + ] + }, + { + "input": "&breve", + "description": "Bad named entity: breve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&breve" + ] + ] + }, + { + "input": "˘", + "description": "Named entity: breve; with a semi-colon", + "output": [ + [ + "Character", + "\u02d8" + ] + ] + }, + { + "input": "¦", + "description": "Named entity: brvbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a6" + ] + ] + }, + { + "input": "¦", + "description": "Named entity: brvbar; with a semi-colon", + "output": [ + [ + "Character", + "\u00a6" + ] + ] + }, + { + "input": "&bscr", + "description": "Bad named entity: bscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bscr" + ] + ] + }, + { + "input": "𝒷", + "description": "Named entity: bscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb7" + ] + ] + }, + { + "input": "&bsemi", + "description": "Bad named entity: bsemi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsemi" + ] + ] + }, + { + "input": "⁏", + "description": "Named entity: bsemi; with a semi-colon", + "output": [ + [ + "Character", + "\u204f" + ] + ] + }, + { + "input": "&bsim", + "description": "Bad named entity: bsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsim" + ] + ] + }, + { + "input": "∽", + "description": "Named entity: bsim; with a semi-colon", + "output": [ + [ + "Character", + "\u223d" + ] + ] + }, + { + "input": "&bsime", + "description": "Bad named entity: bsime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsime" + ] + ] + }, + { + "input": "⋍", + "description": "Named entity: bsime; with a semi-colon", + "output": [ + [ + "Character", + "\u22cd" + ] + ] + }, + { + "input": "&bsol", + "description": "Bad named entity: bsol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsol" + ] + ] + }, + { + "input": "\", + "description": "Named entity: bsol; with a semi-colon", + "output": [ + [ + "Character", + "\\" + ] + ] + }, + { + "input": "&bsolb", + "description": "Bad named entity: bsolb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsolb" + ] + ] + }, + { + "input": "⧅", + "description": "Named entity: bsolb; with a semi-colon", + "output": [ + [ + "Character", + "\u29c5" + ] + ] + }, + { + "input": "&bsolhsub", + "description": "Bad named entity: bsolhsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bsolhsub" + ] + ] + }, + { + "input": "⟈", + "description": "Named entity: bsolhsub; with a semi-colon", + "output": [ + [ + "Character", + "\u27c8" + ] + ] + }, + { + "input": "&bull", + "description": "Bad named entity: bull without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bull" + ] + ] + }, + { + "input": "•", + "description": "Named entity: bull; with a semi-colon", + "output": [ + [ + "Character", + "\u2022" + ] + ] + }, + { + "input": "&bullet", + "description": "Bad named entity: bullet without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bullet" + ] + ] + }, + { + "input": "•", + "description": "Named entity: bullet; with a semi-colon", + "output": [ + [ + "Character", + "\u2022" + ] + ] + }, + { + "input": "&bump", + "description": "Bad named entity: bump without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bump" + ] + ] + }, + { + "input": "≎", + "description": "Named entity: bump; with a semi-colon", + "output": [ + [ + "Character", + "\u224e" + ] + ] + }, + { + "input": "&bumpE", + "description": "Bad named entity: bumpE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bumpE" + ] + ] + }, + { + "input": "⪮", + "description": "Named entity: bumpE; with a semi-colon", + "output": [ + [ + "Character", + "\u2aae" + ] + ] + }, + { + "input": "&bumpe", + "description": "Bad named entity: bumpe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bumpe" + ] + ] + }, + { + "input": "≏", + "description": "Named entity: bumpe; with a semi-colon", + "output": [ + [ + "Character", + "\u224f" + ] + ] + }, + { + "input": "&bumpeq", + "description": "Bad named entity: bumpeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&bumpeq" + ] + ] + }, + { + "input": "≏", + "description": "Named entity: bumpeq; with a semi-colon", + "output": [ + [ + "Character", + "\u224f" + ] + ] + }, + { + "input": "&cacute", + "description": "Bad named entity: cacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cacute" + ] + ] + }, + { + "input": "ć", + "description": "Named entity: cacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0107" + ] + ] + }, + { + "input": "&cap", + "description": "Bad named entity: cap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cap" + ] + ] + }, + { + "input": "∩", + "description": "Named entity: cap; with a semi-colon", + "output": [ + [ + "Character", + "\u2229" + ] + ] + }, + { + "input": "&capand", + "description": "Bad named entity: capand without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&capand" + ] + ] + }, + { + "input": "⩄", + "description": "Named entity: capand; with a semi-colon", + "output": [ + [ + "Character", + "\u2a44" + ] + ] + }, + { + "input": "&capbrcup", + "description": "Bad named entity: capbrcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&capbrcup" + ] + ] + }, + { + "input": "⩉", + "description": "Named entity: capbrcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a49" + ] + ] + }, + { + "input": "&capcap", + "description": "Bad named entity: capcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&capcap" + ] + ] + }, + { + "input": "⩋", + "description": "Named entity: capcap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a4b" + ] + ] + }, + { + "input": "&capcup", + "description": "Bad named entity: capcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&capcup" + ] + ] + }, + { + "input": "⩇", + "description": "Named entity: capcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a47" + ] + ] + }, + { + "input": "&capdot", + "description": "Bad named entity: capdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&capdot" + ] + ] + }, + { + "input": "⩀", + "description": "Named entity: capdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a40" + ] + ] + }, + { + "input": "&caps", + "description": "Bad named entity: caps without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&caps" + ] + ] + }, + { + "input": "∩︀", + "description": "Named entity: caps; with a semi-colon", + "output": [ + [ + "Character", + "\u2229\ufe00" + ] + ] + }, + { + "input": "&caret", + "description": "Bad named entity: caret without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&caret" + ] + ] + }, + { + "input": "⁁", + "description": "Named entity: caret; with a semi-colon", + "output": [ + [ + "Character", + "\u2041" + ] + ] + }, + { + "input": "&caron", + "description": "Bad named entity: caron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&caron" + ] + ] + }, + { + "input": "ˇ", + "description": "Named entity: caron; with a semi-colon", + "output": [ + [ + "Character", + "\u02c7" + ] + ] + }, + { + "input": "&ccaps", + "description": "Bad named entity: ccaps without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ccaps" + ] + ] + }, + { + "input": "⩍", + "description": "Named entity: ccaps; with a semi-colon", + "output": [ + [ + "Character", + "\u2a4d" + ] + ] + }, + { + "input": "&ccaron", + "description": "Bad named entity: ccaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ccaron" + ] + ] + }, + { + "input": "č", + "description": "Named entity: ccaron; with a semi-colon", + "output": [ + [ + "Character", + "\u010d" + ] + ] + }, + { + "input": "ç", + "description": "Named entity: ccedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e7" + ] + ] + }, + { + "input": "ç", + "description": "Named entity: ccedil; with a semi-colon", + "output": [ + [ + "Character", + "\u00e7" + ] + ] + }, + { + "input": "&ccirc", + "description": "Bad named entity: ccirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ccirc" + ] + ] + }, + { + "input": "ĉ", + "description": "Named entity: ccirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0109" + ] + ] + }, + { + "input": "&ccups", + "description": "Bad named entity: ccups without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ccups" + ] + ] + }, + { + "input": "⩌", + "description": "Named entity: ccups; with a semi-colon", + "output": [ + [ + "Character", + "\u2a4c" + ] + ] + }, + { + "input": "&ccupssm", + "description": "Bad named entity: ccupssm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ccupssm" + ] + ] + }, + { + "input": "⩐", + "description": "Named entity: ccupssm; with a semi-colon", + "output": [ + [ + "Character", + "\u2a50" + ] + ] + }, + { + "input": "&cdot", + "description": "Bad named entity: cdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cdot" + ] + ] + }, + { + "input": "ċ", + "description": "Named entity: cdot; with a semi-colon", + "output": [ + [ + "Character", + "\u010b" + ] + ] + }, + { + "input": "¸", + "description": "Named entity: cedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b8" + ] + ] + }, + { + "input": "¸", + "description": "Named entity: cedil; with a semi-colon", + "output": [ + [ + "Character", + "\u00b8" + ] + ] + }, + { + "input": "&cemptyv", + "description": "Bad named entity: cemptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cemptyv" + ] + ] + }, + { + "input": "⦲", + "description": "Named entity: cemptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u29b2" + ] + ] + }, + { + "input": "¢", + "description": "Named entity: cent without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a2" + ] + ] + }, + { + "input": "¢", + "description": "Named entity: cent; with a semi-colon", + "output": [ + [ + "Character", + "\u00a2" + ] + ] + }, + { + "input": "·", + "description": "Named entity: centerdot; with a semi-colon", + "output": [ + [ + "Character", + "\u00b7" + ] + ] + }, + { + "input": "&cfr", + "description": "Bad named entity: cfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cfr" + ] + ] + }, + { + "input": "𝔠", + "description": "Named entity: cfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd20" + ] + ] + }, + { + "input": "&chcy", + "description": "Bad named entity: chcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&chcy" + ] + ] + }, + { + "input": "ч", + "description": "Named entity: chcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0447" + ] + ] + }, + { + "input": "&check", + "description": "Bad named entity: check without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&check" + ] + ] + }, + { + "input": "✓", + "description": "Named entity: check; with a semi-colon", + "output": [ + [ + "Character", + "\u2713" + ] + ] + }, + { + "input": "&checkmark", + "description": "Bad named entity: checkmark without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&checkmark" + ] + ] + }, + { + "input": "✓", + "description": "Named entity: checkmark; with a semi-colon", + "output": [ + [ + "Character", + "\u2713" + ] + ] + }, + { + "input": "&chi", + "description": "Bad named entity: chi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&chi" + ] + ] + }, + { + "input": "χ", + "description": "Named entity: chi; with a semi-colon", + "output": [ + [ + "Character", + "\u03c7" + ] + ] + }, + { + "input": "&cir", + "description": "Bad named entity: cir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cir" + ] + ] + }, + { + "input": "○", + "description": "Named entity: cir; with a semi-colon", + "output": [ + [ + "Character", + "\u25cb" + ] + ] + }, + { + "input": "&cirE", + "description": "Bad named entity: cirE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cirE" + ] + ] + }, + { + "input": "⧃", + "description": "Named entity: cirE; with a semi-colon", + "output": [ + [ + "Character", + "\u29c3" + ] + ] + }, + { + "input": "&circ", + "description": "Bad named entity: circ without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circ" + ] + ] + }, + { + "input": "ˆ", + "description": "Named entity: circ; with a semi-colon", + "output": [ + [ + "Character", + "\u02c6" + ] + ] + }, + { + "input": "&circeq", + "description": "Bad named entity: circeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circeq" + ] + ] + }, + { + "input": "≗", + "description": "Named entity: circeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2257" + ] + ] + }, + { + "input": "&circlearrowleft", + "description": "Bad named entity: circlearrowleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circlearrowleft" + ] + ] + }, + { + "input": "↺", + "description": "Named entity: circlearrowleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21ba" + ] + ] + }, + { + "input": "&circlearrowright", + "description": "Bad named entity: circlearrowright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circlearrowright" + ] + ] + }, + { + "input": "↻", + "description": "Named entity: circlearrowright; with a semi-colon", + "output": [ + [ + "Character", + "\u21bb" + ] + ] + }, + { + "input": "&circledR", + "description": "Bad named entity: circledR without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circledR" + ] + ] + }, + { + "input": "®", + "description": "Named entity: circledR; with a semi-colon", + "output": [ + [ + "Character", + "\u00ae" + ] + ] + }, + { + "input": "&circledS", + "description": "Bad named entity: circledS without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circledS" + ] + ] + }, + { + "input": "Ⓢ", + "description": "Named entity: circledS; with a semi-colon", + "output": [ + [ + "Character", + "\u24c8" + ] + ] + }, + { + "input": "&circledast", + "description": "Bad named entity: circledast without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circledast" + ] + ] + }, + { + "input": "⊛", + "description": "Named entity: circledast; with a semi-colon", + "output": [ + [ + "Character", + "\u229b" + ] + ] + }, + { + "input": "&circledcirc", + "description": "Bad named entity: circledcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circledcirc" + ] + ] + }, + { + "input": "⊚", + "description": "Named entity: circledcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u229a" + ] + ] + }, + { + "input": "&circleddash", + "description": "Bad named entity: circleddash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&circleddash" + ] + ] + }, + { + "input": "⊝", + "description": "Named entity: circleddash; with a semi-colon", + "output": [ + [ + "Character", + "\u229d" + ] + ] + }, + { + "input": "&cire", + "description": "Bad named entity: cire without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cire" + ] + ] + }, + { + "input": "≗", + "description": "Named entity: cire; with a semi-colon", + "output": [ + [ + "Character", + "\u2257" + ] + ] + }, + { + "input": "&cirfnint", + "description": "Bad named entity: cirfnint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cirfnint" + ] + ] + }, + { + "input": "⨐", + "description": "Named entity: cirfnint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a10" + ] + ] + }, + { + "input": "&cirmid", + "description": "Bad named entity: cirmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cirmid" + ] + ] + }, + { + "input": "⫯", + "description": "Named entity: cirmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2aef" + ] + ] + }, + { + "input": "&cirscir", + "description": "Bad named entity: cirscir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cirscir" + ] + ] + }, + { + "input": "⧂", + "description": "Named entity: cirscir; with a semi-colon", + "output": [ + [ + "Character", + "\u29c2" + ] + ] + }, + { + "input": "&clubs", + "description": "Bad named entity: clubs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&clubs" + ] + ] + }, + { + "input": "♣", + "description": "Named entity: clubs; with a semi-colon", + "output": [ + [ + "Character", + "\u2663" + ] + ] + }, + { + "input": "&clubsuit", + "description": "Bad named entity: clubsuit without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&clubsuit" + ] + ] + }, + { + "input": "♣", + "description": "Named entity: clubsuit; with a semi-colon", + "output": [ + [ + "Character", + "\u2663" + ] + ] + }, + { + "input": "&colon", + "description": "Bad named entity: colon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&colon" + ] + ] + }, + { + "input": ":", + "description": "Named entity: colon; with a semi-colon", + "output": [ + [ + "Character", + ":" + ] + ] + }, + { + "input": "&colone", + "description": "Bad named entity: colone without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&colone" + ] + ] + }, + { + "input": "≔", + "description": "Named entity: colone; with a semi-colon", + "output": [ + [ + "Character", + "\u2254" + ] + ] + }, + { + "input": "&coloneq", + "description": "Bad named entity: coloneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&coloneq" + ] + ] + }, + { + "input": "≔", + "description": "Named entity: coloneq; with a semi-colon", + "output": [ + [ + "Character", + "\u2254" + ] + ] + }, + { + "input": "&comma", + "description": "Bad named entity: comma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&comma" + ] + ] + }, + { + "input": ",", + "description": "Named entity: comma; with a semi-colon", + "output": [ + [ + "Character", + "," + ] + ] + }, + { + "input": "&commat", + "description": "Bad named entity: commat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&commat" + ] + ] + }, + { + "input": "@", + "description": "Named entity: commat; with a semi-colon", + "output": [ + [ + "Character", + "@" + ] + ] + }, + { + "input": "&comp", + "description": "Bad named entity: comp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&comp" + ] + ] + }, + { + "input": "∁", + "description": "Named entity: comp; with a semi-colon", + "output": [ + [ + "Character", + "\u2201" + ] + ] + }, + { + "input": "&compfn", + "description": "Bad named entity: compfn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&compfn" + ] + ] + }, + { + "input": "∘", + "description": "Named entity: compfn; with a semi-colon", + "output": [ + [ + "Character", + "\u2218" + ] + ] + }, + { + "input": "&complement", + "description": "Bad named entity: complement without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&complement" + ] + ] + }, + { + "input": "∁", + "description": "Named entity: complement; with a semi-colon", + "output": [ + [ + "Character", + "\u2201" + ] + ] + }, + { + "input": "&complexes", + "description": "Bad named entity: complexes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&complexes" + ] + ] + }, + { + "input": "ℂ", + "description": "Named entity: complexes; with a semi-colon", + "output": [ + [ + "Character", + "\u2102" + ] + ] + }, + { + "input": "&cong", + "description": "Bad named entity: cong without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cong" + ] + ] + }, + { + "input": "≅", + "description": "Named entity: cong; with a semi-colon", + "output": [ + [ + "Character", + "\u2245" + ] + ] + }, + { + "input": "&congdot", + "description": "Bad named entity: congdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&congdot" + ] + ] + }, + { + "input": "⩭", + "description": "Named entity: congdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a6d" + ] + ] + }, + { + "input": "&conint", + "description": "Bad named entity: conint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&conint" + ] + ] + }, + { + "input": "∮", + "description": "Named entity: conint; with a semi-colon", + "output": [ + [ + "Character", + "\u222e" + ] + ] + }, + { + "input": "&copf", + "description": "Bad named entity: copf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&copf" + ] + ] + }, + { + "input": "𝕔", + "description": "Named entity: copf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd54" + ] + ] + }, + { + "input": "&coprod", + "description": "Bad named entity: coprod without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&coprod" + ] + ] + }, + { + "input": "∐", + "description": "Named entity: coprod; with a semi-colon", + "output": [ + [ + "Character", + "\u2210" + ] + ] + }, + { + "input": "©", + "description": "Named entity: copy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a9" + ] + ] + }, + { + "input": "©", + "description": "Named entity: copy; with a semi-colon", + "output": [ + [ + "Character", + "\u00a9" + ] + ] + }, + { + "input": "℗", + "description": "Named entity: copysr; with a semi-colon", + "output": [ + [ + "Character", + "\u2117" + ] + ] + }, + { + "input": "&crarr", + "description": "Bad named entity: crarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&crarr" + ] + ] + }, + { + "input": "↵", + "description": "Named entity: crarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21b5" + ] + ] + }, + { + "input": "&cross", + "description": "Bad named entity: cross without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cross" + ] + ] + }, + { + "input": "✗", + "description": "Named entity: cross; with a semi-colon", + "output": [ + [ + "Character", + "\u2717" + ] + ] + }, + { + "input": "&cscr", + "description": "Bad named entity: cscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cscr" + ] + ] + }, + { + "input": "𝒸", + "description": "Named entity: cscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb8" + ] + ] + }, + { + "input": "&csub", + "description": "Bad named entity: csub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&csub" + ] + ] + }, + { + "input": "⫏", + "description": "Named entity: csub; with a semi-colon", + "output": [ + [ + "Character", + "\u2acf" + ] + ] + }, + { + "input": "&csube", + "description": "Bad named entity: csube without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&csube" + ] + ] + }, + { + "input": "⫑", + "description": "Named entity: csube; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad1" + ] + ] + }, + { + "input": "&csup", + "description": "Bad named entity: csup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&csup" + ] + ] + }, + { + "input": "⫐", + "description": "Named entity: csup; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad0" + ] + ] + }, + { + "input": "&csupe", + "description": "Bad named entity: csupe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&csupe" + ] + ] + }, + { + "input": "⫒", + "description": "Named entity: csupe; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad2" + ] + ] + }, + { + "input": "&ctdot", + "description": "Bad named entity: ctdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ctdot" + ] + ] + }, + { + "input": "⋯", + "description": "Named entity: ctdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22ef" + ] + ] + }, + { + "input": "&cudarrl", + "description": "Bad named entity: cudarrl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cudarrl" + ] + ] + }, + { + "input": "⤸", + "description": "Named entity: cudarrl; with a semi-colon", + "output": [ + [ + "Character", + "\u2938" + ] + ] + }, + { + "input": "&cudarrr", + "description": "Bad named entity: cudarrr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cudarrr" + ] + ] + }, + { + "input": "⤵", + "description": "Named entity: cudarrr; with a semi-colon", + "output": [ + [ + "Character", + "\u2935" + ] + ] + }, + { + "input": "&cuepr", + "description": "Bad named entity: cuepr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cuepr" + ] + ] + }, + { + "input": "⋞", + "description": "Named entity: cuepr; with a semi-colon", + "output": [ + [ + "Character", + "\u22de" + ] + ] + }, + { + "input": "&cuesc", + "description": "Bad named entity: cuesc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cuesc" + ] + ] + }, + { + "input": "⋟", + "description": "Named entity: cuesc; with a semi-colon", + "output": [ + [ + "Character", + "\u22df" + ] + ] + }, + { + "input": "&cularr", + "description": "Bad named entity: cularr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cularr" + ] + ] + }, + { + "input": "↶", + "description": "Named entity: cularr; with a semi-colon", + "output": [ + [ + "Character", + "\u21b6" + ] + ] + }, + { + "input": "&cularrp", + "description": "Bad named entity: cularrp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cularrp" + ] + ] + }, + { + "input": "⤽", + "description": "Named entity: cularrp; with a semi-colon", + "output": [ + [ + "Character", + "\u293d" + ] + ] + }, + { + "input": "&cup", + "description": "Bad named entity: cup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cup" + ] + ] + }, + { + "input": "∪", + "description": "Named entity: cup; with a semi-colon", + "output": [ + [ + "Character", + "\u222a" + ] + ] + }, + { + "input": "&cupbrcap", + "description": "Bad named entity: cupbrcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cupbrcap" + ] + ] + }, + { + "input": "⩈", + "description": "Named entity: cupbrcap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a48" + ] + ] + }, + { + "input": "&cupcap", + "description": "Bad named entity: cupcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cupcap" + ] + ] + }, + { + "input": "⩆", + "description": "Named entity: cupcap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a46" + ] + ] + }, + { + "input": "&cupcup", + "description": "Bad named entity: cupcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cupcup" + ] + ] + }, + { + "input": "⩊", + "description": "Named entity: cupcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a4a" + ] + ] + }, + { + "input": "&cupdot", + "description": "Bad named entity: cupdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cupdot" + ] + ] + }, + { + "input": "⊍", + "description": "Named entity: cupdot; with a semi-colon", + "output": [ + [ + "Character", + "\u228d" + ] + ] + }, + { + "input": "&cupor", + "description": "Bad named entity: cupor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cupor" + ] + ] + }, + { + "input": "⩅", + "description": "Named entity: cupor; with a semi-colon", + "output": [ + [ + "Character", + "\u2a45" + ] + ] + }, + { + "input": "&cups", + "description": "Bad named entity: cups without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cups" + ] + ] + }, + { + "input": "∪︀", + "description": "Named entity: cups; with a semi-colon", + "output": [ + [ + "Character", + "\u222a\ufe00" + ] + ] + }, + { + "input": "&curarr", + "description": "Bad named entity: curarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curarr" + ] + ] + }, + { + "input": "↷", + "description": "Named entity: curarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21b7" + ] + ] + }, + { + "input": "&curarrm", + "description": "Bad named entity: curarrm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curarrm" + ] + ] + }, + { + "input": "⤼", + "description": "Named entity: curarrm; with a semi-colon", + "output": [ + [ + "Character", + "\u293c" + ] + ] + }, + { + "input": "&curlyeqprec", + "description": "Bad named entity: curlyeqprec without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curlyeqprec" + ] + ] + }, + { + "input": "⋞", + "description": "Named entity: curlyeqprec; with a semi-colon", + "output": [ + [ + "Character", + "\u22de" + ] + ] + }, + { + "input": "&curlyeqsucc", + "description": "Bad named entity: curlyeqsucc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curlyeqsucc" + ] + ] + }, + { + "input": "⋟", + "description": "Named entity: curlyeqsucc; with a semi-colon", + "output": [ + [ + "Character", + "\u22df" + ] + ] + }, + { + "input": "&curlyvee", + "description": "Bad named entity: curlyvee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curlyvee" + ] + ] + }, + { + "input": "⋎", + "description": "Named entity: curlyvee; with a semi-colon", + "output": [ + [ + "Character", + "\u22ce" + ] + ] + }, + { + "input": "&curlywedge", + "description": "Bad named entity: curlywedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curlywedge" + ] + ] + }, + { + "input": "⋏", + "description": "Named entity: curlywedge; with a semi-colon", + "output": [ + [ + "Character", + "\u22cf" + ] + ] + }, + { + "input": "¤", + "description": "Named entity: curren without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a4" + ] + ] + }, + { + "input": "¤", + "description": "Named entity: curren; with a semi-colon", + "output": [ + [ + "Character", + "\u00a4" + ] + ] + }, + { + "input": "&curvearrowleft", + "description": "Bad named entity: curvearrowleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curvearrowleft" + ] + ] + }, + { + "input": "↶", + "description": "Named entity: curvearrowleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21b6" + ] + ] + }, + { + "input": "&curvearrowright", + "description": "Bad named entity: curvearrowright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&curvearrowright" + ] + ] + }, + { + "input": "↷", + "description": "Named entity: curvearrowright; with a semi-colon", + "output": [ + [ + "Character", + "\u21b7" + ] + ] + }, + { + "input": "&cuvee", + "description": "Bad named entity: cuvee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cuvee" + ] + ] + }, + { + "input": "⋎", + "description": "Named entity: cuvee; with a semi-colon", + "output": [ + [ + "Character", + "\u22ce" + ] + ] + }, + { + "input": "&cuwed", + "description": "Bad named entity: cuwed without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cuwed" + ] + ] + }, + { + "input": "⋏", + "description": "Named entity: cuwed; with a semi-colon", + "output": [ + [ + "Character", + "\u22cf" + ] + ] + }, + { + "input": "&cwconint", + "description": "Bad named entity: cwconint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cwconint" + ] + ] + }, + { + "input": "∲", + "description": "Named entity: cwconint; with a semi-colon", + "output": [ + [ + "Character", + "\u2232" + ] + ] + }, + { + "input": "&cwint", + "description": "Bad named entity: cwint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cwint" + ] + ] + }, + { + "input": "∱", + "description": "Named entity: cwint; with a semi-colon", + "output": [ + [ + "Character", + "\u2231" + ] + ] + }, + { + "input": "&cylcty", + "description": "Bad named entity: cylcty without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&cylcty" + ] + ] + }, + { + "input": "⌭", + "description": "Named entity: cylcty; with a semi-colon", + "output": [ + [ + "Character", + "\u232d" + ] + ] + }, + { + "input": "&dArr", + "description": "Bad named entity: dArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dArr" + ] + ] + }, + { + "input": "⇓", + "description": "Named entity: dArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d3" + ] + ] + }, + { + "input": "&dHar", + "description": "Bad named entity: dHar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dHar" + ] + ] + }, + { + "input": "⥥", + "description": "Named entity: dHar; with a semi-colon", + "output": [ + [ + "Character", + "\u2965" + ] + ] + }, + { + "input": "&dagger", + "description": "Bad named entity: dagger without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dagger" + ] + ] + }, + { + "input": "†", + "description": "Named entity: dagger; with a semi-colon", + "output": [ + [ + "Character", + "\u2020" + ] + ] + }, + { + "input": "&daleth", + "description": "Bad named entity: daleth without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&daleth" + ] + ] + }, + { + "input": "ℸ", + "description": "Named entity: daleth; with a semi-colon", + "output": [ + [ + "Character", + "\u2138" + ] + ] + }, + { + "input": "&darr", + "description": "Bad named entity: darr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&darr" + ] + ] + }, + { + "input": "↓", + "description": "Named entity: darr; with a semi-colon", + "output": [ + [ + "Character", + "\u2193" + ] + ] + }, + { + "input": "&dash", + "description": "Bad named entity: dash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dash" + ] + ] + }, + { + "input": "‐", + "description": "Named entity: dash; with a semi-colon", + "output": [ + [ + "Character", + "\u2010" + ] + ] + }, + { + "input": "&dashv", + "description": "Bad named entity: dashv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dashv" + ] + ] + }, + { + "input": "⊣", + "description": "Named entity: dashv; with a semi-colon", + "output": [ + [ + "Character", + "\u22a3" + ] + ] + }, + { + "input": "&dbkarow", + "description": "Bad named entity: dbkarow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dbkarow" + ] + ] + }, + { + "input": "⤏", + "description": "Named entity: dbkarow; with a semi-colon", + "output": [ + [ + "Character", + "\u290f" + ] + ] + }, + { + "input": "&dblac", + "description": "Bad named entity: dblac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dblac" + ] + ] + }, + { + "input": "˝", + "description": "Named entity: dblac; with a semi-colon", + "output": [ + [ + "Character", + "\u02dd" + ] + ] + }, + { + "input": "&dcaron", + "description": "Bad named entity: dcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dcaron" + ] + ] + }, + { + "input": "ď", + "description": "Named entity: dcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u010f" + ] + ] + }, + { + "input": "&dcy", + "description": "Bad named entity: dcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dcy" + ] + ] + }, + { + "input": "д", + "description": "Named entity: dcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0434" + ] + ] + }, + { + "input": "&dd", + "description": "Bad named entity: dd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dd" + ] + ] + }, + { + "input": "ⅆ", + "description": "Named entity: dd; with a semi-colon", + "output": [ + [ + "Character", + "\u2146" + ] + ] + }, + { + "input": "&ddagger", + "description": "Bad named entity: ddagger without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ddagger" + ] + ] + }, + { + "input": "‡", + "description": "Named entity: ddagger; with a semi-colon", + "output": [ + [ + "Character", + "\u2021" + ] + ] + }, + { + "input": "&ddarr", + "description": "Bad named entity: ddarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ddarr" + ] + ] + }, + { + "input": "⇊", + "description": "Named entity: ddarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21ca" + ] + ] + }, + { + "input": "&ddotseq", + "description": "Bad named entity: ddotseq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ddotseq" + ] + ] + }, + { + "input": "⩷", + "description": "Named entity: ddotseq; with a semi-colon", + "output": [ + [ + "Character", + "\u2a77" + ] + ] + }, + { + "input": "°", + "description": "Named entity: deg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b0" + ] + ] + }, + { + "input": "°", + "description": "Named entity: deg; with a semi-colon", + "output": [ + [ + "Character", + "\u00b0" + ] + ] + }, + { + "input": "&delta", + "description": "Bad named entity: delta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&delta" + ] + ] + }, + { + "input": "δ", + "description": "Named entity: delta; with a semi-colon", + "output": [ + [ + "Character", + "\u03b4" + ] + ] + }, + { + "input": "&demptyv", + "description": "Bad named entity: demptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&demptyv" + ] + ] + }, + { + "input": "⦱", + "description": "Named entity: demptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u29b1" + ] + ] + }, + { + "input": "&dfisht", + "description": "Bad named entity: dfisht without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dfisht" + ] + ] + }, + { + "input": "⥿", + "description": "Named entity: dfisht; with a semi-colon", + "output": [ + [ + "Character", + "\u297f" + ] + ] + }, + { + "input": "&dfr", + "description": "Bad named entity: dfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dfr" + ] + ] + }, + { + "input": "𝔡", + "description": "Named entity: dfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd21" + ] + ] + }, + { + "input": "&dharl", + "description": "Bad named entity: dharl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dharl" + ] + ] + }, + { + "input": "⇃", + "description": "Named entity: dharl; with a semi-colon", + "output": [ + [ + "Character", + "\u21c3" + ] + ] + }, + { + "input": "&dharr", + "description": "Bad named entity: dharr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dharr" + ] + ] + }, + { + "input": "⇂", + "description": "Named entity: dharr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c2" + ] + ] + }, + { + "input": "&diam", + "description": "Bad named entity: diam without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&diam" + ] + ] + }, + { + "input": "⋄", + "description": "Named entity: diam; with a semi-colon", + "output": [ + [ + "Character", + "\u22c4" + ] + ] + }, + { + "input": "&diamond", + "description": "Bad named entity: diamond without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&diamond" + ] + ] + }, + { + "input": "⋄", + "description": "Named entity: diamond; with a semi-colon", + "output": [ + [ + "Character", + "\u22c4" + ] + ] + }, + { + "input": "&diamondsuit", + "description": "Bad named entity: diamondsuit without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&diamondsuit" + ] + ] + }, + { + "input": "♦", + "description": "Named entity: diamondsuit; with a semi-colon", + "output": [ + [ + "Character", + "\u2666" + ] + ] + }, + { + "input": "&diams", + "description": "Bad named entity: diams without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&diams" + ] + ] + }, + { + "input": "♦", + "description": "Named entity: diams; with a semi-colon", + "output": [ + [ + "Character", + "\u2666" + ] + ] + }, + { + "input": "&die", + "description": "Bad named entity: die without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&die" + ] + ] + }, + { + "input": "¨", + "description": "Named entity: die; with a semi-colon", + "output": [ + [ + "Character", + "\u00a8" + ] + ] + }, + { + "input": "&digamma", + "description": "Bad named entity: digamma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&digamma" + ] + ] + }, + { + "input": "ϝ", + "description": "Named entity: digamma; with a semi-colon", + "output": [ + [ + "Character", + "\u03dd" + ] + ] + }, + { + "input": "&disin", + "description": "Bad named entity: disin without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&disin" + ] + ] + }, + { + "input": "⋲", + "description": "Named entity: disin; with a semi-colon", + "output": [ + [ + "Character", + "\u22f2" + ] + ] + }, + { + "input": "&div", + "description": "Bad named entity: div without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&div" + ] + ] + }, + { + "input": "÷", + "description": "Named entity: div; with a semi-colon", + "output": [ + [ + "Character", + "\u00f7" + ] + ] + }, + { + "input": "÷", + "description": "Named entity: divide without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f7" + ] + ] + }, + { + "input": "÷", + "description": "Named entity: divide; with a semi-colon", + "output": [ + [ + "Character", + "\u00f7" + ] + ] + }, + { + "input": "⋇", + "description": "Named entity: divideontimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22c7" + ] + ] + }, + { + "input": "&divonx", + "description": "Bad named entity: divonx without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&divonx" + ] + ] + }, + { + "input": "⋇", + "description": "Named entity: divonx; with a semi-colon", + "output": [ + [ + "Character", + "\u22c7" + ] + ] + }, + { + "input": "&djcy", + "description": "Bad named entity: djcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&djcy" + ] + ] + }, + { + "input": "ђ", + "description": "Named entity: djcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0452" + ] + ] + }, + { + "input": "&dlcorn", + "description": "Bad named entity: dlcorn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dlcorn" + ] + ] + }, + { + "input": "⌞", + "description": "Named entity: dlcorn; with a semi-colon", + "output": [ + [ + "Character", + "\u231e" + ] + ] + }, + { + "input": "&dlcrop", + "description": "Bad named entity: dlcrop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dlcrop" + ] + ] + }, + { + "input": "⌍", + "description": "Named entity: dlcrop; with a semi-colon", + "output": [ + [ + "Character", + "\u230d" + ] + ] + }, + { + "input": "&dollar", + "description": "Bad named entity: dollar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dollar" + ] + ] + }, + { + "input": "$", + "description": "Named entity: dollar; with a semi-colon", + "output": [ + [ + "Character", + "$" + ] + ] + }, + { + "input": "&dopf", + "description": "Bad named entity: dopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dopf" + ] + ] + }, + { + "input": "𝕕", + "description": "Named entity: dopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd55" + ] + ] + }, + { + "input": "&dot", + "description": "Bad named entity: dot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dot" + ] + ] + }, + { + "input": "˙", + "description": "Named entity: dot; with a semi-colon", + "output": [ + [ + "Character", + "\u02d9" + ] + ] + }, + { + "input": "&doteq", + "description": "Bad named entity: doteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&doteq" + ] + ] + }, + { + "input": "≐", + "description": "Named entity: doteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2250" + ] + ] + }, + { + "input": "&doteqdot", + "description": "Bad named entity: doteqdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&doteqdot" + ] + ] + }, + { + "input": "≑", + "description": "Named entity: doteqdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2251" + ] + ] + }, + { + "input": "&dotminus", + "description": "Bad named entity: dotminus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dotminus" + ] + ] + }, + { + "input": "∸", + "description": "Named entity: dotminus; with a semi-colon", + "output": [ + [ + "Character", + "\u2238" + ] + ] + }, + { + "input": "&dotplus", + "description": "Bad named entity: dotplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dotplus" + ] + ] + }, + { + "input": "∔", + "description": "Named entity: dotplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2214" + ] + ] + }, + { + "input": "&dotsquare", + "description": "Bad named entity: dotsquare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dotsquare" + ] + ] + }, + { + "input": "⊡", + "description": "Named entity: dotsquare; with a semi-colon", + "output": [ + [ + "Character", + "\u22a1" + ] + ] + }, + { + "input": "&doublebarwedge", + "description": "Bad named entity: doublebarwedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&doublebarwedge" + ] + ] + }, + { + "input": "⌆", + "description": "Named entity: doublebarwedge; with a semi-colon", + "output": [ + [ + "Character", + "\u2306" + ] + ] + }, + { + "input": "&downarrow", + "description": "Bad named entity: downarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&downarrow" + ] + ] + }, + { + "input": "↓", + "description": "Named entity: downarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2193" + ] + ] + }, + { + "input": "&downdownarrows", + "description": "Bad named entity: downdownarrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&downdownarrows" + ] + ] + }, + { + "input": "⇊", + "description": "Named entity: downdownarrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21ca" + ] + ] + }, + { + "input": "&downharpoonleft", + "description": "Bad named entity: downharpoonleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&downharpoonleft" + ] + ] + }, + { + "input": "⇃", + "description": "Named entity: downharpoonleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21c3" + ] + ] + }, + { + "input": "&downharpoonright", + "description": "Bad named entity: downharpoonright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&downharpoonright" + ] + ] + }, + { + "input": "⇂", + "description": "Named entity: downharpoonright; with a semi-colon", + "output": [ + [ + "Character", + "\u21c2" + ] + ] + }, + { + "input": "&drbkarow", + "description": "Bad named entity: drbkarow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&drbkarow" + ] + ] + }, + { + "input": "⤐", + "description": "Named entity: drbkarow; with a semi-colon", + "output": [ + [ + "Character", + "\u2910" + ] + ] + }, + { + "input": "&drcorn", + "description": "Bad named entity: drcorn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&drcorn" + ] + ] + }, + { + "input": "⌟", + "description": "Named entity: drcorn; with a semi-colon", + "output": [ + [ + "Character", + "\u231f" + ] + ] + }, + { + "input": "&drcrop", + "description": "Bad named entity: drcrop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&drcrop" + ] + ] + }, + { + "input": "⌌", + "description": "Named entity: drcrop; with a semi-colon", + "output": [ + [ + "Character", + "\u230c" + ] + ] + }, + { + "input": "&dscr", + "description": "Bad named entity: dscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dscr" + ] + ] + }, + { + "input": "𝒹", + "description": "Named entity: dscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcb9" + ] + ] + }, + { + "input": "&dscy", + "description": "Bad named entity: dscy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dscy" + ] + ] + }, + { + "input": "ѕ", + "description": "Named entity: dscy; with a semi-colon", + "output": [ + [ + "Character", + "\u0455" + ] + ] + }, + { + "input": "&dsol", + "description": "Bad named entity: dsol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dsol" + ] + ] + }, + { + "input": "⧶", + "description": "Named entity: dsol; with a semi-colon", + "output": [ + [ + "Character", + "\u29f6" + ] + ] + }, + { + "input": "&dstrok", + "description": "Bad named entity: dstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dstrok" + ] + ] + }, + { + "input": "đ", + "description": "Named entity: dstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0111" + ] + ] + }, + { + "input": "&dtdot", + "description": "Bad named entity: dtdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dtdot" + ] + ] + }, + { + "input": "⋱", + "description": "Named entity: dtdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22f1" + ] + ] + }, + { + "input": "&dtri", + "description": "Bad named entity: dtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dtri" + ] + ] + }, + { + "input": "▿", + "description": "Named entity: dtri; with a semi-colon", + "output": [ + [ + "Character", + "\u25bf" + ] + ] + }, + { + "input": "&dtrif", + "description": "Bad named entity: dtrif without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dtrif" + ] + ] + }, + { + "input": "▾", + "description": "Named entity: dtrif; with a semi-colon", + "output": [ + [ + "Character", + "\u25be" + ] + ] + }, + { + "input": "&duarr", + "description": "Bad named entity: duarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&duarr" + ] + ] + }, + { + "input": "⇵", + "description": "Named entity: duarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21f5" + ] + ] + }, + { + "input": "&duhar", + "description": "Bad named entity: duhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&duhar" + ] + ] + }, + { + "input": "⥯", + "description": "Named entity: duhar; with a semi-colon", + "output": [ + [ + "Character", + "\u296f" + ] + ] + }, + { + "input": "&dwangle", + "description": "Bad named entity: dwangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dwangle" + ] + ] + }, + { + "input": "⦦", + "description": "Named entity: dwangle; with a semi-colon", + "output": [ + [ + "Character", + "\u29a6" + ] + ] + }, + { + "input": "&dzcy", + "description": "Bad named entity: dzcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dzcy" + ] + ] + }, + { + "input": "џ", + "description": "Named entity: dzcy; with a semi-colon", + "output": [ + [ + "Character", + "\u045f" + ] + ] + }, + { + "input": "&dzigrarr", + "description": "Bad named entity: dzigrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&dzigrarr" + ] + ] + }, + { + "input": "⟿", + "description": "Named entity: dzigrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u27ff" + ] + ] + }, + { + "input": "&eDDot", + "description": "Bad named entity: eDDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eDDot" + ] + ] + }, + { + "input": "⩷", + "description": "Named entity: eDDot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a77" + ] + ] + }, + { + "input": "&eDot", + "description": "Bad named entity: eDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eDot" + ] + ] + }, + { + "input": "≑", + "description": "Named entity: eDot; with a semi-colon", + "output": [ + [ + "Character", + "\u2251" + ] + ] + }, + { + "input": "é", + "description": "Named entity: eacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e9" + ] + ] + }, + { + "input": "é", + "description": "Named entity: eacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00e9" + ] + ] + }, + { + "input": "&easter", + "description": "Bad named entity: easter without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&easter" + ] + ] + }, + { + "input": "⩮", + "description": "Named entity: easter; with a semi-colon", + "output": [ + [ + "Character", + "\u2a6e" + ] + ] + }, + { + "input": "&ecaron", + "description": "Bad named entity: ecaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ecaron" + ] + ] + }, + { + "input": "ě", + "description": "Named entity: ecaron; with a semi-colon", + "output": [ + [ + "Character", + "\u011b" + ] + ] + }, + { + "input": "&ecir", + "description": "Bad named entity: ecir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ecir" + ] + ] + }, + { + "input": "≖", + "description": "Named entity: ecir; with a semi-colon", + "output": [ + [ + "Character", + "\u2256" + ] + ] + }, + { + "input": "ê", + "description": "Named entity: ecirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ea" + ] + ] + }, + { + "input": "ê", + "description": "Named entity: ecirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00ea" + ] + ] + }, + { + "input": "&ecolon", + "description": "Bad named entity: ecolon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ecolon" + ] + ] + }, + { + "input": "≕", + "description": "Named entity: ecolon; with a semi-colon", + "output": [ + [ + "Character", + "\u2255" + ] + ] + }, + { + "input": "&ecy", + "description": "Bad named entity: ecy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ecy" + ] + ] + }, + { + "input": "э", + "description": "Named entity: ecy; with a semi-colon", + "output": [ + [ + "Character", + "\u044d" + ] + ] + }, + { + "input": "&edot", + "description": "Bad named entity: edot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&edot" + ] + ] + }, + { + "input": "ė", + "description": "Named entity: edot; with a semi-colon", + "output": [ + [ + "Character", + "\u0117" + ] + ] + }, + { + "input": "&ee", + "description": "Bad named entity: ee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ee" + ] + ] + }, + { + "input": "ⅇ", + "description": "Named entity: ee; with a semi-colon", + "output": [ + [ + "Character", + "\u2147" + ] + ] + }, + { + "input": "&efDot", + "description": "Bad named entity: efDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&efDot" + ] + ] + }, + { + "input": "≒", + "description": "Named entity: efDot; with a semi-colon", + "output": [ + [ + "Character", + "\u2252" + ] + ] + }, + { + "input": "&efr", + "description": "Bad named entity: efr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&efr" + ] + ] + }, + { + "input": "𝔢", + "description": "Named entity: efr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd22" + ] + ] + }, + { + "input": "&eg", + "description": "Bad named entity: eg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eg" + ] + ] + }, + { + "input": "⪚", + "description": "Named entity: eg; with a semi-colon", + "output": [ + [ + "Character", + "\u2a9a" + ] + ] + }, + { + "input": "è", + "description": "Named entity: egrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00e8" + ] + ] + }, + { + "input": "è", + "description": "Named entity: egrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00e8" + ] + ] + }, + { + "input": "&egs", + "description": "Bad named entity: egs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&egs" + ] + ] + }, + { + "input": "⪖", + "description": "Named entity: egs; with a semi-colon", + "output": [ + [ + "Character", + "\u2a96" + ] + ] + }, + { + "input": "&egsdot", + "description": "Bad named entity: egsdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&egsdot" + ] + ] + }, + { + "input": "⪘", + "description": "Named entity: egsdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a98" + ] + ] + }, + { + "input": "&el", + "description": "Bad named entity: el without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&el" + ] + ] + }, + { + "input": "⪙", + "description": "Named entity: el; with a semi-colon", + "output": [ + [ + "Character", + "\u2a99" + ] + ] + }, + { + "input": "&elinters", + "description": "Bad named entity: elinters without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&elinters" + ] + ] + }, + { + "input": "⏧", + "description": "Named entity: elinters; with a semi-colon", + "output": [ + [ + "Character", + "\u23e7" + ] + ] + }, + { + "input": "&ell", + "description": "Bad named entity: ell without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ell" + ] + ] + }, + { + "input": "ℓ", + "description": "Named entity: ell; with a semi-colon", + "output": [ + [ + "Character", + "\u2113" + ] + ] + }, + { + "input": "&els", + "description": "Bad named entity: els without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&els" + ] + ] + }, + { + "input": "⪕", + "description": "Named entity: els; with a semi-colon", + "output": [ + [ + "Character", + "\u2a95" + ] + ] + }, + { + "input": "&elsdot", + "description": "Bad named entity: elsdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&elsdot" + ] + ] + }, + { + "input": "⪗", + "description": "Named entity: elsdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a97" + ] + ] + }, + { + "input": "&emacr", + "description": "Bad named entity: emacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emacr" + ] + ] + }, + { + "input": "ē", + "description": "Named entity: emacr; with a semi-colon", + "output": [ + [ + "Character", + "\u0113" + ] + ] + }, + { + "input": "&empty", + "description": "Bad named entity: empty without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&empty" + ] + ] + }, + { + "input": "∅", + "description": "Named entity: empty; with a semi-colon", + "output": [ + [ + "Character", + "\u2205" + ] + ] + }, + { + "input": "&emptyset", + "description": "Bad named entity: emptyset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emptyset" + ] + ] + }, + { + "input": "∅", + "description": "Named entity: emptyset; with a semi-colon", + "output": [ + [ + "Character", + "\u2205" + ] + ] + }, + { + "input": "&emptyv", + "description": "Bad named entity: emptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emptyv" + ] + ] + }, + { + "input": "∅", + "description": "Named entity: emptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u2205" + ] + ] + }, + { + "input": "&emsp", + "description": "Bad named entity: emsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emsp" + ] + ] + }, + { + "input": "&emsp13", + "description": "Bad named entity: emsp13 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emsp13" + ] + ] + }, + { + "input": " ", + "description": "Named entity: emsp13; with a semi-colon", + "output": [ + [ + "Character", + "\u2004" + ] + ] + }, + { + "input": "&emsp14", + "description": "Bad named entity: emsp14 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&emsp14" + ] + ] + }, + { + "input": " ", + "description": "Named entity: emsp14; with a semi-colon", + "output": [ + [ + "Character", + "\u2005" + ] + ] + }, + { + "input": " ", + "description": "Named entity: emsp; with a semi-colon", + "output": [ + [ + "Character", + "\u2003" + ] + ] + }, + { + "input": "&eng", + "description": "Bad named entity: eng without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eng" + ] + ] + }, + { + "input": "ŋ", + "description": "Named entity: eng; with a semi-colon", + "output": [ + [ + "Character", + "\u014b" + ] + ] + }, + { + "input": "&ensp", + "description": "Bad named entity: ensp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ensp" + ] + ] + }, + { + "input": " ", + "description": "Named entity: ensp; with a semi-colon", + "output": [ + [ + "Character", + "\u2002" + ] + ] + }, + { + "input": "&eogon", + "description": "Bad named entity: eogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eogon" + ] + ] + }, + { + "input": "ę", + "description": "Named entity: eogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0119" + ] + ] + }, + { + "input": "&eopf", + "description": "Bad named entity: eopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eopf" + ] + ] + }, + { + "input": "𝕖", + "description": "Named entity: eopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd56" + ] + ] + }, + { + "input": "&epar", + "description": "Bad named entity: epar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&epar" + ] + ] + }, + { + "input": "⋕", + "description": "Named entity: epar; with a semi-colon", + "output": [ + [ + "Character", + "\u22d5" + ] + ] + }, + { + "input": "&eparsl", + "description": "Bad named entity: eparsl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eparsl" + ] + ] + }, + { + "input": "⧣", + "description": "Named entity: eparsl; with a semi-colon", + "output": [ + [ + "Character", + "\u29e3" + ] + ] + }, + { + "input": "&eplus", + "description": "Bad named entity: eplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eplus" + ] + ] + }, + { + "input": "⩱", + "description": "Named entity: eplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a71" + ] + ] + }, + { + "input": "&epsi", + "description": "Bad named entity: epsi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&epsi" + ] + ] + }, + { + "input": "ε", + "description": "Named entity: epsi; with a semi-colon", + "output": [ + [ + "Character", + "\u03b5" + ] + ] + }, + { + "input": "&epsilon", + "description": "Bad named entity: epsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&epsilon" + ] + ] + }, + { + "input": "ε", + "description": "Named entity: epsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03b5" + ] + ] + }, + { + "input": "&epsiv", + "description": "Bad named entity: epsiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&epsiv" + ] + ] + }, + { + "input": "ϵ", + "description": "Named entity: epsiv; with a semi-colon", + "output": [ + [ + "Character", + "\u03f5" + ] + ] + }, + { + "input": "&eqcirc", + "description": "Bad named entity: eqcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqcirc" + ] + ] + }, + { + "input": "≖", + "description": "Named entity: eqcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u2256" + ] + ] + }, + { + "input": "&eqcolon", + "description": "Bad named entity: eqcolon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqcolon" + ] + ] + }, + { + "input": "≕", + "description": "Named entity: eqcolon; with a semi-colon", + "output": [ + [ + "Character", + "\u2255" + ] + ] + }, + { + "input": "&eqsim", + "description": "Bad named entity: eqsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqsim" + ] + ] + }, + { + "input": "≂", + "description": "Named entity: eqsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2242" + ] + ] + }, + { + "input": "&eqslantgtr", + "description": "Bad named entity: eqslantgtr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqslantgtr" + ] + ] + }, + { + "input": "⪖", + "description": "Named entity: eqslantgtr; with a semi-colon", + "output": [ + [ + "Character", + "\u2a96" + ] + ] + }, + { + "input": "&eqslantless", + "description": "Bad named entity: eqslantless without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqslantless" + ] + ] + }, + { + "input": "⪕", + "description": "Named entity: eqslantless; with a semi-colon", + "output": [ + [ + "Character", + "\u2a95" + ] + ] + }, + { + "input": "&equals", + "description": "Bad named entity: equals without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&equals" + ] + ] + }, + { + "input": "=", + "description": "Named entity: equals; with a semi-colon", + "output": [ + [ + "Character", + "=" + ] + ] + }, + { + "input": "&equest", + "description": "Bad named entity: equest without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&equest" + ] + ] + }, + { + "input": "≟", + "description": "Named entity: equest; with a semi-colon", + "output": [ + [ + "Character", + "\u225f" + ] + ] + }, + { + "input": "&equiv", + "description": "Bad named entity: equiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&equiv" + ] + ] + }, + { + "input": "≡", + "description": "Named entity: equiv; with a semi-colon", + "output": [ + [ + "Character", + "\u2261" + ] + ] + }, + { + "input": "&equivDD", + "description": "Bad named entity: equivDD without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&equivDD" + ] + ] + }, + { + "input": "⩸", + "description": "Named entity: equivDD; with a semi-colon", + "output": [ + [ + "Character", + "\u2a78" + ] + ] + }, + { + "input": "&eqvparsl", + "description": "Bad named entity: eqvparsl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eqvparsl" + ] + ] + }, + { + "input": "⧥", + "description": "Named entity: eqvparsl; with a semi-colon", + "output": [ + [ + "Character", + "\u29e5" + ] + ] + }, + { + "input": "&erDot", + "description": "Bad named entity: erDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&erDot" + ] + ] + }, + { + "input": "≓", + "description": "Named entity: erDot; with a semi-colon", + "output": [ + [ + "Character", + "\u2253" + ] + ] + }, + { + "input": "&erarr", + "description": "Bad named entity: erarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&erarr" + ] + ] + }, + { + "input": "⥱", + "description": "Named entity: erarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2971" + ] + ] + }, + { + "input": "&escr", + "description": "Bad named entity: escr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&escr" + ] + ] + }, + { + "input": "ℯ", + "description": "Named entity: escr; with a semi-colon", + "output": [ + [ + "Character", + "\u212f" + ] + ] + }, + { + "input": "&esdot", + "description": "Bad named entity: esdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&esdot" + ] + ] + }, + { + "input": "≐", + "description": "Named entity: esdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2250" + ] + ] + }, + { + "input": "&esim", + "description": "Bad named entity: esim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&esim" + ] + ] + }, + { + "input": "≂", + "description": "Named entity: esim; with a semi-colon", + "output": [ + [ + "Character", + "\u2242" + ] + ] + }, + { + "input": "&eta", + "description": "Bad named entity: eta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&eta" + ] + ] + }, + { + "input": "η", + "description": "Named entity: eta; with a semi-colon", + "output": [ + [ + "Character", + "\u03b7" + ] + ] + }, + { + "input": "ð", + "description": "Named entity: eth without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f0" + ] + ] + }, + { + "input": "ð", + "description": "Named entity: eth; with a semi-colon", + "output": [ + [ + "Character", + "\u00f0" + ] + ] + }, + { + "input": "ë", + "description": "Named entity: euml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00eb" + ] + ] + }, + { + "input": "ë", + "description": "Named entity: euml; with a semi-colon", + "output": [ + [ + "Character", + "\u00eb" + ] + ] + }, + { + "input": "&euro", + "description": "Bad named entity: euro without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&euro" + ] + ] + }, + { + "input": "€", + "description": "Named entity: euro; with a semi-colon", + "output": [ + [ + "Character", + "\u20ac" + ] + ] + }, + { + "input": "&excl", + "description": "Bad named entity: excl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&excl" + ] + ] + }, + { + "input": "!", + "description": "Named entity: excl; with a semi-colon", + "output": [ + [ + "Character", + "!" + ] + ] + }, + { + "input": "&exist", + "description": "Bad named entity: exist without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&exist" + ] + ] + }, + { + "input": "∃", + "description": "Named entity: exist; with a semi-colon", + "output": [ + [ + "Character", + "\u2203" + ] + ] + }, + { + "input": "&expectation", + "description": "Bad named entity: expectation without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&expectation" + ] + ] + }, + { + "input": "ℰ", + "description": "Named entity: expectation; with a semi-colon", + "output": [ + [ + "Character", + "\u2130" + ] + ] + }, + { + "input": "&exponentiale", + "description": "Bad named entity: exponentiale without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&exponentiale" + ] + ] + }, + { + "input": "ⅇ", + "description": "Named entity: exponentiale; with a semi-colon", + "output": [ + [ + "Character", + "\u2147" + ] + ] + }, + { + "input": "&fallingdotseq", + "description": "Bad named entity: fallingdotseq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fallingdotseq" + ] + ] + }, + { + "input": "≒", + "description": "Named entity: fallingdotseq; with a semi-colon", + "output": [ + [ + "Character", + "\u2252" + ] + ] + }, + { + "input": "&fcy", + "description": "Bad named entity: fcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fcy" + ] + ] + }, + { + "input": "ф", + "description": "Named entity: fcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0444" + ] + ] + }, + { + "input": "&female", + "description": "Bad named entity: female without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&female" + ] + ] + }, + { + "input": "♀", + "description": "Named entity: female; with a semi-colon", + "output": [ + [ + "Character", + "\u2640" + ] + ] + }, + { + "input": "&ffilig", + "description": "Bad named entity: ffilig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ffilig" + ] + ] + }, + { + "input": "ffi", + "description": "Named entity: ffilig; with a semi-colon", + "output": [ + [ + "Character", + "\ufb03" + ] + ] + }, + { + "input": "&fflig", + "description": "Bad named entity: fflig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fflig" + ] + ] + }, + { + "input": "ff", + "description": "Named entity: fflig; with a semi-colon", + "output": [ + [ + "Character", + "\ufb00" + ] + ] + }, + { + "input": "&ffllig", + "description": "Bad named entity: ffllig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ffllig" + ] + ] + }, + { + "input": "ffl", + "description": "Named entity: ffllig; with a semi-colon", + "output": [ + [ + "Character", + "\ufb04" + ] + ] + }, + { + "input": "&ffr", + "description": "Bad named entity: ffr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ffr" + ] + ] + }, + { + "input": "𝔣", + "description": "Named entity: ffr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd23" + ] + ] + }, + { + "input": "&filig", + "description": "Bad named entity: filig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&filig" + ] + ] + }, + { + "input": "fi", + "description": "Named entity: filig; with a semi-colon", + "output": [ + [ + "Character", + "\ufb01" + ] + ] + }, + { + "input": "&fjlig", + "description": "Bad named entity: fjlig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fjlig" + ] + ] + }, + { + "input": "fj", + "description": "Named entity: fjlig; with a semi-colon", + "output": [ + [ + "Character", + "fj" + ] + ] + }, + { + "input": "&flat", + "description": "Bad named entity: flat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&flat" + ] + ] + }, + { + "input": "♭", + "description": "Named entity: flat; with a semi-colon", + "output": [ + [ + "Character", + "\u266d" + ] + ] + }, + { + "input": "&fllig", + "description": "Bad named entity: fllig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fllig" + ] + ] + }, + { + "input": "fl", + "description": "Named entity: fllig; with a semi-colon", + "output": [ + [ + "Character", + "\ufb02" + ] + ] + }, + { + "input": "&fltns", + "description": "Bad named entity: fltns without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fltns" + ] + ] + }, + { + "input": "▱", + "description": "Named entity: fltns; with a semi-colon", + "output": [ + [ + "Character", + "\u25b1" + ] + ] + }, + { + "input": "&fnof", + "description": "Bad named entity: fnof without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fnof" + ] + ] + }, + { + "input": "ƒ", + "description": "Named entity: fnof; with a semi-colon", + "output": [ + [ + "Character", + "\u0192" + ] + ] + }, + { + "input": "&fopf", + "description": "Bad named entity: fopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fopf" + ] + ] + }, + { + "input": "𝕗", + "description": "Named entity: fopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd57" + ] + ] + }, + { + "input": "&forall", + "description": "Bad named entity: forall without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&forall" + ] + ] + }, + { + "input": "∀", + "description": "Named entity: forall; with a semi-colon", + "output": [ + [ + "Character", + "\u2200" + ] + ] + }, + { + "input": "&fork", + "description": "Bad named entity: fork without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fork" + ] + ] + }, + { + "input": "⋔", + "description": "Named entity: fork; with a semi-colon", + "output": [ + [ + "Character", + "\u22d4" + ] + ] + }, + { + "input": "&forkv", + "description": "Bad named entity: forkv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&forkv" + ] + ] + }, + { + "input": "⫙", + "description": "Named entity: forkv; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad9" + ] + ] + }, + { + "input": "&fpartint", + "description": "Bad named entity: fpartint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fpartint" + ] + ] + }, + { + "input": "⨍", + "description": "Named entity: fpartint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a0d" + ] + ] + }, + { + "input": "½", + "description": "Named entity: frac12 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00bd" + ] + ] + }, + { + "input": "½", + "description": "Named entity: frac12; with a semi-colon", + "output": [ + [ + "Character", + "\u00bd" + ] + ] + }, + { + "input": "&frac13", + "description": "Bad named entity: frac13 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac13" + ] + ] + }, + { + "input": "⅓", + "description": "Named entity: frac13; with a semi-colon", + "output": [ + [ + "Character", + "\u2153" + ] + ] + }, + { + "input": "¼", + "description": "Named entity: frac14 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00bc" + ] + ] + }, + { + "input": "¼", + "description": "Named entity: frac14; with a semi-colon", + "output": [ + [ + "Character", + "\u00bc" + ] + ] + }, + { + "input": "&frac15", + "description": "Bad named entity: frac15 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac15" + ] + ] + }, + { + "input": "⅕", + "description": "Named entity: frac15; with a semi-colon", + "output": [ + [ + "Character", + "\u2155" + ] + ] + }, + { + "input": "&frac16", + "description": "Bad named entity: frac16 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac16" + ] + ] + }, + { + "input": "⅙", + "description": "Named entity: frac16; with a semi-colon", + "output": [ + [ + "Character", + "\u2159" + ] + ] + }, + { + "input": "&frac18", + "description": "Bad named entity: frac18 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac18" + ] + ] + }, + { + "input": "⅛", + "description": "Named entity: frac18; with a semi-colon", + "output": [ + [ + "Character", + "\u215b" + ] + ] + }, + { + "input": "&frac23", + "description": "Bad named entity: frac23 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac23" + ] + ] + }, + { + "input": "⅔", + "description": "Named entity: frac23; with a semi-colon", + "output": [ + [ + "Character", + "\u2154" + ] + ] + }, + { + "input": "&frac25", + "description": "Bad named entity: frac25 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac25" + ] + ] + }, + { + "input": "⅖", + "description": "Named entity: frac25; with a semi-colon", + "output": [ + [ + "Character", + "\u2156" + ] + ] + }, + { + "input": "¾", + "description": "Named entity: frac34 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00be" + ] + ] + }, + { + "input": "¾", + "description": "Named entity: frac34; with a semi-colon", + "output": [ + [ + "Character", + "\u00be" + ] + ] + }, + { + "input": "&frac35", + "description": "Bad named entity: frac35 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac35" + ] + ] + }, + { + "input": "⅗", + "description": "Named entity: frac35; with a semi-colon", + "output": [ + [ + "Character", + "\u2157" + ] + ] + }, + { + "input": "&frac38", + "description": "Bad named entity: frac38 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac38" + ] + ] + }, + { + "input": "⅜", + "description": "Named entity: frac38; with a semi-colon", + "output": [ + [ + "Character", + "\u215c" + ] + ] + }, + { + "input": "&frac45", + "description": "Bad named entity: frac45 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac45" + ] + ] + }, + { + "input": "⅘", + "description": "Named entity: frac45; with a semi-colon", + "output": [ + [ + "Character", + "\u2158" + ] + ] + }, + { + "input": "&frac56", + "description": "Bad named entity: frac56 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac56" + ] + ] + }, + { + "input": "⅚", + "description": "Named entity: frac56; with a semi-colon", + "output": [ + [ + "Character", + "\u215a" + ] + ] + }, + { + "input": "&frac58", + "description": "Bad named entity: frac58 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac58" + ] + ] + }, + { + "input": "⅝", + "description": "Named entity: frac58; with a semi-colon", + "output": [ + [ + "Character", + "\u215d" + ] + ] + }, + { + "input": "&frac78", + "description": "Bad named entity: frac78 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frac78" + ] + ] + }, + { + "input": "⅞", + "description": "Named entity: frac78; with a semi-colon", + "output": [ + [ + "Character", + "\u215e" + ] + ] + }, + { + "input": "&frasl", + "description": "Bad named entity: frasl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frasl" + ] + ] + }, + { + "input": "⁄", + "description": "Named entity: frasl; with a semi-colon", + "output": [ + [ + "Character", + "\u2044" + ] + ] + }, + { + "input": "&frown", + "description": "Bad named entity: frown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&frown" + ] + ] + }, + { + "input": "⌢", + "description": "Named entity: frown; with a semi-colon", + "output": [ + [ + "Character", + "\u2322" + ] + ] + }, + { + "input": "&fscr", + "description": "Bad named entity: fscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&fscr" + ] + ] + }, + { + "input": "𝒻", + "description": "Named entity: fscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcbb" + ] + ] + }, + { + "input": "&gE", + "description": "Bad named entity: gE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gE" + ] + ] + }, + { + "input": "≧", + "description": "Named entity: gE; with a semi-colon", + "output": [ + [ + "Character", + "\u2267" + ] + ] + }, + { + "input": "&gEl", + "description": "Bad named entity: gEl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gEl" + ] + ] + }, + { + "input": "⪌", + "description": "Named entity: gEl; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8c" + ] + ] + }, + { + "input": "&gacute", + "description": "Bad named entity: gacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gacute" + ] + ] + }, + { + "input": "ǵ", + "description": "Named entity: gacute; with a semi-colon", + "output": [ + [ + "Character", + "\u01f5" + ] + ] + }, + { + "input": "&gamma", + "description": "Bad named entity: gamma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gamma" + ] + ] + }, + { + "input": "γ", + "description": "Named entity: gamma; with a semi-colon", + "output": [ + [ + "Character", + "\u03b3" + ] + ] + }, + { + "input": "&gammad", + "description": "Bad named entity: gammad without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gammad" + ] + ] + }, + { + "input": "ϝ", + "description": "Named entity: gammad; with a semi-colon", + "output": [ + [ + "Character", + "\u03dd" + ] + ] + }, + { + "input": "&gap", + "description": "Bad named entity: gap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gap" + ] + ] + }, + { + "input": "⪆", + "description": "Named entity: gap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a86" + ] + ] + }, + { + "input": "&gbreve", + "description": "Bad named entity: gbreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gbreve" + ] + ] + }, + { + "input": "ğ", + "description": "Named entity: gbreve; with a semi-colon", + "output": [ + [ + "Character", + "\u011f" + ] + ] + }, + { + "input": "&gcirc", + "description": "Bad named entity: gcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gcirc" + ] + ] + }, + { + "input": "ĝ", + "description": "Named entity: gcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u011d" + ] + ] + }, + { + "input": "&gcy", + "description": "Bad named entity: gcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gcy" + ] + ] + }, + { + "input": "г", + "description": "Named entity: gcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0433" + ] + ] + }, + { + "input": "&gdot", + "description": "Bad named entity: gdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gdot" + ] + ] + }, + { + "input": "ġ", + "description": "Named entity: gdot; with a semi-colon", + "output": [ + [ + "Character", + "\u0121" + ] + ] + }, + { + "input": "&ge", + "description": "Bad named entity: ge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ge" + ] + ] + }, + { + "input": "≥", + "description": "Named entity: ge; with a semi-colon", + "output": [ + [ + "Character", + "\u2265" + ] + ] + }, + { + "input": "&gel", + "description": "Bad named entity: gel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gel" + ] + ] + }, + { + "input": "⋛", + "description": "Named entity: gel; with a semi-colon", + "output": [ + [ + "Character", + "\u22db" + ] + ] + }, + { + "input": "&geq", + "description": "Bad named entity: geq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&geq" + ] + ] + }, + { + "input": "≥", + "description": "Named entity: geq; with a semi-colon", + "output": [ + [ + "Character", + "\u2265" + ] + ] + }, + { + "input": "&geqq", + "description": "Bad named entity: geqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&geqq" + ] + ] + }, + { + "input": "≧", + "description": "Named entity: geqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2267" + ] + ] + }, + { + "input": "&geqslant", + "description": "Bad named entity: geqslant without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&geqslant" + ] + ] + }, + { + "input": "⩾", + "description": "Named entity: geqslant; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e" + ] + ] + }, + { + "input": "&ges", + "description": "Bad named entity: ges without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ges" + ] + ] + }, + { + "input": "⩾", + "description": "Named entity: ges; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e" + ] + ] + }, + { + "input": "&gescc", + "description": "Bad named entity: gescc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gescc" + ] + ] + }, + { + "input": "⪩", + "description": "Named entity: gescc; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa9" + ] + ] + }, + { + "input": "&gesdot", + "description": "Bad named entity: gesdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gesdot" + ] + ] + }, + { + "input": "⪀", + "description": "Named entity: gesdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a80" + ] + ] + }, + { + "input": "&gesdoto", + "description": "Bad named entity: gesdoto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gesdoto" + ] + ] + }, + { + "input": "⪂", + "description": "Named entity: gesdoto; with a semi-colon", + "output": [ + [ + "Character", + "\u2a82" + ] + ] + }, + { + "input": "&gesdotol", + "description": "Bad named entity: gesdotol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gesdotol" + ] + ] + }, + { + "input": "⪄", + "description": "Named entity: gesdotol; with a semi-colon", + "output": [ + [ + "Character", + "\u2a84" + ] + ] + }, + { + "input": "&gesl", + "description": "Bad named entity: gesl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gesl" + ] + ] + }, + { + "input": "⋛︀", + "description": "Named entity: gesl; with a semi-colon", + "output": [ + [ + "Character", + "\u22db\ufe00" + ] + ] + }, + { + "input": "&gesles", + "description": "Bad named entity: gesles without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gesles" + ] + ] + }, + { + "input": "⪔", + "description": "Named entity: gesles; with a semi-colon", + "output": [ + [ + "Character", + "\u2a94" + ] + ] + }, + { + "input": "&gfr", + "description": "Bad named entity: gfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gfr" + ] + ] + }, + { + "input": "𝔤", + "description": "Named entity: gfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd24" + ] + ] + }, + { + "input": "&gg", + "description": "Bad named entity: gg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gg" + ] + ] + }, + { + "input": "≫", + "description": "Named entity: gg; with a semi-colon", + "output": [ + [ + "Character", + "\u226b" + ] + ] + }, + { + "input": "&ggg", + "description": "Bad named entity: ggg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ggg" + ] + ] + }, + { + "input": "⋙", + "description": "Named entity: ggg; with a semi-colon", + "output": [ + [ + "Character", + "\u22d9" + ] + ] + }, + { + "input": "&gimel", + "description": "Bad named entity: gimel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gimel" + ] + ] + }, + { + "input": "ℷ", + "description": "Named entity: gimel; with a semi-colon", + "output": [ + [ + "Character", + "\u2137" + ] + ] + }, + { + "input": "&gjcy", + "description": "Bad named entity: gjcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gjcy" + ] + ] + }, + { + "input": "ѓ", + "description": "Named entity: gjcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0453" + ] + ] + }, + { + "input": "&gl", + "description": "Bad named entity: gl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gl" + ] + ] + }, + { + "input": "≷", + "description": "Named entity: gl; with a semi-colon", + "output": [ + [ + "Character", + "\u2277" + ] + ] + }, + { + "input": "&glE", + "description": "Bad named entity: glE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&glE" + ] + ] + }, + { + "input": "⪒", + "description": "Named entity: glE; with a semi-colon", + "output": [ + [ + "Character", + "\u2a92" + ] + ] + }, + { + "input": "&gla", + "description": "Bad named entity: gla without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gla" + ] + ] + }, + { + "input": "⪥", + "description": "Named entity: gla; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa5" + ] + ] + }, + { + "input": "&glj", + "description": "Bad named entity: glj without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&glj" + ] + ] + }, + { + "input": "⪤", + "description": "Named entity: glj; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa4" + ] + ] + }, + { + "input": "&gnE", + "description": "Bad named entity: gnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gnE" + ] + ] + }, + { + "input": "≩", + "description": "Named entity: gnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2269" + ] + ] + }, + { + "input": "&gnap", + "description": "Bad named entity: gnap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gnap" + ] + ] + }, + { + "input": "⪊", + "description": "Named entity: gnap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8a" + ] + ] + }, + { + "input": "&gnapprox", + "description": "Bad named entity: gnapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gnapprox" + ] + ] + }, + { + "input": "⪊", + "description": "Named entity: gnapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8a" + ] + ] + }, + { + "input": "&gne", + "description": "Bad named entity: gne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gne" + ] + ] + }, + { + "input": "⪈", + "description": "Named entity: gne; with a semi-colon", + "output": [ + [ + "Character", + "\u2a88" + ] + ] + }, + { + "input": "&gneq", + "description": "Bad named entity: gneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gneq" + ] + ] + }, + { + "input": "⪈", + "description": "Named entity: gneq; with a semi-colon", + "output": [ + [ + "Character", + "\u2a88" + ] + ] + }, + { + "input": "&gneqq", + "description": "Bad named entity: gneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gneqq" + ] + ] + }, + { + "input": "≩", + "description": "Named entity: gneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2269" + ] + ] + }, + { + "input": "&gnsim", + "description": "Bad named entity: gnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gnsim" + ] + ] + }, + { + "input": "⋧", + "description": "Named entity: gnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e7" + ] + ] + }, + { + "input": "&gopf", + "description": "Bad named entity: gopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gopf" + ] + ] + }, + { + "input": "𝕘", + "description": "Named entity: gopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd58" + ] + ] + }, + { + "input": "&grave", + "description": "Bad named entity: grave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&grave" + ] + ] + }, + { + "input": "`", + "description": "Named entity: grave; with a semi-colon", + "output": [ + [ + "Character", + "`" + ] + ] + }, + { + "input": "&gscr", + "description": "Bad named entity: gscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gscr" + ] + ] + }, + { + "input": "ℊ", + "description": "Named entity: gscr; with a semi-colon", + "output": [ + [ + "Character", + "\u210a" + ] + ] + }, + { + "input": "&gsim", + "description": "Bad named entity: gsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gsim" + ] + ] + }, + { + "input": "≳", + "description": "Named entity: gsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2273" + ] + ] + }, + { + "input": "&gsime", + "description": "Bad named entity: gsime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gsime" + ] + ] + }, + { + "input": "⪎", + "description": "Named entity: gsime; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8e" + ] + ] + }, + { + "input": "&gsiml", + "description": "Bad named entity: gsiml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gsiml" + ] + ] + }, + { + "input": "⪐", + "description": "Named entity: gsiml; with a semi-colon", + "output": [ + [ + "Character", + "\u2a90" + ] + ] + }, + { + "input": ">", + "description": "Named entity: gt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + ">" + ] + ] + }, + { + "input": ">", + "description": "Named entity: gt; with a semi-colon", + "output": [ + [ + "Character", + ">" + ] + ] + }, + { + "input": "⪧", + "description": "Named entity: gtcc; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa7" + ] + ] + }, + { + "input": "⩺", + "description": "Named entity: gtcir; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7a" + ] + ] + }, + { + "input": "⋗", + "description": "Named entity: gtdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22d7" + ] + ] + }, + { + "input": "⦕", + "description": "Named entity: gtlPar; with a semi-colon", + "output": [ + [ + "Character", + "\u2995" + ] + ] + }, + { + "input": "⩼", + "description": "Named entity: gtquest; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7c" + ] + ] + }, + { + "input": "⪆", + "description": "Named entity: gtrapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2a86" + ] + ] + }, + { + "input": "⥸", + "description": "Named entity: gtrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2978" + ] + ] + }, + { + "input": "⋗", + "description": "Named entity: gtrdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22d7" + ] + ] + }, + { + "input": "⋛", + "description": "Named entity: gtreqless; with a semi-colon", + "output": [ + [ + "Character", + "\u22db" + ] + ] + }, + { + "input": "⪌", + "description": "Named entity: gtreqqless; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8c" + ] + ] + }, + { + "input": "≷", + "description": "Named entity: gtrless; with a semi-colon", + "output": [ + [ + "Character", + "\u2277" + ] + ] + }, + { + "input": "≳", + "description": "Named entity: gtrsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2273" + ] + ] + }, + { + "input": "&gvertneqq", + "description": "Bad named entity: gvertneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gvertneqq" + ] + ] + }, + { + "input": "≩︀", + "description": "Named entity: gvertneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2269\ufe00" + ] + ] + }, + { + "input": "&gvnE", + "description": "Bad named entity: gvnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&gvnE" + ] + ] + }, + { + "input": "≩︀", + "description": "Named entity: gvnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2269\ufe00" + ] + ] + }, + { + "input": "&hArr", + "description": "Bad named entity: hArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hArr" + ] + ] + }, + { + "input": "⇔", + "description": "Named entity: hArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d4" + ] + ] + }, + { + "input": "&hairsp", + "description": "Bad named entity: hairsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hairsp" + ] + ] + }, + { + "input": " ", + "description": "Named entity: hairsp; with a semi-colon", + "output": [ + [ + "Character", + "\u200a" + ] + ] + }, + { + "input": "&half", + "description": "Bad named entity: half without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&half" + ] + ] + }, + { + "input": "½", + "description": "Named entity: half; with a semi-colon", + "output": [ + [ + "Character", + "\u00bd" + ] + ] + }, + { + "input": "&hamilt", + "description": "Bad named entity: hamilt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hamilt" + ] + ] + }, + { + "input": "ℋ", + "description": "Named entity: hamilt; with a semi-colon", + "output": [ + [ + "Character", + "\u210b" + ] + ] + }, + { + "input": "&hardcy", + "description": "Bad named entity: hardcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hardcy" + ] + ] + }, + { + "input": "ъ", + "description": "Named entity: hardcy; with a semi-colon", + "output": [ + [ + "Character", + "\u044a" + ] + ] + }, + { + "input": "&harr", + "description": "Bad named entity: harr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&harr" + ] + ] + }, + { + "input": "↔", + "description": "Named entity: harr; with a semi-colon", + "output": [ + [ + "Character", + "\u2194" + ] + ] + }, + { + "input": "&harrcir", + "description": "Bad named entity: harrcir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&harrcir" + ] + ] + }, + { + "input": "⥈", + "description": "Named entity: harrcir; with a semi-colon", + "output": [ + [ + "Character", + "\u2948" + ] + ] + }, + { + "input": "&harrw", + "description": "Bad named entity: harrw without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&harrw" + ] + ] + }, + { + "input": "↭", + "description": "Named entity: harrw; with a semi-colon", + "output": [ + [ + "Character", + "\u21ad" + ] + ] + }, + { + "input": "&hbar", + "description": "Bad named entity: hbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hbar" + ] + ] + }, + { + "input": "ℏ", + "description": "Named entity: hbar; with a semi-colon", + "output": [ + [ + "Character", + "\u210f" + ] + ] + }, + { + "input": "&hcirc", + "description": "Bad named entity: hcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hcirc" + ] + ] + }, + { + "input": "ĥ", + "description": "Named entity: hcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0125" + ] + ] + }, + { + "input": "&hearts", + "description": "Bad named entity: hearts without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hearts" + ] + ] + }, + { + "input": "♥", + "description": "Named entity: hearts; with a semi-colon", + "output": [ + [ + "Character", + "\u2665" + ] + ] + }, + { + "input": "&heartsuit", + "description": "Bad named entity: heartsuit without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&heartsuit" + ] + ] + }, + { + "input": "♥", + "description": "Named entity: heartsuit; with a semi-colon", + "output": [ + [ + "Character", + "\u2665" + ] + ] + }, + { + "input": "&hellip", + "description": "Bad named entity: hellip without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hellip" + ] + ] + }, + { + "input": "…", + "description": "Named entity: hellip; with a semi-colon", + "output": [ + [ + "Character", + "\u2026" + ] + ] + }, + { + "input": "&hercon", + "description": "Bad named entity: hercon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hercon" + ] + ] + }, + { + "input": "⊹", + "description": "Named entity: hercon; with a semi-colon", + "output": [ + [ + "Character", + "\u22b9" + ] + ] + }, + { + "input": "&hfr", + "description": "Bad named entity: hfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hfr" + ] + ] + }, + { + "input": "𝔥", + "description": "Named entity: hfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd25" + ] + ] + }, + { + "input": "&hksearow", + "description": "Bad named entity: hksearow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hksearow" + ] + ] + }, + { + "input": "⤥", + "description": "Named entity: hksearow; with a semi-colon", + "output": [ + [ + "Character", + "\u2925" + ] + ] + }, + { + "input": "&hkswarow", + "description": "Bad named entity: hkswarow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hkswarow" + ] + ] + }, + { + "input": "⤦", + "description": "Named entity: hkswarow; with a semi-colon", + "output": [ + [ + "Character", + "\u2926" + ] + ] + }, + { + "input": "&hoarr", + "description": "Bad named entity: hoarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hoarr" + ] + ] + }, + { + "input": "⇿", + "description": "Named entity: hoarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21ff" + ] + ] + }, + { + "input": "&homtht", + "description": "Bad named entity: homtht without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&homtht" + ] + ] + }, + { + "input": "∻", + "description": "Named entity: homtht; with a semi-colon", + "output": [ + [ + "Character", + "\u223b" + ] + ] + }, + { + "input": "&hookleftarrow", + "description": "Bad named entity: hookleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hookleftarrow" + ] + ] + }, + { + "input": "↩", + "description": "Named entity: hookleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a9" + ] + ] + }, + { + "input": "&hookrightarrow", + "description": "Bad named entity: hookrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hookrightarrow" + ] + ] + }, + { + "input": "↪", + "description": "Named entity: hookrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21aa" + ] + ] + }, + { + "input": "&hopf", + "description": "Bad named entity: hopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hopf" + ] + ] + }, + { + "input": "𝕙", + "description": "Named entity: hopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd59" + ] + ] + }, + { + "input": "&horbar", + "description": "Bad named entity: horbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&horbar" + ] + ] + }, + { + "input": "―", + "description": "Named entity: horbar; with a semi-colon", + "output": [ + [ + "Character", + "\u2015" + ] + ] + }, + { + "input": "&hscr", + "description": "Bad named entity: hscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hscr" + ] + ] + }, + { + "input": "𝒽", + "description": "Named entity: hscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcbd" + ] + ] + }, + { + "input": "&hslash", + "description": "Bad named entity: hslash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hslash" + ] + ] + }, + { + "input": "ℏ", + "description": "Named entity: hslash; with a semi-colon", + "output": [ + [ + "Character", + "\u210f" + ] + ] + }, + { + "input": "&hstrok", + "description": "Bad named entity: hstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hstrok" + ] + ] + }, + { + "input": "ħ", + "description": "Named entity: hstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0127" + ] + ] + }, + { + "input": "&hybull", + "description": "Bad named entity: hybull without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hybull" + ] + ] + }, + { + "input": "⁃", + "description": "Named entity: hybull; with a semi-colon", + "output": [ + [ + "Character", + "\u2043" + ] + ] + }, + { + "input": "&hyphen", + "description": "Bad named entity: hyphen without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&hyphen" + ] + ] + }, + { + "input": "‐", + "description": "Named entity: hyphen; with a semi-colon", + "output": [ + [ + "Character", + "\u2010" + ] + ] + }, + { + "input": "í", + "description": "Named entity: iacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ed" + ] + ] + }, + { + "input": "í", + "description": "Named entity: iacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00ed" + ] + ] + }, + { + "input": "&ic", + "description": "Bad named entity: ic without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ic" + ] + ] + }, + { + "input": "⁣", + "description": "Named entity: ic; with a semi-colon", + "output": [ + [ + "Character", + "\u2063" + ] + ] + }, + { + "input": "î", + "description": "Named entity: icirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ee" + ] + ] + }, + { + "input": "î", + "description": "Named entity: icirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00ee" + ] + ] + }, + { + "input": "&icy", + "description": "Bad named entity: icy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&icy" + ] + ] + }, + { + "input": "и", + "description": "Named entity: icy; with a semi-colon", + "output": [ + [ + "Character", + "\u0438" + ] + ] + }, + { + "input": "&iecy", + "description": "Bad named entity: iecy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iecy" + ] + ] + }, + { + "input": "е", + "description": "Named entity: iecy; with a semi-colon", + "output": [ + [ + "Character", + "\u0435" + ] + ] + }, + { + "input": "¡", + "description": "Named entity: iexcl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a1" + ] + ] + }, + { + "input": "¡", + "description": "Named entity: iexcl; with a semi-colon", + "output": [ + [ + "Character", + "\u00a1" + ] + ] + }, + { + "input": "&iff", + "description": "Bad named entity: iff without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iff" + ] + ] + }, + { + "input": "⇔", + "description": "Named entity: iff; with a semi-colon", + "output": [ + [ + "Character", + "\u21d4" + ] + ] + }, + { + "input": "&ifr", + "description": "Bad named entity: ifr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ifr" + ] + ] + }, + { + "input": "𝔦", + "description": "Named entity: ifr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd26" + ] + ] + }, + { + "input": "ì", + "description": "Named entity: igrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ec" + ] + ] + }, + { + "input": "ì", + "description": "Named entity: igrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00ec" + ] + ] + }, + { + "input": "&ii", + "description": "Bad named entity: ii without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ii" + ] + ] + }, + { + "input": "ⅈ", + "description": "Named entity: ii; with a semi-colon", + "output": [ + [ + "Character", + "\u2148" + ] + ] + }, + { + "input": "&iiiint", + "description": "Bad named entity: iiiint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iiiint" + ] + ] + }, + { + "input": "⨌", + "description": "Named entity: iiiint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a0c" + ] + ] + }, + { + "input": "&iiint", + "description": "Bad named entity: iiint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iiint" + ] + ] + }, + { + "input": "∭", + "description": "Named entity: iiint; with a semi-colon", + "output": [ + [ + "Character", + "\u222d" + ] + ] + }, + { + "input": "&iinfin", + "description": "Bad named entity: iinfin without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iinfin" + ] + ] + }, + { + "input": "⧜", + "description": "Named entity: iinfin; with a semi-colon", + "output": [ + [ + "Character", + "\u29dc" + ] + ] + }, + { + "input": "&iiota", + "description": "Bad named entity: iiota without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iiota" + ] + ] + }, + { + "input": "℩", + "description": "Named entity: iiota; with a semi-colon", + "output": [ + [ + "Character", + "\u2129" + ] + ] + }, + { + "input": "&ijlig", + "description": "Bad named entity: ijlig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ijlig" + ] + ] + }, + { + "input": "ij", + "description": "Named entity: ijlig; with a semi-colon", + "output": [ + [ + "Character", + "\u0133" + ] + ] + }, + { + "input": "&imacr", + "description": "Bad named entity: imacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imacr" + ] + ] + }, + { + "input": "ī", + "description": "Named entity: imacr; with a semi-colon", + "output": [ + [ + "Character", + "\u012b" + ] + ] + }, + { + "input": "&image", + "description": "Bad named entity: image without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&image" + ] + ] + }, + { + "input": "ℑ", + "description": "Named entity: image; with a semi-colon", + "output": [ + [ + "Character", + "\u2111" + ] + ] + }, + { + "input": "&imagline", + "description": "Bad named entity: imagline without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imagline" + ] + ] + }, + { + "input": "ℐ", + "description": "Named entity: imagline; with a semi-colon", + "output": [ + [ + "Character", + "\u2110" + ] + ] + }, + { + "input": "&imagpart", + "description": "Bad named entity: imagpart without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imagpart" + ] + ] + }, + { + "input": "ℑ", + "description": "Named entity: imagpart; with a semi-colon", + "output": [ + [ + "Character", + "\u2111" + ] + ] + }, + { + "input": "&imath", + "description": "Bad named entity: imath without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imath" + ] + ] + }, + { + "input": "ı", + "description": "Named entity: imath; with a semi-colon", + "output": [ + [ + "Character", + "\u0131" + ] + ] + }, + { + "input": "&imof", + "description": "Bad named entity: imof without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imof" + ] + ] + }, + { + "input": "⊷", + "description": "Named entity: imof; with a semi-colon", + "output": [ + [ + "Character", + "\u22b7" + ] + ] + }, + { + "input": "&imped", + "description": "Bad named entity: imped without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&imped" + ] + ] + }, + { + "input": "Ƶ", + "description": "Named entity: imped; with a semi-colon", + "output": [ + [ + "Character", + "\u01b5" + ] + ] + }, + { + "input": "&in", + "description": "Bad named entity: in without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&in" + ] + ] + }, + { + "input": "∈", + "description": "Named entity: in; with a semi-colon", + "output": [ + [ + "Character", + "\u2208" + ] + ] + }, + { + "input": "&incare", + "description": "Bad named entity: incare without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&incare" + ] + ] + }, + { + "input": "℅", + "description": "Named entity: incare; with a semi-colon", + "output": [ + [ + "Character", + "\u2105" + ] + ] + }, + { + "input": "&infin", + "description": "Bad named entity: infin without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&infin" + ] + ] + }, + { + "input": "∞", + "description": "Named entity: infin; with a semi-colon", + "output": [ + [ + "Character", + "\u221e" + ] + ] + }, + { + "input": "&infintie", + "description": "Bad named entity: infintie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&infintie" + ] + ] + }, + { + "input": "⧝", + "description": "Named entity: infintie; with a semi-colon", + "output": [ + [ + "Character", + "\u29dd" + ] + ] + }, + { + "input": "&inodot", + "description": "Bad named entity: inodot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&inodot" + ] + ] + }, + { + "input": "ı", + "description": "Named entity: inodot; with a semi-colon", + "output": [ + [ + "Character", + "\u0131" + ] + ] + }, + { + "input": "&int", + "description": "Bad named entity: int without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&int" + ] + ] + }, + { + "input": "∫", + "description": "Named entity: int; with a semi-colon", + "output": [ + [ + "Character", + "\u222b" + ] + ] + }, + { + "input": "&intcal", + "description": "Bad named entity: intcal without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&intcal" + ] + ] + }, + { + "input": "⊺", + "description": "Named entity: intcal; with a semi-colon", + "output": [ + [ + "Character", + "\u22ba" + ] + ] + }, + { + "input": "&integers", + "description": "Bad named entity: integers without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&integers" + ] + ] + }, + { + "input": "ℤ", + "description": "Named entity: integers; with a semi-colon", + "output": [ + [ + "Character", + "\u2124" + ] + ] + }, + { + "input": "&intercal", + "description": "Bad named entity: intercal without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&intercal" + ] + ] + }, + { + "input": "⊺", + "description": "Named entity: intercal; with a semi-colon", + "output": [ + [ + "Character", + "\u22ba" + ] + ] + }, + { + "input": "&intlarhk", + "description": "Bad named entity: intlarhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&intlarhk" + ] + ] + }, + { + "input": "⨗", + "description": "Named entity: intlarhk; with a semi-colon", + "output": [ + [ + "Character", + "\u2a17" + ] + ] + }, + { + "input": "&intprod", + "description": "Bad named entity: intprod without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&intprod" + ] + ] + }, + { + "input": "⨼", + "description": "Named entity: intprod; with a semi-colon", + "output": [ + [ + "Character", + "\u2a3c" + ] + ] + }, + { + "input": "&iocy", + "description": "Bad named entity: iocy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iocy" + ] + ] + }, + { + "input": "ё", + "description": "Named entity: iocy; with a semi-colon", + "output": [ + [ + "Character", + "\u0451" + ] + ] + }, + { + "input": "&iogon", + "description": "Bad named entity: iogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iogon" + ] + ] + }, + { + "input": "į", + "description": "Named entity: iogon; with a semi-colon", + "output": [ + [ + "Character", + "\u012f" + ] + ] + }, + { + "input": "&iopf", + "description": "Bad named entity: iopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iopf" + ] + ] + }, + { + "input": "𝕚", + "description": "Named entity: iopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5a" + ] + ] + }, + { + "input": "&iota", + "description": "Bad named entity: iota without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iota" + ] + ] + }, + { + "input": "ι", + "description": "Named entity: iota; with a semi-colon", + "output": [ + [ + "Character", + "\u03b9" + ] + ] + }, + { + "input": "&iprod", + "description": "Bad named entity: iprod without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iprod" + ] + ] + }, + { + "input": "⨼", + "description": "Named entity: iprod; with a semi-colon", + "output": [ + [ + "Character", + "\u2a3c" + ] + ] + }, + { + "input": "¿", + "description": "Named entity: iquest without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00bf" + ] + ] + }, + { + "input": "¿", + "description": "Named entity: iquest; with a semi-colon", + "output": [ + [ + "Character", + "\u00bf" + ] + ] + }, + { + "input": "&iscr", + "description": "Bad named entity: iscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iscr" + ] + ] + }, + { + "input": "𝒾", + "description": "Named entity: iscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcbe" + ] + ] + }, + { + "input": "&isin", + "description": "Bad named entity: isin without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isin" + ] + ] + }, + { + "input": "∈", + "description": "Named entity: isin; with a semi-colon", + "output": [ + [ + "Character", + "\u2208" + ] + ] + }, + { + "input": "&isinE", + "description": "Bad named entity: isinE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isinE" + ] + ] + }, + { + "input": "⋹", + "description": "Named entity: isinE; with a semi-colon", + "output": [ + [ + "Character", + "\u22f9" + ] + ] + }, + { + "input": "&isindot", + "description": "Bad named entity: isindot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isindot" + ] + ] + }, + { + "input": "⋵", + "description": "Named entity: isindot; with a semi-colon", + "output": [ + [ + "Character", + "\u22f5" + ] + ] + }, + { + "input": "&isins", + "description": "Bad named entity: isins without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isins" + ] + ] + }, + { + "input": "⋴", + "description": "Named entity: isins; with a semi-colon", + "output": [ + [ + "Character", + "\u22f4" + ] + ] + }, + { + "input": "&isinsv", + "description": "Bad named entity: isinsv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isinsv" + ] + ] + }, + { + "input": "⋳", + "description": "Named entity: isinsv; with a semi-colon", + "output": [ + [ + "Character", + "\u22f3" + ] + ] + }, + { + "input": "&isinv", + "description": "Bad named entity: isinv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&isinv" + ] + ] + }, + { + "input": "∈", + "description": "Named entity: isinv; with a semi-colon", + "output": [ + [ + "Character", + "\u2208" + ] + ] + }, + { + "input": "&it", + "description": "Bad named entity: it without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&it" + ] + ] + }, + { + "input": "⁢", + "description": "Named entity: it; with a semi-colon", + "output": [ + [ + "Character", + "\u2062" + ] + ] + }, + { + "input": "&itilde", + "description": "Bad named entity: itilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&itilde" + ] + ] + }, + { + "input": "ĩ", + "description": "Named entity: itilde; with a semi-colon", + "output": [ + [ + "Character", + "\u0129" + ] + ] + }, + { + "input": "&iukcy", + "description": "Bad named entity: iukcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&iukcy" + ] + ] + }, + { + "input": "і", + "description": "Named entity: iukcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0456" + ] + ] + }, + { + "input": "ï", + "description": "Named entity: iuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ef" + ] + ] + }, + { + "input": "ï", + "description": "Named entity: iuml; with a semi-colon", + "output": [ + [ + "Character", + "\u00ef" + ] + ] + }, + { + "input": "&jcirc", + "description": "Bad named entity: jcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jcirc" + ] + ] + }, + { + "input": "ĵ", + "description": "Named entity: jcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0135" + ] + ] + }, + { + "input": "&jcy", + "description": "Bad named entity: jcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jcy" + ] + ] + }, + { + "input": "й", + "description": "Named entity: jcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0439" + ] + ] + }, + { + "input": "&jfr", + "description": "Bad named entity: jfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jfr" + ] + ] + }, + { + "input": "𝔧", + "description": "Named entity: jfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd27" + ] + ] + }, + { + "input": "&jmath", + "description": "Bad named entity: jmath without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jmath" + ] + ] + }, + { + "input": "ȷ", + "description": "Named entity: jmath; with a semi-colon", + "output": [ + [ + "Character", + "\u0237" + ] + ] + }, + { + "input": "&jopf", + "description": "Bad named entity: jopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jopf" + ] + ] + }, + { + "input": "𝕛", + "description": "Named entity: jopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5b" + ] + ] + }, + { + "input": "&jscr", + "description": "Bad named entity: jscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jscr" + ] + ] + }, + { + "input": "𝒿", + "description": "Named entity: jscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcbf" + ] + ] + }, + { + "input": "&jsercy", + "description": "Bad named entity: jsercy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jsercy" + ] + ] + }, + { + "input": "ј", + "description": "Named entity: jsercy; with a semi-colon", + "output": [ + [ + "Character", + "\u0458" + ] + ] + }, + { + "input": "&jukcy", + "description": "Bad named entity: jukcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&jukcy" + ] + ] + }, + { + "input": "є", + "description": "Named entity: jukcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0454" + ] + ] + }, + { + "input": "&kappa", + "description": "Bad named entity: kappa without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kappa" + ] + ] + }, + { + "input": "κ", + "description": "Named entity: kappa; with a semi-colon", + "output": [ + [ + "Character", + "\u03ba" + ] + ] + }, + { + "input": "&kappav", + "description": "Bad named entity: kappav without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kappav" + ] + ] + }, + { + "input": "ϰ", + "description": "Named entity: kappav; with a semi-colon", + "output": [ + [ + "Character", + "\u03f0" + ] + ] + }, + { + "input": "&kcedil", + "description": "Bad named entity: kcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kcedil" + ] + ] + }, + { + "input": "ķ", + "description": "Named entity: kcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0137" + ] + ] + }, + { + "input": "&kcy", + "description": "Bad named entity: kcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kcy" + ] + ] + }, + { + "input": "к", + "description": "Named entity: kcy; with a semi-colon", + "output": [ + [ + "Character", + "\u043a" + ] + ] + }, + { + "input": "&kfr", + "description": "Bad named entity: kfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kfr" + ] + ] + }, + { + "input": "𝔨", + "description": "Named entity: kfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd28" + ] + ] + }, + { + "input": "&kgreen", + "description": "Bad named entity: kgreen without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kgreen" + ] + ] + }, + { + "input": "ĸ", + "description": "Named entity: kgreen; with a semi-colon", + "output": [ + [ + "Character", + "\u0138" + ] + ] + }, + { + "input": "&khcy", + "description": "Bad named entity: khcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&khcy" + ] + ] + }, + { + "input": "х", + "description": "Named entity: khcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0445" + ] + ] + }, + { + "input": "&kjcy", + "description": "Bad named entity: kjcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kjcy" + ] + ] + }, + { + "input": "ќ", + "description": "Named entity: kjcy; with a semi-colon", + "output": [ + [ + "Character", + "\u045c" + ] + ] + }, + { + "input": "&kopf", + "description": "Bad named entity: kopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kopf" + ] + ] + }, + { + "input": "𝕜", + "description": "Named entity: kopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5c" + ] + ] + }, + { + "input": "&kscr", + "description": "Bad named entity: kscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&kscr" + ] + ] + }, + { + "input": "𝓀", + "description": "Named entity: kscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc0" + ] + ] + }, + { + "input": "&lAarr", + "description": "Bad named entity: lAarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lAarr" + ] + ] + }, + { + "input": "⇚", + "description": "Named entity: lAarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21da" + ] + ] + }, + { + "input": "&lArr", + "description": "Bad named entity: lArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lArr" + ] + ] + }, + { + "input": "⇐", + "description": "Named entity: lArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d0" + ] + ] + }, + { + "input": "&lAtail", + "description": "Bad named entity: lAtail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lAtail" + ] + ] + }, + { + "input": "⤛", + "description": "Named entity: lAtail; with a semi-colon", + "output": [ + [ + "Character", + "\u291b" + ] + ] + }, + { + "input": "&lBarr", + "description": "Bad named entity: lBarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lBarr" + ] + ] + }, + { + "input": "⤎", + "description": "Named entity: lBarr; with a semi-colon", + "output": [ + [ + "Character", + "\u290e" + ] + ] + }, + { + "input": "&lE", + "description": "Bad named entity: lE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lE" + ] + ] + }, + { + "input": "≦", + "description": "Named entity: lE; with a semi-colon", + "output": [ + [ + "Character", + "\u2266" + ] + ] + }, + { + "input": "&lEg", + "description": "Bad named entity: lEg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lEg" + ] + ] + }, + { + "input": "⪋", + "description": "Named entity: lEg; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8b" + ] + ] + }, + { + "input": "&lHar", + "description": "Bad named entity: lHar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lHar" + ] + ] + }, + { + "input": "⥢", + "description": "Named entity: lHar; with a semi-colon", + "output": [ + [ + "Character", + "\u2962" + ] + ] + }, + { + "input": "&lacute", + "description": "Bad named entity: lacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lacute" + ] + ] + }, + { + "input": "ĺ", + "description": "Named entity: lacute; with a semi-colon", + "output": [ + [ + "Character", + "\u013a" + ] + ] + }, + { + "input": "&laemptyv", + "description": "Bad named entity: laemptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&laemptyv" + ] + ] + }, + { + "input": "⦴", + "description": "Named entity: laemptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u29b4" + ] + ] + }, + { + "input": "&lagran", + "description": "Bad named entity: lagran without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lagran" + ] + ] + }, + { + "input": "ℒ", + "description": "Named entity: lagran; with a semi-colon", + "output": [ + [ + "Character", + "\u2112" + ] + ] + }, + { + "input": "&lambda", + "description": "Bad named entity: lambda without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lambda" + ] + ] + }, + { + "input": "λ", + "description": "Named entity: lambda; with a semi-colon", + "output": [ + [ + "Character", + "\u03bb" + ] + ] + }, + { + "input": "&lang", + "description": "Bad named entity: lang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lang" + ] + ] + }, + { + "input": "⟨", + "description": "Named entity: lang; with a semi-colon", + "output": [ + [ + "Character", + "\u27e8" + ] + ] + }, + { + "input": "&langd", + "description": "Bad named entity: langd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&langd" + ] + ] + }, + { + "input": "⦑", + "description": "Named entity: langd; with a semi-colon", + "output": [ + [ + "Character", + "\u2991" + ] + ] + }, + { + "input": "&langle", + "description": "Bad named entity: langle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&langle" + ] + ] + }, + { + "input": "⟨", + "description": "Named entity: langle; with a semi-colon", + "output": [ + [ + "Character", + "\u27e8" + ] + ] + }, + { + "input": "&lap", + "description": "Bad named entity: lap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lap" + ] + ] + }, + { + "input": "⪅", + "description": "Named entity: lap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a85" + ] + ] + }, + { + "input": "«", + "description": "Named entity: laquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ab" + ] + ] + }, + { + "input": "«", + "description": "Named entity: laquo; with a semi-colon", + "output": [ + [ + "Character", + "\u00ab" + ] + ] + }, + { + "input": "&larr", + "description": "Bad named entity: larr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larr" + ] + ] + }, + { + "input": "←", + "description": "Named entity: larr; with a semi-colon", + "output": [ + [ + "Character", + "\u2190" + ] + ] + }, + { + "input": "&larrb", + "description": "Bad named entity: larrb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrb" + ] + ] + }, + { + "input": "⇤", + "description": "Named entity: larrb; with a semi-colon", + "output": [ + [ + "Character", + "\u21e4" + ] + ] + }, + { + "input": "&larrbfs", + "description": "Bad named entity: larrbfs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrbfs" + ] + ] + }, + { + "input": "⤟", + "description": "Named entity: larrbfs; with a semi-colon", + "output": [ + [ + "Character", + "\u291f" + ] + ] + }, + { + "input": "&larrfs", + "description": "Bad named entity: larrfs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrfs" + ] + ] + }, + { + "input": "⤝", + "description": "Named entity: larrfs; with a semi-colon", + "output": [ + [ + "Character", + "\u291d" + ] + ] + }, + { + "input": "&larrhk", + "description": "Bad named entity: larrhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrhk" + ] + ] + }, + { + "input": "↩", + "description": "Named entity: larrhk; with a semi-colon", + "output": [ + [ + "Character", + "\u21a9" + ] + ] + }, + { + "input": "&larrlp", + "description": "Bad named entity: larrlp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrlp" + ] + ] + }, + { + "input": "↫", + "description": "Named entity: larrlp; with a semi-colon", + "output": [ + [ + "Character", + "\u21ab" + ] + ] + }, + { + "input": "&larrpl", + "description": "Bad named entity: larrpl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrpl" + ] + ] + }, + { + "input": "⤹", + "description": "Named entity: larrpl; with a semi-colon", + "output": [ + [ + "Character", + "\u2939" + ] + ] + }, + { + "input": "&larrsim", + "description": "Bad named entity: larrsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrsim" + ] + ] + }, + { + "input": "⥳", + "description": "Named entity: larrsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2973" + ] + ] + }, + { + "input": "&larrtl", + "description": "Bad named entity: larrtl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&larrtl" + ] + ] + }, + { + "input": "↢", + "description": "Named entity: larrtl; with a semi-colon", + "output": [ + [ + "Character", + "\u21a2" + ] + ] + }, + { + "input": "&lat", + "description": "Bad named entity: lat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lat" + ] + ] + }, + { + "input": "⪫", + "description": "Named entity: lat; with a semi-colon", + "output": [ + [ + "Character", + "\u2aab" + ] + ] + }, + { + "input": "&latail", + "description": "Bad named entity: latail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&latail" + ] + ] + }, + { + "input": "⤙", + "description": "Named entity: latail; with a semi-colon", + "output": [ + [ + "Character", + "\u2919" + ] + ] + }, + { + "input": "&late", + "description": "Bad named entity: late without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&late" + ] + ] + }, + { + "input": "⪭", + "description": "Named entity: late; with a semi-colon", + "output": [ + [ + "Character", + "\u2aad" + ] + ] + }, + { + "input": "&lates", + "description": "Bad named entity: lates without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lates" + ] + ] + }, + { + "input": "⪭︀", + "description": "Named entity: lates; with a semi-colon", + "output": [ + [ + "Character", + "\u2aad\ufe00" + ] + ] + }, + { + "input": "&lbarr", + "description": "Bad named entity: lbarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbarr" + ] + ] + }, + { + "input": "⤌", + "description": "Named entity: lbarr; with a semi-colon", + "output": [ + [ + "Character", + "\u290c" + ] + ] + }, + { + "input": "&lbbrk", + "description": "Bad named entity: lbbrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbbrk" + ] + ] + }, + { + "input": "❲", + "description": "Named entity: lbbrk; with a semi-colon", + "output": [ + [ + "Character", + "\u2772" + ] + ] + }, + { + "input": "&lbrace", + "description": "Bad named entity: lbrace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbrace" + ] + ] + }, + { + "input": "{", + "description": "Named entity: lbrace; with a semi-colon", + "output": [ + [ + "Character", + "{" + ] + ] + }, + { + "input": "&lbrack", + "description": "Bad named entity: lbrack without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbrack" + ] + ] + }, + { + "input": "[", + "description": "Named entity: lbrack; with a semi-colon", + "output": [ + [ + "Character", + "[" + ] + ] + }, + { + "input": "&lbrke", + "description": "Bad named entity: lbrke without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbrke" + ] + ] + }, + { + "input": "⦋", + "description": "Named entity: lbrke; with a semi-colon", + "output": [ + [ + "Character", + "\u298b" + ] + ] + }, + { + "input": "&lbrksld", + "description": "Bad named entity: lbrksld without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbrksld" + ] + ] + }, + { + "input": "⦏", + "description": "Named entity: lbrksld; with a semi-colon", + "output": [ + [ + "Character", + "\u298f" + ] + ] + }, + { + "input": "&lbrkslu", + "description": "Bad named entity: lbrkslu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lbrkslu" + ] + ] + }, + { + "input": "⦍", + "description": "Named entity: lbrkslu; with a semi-colon", + "output": [ + [ + "Character", + "\u298d" + ] + ] + }, + { + "input": "&lcaron", + "description": "Bad named entity: lcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lcaron" + ] + ] + }, + { + "input": "ľ", + "description": "Named entity: lcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u013e" + ] + ] + }, + { + "input": "&lcedil", + "description": "Bad named entity: lcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lcedil" + ] + ] + }, + { + "input": "ļ", + "description": "Named entity: lcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u013c" + ] + ] + }, + { + "input": "&lceil", + "description": "Bad named entity: lceil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lceil" + ] + ] + }, + { + "input": "⌈", + "description": "Named entity: lceil; with a semi-colon", + "output": [ + [ + "Character", + "\u2308" + ] + ] + }, + { + "input": "&lcub", + "description": "Bad named entity: lcub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lcub" + ] + ] + }, + { + "input": "{", + "description": "Named entity: lcub; with a semi-colon", + "output": [ + [ + "Character", + "{" + ] + ] + }, + { + "input": "&lcy", + "description": "Bad named entity: lcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lcy" + ] + ] + }, + { + "input": "л", + "description": "Named entity: lcy; with a semi-colon", + "output": [ + [ + "Character", + "\u043b" + ] + ] + }, + { + "input": "&ldca", + "description": "Bad named entity: ldca without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldca" + ] + ] + }, + { + "input": "⤶", + "description": "Named entity: ldca; with a semi-colon", + "output": [ + [ + "Character", + "\u2936" + ] + ] + }, + { + "input": "&ldquo", + "description": "Bad named entity: ldquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldquo" + ] + ] + }, + { + "input": "“", + "description": "Named entity: ldquo; with a semi-colon", + "output": [ + [ + "Character", + "\u201c" + ] + ] + }, + { + "input": "&ldquor", + "description": "Bad named entity: ldquor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldquor" + ] + ] + }, + { + "input": "„", + "description": "Named entity: ldquor; with a semi-colon", + "output": [ + [ + "Character", + "\u201e" + ] + ] + }, + { + "input": "&ldrdhar", + "description": "Bad named entity: ldrdhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldrdhar" + ] + ] + }, + { + "input": "⥧", + "description": "Named entity: ldrdhar; with a semi-colon", + "output": [ + [ + "Character", + "\u2967" + ] + ] + }, + { + "input": "&ldrushar", + "description": "Bad named entity: ldrushar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldrushar" + ] + ] + }, + { + "input": "⥋", + "description": "Named entity: ldrushar; with a semi-colon", + "output": [ + [ + "Character", + "\u294b" + ] + ] + }, + { + "input": "&ldsh", + "description": "Bad named entity: ldsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ldsh" + ] + ] + }, + { + "input": "↲", + "description": "Named entity: ldsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b2" + ] + ] + }, + { + "input": "&le", + "description": "Bad named entity: le without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&le" + ] + ] + }, + { + "input": "≤", + "description": "Named entity: le; with a semi-colon", + "output": [ + [ + "Character", + "\u2264" + ] + ] + }, + { + "input": "&leftarrow", + "description": "Bad named entity: leftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftarrow" + ] + ] + }, + { + "input": "←", + "description": "Named entity: leftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2190" + ] + ] + }, + { + "input": "&leftarrowtail", + "description": "Bad named entity: leftarrowtail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftarrowtail" + ] + ] + }, + { + "input": "↢", + "description": "Named entity: leftarrowtail; with a semi-colon", + "output": [ + [ + "Character", + "\u21a2" + ] + ] + }, + { + "input": "&leftharpoondown", + "description": "Bad named entity: leftharpoondown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftharpoondown" + ] + ] + }, + { + "input": "↽", + "description": "Named entity: leftharpoondown; with a semi-colon", + "output": [ + [ + "Character", + "\u21bd" + ] + ] + }, + { + "input": "&leftharpoonup", + "description": "Bad named entity: leftharpoonup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftharpoonup" + ] + ] + }, + { + "input": "↼", + "description": "Named entity: leftharpoonup; with a semi-colon", + "output": [ + [ + "Character", + "\u21bc" + ] + ] + }, + { + "input": "&leftleftarrows", + "description": "Bad named entity: leftleftarrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftleftarrows" + ] + ] + }, + { + "input": "⇇", + "description": "Named entity: leftleftarrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21c7" + ] + ] + }, + { + "input": "&leftrightarrow", + "description": "Bad named entity: leftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftrightarrow" + ] + ] + }, + { + "input": "↔", + "description": "Named entity: leftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2194" + ] + ] + }, + { + "input": "&leftrightarrows", + "description": "Bad named entity: leftrightarrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftrightarrows" + ] + ] + }, + { + "input": "⇆", + "description": "Named entity: leftrightarrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21c6" + ] + ] + }, + { + "input": "&leftrightharpoons", + "description": "Bad named entity: leftrightharpoons without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftrightharpoons" + ] + ] + }, + { + "input": "⇋", + "description": "Named entity: leftrightharpoons; with a semi-colon", + "output": [ + [ + "Character", + "\u21cb" + ] + ] + }, + { + "input": "&leftrightsquigarrow", + "description": "Bad named entity: leftrightsquigarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftrightsquigarrow" + ] + ] + }, + { + "input": "↭", + "description": "Named entity: leftrightsquigarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21ad" + ] + ] + }, + { + "input": "&leftthreetimes", + "description": "Bad named entity: leftthreetimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leftthreetimes" + ] + ] + }, + { + "input": "⋋", + "description": "Named entity: leftthreetimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22cb" + ] + ] + }, + { + "input": "&leg", + "description": "Bad named entity: leg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leg" + ] + ] + }, + { + "input": "⋚", + "description": "Named entity: leg; with a semi-colon", + "output": [ + [ + "Character", + "\u22da" + ] + ] + }, + { + "input": "&leq", + "description": "Bad named entity: leq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leq" + ] + ] + }, + { + "input": "≤", + "description": "Named entity: leq; with a semi-colon", + "output": [ + [ + "Character", + "\u2264" + ] + ] + }, + { + "input": "&leqq", + "description": "Bad named entity: leqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leqq" + ] + ] + }, + { + "input": "≦", + "description": "Named entity: leqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2266" + ] + ] + }, + { + "input": "&leqslant", + "description": "Bad named entity: leqslant without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&leqslant" + ] + ] + }, + { + "input": "⩽", + "description": "Named entity: leqslant; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d" + ] + ] + }, + { + "input": "&les", + "description": "Bad named entity: les without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&les" + ] + ] + }, + { + "input": "⩽", + "description": "Named entity: les; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d" + ] + ] + }, + { + "input": "&lescc", + "description": "Bad named entity: lescc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lescc" + ] + ] + }, + { + "input": "⪨", + "description": "Named entity: lescc; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa8" + ] + ] + }, + { + "input": "&lesdot", + "description": "Bad named entity: lesdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesdot" + ] + ] + }, + { + "input": "⩿", + "description": "Named entity: lesdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7f" + ] + ] + }, + { + "input": "&lesdoto", + "description": "Bad named entity: lesdoto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesdoto" + ] + ] + }, + { + "input": "⪁", + "description": "Named entity: lesdoto; with a semi-colon", + "output": [ + [ + "Character", + "\u2a81" + ] + ] + }, + { + "input": "&lesdotor", + "description": "Bad named entity: lesdotor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesdotor" + ] + ] + }, + { + "input": "⪃", + "description": "Named entity: lesdotor; with a semi-colon", + "output": [ + [ + "Character", + "\u2a83" + ] + ] + }, + { + "input": "&lesg", + "description": "Bad named entity: lesg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesg" + ] + ] + }, + { + "input": "⋚︀", + "description": "Named entity: lesg; with a semi-colon", + "output": [ + [ + "Character", + "\u22da\ufe00" + ] + ] + }, + { + "input": "&lesges", + "description": "Bad named entity: lesges without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesges" + ] + ] + }, + { + "input": "⪓", + "description": "Named entity: lesges; with a semi-colon", + "output": [ + [ + "Character", + "\u2a93" + ] + ] + }, + { + "input": "&lessapprox", + "description": "Bad named entity: lessapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lessapprox" + ] + ] + }, + { + "input": "⪅", + "description": "Named entity: lessapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2a85" + ] + ] + }, + { + "input": "&lessdot", + "description": "Bad named entity: lessdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lessdot" + ] + ] + }, + { + "input": "⋖", + "description": "Named entity: lessdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22d6" + ] + ] + }, + { + "input": "&lesseqgtr", + "description": "Bad named entity: lesseqgtr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesseqgtr" + ] + ] + }, + { + "input": "⋚", + "description": "Named entity: lesseqgtr; with a semi-colon", + "output": [ + [ + "Character", + "\u22da" + ] + ] + }, + { + "input": "&lesseqqgtr", + "description": "Bad named entity: lesseqqgtr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesseqqgtr" + ] + ] + }, + { + "input": "⪋", + "description": "Named entity: lesseqqgtr; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8b" + ] + ] + }, + { + "input": "&lessgtr", + "description": "Bad named entity: lessgtr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lessgtr" + ] + ] + }, + { + "input": "≶", + "description": "Named entity: lessgtr; with a semi-colon", + "output": [ + [ + "Character", + "\u2276" + ] + ] + }, + { + "input": "&lesssim", + "description": "Bad named entity: lesssim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lesssim" + ] + ] + }, + { + "input": "≲", + "description": "Named entity: lesssim; with a semi-colon", + "output": [ + [ + "Character", + "\u2272" + ] + ] + }, + { + "input": "&lfisht", + "description": "Bad named entity: lfisht without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lfisht" + ] + ] + }, + { + "input": "⥼", + "description": "Named entity: lfisht; with a semi-colon", + "output": [ + [ + "Character", + "\u297c" + ] + ] + }, + { + "input": "&lfloor", + "description": "Bad named entity: lfloor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lfloor" + ] + ] + }, + { + "input": "⌊", + "description": "Named entity: lfloor; with a semi-colon", + "output": [ + [ + "Character", + "\u230a" + ] + ] + }, + { + "input": "&lfr", + "description": "Bad named entity: lfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lfr" + ] + ] + }, + { + "input": "𝔩", + "description": "Named entity: lfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd29" + ] + ] + }, + { + "input": "&lg", + "description": "Bad named entity: lg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lg" + ] + ] + }, + { + "input": "≶", + "description": "Named entity: lg; with a semi-colon", + "output": [ + [ + "Character", + "\u2276" + ] + ] + }, + { + "input": "&lgE", + "description": "Bad named entity: lgE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lgE" + ] + ] + }, + { + "input": "⪑", + "description": "Named entity: lgE; with a semi-colon", + "output": [ + [ + "Character", + "\u2a91" + ] + ] + }, + { + "input": "&lhard", + "description": "Bad named entity: lhard without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lhard" + ] + ] + }, + { + "input": "↽", + "description": "Named entity: lhard; with a semi-colon", + "output": [ + [ + "Character", + "\u21bd" + ] + ] + }, + { + "input": "&lharu", + "description": "Bad named entity: lharu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lharu" + ] + ] + }, + { + "input": "↼", + "description": "Named entity: lharu; with a semi-colon", + "output": [ + [ + "Character", + "\u21bc" + ] + ] + }, + { + "input": "&lharul", + "description": "Bad named entity: lharul without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lharul" + ] + ] + }, + { + "input": "⥪", + "description": "Named entity: lharul; with a semi-colon", + "output": [ + [ + "Character", + "\u296a" + ] + ] + }, + { + "input": "&lhblk", + "description": "Bad named entity: lhblk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lhblk" + ] + ] + }, + { + "input": "▄", + "description": "Named entity: lhblk; with a semi-colon", + "output": [ + [ + "Character", + "\u2584" + ] + ] + }, + { + "input": "&ljcy", + "description": "Bad named entity: ljcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ljcy" + ] + ] + }, + { + "input": "љ", + "description": "Named entity: ljcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0459" + ] + ] + }, + { + "input": "&ll", + "description": "Bad named entity: ll without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ll" + ] + ] + }, + { + "input": "≪", + "description": "Named entity: ll; with a semi-colon", + "output": [ + [ + "Character", + "\u226a" + ] + ] + }, + { + "input": "&llarr", + "description": "Bad named entity: llarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&llarr" + ] + ] + }, + { + "input": "⇇", + "description": "Named entity: llarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c7" + ] + ] + }, + { + "input": "&llcorner", + "description": "Bad named entity: llcorner without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&llcorner" + ] + ] + }, + { + "input": "⌞", + "description": "Named entity: llcorner; with a semi-colon", + "output": [ + [ + "Character", + "\u231e" + ] + ] + }, + { + "input": "&llhard", + "description": "Bad named entity: llhard without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&llhard" + ] + ] + }, + { + "input": "⥫", + "description": "Named entity: llhard; with a semi-colon", + "output": [ + [ + "Character", + "\u296b" + ] + ] + }, + { + "input": "&lltri", + "description": "Bad named entity: lltri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lltri" + ] + ] + }, + { + "input": "◺", + "description": "Named entity: lltri; with a semi-colon", + "output": [ + [ + "Character", + "\u25fa" + ] + ] + }, + { + "input": "&lmidot", + "description": "Bad named entity: lmidot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lmidot" + ] + ] + }, + { + "input": "ŀ", + "description": "Named entity: lmidot; with a semi-colon", + "output": [ + [ + "Character", + "\u0140" + ] + ] + }, + { + "input": "&lmoust", + "description": "Bad named entity: lmoust without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lmoust" + ] + ] + }, + { + "input": "⎰", + "description": "Named entity: lmoust; with a semi-colon", + "output": [ + [ + "Character", + "\u23b0" + ] + ] + }, + { + "input": "&lmoustache", + "description": "Bad named entity: lmoustache without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lmoustache" + ] + ] + }, + { + "input": "⎰", + "description": "Named entity: lmoustache; with a semi-colon", + "output": [ + [ + "Character", + "\u23b0" + ] + ] + }, + { + "input": "&lnE", + "description": "Bad named entity: lnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lnE" + ] + ] + }, + { + "input": "≨", + "description": "Named entity: lnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2268" + ] + ] + }, + { + "input": "&lnap", + "description": "Bad named entity: lnap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lnap" + ] + ] + }, + { + "input": "⪉", + "description": "Named entity: lnap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a89" + ] + ] + }, + { + "input": "&lnapprox", + "description": "Bad named entity: lnapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lnapprox" + ] + ] + }, + { + "input": "⪉", + "description": "Named entity: lnapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2a89" + ] + ] + }, + { + "input": "&lne", + "description": "Bad named entity: lne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lne" + ] + ] + }, + { + "input": "⪇", + "description": "Named entity: lne; with a semi-colon", + "output": [ + [ + "Character", + "\u2a87" + ] + ] + }, + { + "input": "&lneq", + "description": "Bad named entity: lneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lneq" + ] + ] + }, + { + "input": "⪇", + "description": "Named entity: lneq; with a semi-colon", + "output": [ + [ + "Character", + "\u2a87" + ] + ] + }, + { + "input": "&lneqq", + "description": "Bad named entity: lneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lneqq" + ] + ] + }, + { + "input": "≨", + "description": "Named entity: lneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2268" + ] + ] + }, + { + "input": "&lnsim", + "description": "Bad named entity: lnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lnsim" + ] + ] + }, + { + "input": "⋦", + "description": "Named entity: lnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e6" + ] + ] + }, + { + "input": "&loang", + "description": "Bad named entity: loang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&loang" + ] + ] + }, + { + "input": "⟬", + "description": "Named entity: loang; with a semi-colon", + "output": [ + [ + "Character", + "\u27ec" + ] + ] + }, + { + "input": "&loarr", + "description": "Bad named entity: loarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&loarr" + ] + ] + }, + { + "input": "⇽", + "description": "Named entity: loarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21fd" + ] + ] + }, + { + "input": "&lobrk", + "description": "Bad named entity: lobrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lobrk" + ] + ] + }, + { + "input": "⟦", + "description": "Named entity: lobrk; with a semi-colon", + "output": [ + [ + "Character", + "\u27e6" + ] + ] + }, + { + "input": "&longleftarrow", + "description": "Bad named entity: longleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&longleftarrow" + ] + ] + }, + { + "input": "⟵", + "description": "Named entity: longleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f5" + ] + ] + }, + { + "input": "&longleftrightarrow", + "description": "Bad named entity: longleftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&longleftrightarrow" + ] + ] + }, + { + "input": "⟷", + "description": "Named entity: longleftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f7" + ] + ] + }, + { + "input": "&longmapsto", + "description": "Bad named entity: longmapsto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&longmapsto" + ] + ] + }, + { + "input": "⟼", + "description": "Named entity: longmapsto; with a semi-colon", + "output": [ + [ + "Character", + "\u27fc" + ] + ] + }, + { + "input": "&longrightarrow", + "description": "Bad named entity: longrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&longrightarrow" + ] + ] + }, + { + "input": "⟶", + "description": "Named entity: longrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u27f6" + ] + ] + }, + { + "input": "&looparrowleft", + "description": "Bad named entity: looparrowleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&looparrowleft" + ] + ] + }, + { + "input": "↫", + "description": "Named entity: looparrowleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21ab" + ] + ] + }, + { + "input": "&looparrowright", + "description": "Bad named entity: looparrowright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&looparrowright" + ] + ] + }, + { + "input": "↬", + "description": "Named entity: looparrowright; with a semi-colon", + "output": [ + [ + "Character", + "\u21ac" + ] + ] + }, + { + "input": "&lopar", + "description": "Bad named entity: lopar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lopar" + ] + ] + }, + { + "input": "⦅", + "description": "Named entity: lopar; with a semi-colon", + "output": [ + [ + "Character", + "\u2985" + ] + ] + }, + { + "input": "&lopf", + "description": "Bad named entity: lopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lopf" + ] + ] + }, + { + "input": "𝕝", + "description": "Named entity: lopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5d" + ] + ] + }, + { + "input": "&loplus", + "description": "Bad named entity: loplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&loplus" + ] + ] + }, + { + "input": "⨭", + "description": "Named entity: loplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a2d" + ] + ] + }, + { + "input": "&lotimes", + "description": "Bad named entity: lotimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lotimes" + ] + ] + }, + { + "input": "⨴", + "description": "Named entity: lotimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2a34" + ] + ] + }, + { + "input": "&lowast", + "description": "Bad named entity: lowast without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lowast" + ] + ] + }, + { + "input": "∗", + "description": "Named entity: lowast; with a semi-colon", + "output": [ + [ + "Character", + "\u2217" + ] + ] + }, + { + "input": "&lowbar", + "description": "Bad named entity: lowbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lowbar" + ] + ] + }, + { + "input": "_", + "description": "Named entity: lowbar; with a semi-colon", + "output": [ + [ + "Character", + "_" + ] + ] + }, + { + "input": "&loz", + "description": "Bad named entity: loz without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&loz" + ] + ] + }, + { + "input": "◊", + "description": "Named entity: loz; with a semi-colon", + "output": [ + [ + "Character", + "\u25ca" + ] + ] + }, + { + "input": "&lozenge", + "description": "Bad named entity: lozenge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lozenge" + ] + ] + }, + { + "input": "◊", + "description": "Named entity: lozenge; with a semi-colon", + "output": [ + [ + "Character", + "\u25ca" + ] + ] + }, + { + "input": "&lozf", + "description": "Bad named entity: lozf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lozf" + ] + ] + }, + { + "input": "⧫", + "description": "Named entity: lozf; with a semi-colon", + "output": [ + [ + "Character", + "\u29eb" + ] + ] + }, + { + "input": "&lpar", + "description": "Bad named entity: lpar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lpar" + ] + ] + }, + { + "input": "(", + "description": "Named entity: lpar; with a semi-colon", + "output": [ + [ + "Character", + "(" + ] + ] + }, + { + "input": "&lparlt", + "description": "Bad named entity: lparlt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lparlt" + ] + ] + }, + { + "input": "⦓", + "description": "Named entity: lparlt; with a semi-colon", + "output": [ + [ + "Character", + "\u2993" + ] + ] + }, + { + "input": "&lrarr", + "description": "Bad named entity: lrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrarr" + ] + ] + }, + { + "input": "⇆", + "description": "Named entity: lrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c6" + ] + ] + }, + { + "input": "&lrcorner", + "description": "Bad named entity: lrcorner without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrcorner" + ] + ] + }, + { + "input": "⌟", + "description": "Named entity: lrcorner; with a semi-colon", + "output": [ + [ + "Character", + "\u231f" + ] + ] + }, + { + "input": "&lrhar", + "description": "Bad named entity: lrhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrhar" + ] + ] + }, + { + "input": "⇋", + "description": "Named entity: lrhar; with a semi-colon", + "output": [ + [ + "Character", + "\u21cb" + ] + ] + }, + { + "input": "&lrhard", + "description": "Bad named entity: lrhard without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrhard" + ] + ] + }, + { + "input": "⥭", + "description": "Named entity: lrhard; with a semi-colon", + "output": [ + [ + "Character", + "\u296d" + ] + ] + }, + { + "input": "&lrm", + "description": "Bad named entity: lrm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrm" + ] + ] + }, + { + "input": "‎", + "description": "Named entity: lrm; with a semi-colon", + "output": [ + [ + "Character", + "\u200e" + ] + ] + }, + { + "input": "&lrtri", + "description": "Bad named entity: lrtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lrtri" + ] + ] + }, + { + "input": "⊿", + "description": "Named entity: lrtri; with a semi-colon", + "output": [ + [ + "Character", + "\u22bf" + ] + ] + }, + { + "input": "&lsaquo", + "description": "Bad named entity: lsaquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsaquo" + ] + ] + }, + { + "input": "‹", + "description": "Named entity: lsaquo; with a semi-colon", + "output": [ + [ + "Character", + "\u2039" + ] + ] + }, + { + "input": "&lscr", + "description": "Bad named entity: lscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lscr" + ] + ] + }, + { + "input": "𝓁", + "description": "Named entity: lscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc1" + ] + ] + }, + { + "input": "&lsh", + "description": "Bad named entity: lsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsh" + ] + ] + }, + { + "input": "↰", + "description": "Named entity: lsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b0" + ] + ] + }, + { + "input": "&lsim", + "description": "Bad named entity: lsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsim" + ] + ] + }, + { + "input": "≲", + "description": "Named entity: lsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2272" + ] + ] + }, + { + "input": "&lsime", + "description": "Bad named entity: lsime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsime" + ] + ] + }, + { + "input": "⪍", + "description": "Named entity: lsime; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8d" + ] + ] + }, + { + "input": "&lsimg", + "description": "Bad named entity: lsimg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsimg" + ] + ] + }, + { + "input": "⪏", + "description": "Named entity: lsimg; with a semi-colon", + "output": [ + [ + "Character", + "\u2a8f" + ] + ] + }, + { + "input": "&lsqb", + "description": "Bad named entity: lsqb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsqb" + ] + ] + }, + { + "input": "[", + "description": "Named entity: lsqb; with a semi-colon", + "output": [ + [ + "Character", + "[" + ] + ] + }, + { + "input": "&lsquo", + "description": "Bad named entity: lsquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsquo" + ] + ] + }, + { + "input": "‘", + "description": "Named entity: lsquo; with a semi-colon", + "output": [ + [ + "Character", + "\u2018" + ] + ] + }, + { + "input": "&lsquor", + "description": "Bad named entity: lsquor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lsquor" + ] + ] + }, + { + "input": "‚", + "description": "Named entity: lsquor; with a semi-colon", + "output": [ + [ + "Character", + "\u201a" + ] + ] + }, + { + "input": "&lstrok", + "description": "Bad named entity: lstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lstrok" + ] + ] + }, + { + "input": "ł", + "description": "Named entity: lstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0142" + ] + ] + }, + { + "input": "<", + "description": "Named entity: lt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "<" + ] + ] + }, + { + "input": "<", + "description": "Named entity: lt; with a semi-colon", + "output": [ + [ + "Character", + "<" + ] + ] + }, + { + "input": "⪦", + "description": "Named entity: ltcc; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa6" + ] + ] + }, + { + "input": "⩹", + "description": "Named entity: ltcir; with a semi-colon", + "output": [ + [ + "Character", + "\u2a79" + ] + ] + }, + { + "input": "⋖", + "description": "Named entity: ltdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22d6" + ] + ] + }, + { + "input": "⋋", + "description": "Named entity: lthree; with a semi-colon", + "output": [ + [ + "Character", + "\u22cb" + ] + ] + }, + { + "input": "⋉", + "description": "Named entity: ltimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22c9" + ] + ] + }, + { + "input": "⥶", + "description": "Named entity: ltlarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2976" + ] + ] + }, + { + "input": "⩻", + "description": "Named entity: ltquest; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7b" + ] + ] + }, + { + "input": "⦖", + "description": "Named entity: ltrPar; with a semi-colon", + "output": [ + [ + "Character", + "\u2996" + ] + ] + }, + { + "input": "◃", + "description": "Named entity: ltri; with a semi-colon", + "output": [ + [ + "Character", + "\u25c3" + ] + ] + }, + { + "input": "⊴", + "description": "Named entity: ltrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22b4" + ] + ] + }, + { + "input": "◂", + "description": "Named entity: ltrif; with a semi-colon", + "output": [ + [ + "Character", + "\u25c2" + ] + ] + }, + { + "input": "&lurdshar", + "description": "Bad named entity: lurdshar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lurdshar" + ] + ] + }, + { + "input": "⥊", + "description": "Named entity: lurdshar; with a semi-colon", + "output": [ + [ + "Character", + "\u294a" + ] + ] + }, + { + "input": "&luruhar", + "description": "Bad named entity: luruhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&luruhar" + ] + ] + }, + { + "input": "⥦", + "description": "Named entity: luruhar; with a semi-colon", + "output": [ + [ + "Character", + "\u2966" + ] + ] + }, + { + "input": "&lvertneqq", + "description": "Bad named entity: lvertneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lvertneqq" + ] + ] + }, + { + "input": "≨︀", + "description": "Named entity: lvertneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2268\ufe00" + ] + ] + }, + { + "input": "&lvnE", + "description": "Bad named entity: lvnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&lvnE" + ] + ] + }, + { + "input": "≨︀", + "description": "Named entity: lvnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2268\ufe00" + ] + ] + }, + { + "input": "&mDDot", + "description": "Bad named entity: mDDot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mDDot" + ] + ] + }, + { + "input": "∺", + "description": "Named entity: mDDot; with a semi-colon", + "output": [ + [ + "Character", + "\u223a" + ] + ] + }, + { + "input": "¯", + "description": "Named entity: macr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00af" + ] + ] + }, + { + "input": "¯", + "description": "Named entity: macr; with a semi-colon", + "output": [ + [ + "Character", + "\u00af" + ] + ] + }, + { + "input": "&male", + "description": "Bad named entity: male without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&male" + ] + ] + }, + { + "input": "♂", + "description": "Named entity: male; with a semi-colon", + "output": [ + [ + "Character", + "\u2642" + ] + ] + }, + { + "input": "&malt", + "description": "Bad named entity: malt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&malt" + ] + ] + }, + { + "input": "✠", + "description": "Named entity: malt; with a semi-colon", + "output": [ + [ + "Character", + "\u2720" + ] + ] + }, + { + "input": "&maltese", + "description": "Bad named entity: maltese without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&maltese" + ] + ] + }, + { + "input": "✠", + "description": "Named entity: maltese; with a semi-colon", + "output": [ + [ + "Character", + "\u2720" + ] + ] + }, + { + "input": "&map", + "description": "Bad named entity: map without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&map" + ] + ] + }, + { + "input": "↦", + "description": "Named entity: map; with a semi-colon", + "output": [ + [ + "Character", + "\u21a6" + ] + ] + }, + { + "input": "&mapsto", + "description": "Bad named entity: mapsto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mapsto" + ] + ] + }, + { + "input": "↦", + "description": "Named entity: mapsto; with a semi-colon", + "output": [ + [ + "Character", + "\u21a6" + ] + ] + }, + { + "input": "&mapstodown", + "description": "Bad named entity: mapstodown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mapstodown" + ] + ] + }, + { + "input": "↧", + "description": "Named entity: mapstodown; with a semi-colon", + "output": [ + [ + "Character", + "\u21a7" + ] + ] + }, + { + "input": "&mapstoleft", + "description": "Bad named entity: mapstoleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mapstoleft" + ] + ] + }, + { + "input": "↤", + "description": "Named entity: mapstoleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21a4" + ] + ] + }, + { + "input": "&mapstoup", + "description": "Bad named entity: mapstoup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mapstoup" + ] + ] + }, + { + "input": "↥", + "description": "Named entity: mapstoup; with a semi-colon", + "output": [ + [ + "Character", + "\u21a5" + ] + ] + }, + { + "input": "&marker", + "description": "Bad named entity: marker without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&marker" + ] + ] + }, + { + "input": "▮", + "description": "Named entity: marker; with a semi-colon", + "output": [ + [ + "Character", + "\u25ae" + ] + ] + }, + { + "input": "&mcomma", + "description": "Bad named entity: mcomma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mcomma" + ] + ] + }, + { + "input": "⨩", + "description": "Named entity: mcomma; with a semi-colon", + "output": [ + [ + "Character", + "\u2a29" + ] + ] + }, + { + "input": "&mcy", + "description": "Bad named entity: mcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mcy" + ] + ] + }, + { + "input": "м", + "description": "Named entity: mcy; with a semi-colon", + "output": [ + [ + "Character", + "\u043c" + ] + ] + }, + { + "input": "&mdash", + "description": "Bad named entity: mdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mdash" + ] + ] + }, + { + "input": "—", + "description": "Named entity: mdash; with a semi-colon", + "output": [ + [ + "Character", + "\u2014" + ] + ] + }, + { + "input": "&measuredangle", + "description": "Bad named entity: measuredangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&measuredangle" + ] + ] + }, + { + "input": "∡", + "description": "Named entity: measuredangle; with a semi-colon", + "output": [ + [ + "Character", + "\u2221" + ] + ] + }, + { + "input": "&mfr", + "description": "Bad named entity: mfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mfr" + ] + ] + }, + { + "input": "𝔪", + "description": "Named entity: mfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2a" + ] + ] + }, + { + "input": "&mho", + "description": "Bad named entity: mho without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mho" + ] + ] + }, + { + "input": "℧", + "description": "Named entity: mho; with a semi-colon", + "output": [ + [ + "Character", + "\u2127" + ] + ] + }, + { + "input": "µ", + "description": "Named entity: micro without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b5" + ] + ] + }, + { + "input": "µ", + "description": "Named entity: micro; with a semi-colon", + "output": [ + [ + "Character", + "\u00b5" + ] + ] + }, + { + "input": "&mid", + "description": "Bad named entity: mid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mid" + ] + ] + }, + { + "input": "∣", + "description": "Named entity: mid; with a semi-colon", + "output": [ + [ + "Character", + "\u2223" + ] + ] + }, + { + "input": "&midast", + "description": "Bad named entity: midast without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&midast" + ] + ] + }, + { + "input": "*", + "description": "Named entity: midast; with a semi-colon", + "output": [ + [ + "Character", + "*" + ] + ] + }, + { + "input": "&midcir", + "description": "Bad named entity: midcir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&midcir" + ] + ] + }, + { + "input": "⫰", + "description": "Named entity: midcir; with a semi-colon", + "output": [ + [ + "Character", + "\u2af0" + ] + ] + }, + { + "input": "·", + "description": "Named entity: middot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b7" + ] + ] + }, + { + "input": "·", + "description": "Named entity: middot; with a semi-colon", + "output": [ + [ + "Character", + "\u00b7" + ] + ] + }, + { + "input": "&minus", + "description": "Bad named entity: minus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&minus" + ] + ] + }, + { + "input": "−", + "description": "Named entity: minus; with a semi-colon", + "output": [ + [ + "Character", + "\u2212" + ] + ] + }, + { + "input": "&minusb", + "description": "Bad named entity: minusb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&minusb" + ] + ] + }, + { + "input": "⊟", + "description": "Named entity: minusb; with a semi-colon", + "output": [ + [ + "Character", + "\u229f" + ] + ] + }, + { + "input": "&minusd", + "description": "Bad named entity: minusd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&minusd" + ] + ] + }, + { + "input": "∸", + "description": "Named entity: minusd; with a semi-colon", + "output": [ + [ + "Character", + "\u2238" + ] + ] + }, + { + "input": "&minusdu", + "description": "Bad named entity: minusdu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&minusdu" + ] + ] + }, + { + "input": "⨪", + "description": "Named entity: minusdu; with a semi-colon", + "output": [ + [ + "Character", + "\u2a2a" + ] + ] + }, + { + "input": "&mlcp", + "description": "Bad named entity: mlcp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mlcp" + ] + ] + }, + { + "input": "⫛", + "description": "Named entity: mlcp; with a semi-colon", + "output": [ + [ + "Character", + "\u2adb" + ] + ] + }, + { + "input": "&mldr", + "description": "Bad named entity: mldr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mldr" + ] + ] + }, + { + "input": "…", + "description": "Named entity: mldr; with a semi-colon", + "output": [ + [ + "Character", + "\u2026" + ] + ] + }, + { + "input": "&mnplus", + "description": "Bad named entity: mnplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mnplus" + ] + ] + }, + { + "input": "∓", + "description": "Named entity: mnplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2213" + ] + ] + }, + { + "input": "&models", + "description": "Bad named entity: models without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&models" + ] + ] + }, + { + "input": "⊧", + "description": "Named entity: models; with a semi-colon", + "output": [ + [ + "Character", + "\u22a7" + ] + ] + }, + { + "input": "&mopf", + "description": "Bad named entity: mopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mopf" + ] + ] + }, + { + "input": "𝕞", + "description": "Named entity: mopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5e" + ] + ] + }, + { + "input": "&mp", + "description": "Bad named entity: mp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mp" + ] + ] + }, + { + "input": "∓", + "description": "Named entity: mp; with a semi-colon", + "output": [ + [ + "Character", + "\u2213" + ] + ] + }, + { + "input": "&mscr", + "description": "Bad named entity: mscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mscr" + ] + ] + }, + { + "input": "𝓂", + "description": "Named entity: mscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc2" + ] + ] + }, + { + "input": "&mstpos", + "description": "Bad named entity: mstpos without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mstpos" + ] + ] + }, + { + "input": "∾", + "description": "Named entity: mstpos; with a semi-colon", + "output": [ + [ + "Character", + "\u223e" + ] + ] + }, + { + "input": "&mu", + "description": "Bad named entity: mu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mu" + ] + ] + }, + { + "input": "μ", + "description": "Named entity: mu; with a semi-colon", + "output": [ + [ + "Character", + "\u03bc" + ] + ] + }, + { + "input": "&multimap", + "description": "Bad named entity: multimap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&multimap" + ] + ] + }, + { + "input": "⊸", + "description": "Named entity: multimap; with a semi-colon", + "output": [ + [ + "Character", + "\u22b8" + ] + ] + }, + { + "input": "&mumap", + "description": "Bad named entity: mumap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&mumap" + ] + ] + }, + { + "input": "⊸", + "description": "Named entity: mumap; with a semi-colon", + "output": [ + [ + "Character", + "\u22b8" + ] + ] + }, + { + "input": "&nGg", + "description": "Bad named entity: nGg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nGg" + ] + ] + }, + { + "input": "⋙̸", + "description": "Named entity: nGg; with a semi-colon", + "output": [ + [ + "Character", + "\u22d9\u0338" + ] + ] + }, + { + "input": "&nGt", + "description": "Bad named entity: nGt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nGt" + ] + ] + }, + { + "input": "≫⃒", + "description": "Named entity: nGt; with a semi-colon", + "output": [ + [ + "Character", + "\u226b\u20d2" + ] + ] + }, + { + "input": "&nGtv", + "description": "Bad named entity: nGtv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nGtv" + ] + ] + }, + { + "input": "≫̸", + "description": "Named entity: nGtv; with a semi-colon", + "output": [ + [ + "Character", + "\u226b\u0338" + ] + ] + }, + { + "input": "&nLeftarrow", + "description": "Bad named entity: nLeftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nLeftarrow" + ] + ] + }, + { + "input": "⇍", + "description": "Named entity: nLeftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21cd" + ] + ] + }, + { + "input": "&nLeftrightarrow", + "description": "Bad named entity: nLeftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nLeftrightarrow" + ] + ] + }, + { + "input": "⇎", + "description": "Named entity: nLeftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21ce" + ] + ] + }, + { + "input": "&nLl", + "description": "Bad named entity: nLl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nLl" + ] + ] + }, + { + "input": "⋘̸", + "description": "Named entity: nLl; with a semi-colon", + "output": [ + [ + "Character", + "\u22d8\u0338" + ] + ] + }, + { + "input": "&nLt", + "description": "Bad named entity: nLt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nLt" + ] + ] + }, + { + "input": "≪⃒", + "description": "Named entity: nLt; with a semi-colon", + "output": [ + [ + "Character", + "\u226a\u20d2" + ] + ] + }, + { + "input": "&nLtv", + "description": "Bad named entity: nLtv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nLtv" + ] + ] + }, + { + "input": "≪̸", + "description": "Named entity: nLtv; with a semi-colon", + "output": [ + [ + "Character", + "\u226a\u0338" + ] + ] + }, + { + "input": "&nRightarrow", + "description": "Bad named entity: nRightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nRightarrow" + ] + ] + }, + { + "input": "⇏", + "description": "Named entity: nRightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21cf" + ] + ] + }, + { + "input": "&nVDash", + "description": "Bad named entity: nVDash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nVDash" + ] + ] + }, + { + "input": "⊯", + "description": "Named entity: nVDash; with a semi-colon", + "output": [ + [ + "Character", + "\u22af" + ] + ] + }, + { + "input": "&nVdash", + "description": "Bad named entity: nVdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nVdash" + ] + ] + }, + { + "input": "⊮", + "description": "Named entity: nVdash; with a semi-colon", + "output": [ + [ + "Character", + "\u22ae" + ] + ] + }, + { + "input": "&nabla", + "description": "Bad named entity: nabla without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nabla" + ] + ] + }, + { + "input": "∇", + "description": "Named entity: nabla; with a semi-colon", + "output": [ + [ + "Character", + "\u2207" + ] + ] + }, + { + "input": "&nacute", + "description": "Bad named entity: nacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nacute" + ] + ] + }, + { + "input": "ń", + "description": "Named entity: nacute; with a semi-colon", + "output": [ + [ + "Character", + "\u0144" + ] + ] + }, + { + "input": "&nang", + "description": "Bad named entity: nang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nang" + ] + ] + }, + { + "input": "∠⃒", + "description": "Named entity: nang; with a semi-colon", + "output": [ + [ + "Character", + "\u2220\u20d2" + ] + ] + }, + { + "input": "&nap", + "description": "Bad named entity: nap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nap" + ] + ] + }, + { + "input": "≉", + "description": "Named entity: nap; with a semi-colon", + "output": [ + [ + "Character", + "\u2249" + ] + ] + }, + { + "input": "&napE", + "description": "Bad named entity: napE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&napE" + ] + ] + }, + { + "input": "⩰̸", + "description": "Named entity: napE; with a semi-colon", + "output": [ + [ + "Character", + "\u2a70\u0338" + ] + ] + }, + { + "input": "&napid", + "description": "Bad named entity: napid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&napid" + ] + ] + }, + { + "input": "≋̸", + "description": "Named entity: napid; with a semi-colon", + "output": [ + [ + "Character", + "\u224b\u0338" + ] + ] + }, + { + "input": "&napos", + "description": "Bad named entity: napos without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&napos" + ] + ] + }, + { + "input": "ʼn", + "description": "Named entity: napos; with a semi-colon", + "output": [ + [ + "Character", + "\u0149" + ] + ] + }, + { + "input": "&napprox", + "description": "Bad named entity: napprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&napprox" + ] + ] + }, + { + "input": "≉", + "description": "Named entity: napprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2249" + ] + ] + }, + { + "input": "&natur", + "description": "Bad named entity: natur without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&natur" + ] + ] + }, + { + "input": "♮", + "description": "Named entity: natur; with a semi-colon", + "output": [ + [ + "Character", + "\u266e" + ] + ] + }, + { + "input": "&natural", + "description": "Bad named entity: natural without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&natural" + ] + ] + }, + { + "input": "♮", + "description": "Named entity: natural; with a semi-colon", + "output": [ + [ + "Character", + "\u266e" + ] + ] + }, + { + "input": "&naturals", + "description": "Bad named entity: naturals without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&naturals" + ] + ] + }, + { + "input": "ℕ", + "description": "Named entity: naturals; with a semi-colon", + "output": [ + [ + "Character", + "\u2115" + ] + ] + }, + { + "input": " ", + "description": "Named entity: nbsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a0" + ] + ] + }, + { + "input": " ", + "description": "Named entity: nbsp; with a semi-colon", + "output": [ + [ + "Character", + "\u00a0" + ] + ] + }, + { + "input": "&nbump", + "description": "Bad named entity: nbump without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nbump" + ] + ] + }, + { + "input": "≎̸", + "description": "Named entity: nbump; with a semi-colon", + "output": [ + [ + "Character", + "\u224e\u0338" + ] + ] + }, + { + "input": "&nbumpe", + "description": "Bad named entity: nbumpe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nbumpe" + ] + ] + }, + { + "input": "≏̸", + "description": "Named entity: nbumpe; with a semi-colon", + "output": [ + [ + "Character", + "\u224f\u0338" + ] + ] + }, + { + "input": "&ncap", + "description": "Bad named entity: ncap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncap" + ] + ] + }, + { + "input": "⩃", + "description": "Named entity: ncap; with a semi-colon", + "output": [ + [ + "Character", + "\u2a43" + ] + ] + }, + { + "input": "&ncaron", + "description": "Bad named entity: ncaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncaron" + ] + ] + }, + { + "input": "ň", + "description": "Named entity: ncaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0148" + ] + ] + }, + { + "input": "&ncedil", + "description": "Bad named entity: ncedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncedil" + ] + ] + }, + { + "input": "ņ", + "description": "Named entity: ncedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0146" + ] + ] + }, + { + "input": "&ncong", + "description": "Bad named entity: ncong without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncong" + ] + ] + }, + { + "input": "≇", + "description": "Named entity: ncong; with a semi-colon", + "output": [ + [ + "Character", + "\u2247" + ] + ] + }, + { + "input": "&ncongdot", + "description": "Bad named entity: ncongdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncongdot" + ] + ] + }, + { + "input": "⩭̸", + "description": "Named entity: ncongdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a6d\u0338" + ] + ] + }, + { + "input": "&ncup", + "description": "Bad named entity: ncup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncup" + ] + ] + }, + { + "input": "⩂", + "description": "Named entity: ncup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a42" + ] + ] + }, + { + "input": "&ncy", + "description": "Bad named entity: ncy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ncy" + ] + ] + }, + { + "input": "н", + "description": "Named entity: ncy; with a semi-colon", + "output": [ + [ + "Character", + "\u043d" + ] + ] + }, + { + "input": "&ndash", + "description": "Bad named entity: ndash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ndash" + ] + ] + }, + { + "input": "–", + "description": "Named entity: ndash; with a semi-colon", + "output": [ + [ + "Character", + "\u2013" + ] + ] + }, + { + "input": "&ne", + "description": "Bad named entity: ne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ne" + ] + ] + }, + { + "input": "≠", + "description": "Named entity: ne; with a semi-colon", + "output": [ + [ + "Character", + "\u2260" + ] + ] + }, + { + "input": "&neArr", + "description": "Bad named entity: neArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&neArr" + ] + ] + }, + { + "input": "⇗", + "description": "Named entity: neArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d7" + ] + ] + }, + { + "input": "&nearhk", + "description": "Bad named entity: nearhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nearhk" + ] + ] + }, + { + "input": "⤤", + "description": "Named entity: nearhk; with a semi-colon", + "output": [ + [ + "Character", + "\u2924" + ] + ] + }, + { + "input": "&nearr", + "description": "Bad named entity: nearr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nearr" + ] + ] + }, + { + "input": "↗", + "description": "Named entity: nearr; with a semi-colon", + "output": [ + [ + "Character", + "\u2197" + ] + ] + }, + { + "input": "&nearrow", + "description": "Bad named entity: nearrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nearrow" + ] + ] + }, + { + "input": "↗", + "description": "Named entity: nearrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2197" + ] + ] + }, + { + "input": "&nedot", + "description": "Bad named entity: nedot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nedot" + ] + ] + }, + { + "input": "≐̸", + "description": "Named entity: nedot; with a semi-colon", + "output": [ + [ + "Character", + "\u2250\u0338" + ] + ] + }, + { + "input": "&nequiv", + "description": "Bad named entity: nequiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nequiv" + ] + ] + }, + { + "input": "≢", + "description": "Named entity: nequiv; with a semi-colon", + "output": [ + [ + "Character", + "\u2262" + ] + ] + }, + { + "input": "&nesear", + "description": "Bad named entity: nesear without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nesear" + ] + ] + }, + { + "input": "⤨", + "description": "Named entity: nesear; with a semi-colon", + "output": [ + [ + "Character", + "\u2928" + ] + ] + }, + { + "input": "&nesim", + "description": "Bad named entity: nesim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nesim" + ] + ] + }, + { + "input": "≂̸", + "description": "Named entity: nesim; with a semi-colon", + "output": [ + [ + "Character", + "\u2242\u0338" + ] + ] + }, + { + "input": "&nexist", + "description": "Bad named entity: nexist without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nexist" + ] + ] + }, + { + "input": "∄", + "description": "Named entity: nexist; with a semi-colon", + "output": [ + [ + "Character", + "\u2204" + ] + ] + }, + { + "input": "&nexists", + "description": "Bad named entity: nexists without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nexists" + ] + ] + }, + { + "input": "∄", + "description": "Named entity: nexists; with a semi-colon", + "output": [ + [ + "Character", + "\u2204" + ] + ] + }, + { + "input": "&nfr", + "description": "Bad named entity: nfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nfr" + ] + ] + }, + { + "input": "𝔫", + "description": "Named entity: nfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2b" + ] + ] + }, + { + "input": "&ngE", + "description": "Bad named entity: ngE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngE" + ] + ] + }, + { + "input": "≧̸", + "description": "Named entity: ngE; with a semi-colon", + "output": [ + [ + "Character", + "\u2267\u0338" + ] + ] + }, + { + "input": "&nge", + "description": "Bad named entity: nge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nge" + ] + ] + }, + { + "input": "≱", + "description": "Named entity: nge; with a semi-colon", + "output": [ + [ + "Character", + "\u2271" + ] + ] + }, + { + "input": "&ngeq", + "description": "Bad named entity: ngeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngeq" + ] + ] + }, + { + "input": "≱", + "description": "Named entity: ngeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2271" + ] + ] + }, + { + "input": "&ngeqq", + "description": "Bad named entity: ngeqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngeqq" + ] + ] + }, + { + "input": "≧̸", + "description": "Named entity: ngeqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2267\u0338" + ] + ] + }, + { + "input": "&ngeqslant", + "description": "Bad named entity: ngeqslant without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngeqslant" + ] + ] + }, + { + "input": "⩾̸", + "description": "Named entity: ngeqslant; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e\u0338" + ] + ] + }, + { + "input": "&nges", + "description": "Bad named entity: nges without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nges" + ] + ] + }, + { + "input": "⩾̸", + "description": "Named entity: nges; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7e\u0338" + ] + ] + }, + { + "input": "&ngsim", + "description": "Bad named entity: ngsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngsim" + ] + ] + }, + { + "input": "≵", + "description": "Named entity: ngsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2275" + ] + ] + }, + { + "input": "&ngt", + "description": "Bad named entity: ngt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngt" + ] + ] + }, + { + "input": "≯", + "description": "Named entity: ngt; with a semi-colon", + "output": [ + [ + "Character", + "\u226f" + ] + ] + }, + { + "input": "&ngtr", + "description": "Bad named entity: ngtr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ngtr" + ] + ] + }, + { + "input": "≯", + "description": "Named entity: ngtr; with a semi-colon", + "output": [ + [ + "Character", + "\u226f" + ] + ] + }, + { + "input": "&nhArr", + "description": "Bad named entity: nhArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nhArr" + ] + ] + }, + { + "input": "⇎", + "description": "Named entity: nhArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21ce" + ] + ] + }, + { + "input": "&nharr", + "description": "Bad named entity: nharr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nharr" + ] + ] + }, + { + "input": "↮", + "description": "Named entity: nharr; with a semi-colon", + "output": [ + [ + "Character", + "\u21ae" + ] + ] + }, + { + "input": "&nhpar", + "description": "Bad named entity: nhpar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nhpar" + ] + ] + }, + { + "input": "⫲", + "description": "Named entity: nhpar; with a semi-colon", + "output": [ + [ + "Character", + "\u2af2" + ] + ] + }, + { + "input": "&ni", + "description": "Bad named entity: ni without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ni" + ] + ] + }, + { + "input": "∋", + "description": "Named entity: ni; with a semi-colon", + "output": [ + [ + "Character", + "\u220b" + ] + ] + }, + { + "input": "&nis", + "description": "Bad named entity: nis without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nis" + ] + ] + }, + { + "input": "⋼", + "description": "Named entity: nis; with a semi-colon", + "output": [ + [ + "Character", + "\u22fc" + ] + ] + }, + { + "input": "&nisd", + "description": "Bad named entity: nisd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nisd" + ] + ] + }, + { + "input": "⋺", + "description": "Named entity: nisd; with a semi-colon", + "output": [ + [ + "Character", + "\u22fa" + ] + ] + }, + { + "input": "&niv", + "description": "Bad named entity: niv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&niv" + ] + ] + }, + { + "input": "∋", + "description": "Named entity: niv; with a semi-colon", + "output": [ + [ + "Character", + "\u220b" + ] + ] + }, + { + "input": "&njcy", + "description": "Bad named entity: njcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&njcy" + ] + ] + }, + { + "input": "њ", + "description": "Named entity: njcy; with a semi-colon", + "output": [ + [ + "Character", + "\u045a" + ] + ] + }, + { + "input": "&nlArr", + "description": "Bad named entity: nlArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nlArr" + ] + ] + }, + { + "input": "⇍", + "description": "Named entity: nlArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21cd" + ] + ] + }, + { + "input": "&nlE", + "description": "Bad named entity: nlE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nlE" + ] + ] + }, + { + "input": "≦̸", + "description": "Named entity: nlE; with a semi-colon", + "output": [ + [ + "Character", + "\u2266\u0338" + ] + ] + }, + { + "input": "&nlarr", + "description": "Bad named entity: nlarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nlarr" + ] + ] + }, + { + "input": "↚", + "description": "Named entity: nlarr; with a semi-colon", + "output": [ + [ + "Character", + "\u219a" + ] + ] + }, + { + "input": "&nldr", + "description": "Bad named entity: nldr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nldr" + ] + ] + }, + { + "input": "‥", + "description": "Named entity: nldr; with a semi-colon", + "output": [ + [ + "Character", + "\u2025" + ] + ] + }, + { + "input": "&nle", + "description": "Bad named entity: nle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nle" + ] + ] + }, + { + "input": "≰", + "description": "Named entity: nle; with a semi-colon", + "output": [ + [ + "Character", + "\u2270" + ] + ] + }, + { + "input": "&nleftarrow", + "description": "Bad named entity: nleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nleftarrow" + ] + ] + }, + { + "input": "↚", + "description": "Named entity: nleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u219a" + ] + ] + }, + { + "input": "&nleftrightarrow", + "description": "Bad named entity: nleftrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nleftrightarrow" + ] + ] + }, + { + "input": "↮", + "description": "Named entity: nleftrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21ae" + ] + ] + }, + { + "input": "&nleq", + "description": "Bad named entity: nleq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nleq" + ] + ] + }, + { + "input": "≰", + "description": "Named entity: nleq; with a semi-colon", + "output": [ + [ + "Character", + "\u2270" + ] + ] + }, + { + "input": "&nleqq", + "description": "Bad named entity: nleqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nleqq" + ] + ] + }, + { + "input": "≦̸", + "description": "Named entity: nleqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2266\u0338" + ] + ] + }, + { + "input": "&nleqslant", + "description": "Bad named entity: nleqslant without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nleqslant" + ] + ] + }, + { + "input": "⩽̸", + "description": "Named entity: nleqslant; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d\u0338" + ] + ] + }, + { + "input": "&nles", + "description": "Bad named entity: nles without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nles" + ] + ] + }, + { + "input": "⩽̸", + "description": "Named entity: nles; with a semi-colon", + "output": [ + [ + "Character", + "\u2a7d\u0338" + ] + ] + }, + { + "input": "&nless", + "description": "Bad named entity: nless without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nless" + ] + ] + }, + { + "input": "≮", + "description": "Named entity: nless; with a semi-colon", + "output": [ + [ + "Character", + "\u226e" + ] + ] + }, + { + "input": "&nlsim", + "description": "Bad named entity: nlsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nlsim" + ] + ] + }, + { + "input": "≴", + "description": "Named entity: nlsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2274" + ] + ] + }, + { + "input": "&nlt", + "description": "Bad named entity: nlt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nlt" + ] + ] + }, + { + "input": "≮", + "description": "Named entity: nlt; with a semi-colon", + "output": [ + [ + "Character", + "\u226e" + ] + ] + }, + { + "input": "&nltri", + "description": "Bad named entity: nltri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nltri" + ] + ] + }, + { + "input": "⋪", + "description": "Named entity: nltri; with a semi-colon", + "output": [ + [ + "Character", + "\u22ea" + ] + ] + }, + { + "input": "&nltrie", + "description": "Bad named entity: nltrie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nltrie" + ] + ] + }, + { + "input": "⋬", + "description": "Named entity: nltrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22ec" + ] + ] + }, + { + "input": "&nmid", + "description": "Bad named entity: nmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nmid" + ] + ] + }, + { + "input": "∤", + "description": "Named entity: nmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2224" + ] + ] + }, + { + "input": "&nopf", + "description": "Bad named entity: nopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nopf" + ] + ] + }, + { + "input": "𝕟", + "description": "Named entity: nopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd5f" + ] + ] + }, + { + "input": "¬", + "description": "Named entity: not without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ac" + ] + ] + }, + { + "input": "¬", + "description": "Named entity: not; with a semi-colon", + "output": [ + [ + "Character", + "\u00ac" + ] + ] + }, + { + "input": "∉", + "description": "Named entity: notin; with a semi-colon", + "output": [ + [ + "Character", + "\u2209" + ] + ] + }, + { + "input": "⋹̸", + "description": "Named entity: notinE; with a semi-colon", + "output": [ + [ + "Character", + "\u22f9\u0338" + ] + ] + }, + { + "input": "⋵̸", + "description": "Named entity: notindot; with a semi-colon", + "output": [ + [ + "Character", + "\u22f5\u0338" + ] + ] + }, + { + "input": "∉", + "description": "Named entity: notinva; with a semi-colon", + "output": [ + [ + "Character", + "\u2209" + ] + ] + }, + { + "input": "⋷", + "description": "Named entity: notinvb; with a semi-colon", + "output": [ + [ + "Character", + "\u22f7" + ] + ] + }, + { + "input": "⋶", + "description": "Named entity: notinvc; with a semi-colon", + "output": [ + [ + "Character", + "\u22f6" + ] + ] + }, + { + "input": "∌", + "description": "Named entity: notni; with a semi-colon", + "output": [ + [ + "Character", + "\u220c" + ] + ] + }, + { + "input": "∌", + "description": "Named entity: notniva; with a semi-colon", + "output": [ + [ + "Character", + "\u220c" + ] + ] + }, + { + "input": "⋾", + "description": "Named entity: notnivb; with a semi-colon", + "output": [ + [ + "Character", + "\u22fe" + ] + ] + }, + { + "input": "⋽", + "description": "Named entity: notnivc; with a semi-colon", + "output": [ + [ + "Character", + "\u22fd" + ] + ] + }, + { + "input": "&npar", + "description": "Bad named entity: npar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npar" + ] + ] + }, + { + "input": "∦", + "description": "Named entity: npar; with a semi-colon", + "output": [ + [ + "Character", + "\u2226" + ] + ] + }, + { + "input": "&nparallel", + "description": "Bad named entity: nparallel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nparallel" + ] + ] + }, + { + "input": "∦", + "description": "Named entity: nparallel; with a semi-colon", + "output": [ + [ + "Character", + "\u2226" + ] + ] + }, + { + "input": "&nparsl", + "description": "Bad named entity: nparsl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nparsl" + ] + ] + }, + { + "input": "⫽⃥", + "description": "Named entity: nparsl; with a semi-colon", + "output": [ + [ + "Character", + "\u2afd\u20e5" + ] + ] + }, + { + "input": "&npart", + "description": "Bad named entity: npart without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npart" + ] + ] + }, + { + "input": "∂̸", + "description": "Named entity: npart; with a semi-colon", + "output": [ + [ + "Character", + "\u2202\u0338" + ] + ] + }, + { + "input": "&npolint", + "description": "Bad named entity: npolint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npolint" + ] + ] + }, + { + "input": "⨔", + "description": "Named entity: npolint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a14" + ] + ] + }, + { + "input": "&npr", + "description": "Bad named entity: npr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npr" + ] + ] + }, + { + "input": "⊀", + "description": "Named entity: npr; with a semi-colon", + "output": [ + [ + "Character", + "\u2280" + ] + ] + }, + { + "input": "&nprcue", + "description": "Bad named entity: nprcue without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nprcue" + ] + ] + }, + { + "input": "⋠", + "description": "Named entity: nprcue; with a semi-colon", + "output": [ + [ + "Character", + "\u22e0" + ] + ] + }, + { + "input": "&npre", + "description": "Bad named entity: npre without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npre" + ] + ] + }, + { + "input": "⪯̸", + "description": "Named entity: npre; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf\u0338" + ] + ] + }, + { + "input": "&nprec", + "description": "Bad named entity: nprec without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nprec" + ] + ] + }, + { + "input": "⊀", + "description": "Named entity: nprec; with a semi-colon", + "output": [ + [ + "Character", + "\u2280" + ] + ] + }, + { + "input": "&npreceq", + "description": "Bad named entity: npreceq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&npreceq" + ] + ] + }, + { + "input": "⪯̸", + "description": "Named entity: npreceq; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf\u0338" + ] + ] + }, + { + "input": "&nrArr", + "description": "Bad named entity: nrArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrArr" + ] + ] + }, + { + "input": "⇏", + "description": "Named entity: nrArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21cf" + ] + ] + }, + { + "input": "&nrarr", + "description": "Bad named entity: nrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrarr" + ] + ] + }, + { + "input": "↛", + "description": "Named entity: nrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u219b" + ] + ] + }, + { + "input": "&nrarrc", + "description": "Bad named entity: nrarrc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrarrc" + ] + ] + }, + { + "input": "⤳̸", + "description": "Named entity: nrarrc; with a semi-colon", + "output": [ + [ + "Character", + "\u2933\u0338" + ] + ] + }, + { + "input": "&nrarrw", + "description": "Bad named entity: nrarrw without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrarrw" + ] + ] + }, + { + "input": "↝̸", + "description": "Named entity: nrarrw; with a semi-colon", + "output": [ + [ + "Character", + "\u219d\u0338" + ] + ] + }, + { + "input": "&nrightarrow", + "description": "Bad named entity: nrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrightarrow" + ] + ] + }, + { + "input": "↛", + "description": "Named entity: nrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u219b" + ] + ] + }, + { + "input": "&nrtri", + "description": "Bad named entity: nrtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrtri" + ] + ] + }, + { + "input": "⋫", + "description": "Named entity: nrtri; with a semi-colon", + "output": [ + [ + "Character", + "\u22eb" + ] + ] + }, + { + "input": "&nrtrie", + "description": "Bad named entity: nrtrie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nrtrie" + ] + ] + }, + { + "input": "⋭", + "description": "Named entity: nrtrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22ed" + ] + ] + }, + { + "input": "&nsc", + "description": "Bad named entity: nsc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsc" + ] + ] + }, + { + "input": "⊁", + "description": "Named entity: nsc; with a semi-colon", + "output": [ + [ + "Character", + "\u2281" + ] + ] + }, + { + "input": "&nsccue", + "description": "Bad named entity: nsccue without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsccue" + ] + ] + }, + { + "input": "⋡", + "description": "Named entity: nsccue; with a semi-colon", + "output": [ + [ + "Character", + "\u22e1" + ] + ] + }, + { + "input": "&nsce", + "description": "Bad named entity: nsce without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsce" + ] + ] + }, + { + "input": "⪰̸", + "description": "Named entity: nsce; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0\u0338" + ] + ] + }, + { + "input": "&nscr", + "description": "Bad named entity: nscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nscr" + ] + ] + }, + { + "input": "𝓃", + "description": "Named entity: nscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc3" + ] + ] + }, + { + "input": "&nshortmid", + "description": "Bad named entity: nshortmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nshortmid" + ] + ] + }, + { + "input": "∤", + "description": "Named entity: nshortmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2224" + ] + ] + }, + { + "input": "&nshortparallel", + "description": "Bad named entity: nshortparallel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nshortparallel" + ] + ] + }, + { + "input": "∦", + "description": "Named entity: nshortparallel; with a semi-colon", + "output": [ + [ + "Character", + "\u2226" + ] + ] + }, + { + "input": "&nsim", + "description": "Bad named entity: nsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsim" + ] + ] + }, + { + "input": "≁", + "description": "Named entity: nsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2241" + ] + ] + }, + { + "input": "&nsime", + "description": "Bad named entity: nsime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsime" + ] + ] + }, + { + "input": "≄", + "description": "Named entity: nsime; with a semi-colon", + "output": [ + [ + "Character", + "\u2244" + ] + ] + }, + { + "input": "&nsimeq", + "description": "Bad named entity: nsimeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsimeq" + ] + ] + }, + { + "input": "≄", + "description": "Named entity: nsimeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2244" + ] + ] + }, + { + "input": "&nsmid", + "description": "Bad named entity: nsmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsmid" + ] + ] + }, + { + "input": "∤", + "description": "Named entity: nsmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2224" + ] + ] + }, + { + "input": "&nspar", + "description": "Bad named entity: nspar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nspar" + ] + ] + }, + { + "input": "∦", + "description": "Named entity: nspar; with a semi-colon", + "output": [ + [ + "Character", + "\u2226" + ] + ] + }, + { + "input": "&nsqsube", + "description": "Bad named entity: nsqsube without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsqsube" + ] + ] + }, + { + "input": "⋢", + "description": "Named entity: nsqsube; with a semi-colon", + "output": [ + [ + "Character", + "\u22e2" + ] + ] + }, + { + "input": "&nsqsupe", + "description": "Bad named entity: nsqsupe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsqsupe" + ] + ] + }, + { + "input": "⋣", + "description": "Named entity: nsqsupe; with a semi-colon", + "output": [ + [ + "Character", + "\u22e3" + ] + ] + }, + { + "input": "&nsub", + "description": "Bad named entity: nsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsub" + ] + ] + }, + { + "input": "⊄", + "description": "Named entity: nsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2284" + ] + ] + }, + { + "input": "&nsubE", + "description": "Bad named entity: nsubE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsubE" + ] + ] + }, + { + "input": "⫅̸", + "description": "Named entity: nsubE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac5\u0338" + ] + ] + }, + { + "input": "&nsube", + "description": "Bad named entity: nsube without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsube" + ] + ] + }, + { + "input": "⊈", + "description": "Named entity: nsube; with a semi-colon", + "output": [ + [ + "Character", + "\u2288" + ] + ] + }, + { + "input": "&nsubset", + "description": "Bad named entity: nsubset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsubset" + ] + ] + }, + { + "input": "⊂⃒", + "description": "Named entity: nsubset; with a semi-colon", + "output": [ + [ + "Character", + "\u2282\u20d2" + ] + ] + }, + { + "input": "&nsubseteq", + "description": "Bad named entity: nsubseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsubseteq" + ] + ] + }, + { + "input": "⊈", + "description": "Named entity: nsubseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2288" + ] + ] + }, + { + "input": "&nsubseteqq", + "description": "Bad named entity: nsubseteqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsubseteqq" + ] + ] + }, + { + "input": "⫅̸", + "description": "Named entity: nsubseteqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac5\u0338" + ] + ] + }, + { + "input": "&nsucc", + "description": "Bad named entity: nsucc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsucc" + ] + ] + }, + { + "input": "⊁", + "description": "Named entity: nsucc; with a semi-colon", + "output": [ + [ + "Character", + "\u2281" + ] + ] + }, + { + "input": "&nsucceq", + "description": "Bad named entity: nsucceq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsucceq" + ] + ] + }, + { + "input": "⪰̸", + "description": "Named entity: nsucceq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0\u0338" + ] + ] + }, + { + "input": "&nsup", + "description": "Bad named entity: nsup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsup" + ] + ] + }, + { + "input": "⊅", + "description": "Named entity: nsup; with a semi-colon", + "output": [ + [ + "Character", + "\u2285" + ] + ] + }, + { + "input": "&nsupE", + "description": "Bad named entity: nsupE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsupE" + ] + ] + }, + { + "input": "⫆̸", + "description": "Named entity: nsupE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac6\u0338" + ] + ] + }, + { + "input": "&nsupe", + "description": "Bad named entity: nsupe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsupe" + ] + ] + }, + { + "input": "⊉", + "description": "Named entity: nsupe; with a semi-colon", + "output": [ + [ + "Character", + "\u2289" + ] + ] + }, + { + "input": "&nsupset", + "description": "Bad named entity: nsupset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsupset" + ] + ] + }, + { + "input": "⊃⃒", + "description": "Named entity: nsupset; with a semi-colon", + "output": [ + [ + "Character", + "\u2283\u20d2" + ] + ] + }, + { + "input": "&nsupseteq", + "description": "Bad named entity: nsupseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsupseteq" + ] + ] + }, + { + "input": "⊉", + "description": "Named entity: nsupseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2289" + ] + ] + }, + { + "input": "&nsupseteqq", + "description": "Bad named entity: nsupseteqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nsupseteqq" + ] + ] + }, + { + "input": "⫆̸", + "description": "Named entity: nsupseteqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac6\u0338" + ] + ] + }, + { + "input": "&ntgl", + "description": "Bad named entity: ntgl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntgl" + ] + ] + }, + { + "input": "≹", + "description": "Named entity: ntgl; with a semi-colon", + "output": [ + [ + "Character", + "\u2279" + ] + ] + }, + { + "input": "ñ", + "description": "Named entity: ntilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f1" + ] + ] + }, + { + "input": "ñ", + "description": "Named entity: ntilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00f1" + ] + ] + }, + { + "input": "&ntlg", + "description": "Bad named entity: ntlg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntlg" + ] + ] + }, + { + "input": "≸", + "description": "Named entity: ntlg; with a semi-colon", + "output": [ + [ + "Character", + "\u2278" + ] + ] + }, + { + "input": "&ntriangleleft", + "description": "Bad named entity: ntriangleleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntriangleleft" + ] + ] + }, + { + "input": "⋪", + "description": "Named entity: ntriangleleft; with a semi-colon", + "output": [ + [ + "Character", + "\u22ea" + ] + ] + }, + { + "input": "&ntrianglelefteq", + "description": "Bad named entity: ntrianglelefteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntrianglelefteq" + ] + ] + }, + { + "input": "⋬", + "description": "Named entity: ntrianglelefteq; with a semi-colon", + "output": [ + [ + "Character", + "\u22ec" + ] + ] + }, + { + "input": "&ntriangleright", + "description": "Bad named entity: ntriangleright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntriangleright" + ] + ] + }, + { + "input": "⋫", + "description": "Named entity: ntriangleright; with a semi-colon", + "output": [ + [ + "Character", + "\u22eb" + ] + ] + }, + { + "input": "&ntrianglerighteq", + "description": "Bad named entity: ntrianglerighteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ntrianglerighteq" + ] + ] + }, + { + "input": "⋭", + "description": "Named entity: ntrianglerighteq; with a semi-colon", + "output": [ + [ + "Character", + "\u22ed" + ] + ] + }, + { + "input": "&nu", + "description": "Bad named entity: nu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nu" + ] + ] + }, + { + "input": "ν", + "description": "Named entity: nu; with a semi-colon", + "output": [ + [ + "Character", + "\u03bd" + ] + ] + }, + { + "input": "&num", + "description": "Bad named entity: num without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&num" + ] + ] + }, + { + "input": "#", + "description": "Named entity: num; with a semi-colon", + "output": [ + [ + "Character", + "#" + ] + ] + }, + { + "input": "&numero", + "description": "Bad named entity: numero without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&numero" + ] + ] + }, + { + "input": "№", + "description": "Named entity: numero; with a semi-colon", + "output": [ + [ + "Character", + "\u2116" + ] + ] + }, + { + "input": "&numsp", + "description": "Bad named entity: numsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&numsp" + ] + ] + }, + { + "input": " ", + "description": "Named entity: numsp; with a semi-colon", + "output": [ + [ + "Character", + "\u2007" + ] + ] + }, + { + "input": "&nvDash", + "description": "Bad named entity: nvDash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvDash" + ] + ] + }, + { + "input": "⊭", + "description": "Named entity: nvDash; with a semi-colon", + "output": [ + [ + "Character", + "\u22ad" + ] + ] + }, + { + "input": "&nvHarr", + "description": "Bad named entity: nvHarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvHarr" + ] + ] + }, + { + "input": "⤄", + "description": "Named entity: nvHarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2904" + ] + ] + }, + { + "input": "&nvap", + "description": "Bad named entity: nvap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvap" + ] + ] + }, + { + "input": "≍⃒", + "description": "Named entity: nvap; with a semi-colon", + "output": [ + [ + "Character", + "\u224d\u20d2" + ] + ] + }, + { + "input": "&nvdash", + "description": "Bad named entity: nvdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvdash" + ] + ] + }, + { + "input": "⊬", + "description": "Named entity: nvdash; with a semi-colon", + "output": [ + [ + "Character", + "\u22ac" + ] + ] + }, + { + "input": "&nvge", + "description": "Bad named entity: nvge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvge" + ] + ] + }, + { + "input": "≥⃒", + "description": "Named entity: nvge; with a semi-colon", + "output": [ + [ + "Character", + "\u2265\u20d2" + ] + ] + }, + { + "input": "&nvgt", + "description": "Bad named entity: nvgt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvgt" + ] + ] + }, + { + "input": ">⃒", + "description": "Named entity: nvgt; with a semi-colon", + "output": [ + [ + "Character", + ">\u20d2" + ] + ] + }, + { + "input": "&nvinfin", + "description": "Bad named entity: nvinfin without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvinfin" + ] + ] + }, + { + "input": "⧞", + "description": "Named entity: nvinfin; with a semi-colon", + "output": [ + [ + "Character", + "\u29de" + ] + ] + }, + { + "input": "&nvlArr", + "description": "Bad named entity: nvlArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvlArr" + ] + ] + }, + { + "input": "⤂", + "description": "Named entity: nvlArr; with a semi-colon", + "output": [ + [ + "Character", + "\u2902" + ] + ] + }, + { + "input": "&nvle", + "description": "Bad named entity: nvle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvle" + ] + ] + }, + { + "input": "≤⃒", + "description": "Named entity: nvle; with a semi-colon", + "output": [ + [ + "Character", + "\u2264\u20d2" + ] + ] + }, + { + "input": "&nvlt", + "description": "Bad named entity: nvlt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvlt" + ] + ] + }, + { + "input": "<⃒", + "description": "Named entity: nvlt; with a semi-colon", + "output": [ + [ + "Character", + "<\u20d2" + ] + ] + }, + { + "input": "&nvltrie", + "description": "Bad named entity: nvltrie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvltrie" + ] + ] + }, + { + "input": "⊴⃒", + "description": "Named entity: nvltrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22b4\u20d2" + ] + ] + }, + { + "input": "&nvrArr", + "description": "Bad named entity: nvrArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvrArr" + ] + ] + }, + { + "input": "⤃", + "description": "Named entity: nvrArr; with a semi-colon", + "output": [ + [ + "Character", + "\u2903" + ] + ] + }, + { + "input": "&nvrtrie", + "description": "Bad named entity: nvrtrie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvrtrie" + ] + ] + }, + { + "input": "⊵⃒", + "description": "Named entity: nvrtrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22b5\u20d2" + ] + ] + }, + { + "input": "&nvsim", + "description": "Bad named entity: nvsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nvsim" + ] + ] + }, + { + "input": "∼⃒", + "description": "Named entity: nvsim; with a semi-colon", + "output": [ + [ + "Character", + "\u223c\u20d2" + ] + ] + }, + { + "input": "&nwArr", + "description": "Bad named entity: nwArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nwArr" + ] + ] + }, + { + "input": "⇖", + "description": "Named entity: nwArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d6" + ] + ] + }, + { + "input": "&nwarhk", + "description": "Bad named entity: nwarhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nwarhk" + ] + ] + }, + { + "input": "⤣", + "description": "Named entity: nwarhk; with a semi-colon", + "output": [ + [ + "Character", + "\u2923" + ] + ] + }, + { + "input": "&nwarr", + "description": "Bad named entity: nwarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nwarr" + ] + ] + }, + { + "input": "↖", + "description": "Named entity: nwarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2196" + ] + ] + }, + { + "input": "&nwarrow", + "description": "Bad named entity: nwarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nwarrow" + ] + ] + }, + { + "input": "↖", + "description": "Named entity: nwarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2196" + ] + ] + }, + { + "input": "&nwnear", + "description": "Bad named entity: nwnear without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&nwnear" + ] + ] + }, + { + "input": "⤧", + "description": "Named entity: nwnear; with a semi-colon", + "output": [ + [ + "Character", + "\u2927" + ] + ] + }, + { + "input": "&oS", + "description": "Bad named entity: oS without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oS" + ] + ] + }, + { + "input": "Ⓢ", + "description": "Named entity: oS; with a semi-colon", + "output": [ + [ + "Character", + "\u24c8" + ] + ] + }, + { + "input": "ó", + "description": "Named entity: oacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f3" + ] + ] + }, + { + "input": "ó", + "description": "Named entity: oacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00f3" + ] + ] + }, + { + "input": "&oast", + "description": "Bad named entity: oast without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oast" + ] + ] + }, + { + "input": "⊛", + "description": "Named entity: oast; with a semi-colon", + "output": [ + [ + "Character", + "\u229b" + ] + ] + }, + { + "input": "&ocir", + "description": "Bad named entity: ocir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ocir" + ] + ] + }, + { + "input": "⊚", + "description": "Named entity: ocir; with a semi-colon", + "output": [ + [ + "Character", + "\u229a" + ] + ] + }, + { + "input": "ô", + "description": "Named entity: ocirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f4" + ] + ] + }, + { + "input": "ô", + "description": "Named entity: ocirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00f4" + ] + ] + }, + { + "input": "&ocy", + "description": "Bad named entity: ocy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ocy" + ] + ] + }, + { + "input": "о", + "description": "Named entity: ocy; with a semi-colon", + "output": [ + [ + "Character", + "\u043e" + ] + ] + }, + { + "input": "&odash", + "description": "Bad named entity: odash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&odash" + ] + ] + }, + { + "input": "⊝", + "description": "Named entity: odash; with a semi-colon", + "output": [ + [ + "Character", + "\u229d" + ] + ] + }, + { + "input": "&odblac", + "description": "Bad named entity: odblac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&odblac" + ] + ] + }, + { + "input": "ő", + "description": "Named entity: odblac; with a semi-colon", + "output": [ + [ + "Character", + "\u0151" + ] + ] + }, + { + "input": "&odiv", + "description": "Bad named entity: odiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&odiv" + ] + ] + }, + { + "input": "⨸", + "description": "Named entity: odiv; with a semi-colon", + "output": [ + [ + "Character", + "\u2a38" + ] + ] + }, + { + "input": "&odot", + "description": "Bad named entity: odot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&odot" + ] + ] + }, + { + "input": "⊙", + "description": "Named entity: odot; with a semi-colon", + "output": [ + [ + "Character", + "\u2299" + ] + ] + }, + { + "input": "&odsold", + "description": "Bad named entity: odsold without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&odsold" + ] + ] + }, + { + "input": "⦼", + "description": "Named entity: odsold; with a semi-colon", + "output": [ + [ + "Character", + "\u29bc" + ] + ] + }, + { + "input": "&oelig", + "description": "Bad named entity: oelig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oelig" + ] + ] + }, + { + "input": "œ", + "description": "Named entity: oelig; with a semi-colon", + "output": [ + [ + "Character", + "\u0153" + ] + ] + }, + { + "input": "&ofcir", + "description": "Bad named entity: ofcir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ofcir" + ] + ] + }, + { + "input": "⦿", + "description": "Named entity: ofcir; with a semi-colon", + "output": [ + [ + "Character", + "\u29bf" + ] + ] + }, + { + "input": "&ofr", + "description": "Bad named entity: ofr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ofr" + ] + ] + }, + { + "input": "𝔬", + "description": "Named entity: ofr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2c" + ] + ] + }, + { + "input": "&ogon", + "description": "Bad named entity: ogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ogon" + ] + ] + }, + { + "input": "˛", + "description": "Named entity: ogon; with a semi-colon", + "output": [ + [ + "Character", + "\u02db" + ] + ] + }, + { + "input": "ò", + "description": "Named entity: ograve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f2" + ] + ] + }, + { + "input": "ò", + "description": "Named entity: ograve; with a semi-colon", + "output": [ + [ + "Character", + "\u00f2" + ] + ] + }, + { + "input": "&ogt", + "description": "Bad named entity: ogt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ogt" + ] + ] + }, + { + "input": "⧁", + "description": "Named entity: ogt; with a semi-colon", + "output": [ + [ + "Character", + "\u29c1" + ] + ] + }, + { + "input": "&ohbar", + "description": "Bad named entity: ohbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ohbar" + ] + ] + }, + { + "input": "⦵", + "description": "Named entity: ohbar; with a semi-colon", + "output": [ + [ + "Character", + "\u29b5" + ] + ] + }, + { + "input": "&ohm", + "description": "Bad named entity: ohm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ohm" + ] + ] + }, + { + "input": "Ω", + "description": "Named entity: ohm; with a semi-colon", + "output": [ + [ + "Character", + "\u03a9" + ] + ] + }, + { + "input": "&oint", + "description": "Bad named entity: oint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oint" + ] + ] + }, + { + "input": "∮", + "description": "Named entity: oint; with a semi-colon", + "output": [ + [ + "Character", + "\u222e" + ] + ] + }, + { + "input": "&olarr", + "description": "Bad named entity: olarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&olarr" + ] + ] + }, + { + "input": "↺", + "description": "Named entity: olarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21ba" + ] + ] + }, + { + "input": "&olcir", + "description": "Bad named entity: olcir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&olcir" + ] + ] + }, + { + "input": "⦾", + "description": "Named entity: olcir; with a semi-colon", + "output": [ + [ + "Character", + "\u29be" + ] + ] + }, + { + "input": "&olcross", + "description": "Bad named entity: olcross without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&olcross" + ] + ] + }, + { + "input": "⦻", + "description": "Named entity: olcross; with a semi-colon", + "output": [ + [ + "Character", + "\u29bb" + ] + ] + }, + { + "input": "&oline", + "description": "Bad named entity: oline without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oline" + ] + ] + }, + { + "input": "‾", + "description": "Named entity: oline; with a semi-colon", + "output": [ + [ + "Character", + "\u203e" + ] + ] + }, + { + "input": "&olt", + "description": "Bad named entity: olt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&olt" + ] + ] + }, + { + "input": "⧀", + "description": "Named entity: olt; with a semi-colon", + "output": [ + [ + "Character", + "\u29c0" + ] + ] + }, + { + "input": "&omacr", + "description": "Bad named entity: omacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&omacr" + ] + ] + }, + { + "input": "ō", + "description": "Named entity: omacr; with a semi-colon", + "output": [ + [ + "Character", + "\u014d" + ] + ] + }, + { + "input": "&omega", + "description": "Bad named entity: omega without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&omega" + ] + ] + }, + { + "input": "ω", + "description": "Named entity: omega; with a semi-colon", + "output": [ + [ + "Character", + "\u03c9" + ] + ] + }, + { + "input": "&omicron", + "description": "Bad named entity: omicron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&omicron" + ] + ] + }, + { + "input": "ο", + "description": "Named entity: omicron; with a semi-colon", + "output": [ + [ + "Character", + "\u03bf" + ] + ] + }, + { + "input": "&omid", + "description": "Bad named entity: omid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&omid" + ] + ] + }, + { + "input": "⦶", + "description": "Named entity: omid; with a semi-colon", + "output": [ + [ + "Character", + "\u29b6" + ] + ] + }, + { + "input": "&ominus", + "description": "Bad named entity: ominus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ominus" + ] + ] + }, + { + "input": "⊖", + "description": "Named entity: ominus; with a semi-colon", + "output": [ + [ + "Character", + "\u2296" + ] + ] + }, + { + "input": "&oopf", + "description": "Bad named entity: oopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oopf" + ] + ] + }, + { + "input": "𝕠", + "description": "Named entity: oopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd60" + ] + ] + }, + { + "input": "&opar", + "description": "Bad named entity: opar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&opar" + ] + ] + }, + { + "input": "⦷", + "description": "Named entity: opar; with a semi-colon", + "output": [ + [ + "Character", + "\u29b7" + ] + ] + }, + { + "input": "&operp", + "description": "Bad named entity: operp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&operp" + ] + ] + }, + { + "input": "⦹", + "description": "Named entity: operp; with a semi-colon", + "output": [ + [ + "Character", + "\u29b9" + ] + ] + }, + { + "input": "&oplus", + "description": "Bad named entity: oplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oplus" + ] + ] + }, + { + "input": "⊕", + "description": "Named entity: oplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2295" + ] + ] + }, + { + "input": "&or", + "description": "Bad named entity: or without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&or" + ] + ] + }, + { + "input": "∨", + "description": "Named entity: or; with a semi-colon", + "output": [ + [ + "Character", + "\u2228" + ] + ] + }, + { + "input": "&orarr", + "description": "Bad named entity: orarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&orarr" + ] + ] + }, + { + "input": "↻", + "description": "Named entity: orarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21bb" + ] + ] + }, + { + "input": "&ord", + "description": "Bad named entity: ord without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ord" + ] + ] + }, + { + "input": "⩝", + "description": "Named entity: ord; with a semi-colon", + "output": [ + [ + "Character", + "\u2a5d" + ] + ] + }, + { + "input": "&order", + "description": "Bad named entity: order without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&order" + ] + ] + }, + { + "input": "ℴ", + "description": "Named entity: order; with a semi-colon", + "output": [ + [ + "Character", + "\u2134" + ] + ] + }, + { + "input": "&orderof", + "description": "Bad named entity: orderof without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&orderof" + ] + ] + }, + { + "input": "ℴ", + "description": "Named entity: orderof; with a semi-colon", + "output": [ + [ + "Character", + "\u2134" + ] + ] + }, + { + "input": "ª", + "description": "Named entity: ordf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00aa" + ] + ] + }, + { + "input": "ª", + "description": "Named entity: ordf; with a semi-colon", + "output": [ + [ + "Character", + "\u00aa" + ] + ] + }, + { + "input": "º", + "description": "Named entity: ordm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ba" + ] + ] + }, + { + "input": "º", + "description": "Named entity: ordm; with a semi-colon", + "output": [ + [ + "Character", + "\u00ba" + ] + ] + }, + { + "input": "&origof", + "description": "Bad named entity: origof without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&origof" + ] + ] + }, + { + "input": "⊶", + "description": "Named entity: origof; with a semi-colon", + "output": [ + [ + "Character", + "\u22b6" + ] + ] + }, + { + "input": "&oror", + "description": "Bad named entity: oror without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oror" + ] + ] + }, + { + "input": "⩖", + "description": "Named entity: oror; with a semi-colon", + "output": [ + [ + "Character", + "\u2a56" + ] + ] + }, + { + "input": "&orslope", + "description": "Bad named entity: orslope without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&orslope" + ] + ] + }, + { + "input": "⩗", + "description": "Named entity: orslope; with a semi-colon", + "output": [ + [ + "Character", + "\u2a57" + ] + ] + }, + { + "input": "&orv", + "description": "Bad named entity: orv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&orv" + ] + ] + }, + { + "input": "⩛", + "description": "Named entity: orv; with a semi-colon", + "output": [ + [ + "Character", + "\u2a5b" + ] + ] + }, + { + "input": "&oscr", + "description": "Bad named entity: oscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&oscr" + ] + ] + }, + { + "input": "ℴ", + "description": "Named entity: oscr; with a semi-colon", + "output": [ + [ + "Character", + "\u2134" + ] + ] + }, + { + "input": "ø", + "description": "Named entity: oslash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f8" + ] + ] + }, + { + "input": "ø", + "description": "Named entity: oslash; with a semi-colon", + "output": [ + [ + "Character", + "\u00f8" + ] + ] + }, + { + "input": "&osol", + "description": "Bad named entity: osol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&osol" + ] + ] + }, + { + "input": "⊘", + "description": "Named entity: osol; with a semi-colon", + "output": [ + [ + "Character", + "\u2298" + ] + ] + }, + { + "input": "õ", + "description": "Named entity: otilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f5" + ] + ] + }, + { + "input": "õ", + "description": "Named entity: otilde; with a semi-colon", + "output": [ + [ + "Character", + "\u00f5" + ] + ] + }, + { + "input": "&otimes", + "description": "Bad named entity: otimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&otimes" + ] + ] + }, + { + "input": "⊗", + "description": "Named entity: otimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2297" + ] + ] + }, + { + "input": "&otimesas", + "description": "Bad named entity: otimesas without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&otimesas" + ] + ] + }, + { + "input": "⨶", + "description": "Named entity: otimesas; with a semi-colon", + "output": [ + [ + "Character", + "\u2a36" + ] + ] + }, + { + "input": "ö", + "description": "Named entity: ouml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f6" + ] + ] + }, + { + "input": "ö", + "description": "Named entity: ouml; with a semi-colon", + "output": [ + [ + "Character", + "\u00f6" + ] + ] + }, + { + "input": "&ovbar", + "description": "Bad named entity: ovbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ovbar" + ] + ] + }, + { + "input": "⌽", + "description": "Named entity: ovbar; with a semi-colon", + "output": [ + [ + "Character", + "\u233d" + ] + ] + }, + { + "input": "&par", + "description": "Bad named entity: par without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&par" + ] + ] + }, + { + "input": "∥", + "description": "Named entity: par; with a semi-colon", + "output": [ + [ + "Character", + "\u2225" + ] + ] + }, + { + "input": "¶", + "description": "Named entity: para without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b6" + ] + ] + }, + { + "input": "¶", + "description": "Named entity: para; with a semi-colon", + "output": [ + [ + "Character", + "\u00b6" + ] + ] + }, + { + "input": "∥", + "description": "Named entity: parallel; with a semi-colon", + "output": [ + [ + "Character", + "\u2225" + ] + ] + }, + { + "input": "&parsim", + "description": "Bad named entity: parsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&parsim" + ] + ] + }, + { + "input": "⫳", + "description": "Named entity: parsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2af3" + ] + ] + }, + { + "input": "&parsl", + "description": "Bad named entity: parsl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&parsl" + ] + ] + }, + { + "input": "⫽", + "description": "Named entity: parsl; with a semi-colon", + "output": [ + [ + "Character", + "\u2afd" + ] + ] + }, + { + "input": "&part", + "description": "Bad named entity: part without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&part" + ] + ] + }, + { + "input": "∂", + "description": "Named entity: part; with a semi-colon", + "output": [ + [ + "Character", + "\u2202" + ] + ] + }, + { + "input": "&pcy", + "description": "Bad named entity: pcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pcy" + ] + ] + }, + { + "input": "п", + "description": "Named entity: pcy; with a semi-colon", + "output": [ + [ + "Character", + "\u043f" + ] + ] + }, + { + "input": "&percnt", + "description": "Bad named entity: percnt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&percnt" + ] + ] + }, + { + "input": "%", + "description": "Named entity: percnt; with a semi-colon", + "output": [ + [ + "Character", + "%" + ] + ] + }, + { + "input": "&period", + "description": "Bad named entity: period without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&period" + ] + ] + }, + { + "input": ".", + "description": "Named entity: period; with a semi-colon", + "output": [ + [ + "Character", + "." + ] + ] + }, + { + "input": "&permil", + "description": "Bad named entity: permil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&permil" + ] + ] + }, + { + "input": "‰", + "description": "Named entity: permil; with a semi-colon", + "output": [ + [ + "Character", + "\u2030" + ] + ] + }, + { + "input": "&perp", + "description": "Bad named entity: perp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&perp" + ] + ] + }, + { + "input": "⊥", + "description": "Named entity: perp; with a semi-colon", + "output": [ + [ + "Character", + "\u22a5" + ] + ] + }, + { + "input": "&pertenk", + "description": "Bad named entity: pertenk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pertenk" + ] + ] + }, + { + "input": "‱", + "description": "Named entity: pertenk; with a semi-colon", + "output": [ + [ + "Character", + "\u2031" + ] + ] + }, + { + "input": "&pfr", + "description": "Bad named entity: pfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pfr" + ] + ] + }, + { + "input": "𝔭", + "description": "Named entity: pfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2d" + ] + ] + }, + { + "input": "&phi", + "description": "Bad named entity: phi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&phi" + ] + ] + }, + { + "input": "φ", + "description": "Named entity: phi; with a semi-colon", + "output": [ + [ + "Character", + "\u03c6" + ] + ] + }, + { + "input": "&phiv", + "description": "Bad named entity: phiv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&phiv" + ] + ] + }, + { + "input": "ϕ", + "description": "Named entity: phiv; with a semi-colon", + "output": [ + [ + "Character", + "\u03d5" + ] + ] + }, + { + "input": "&phmmat", + "description": "Bad named entity: phmmat without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&phmmat" + ] + ] + }, + { + "input": "ℳ", + "description": "Named entity: phmmat; with a semi-colon", + "output": [ + [ + "Character", + "\u2133" + ] + ] + }, + { + "input": "&phone", + "description": "Bad named entity: phone without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&phone" + ] + ] + }, + { + "input": "☎", + "description": "Named entity: phone; with a semi-colon", + "output": [ + [ + "Character", + "\u260e" + ] + ] + }, + { + "input": "&pi", + "description": "Bad named entity: pi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pi" + ] + ] + }, + { + "input": "π", + "description": "Named entity: pi; with a semi-colon", + "output": [ + [ + "Character", + "\u03c0" + ] + ] + }, + { + "input": "&pitchfork", + "description": "Bad named entity: pitchfork without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pitchfork" + ] + ] + }, + { + "input": "⋔", + "description": "Named entity: pitchfork; with a semi-colon", + "output": [ + [ + "Character", + "\u22d4" + ] + ] + }, + { + "input": "&piv", + "description": "Bad named entity: piv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&piv" + ] + ] + }, + { + "input": "ϖ", + "description": "Named entity: piv; with a semi-colon", + "output": [ + [ + "Character", + "\u03d6" + ] + ] + }, + { + "input": "&planck", + "description": "Bad named entity: planck without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&planck" + ] + ] + }, + { + "input": "ℏ", + "description": "Named entity: planck; with a semi-colon", + "output": [ + [ + "Character", + "\u210f" + ] + ] + }, + { + "input": "&planckh", + "description": "Bad named entity: planckh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&planckh" + ] + ] + }, + { + "input": "ℎ", + "description": "Named entity: planckh; with a semi-colon", + "output": [ + [ + "Character", + "\u210e" + ] + ] + }, + { + "input": "&plankv", + "description": "Bad named entity: plankv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plankv" + ] + ] + }, + { + "input": "ℏ", + "description": "Named entity: plankv; with a semi-colon", + "output": [ + [ + "Character", + "\u210f" + ] + ] + }, + { + "input": "&plus", + "description": "Bad named entity: plus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plus" + ] + ] + }, + { + "input": "+", + "description": "Named entity: plus; with a semi-colon", + "output": [ + [ + "Character", + "+" + ] + ] + }, + { + "input": "&plusacir", + "description": "Bad named entity: plusacir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plusacir" + ] + ] + }, + { + "input": "⨣", + "description": "Named entity: plusacir; with a semi-colon", + "output": [ + [ + "Character", + "\u2a23" + ] + ] + }, + { + "input": "&plusb", + "description": "Bad named entity: plusb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plusb" + ] + ] + }, + { + "input": "⊞", + "description": "Named entity: plusb; with a semi-colon", + "output": [ + [ + "Character", + "\u229e" + ] + ] + }, + { + "input": "&pluscir", + "description": "Bad named entity: pluscir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pluscir" + ] + ] + }, + { + "input": "⨢", + "description": "Named entity: pluscir; with a semi-colon", + "output": [ + [ + "Character", + "\u2a22" + ] + ] + }, + { + "input": "&plusdo", + "description": "Bad named entity: plusdo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plusdo" + ] + ] + }, + { + "input": "∔", + "description": "Named entity: plusdo; with a semi-colon", + "output": [ + [ + "Character", + "\u2214" + ] + ] + }, + { + "input": "&plusdu", + "description": "Bad named entity: plusdu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plusdu" + ] + ] + }, + { + "input": "⨥", + "description": "Named entity: plusdu; with a semi-colon", + "output": [ + [ + "Character", + "\u2a25" + ] + ] + }, + { + "input": "&pluse", + "description": "Bad named entity: pluse without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pluse" + ] + ] + }, + { + "input": "⩲", + "description": "Named entity: pluse; with a semi-colon", + "output": [ + [ + "Character", + "\u2a72" + ] + ] + }, + { + "input": "±", + "description": "Named entity: plusmn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b1" + ] + ] + }, + { + "input": "±", + "description": "Named entity: plusmn; with a semi-colon", + "output": [ + [ + "Character", + "\u00b1" + ] + ] + }, + { + "input": "&plussim", + "description": "Bad named entity: plussim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plussim" + ] + ] + }, + { + "input": "⨦", + "description": "Named entity: plussim; with a semi-colon", + "output": [ + [ + "Character", + "\u2a26" + ] + ] + }, + { + "input": "&plustwo", + "description": "Bad named entity: plustwo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&plustwo" + ] + ] + }, + { + "input": "⨧", + "description": "Named entity: plustwo; with a semi-colon", + "output": [ + [ + "Character", + "\u2a27" + ] + ] + }, + { + "input": "&pm", + "description": "Bad named entity: pm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pm" + ] + ] + }, + { + "input": "±", + "description": "Named entity: pm; with a semi-colon", + "output": [ + [ + "Character", + "\u00b1" + ] + ] + }, + { + "input": "&pointint", + "description": "Bad named entity: pointint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pointint" + ] + ] + }, + { + "input": "⨕", + "description": "Named entity: pointint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a15" + ] + ] + }, + { + "input": "&popf", + "description": "Bad named entity: popf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&popf" + ] + ] + }, + { + "input": "𝕡", + "description": "Named entity: popf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd61" + ] + ] + }, + { + "input": "£", + "description": "Named entity: pound without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a3" + ] + ] + }, + { + "input": "£", + "description": "Named entity: pound; with a semi-colon", + "output": [ + [ + "Character", + "\u00a3" + ] + ] + }, + { + "input": "&pr", + "description": "Bad named entity: pr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pr" + ] + ] + }, + { + "input": "≺", + "description": "Named entity: pr; with a semi-colon", + "output": [ + [ + "Character", + "\u227a" + ] + ] + }, + { + "input": "&prE", + "description": "Bad named entity: prE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prE" + ] + ] + }, + { + "input": "⪳", + "description": "Named entity: prE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab3" + ] + ] + }, + { + "input": "&prap", + "description": "Bad named entity: prap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prap" + ] + ] + }, + { + "input": "⪷", + "description": "Named entity: prap; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab7" + ] + ] + }, + { + "input": "&prcue", + "description": "Bad named entity: prcue without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prcue" + ] + ] + }, + { + "input": "≼", + "description": "Named entity: prcue; with a semi-colon", + "output": [ + [ + "Character", + "\u227c" + ] + ] + }, + { + "input": "&pre", + "description": "Bad named entity: pre without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pre" + ] + ] + }, + { + "input": "⪯", + "description": "Named entity: pre; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf" + ] + ] + }, + { + "input": "&prec", + "description": "Bad named entity: prec without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prec" + ] + ] + }, + { + "input": "≺", + "description": "Named entity: prec; with a semi-colon", + "output": [ + [ + "Character", + "\u227a" + ] + ] + }, + { + "input": "&precapprox", + "description": "Bad named entity: precapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&precapprox" + ] + ] + }, + { + "input": "⪷", + "description": "Named entity: precapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab7" + ] + ] + }, + { + "input": "&preccurlyeq", + "description": "Bad named entity: preccurlyeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&preccurlyeq" + ] + ] + }, + { + "input": "≼", + "description": "Named entity: preccurlyeq; with a semi-colon", + "output": [ + [ + "Character", + "\u227c" + ] + ] + }, + { + "input": "&preceq", + "description": "Bad named entity: preceq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&preceq" + ] + ] + }, + { + "input": "⪯", + "description": "Named entity: preceq; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaf" + ] + ] + }, + { + "input": "&precnapprox", + "description": "Bad named entity: precnapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&precnapprox" + ] + ] + }, + { + "input": "⪹", + "description": "Named entity: precnapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab9" + ] + ] + }, + { + "input": "&precneqq", + "description": "Bad named entity: precneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&precneqq" + ] + ] + }, + { + "input": "⪵", + "description": "Named entity: precneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab5" + ] + ] + }, + { + "input": "&precnsim", + "description": "Bad named entity: precnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&precnsim" + ] + ] + }, + { + "input": "⋨", + "description": "Named entity: precnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e8" + ] + ] + }, + { + "input": "&precsim", + "description": "Bad named entity: precsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&precsim" + ] + ] + }, + { + "input": "≾", + "description": "Named entity: precsim; with a semi-colon", + "output": [ + [ + "Character", + "\u227e" + ] + ] + }, + { + "input": "&prime", + "description": "Bad named entity: prime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prime" + ] + ] + }, + { + "input": "′", + "description": "Named entity: prime; with a semi-colon", + "output": [ + [ + "Character", + "\u2032" + ] + ] + }, + { + "input": "&primes", + "description": "Bad named entity: primes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&primes" + ] + ] + }, + { + "input": "ℙ", + "description": "Named entity: primes; with a semi-colon", + "output": [ + [ + "Character", + "\u2119" + ] + ] + }, + { + "input": "&prnE", + "description": "Bad named entity: prnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prnE" + ] + ] + }, + { + "input": "⪵", + "description": "Named entity: prnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab5" + ] + ] + }, + { + "input": "&prnap", + "description": "Bad named entity: prnap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prnap" + ] + ] + }, + { + "input": "⪹", + "description": "Named entity: prnap; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab9" + ] + ] + }, + { + "input": "&prnsim", + "description": "Bad named entity: prnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prnsim" + ] + ] + }, + { + "input": "⋨", + "description": "Named entity: prnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e8" + ] + ] + }, + { + "input": "&prod", + "description": "Bad named entity: prod without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prod" + ] + ] + }, + { + "input": "∏", + "description": "Named entity: prod; with a semi-colon", + "output": [ + [ + "Character", + "\u220f" + ] + ] + }, + { + "input": "&profalar", + "description": "Bad named entity: profalar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&profalar" + ] + ] + }, + { + "input": "⌮", + "description": "Named entity: profalar; with a semi-colon", + "output": [ + [ + "Character", + "\u232e" + ] + ] + }, + { + "input": "&profline", + "description": "Bad named entity: profline without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&profline" + ] + ] + }, + { + "input": "⌒", + "description": "Named entity: profline; with a semi-colon", + "output": [ + [ + "Character", + "\u2312" + ] + ] + }, + { + "input": "&profsurf", + "description": "Bad named entity: profsurf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&profsurf" + ] + ] + }, + { + "input": "⌓", + "description": "Named entity: profsurf; with a semi-colon", + "output": [ + [ + "Character", + "\u2313" + ] + ] + }, + { + "input": "&prop", + "description": "Bad named entity: prop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prop" + ] + ] + }, + { + "input": "∝", + "description": "Named entity: prop; with a semi-colon", + "output": [ + [ + "Character", + "\u221d" + ] + ] + }, + { + "input": "&propto", + "description": "Bad named entity: propto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&propto" + ] + ] + }, + { + "input": "∝", + "description": "Named entity: propto; with a semi-colon", + "output": [ + [ + "Character", + "\u221d" + ] + ] + }, + { + "input": "&prsim", + "description": "Bad named entity: prsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prsim" + ] + ] + }, + { + "input": "≾", + "description": "Named entity: prsim; with a semi-colon", + "output": [ + [ + "Character", + "\u227e" + ] + ] + }, + { + "input": "&prurel", + "description": "Bad named entity: prurel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&prurel" + ] + ] + }, + { + "input": "⊰", + "description": "Named entity: prurel; with a semi-colon", + "output": [ + [ + "Character", + "\u22b0" + ] + ] + }, + { + "input": "&pscr", + "description": "Bad named entity: pscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&pscr" + ] + ] + }, + { + "input": "𝓅", + "description": "Named entity: pscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc5" + ] + ] + }, + { + "input": "&psi", + "description": "Bad named entity: psi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&psi" + ] + ] + }, + { + "input": "ψ", + "description": "Named entity: psi; with a semi-colon", + "output": [ + [ + "Character", + "\u03c8" + ] + ] + }, + { + "input": "&puncsp", + "description": "Bad named entity: puncsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&puncsp" + ] + ] + }, + { + "input": " ", + "description": "Named entity: puncsp; with a semi-colon", + "output": [ + [ + "Character", + "\u2008" + ] + ] + }, + { + "input": "&qfr", + "description": "Bad named entity: qfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&qfr" + ] + ] + }, + { + "input": "𝔮", + "description": "Named entity: qfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2e" + ] + ] + }, + { + "input": "&qint", + "description": "Bad named entity: qint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&qint" + ] + ] + }, + { + "input": "⨌", + "description": "Named entity: qint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a0c" + ] + ] + }, + { + "input": "&qopf", + "description": "Bad named entity: qopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&qopf" + ] + ] + }, + { + "input": "𝕢", + "description": "Named entity: qopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd62" + ] + ] + }, + { + "input": "&qprime", + "description": "Bad named entity: qprime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&qprime" + ] + ] + }, + { + "input": "⁗", + "description": "Named entity: qprime; with a semi-colon", + "output": [ + [ + "Character", + "\u2057" + ] + ] + }, + { + "input": "&qscr", + "description": "Bad named entity: qscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&qscr" + ] + ] + }, + { + "input": "𝓆", + "description": "Named entity: qscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc6" + ] + ] + }, + { + "input": "&quaternions", + "description": "Bad named entity: quaternions without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&quaternions" + ] + ] + }, + { + "input": "ℍ", + "description": "Named entity: quaternions; with a semi-colon", + "output": [ + [ + "Character", + "\u210d" + ] + ] + }, + { + "input": "&quatint", + "description": "Bad named entity: quatint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&quatint" + ] + ] + }, + { + "input": "⨖", + "description": "Named entity: quatint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a16" + ] + ] + }, + { + "input": "&quest", + "description": "Bad named entity: quest without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&quest" + ] + ] + }, + { + "input": "?", + "description": "Named entity: quest; with a semi-colon", + "output": [ + [ + "Character", + "?" + ] + ] + }, + { + "input": "&questeq", + "description": "Bad named entity: questeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&questeq" + ] + ] + }, + { + "input": "≟", + "description": "Named entity: questeq; with a semi-colon", + "output": [ + [ + "Character", + "\u225f" + ] + ] + }, + { + "input": """, + "description": "Named entity: quot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\"" + ] + ] + }, + { + "input": """, + "description": "Named entity: quot; with a semi-colon", + "output": [ + [ + "Character", + "\"" + ] + ] + }, + { + "input": "&rAarr", + "description": "Bad named entity: rAarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rAarr" + ] + ] + }, + { + "input": "⇛", + "description": "Named entity: rAarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21db" + ] + ] + }, + { + "input": "&rArr", + "description": "Bad named entity: rArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rArr" + ] + ] + }, + { + "input": "⇒", + "description": "Named entity: rArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d2" + ] + ] + }, + { + "input": "&rAtail", + "description": "Bad named entity: rAtail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rAtail" + ] + ] + }, + { + "input": "⤜", + "description": "Named entity: rAtail; with a semi-colon", + "output": [ + [ + "Character", + "\u291c" + ] + ] + }, + { + "input": "&rBarr", + "description": "Bad named entity: rBarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rBarr" + ] + ] + }, + { + "input": "⤏", + "description": "Named entity: rBarr; with a semi-colon", + "output": [ + [ + "Character", + "\u290f" + ] + ] + }, + { + "input": "&rHar", + "description": "Bad named entity: rHar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rHar" + ] + ] + }, + { + "input": "⥤", + "description": "Named entity: rHar; with a semi-colon", + "output": [ + [ + "Character", + "\u2964" + ] + ] + }, + { + "input": "&race", + "description": "Bad named entity: race without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&race" + ] + ] + }, + { + "input": "∽̱", + "description": "Named entity: race; with a semi-colon", + "output": [ + [ + "Character", + "\u223d\u0331" + ] + ] + }, + { + "input": "&racute", + "description": "Bad named entity: racute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&racute" + ] + ] + }, + { + "input": "ŕ", + "description": "Named entity: racute; with a semi-colon", + "output": [ + [ + "Character", + "\u0155" + ] + ] + }, + { + "input": "&radic", + "description": "Bad named entity: radic without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&radic" + ] + ] + }, + { + "input": "√", + "description": "Named entity: radic; with a semi-colon", + "output": [ + [ + "Character", + "\u221a" + ] + ] + }, + { + "input": "&raemptyv", + "description": "Bad named entity: raemptyv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&raemptyv" + ] + ] + }, + { + "input": "⦳", + "description": "Named entity: raemptyv; with a semi-colon", + "output": [ + [ + "Character", + "\u29b3" + ] + ] + }, + { + "input": "&rang", + "description": "Bad named entity: rang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rang" + ] + ] + }, + { + "input": "⟩", + "description": "Named entity: rang; with a semi-colon", + "output": [ + [ + "Character", + "\u27e9" + ] + ] + }, + { + "input": "&rangd", + "description": "Bad named entity: rangd without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rangd" + ] + ] + }, + { + "input": "⦒", + "description": "Named entity: rangd; with a semi-colon", + "output": [ + [ + "Character", + "\u2992" + ] + ] + }, + { + "input": "&range", + "description": "Bad named entity: range without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&range" + ] + ] + }, + { + "input": "⦥", + "description": "Named entity: range; with a semi-colon", + "output": [ + [ + "Character", + "\u29a5" + ] + ] + }, + { + "input": "&rangle", + "description": "Bad named entity: rangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rangle" + ] + ] + }, + { + "input": "⟩", + "description": "Named entity: rangle; with a semi-colon", + "output": [ + [ + "Character", + "\u27e9" + ] + ] + }, + { + "input": "»", + "description": "Named entity: raquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00bb" + ] + ] + }, + { + "input": "»", + "description": "Named entity: raquo; with a semi-colon", + "output": [ + [ + "Character", + "\u00bb" + ] + ] + }, + { + "input": "&rarr", + "description": "Bad named entity: rarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarr" + ] + ] + }, + { + "input": "→", + "description": "Named entity: rarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2192" + ] + ] + }, + { + "input": "&rarrap", + "description": "Bad named entity: rarrap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrap" + ] + ] + }, + { + "input": "⥵", + "description": "Named entity: rarrap; with a semi-colon", + "output": [ + [ + "Character", + "\u2975" + ] + ] + }, + { + "input": "&rarrb", + "description": "Bad named entity: rarrb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrb" + ] + ] + }, + { + "input": "⇥", + "description": "Named entity: rarrb; with a semi-colon", + "output": [ + [ + "Character", + "\u21e5" + ] + ] + }, + { + "input": "&rarrbfs", + "description": "Bad named entity: rarrbfs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrbfs" + ] + ] + }, + { + "input": "⤠", + "description": "Named entity: rarrbfs; with a semi-colon", + "output": [ + [ + "Character", + "\u2920" + ] + ] + }, + { + "input": "&rarrc", + "description": "Bad named entity: rarrc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrc" + ] + ] + }, + { + "input": "⤳", + "description": "Named entity: rarrc; with a semi-colon", + "output": [ + [ + "Character", + "\u2933" + ] + ] + }, + { + "input": "&rarrfs", + "description": "Bad named entity: rarrfs without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrfs" + ] + ] + }, + { + "input": "⤞", + "description": "Named entity: rarrfs; with a semi-colon", + "output": [ + [ + "Character", + "\u291e" + ] + ] + }, + { + "input": "&rarrhk", + "description": "Bad named entity: rarrhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrhk" + ] + ] + }, + { + "input": "↪", + "description": "Named entity: rarrhk; with a semi-colon", + "output": [ + [ + "Character", + "\u21aa" + ] + ] + }, + { + "input": "&rarrlp", + "description": "Bad named entity: rarrlp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrlp" + ] + ] + }, + { + "input": "↬", + "description": "Named entity: rarrlp; with a semi-colon", + "output": [ + [ + "Character", + "\u21ac" + ] + ] + }, + { + "input": "&rarrpl", + "description": "Bad named entity: rarrpl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrpl" + ] + ] + }, + { + "input": "⥅", + "description": "Named entity: rarrpl; with a semi-colon", + "output": [ + [ + "Character", + "\u2945" + ] + ] + }, + { + "input": "&rarrsim", + "description": "Bad named entity: rarrsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrsim" + ] + ] + }, + { + "input": "⥴", + "description": "Named entity: rarrsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2974" + ] + ] + }, + { + "input": "&rarrtl", + "description": "Bad named entity: rarrtl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrtl" + ] + ] + }, + { + "input": "↣", + "description": "Named entity: rarrtl; with a semi-colon", + "output": [ + [ + "Character", + "\u21a3" + ] + ] + }, + { + "input": "&rarrw", + "description": "Bad named entity: rarrw without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rarrw" + ] + ] + }, + { + "input": "↝", + "description": "Named entity: rarrw; with a semi-colon", + "output": [ + [ + "Character", + "\u219d" + ] + ] + }, + { + "input": "&ratail", + "description": "Bad named entity: ratail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ratail" + ] + ] + }, + { + "input": "⤚", + "description": "Named entity: ratail; with a semi-colon", + "output": [ + [ + "Character", + "\u291a" + ] + ] + }, + { + "input": "&ratio", + "description": "Bad named entity: ratio without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ratio" + ] + ] + }, + { + "input": "∶", + "description": "Named entity: ratio; with a semi-colon", + "output": [ + [ + "Character", + "\u2236" + ] + ] + }, + { + "input": "&rationals", + "description": "Bad named entity: rationals without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rationals" + ] + ] + }, + { + "input": "ℚ", + "description": "Named entity: rationals; with a semi-colon", + "output": [ + [ + "Character", + "\u211a" + ] + ] + }, + { + "input": "&rbarr", + "description": "Bad named entity: rbarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbarr" + ] + ] + }, + { + "input": "⤍", + "description": "Named entity: rbarr; with a semi-colon", + "output": [ + [ + "Character", + "\u290d" + ] + ] + }, + { + "input": "&rbbrk", + "description": "Bad named entity: rbbrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbbrk" + ] + ] + }, + { + "input": "❳", + "description": "Named entity: rbbrk; with a semi-colon", + "output": [ + [ + "Character", + "\u2773" + ] + ] + }, + { + "input": "&rbrace", + "description": "Bad named entity: rbrace without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbrace" + ] + ] + }, + { + "input": "}", + "description": "Named entity: rbrace; with a semi-colon", + "output": [ + [ + "Character", + "}" + ] + ] + }, + { + "input": "&rbrack", + "description": "Bad named entity: rbrack without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbrack" + ] + ] + }, + { + "input": "]", + "description": "Named entity: rbrack; with a semi-colon", + "output": [ + [ + "Character", + "]" + ] + ] + }, + { + "input": "&rbrke", + "description": "Bad named entity: rbrke without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbrke" + ] + ] + }, + { + "input": "⦌", + "description": "Named entity: rbrke; with a semi-colon", + "output": [ + [ + "Character", + "\u298c" + ] + ] + }, + { + "input": "&rbrksld", + "description": "Bad named entity: rbrksld without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbrksld" + ] + ] + }, + { + "input": "⦎", + "description": "Named entity: rbrksld; with a semi-colon", + "output": [ + [ + "Character", + "\u298e" + ] + ] + }, + { + "input": "&rbrkslu", + "description": "Bad named entity: rbrkslu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rbrkslu" + ] + ] + }, + { + "input": "⦐", + "description": "Named entity: rbrkslu; with a semi-colon", + "output": [ + [ + "Character", + "\u2990" + ] + ] + }, + { + "input": "&rcaron", + "description": "Bad named entity: rcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rcaron" + ] + ] + }, + { + "input": "ř", + "description": "Named entity: rcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0159" + ] + ] + }, + { + "input": "&rcedil", + "description": "Bad named entity: rcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rcedil" + ] + ] + }, + { + "input": "ŗ", + "description": "Named entity: rcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0157" + ] + ] + }, + { + "input": "&rceil", + "description": "Bad named entity: rceil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rceil" + ] + ] + }, + { + "input": "⌉", + "description": "Named entity: rceil; with a semi-colon", + "output": [ + [ + "Character", + "\u2309" + ] + ] + }, + { + "input": "&rcub", + "description": "Bad named entity: rcub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rcub" + ] + ] + }, + { + "input": "}", + "description": "Named entity: rcub; with a semi-colon", + "output": [ + [ + "Character", + "}" + ] + ] + }, + { + "input": "&rcy", + "description": "Bad named entity: rcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rcy" + ] + ] + }, + { + "input": "р", + "description": "Named entity: rcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0440" + ] + ] + }, + { + "input": "&rdca", + "description": "Bad named entity: rdca without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rdca" + ] + ] + }, + { + "input": "⤷", + "description": "Named entity: rdca; with a semi-colon", + "output": [ + [ + "Character", + "\u2937" + ] + ] + }, + { + "input": "&rdldhar", + "description": "Bad named entity: rdldhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rdldhar" + ] + ] + }, + { + "input": "⥩", + "description": "Named entity: rdldhar; with a semi-colon", + "output": [ + [ + "Character", + "\u2969" + ] + ] + }, + { + "input": "&rdquo", + "description": "Bad named entity: rdquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rdquo" + ] + ] + }, + { + "input": "”", + "description": "Named entity: rdquo; with a semi-colon", + "output": [ + [ + "Character", + "\u201d" + ] + ] + }, + { + "input": "&rdquor", + "description": "Bad named entity: rdquor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rdquor" + ] + ] + }, + { + "input": "”", + "description": "Named entity: rdquor; with a semi-colon", + "output": [ + [ + "Character", + "\u201d" + ] + ] + }, + { + "input": "&rdsh", + "description": "Bad named entity: rdsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rdsh" + ] + ] + }, + { + "input": "↳", + "description": "Named entity: rdsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b3" + ] + ] + }, + { + "input": "&real", + "description": "Bad named entity: real without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&real" + ] + ] + }, + { + "input": "ℜ", + "description": "Named entity: real; with a semi-colon", + "output": [ + [ + "Character", + "\u211c" + ] + ] + }, + { + "input": "&realine", + "description": "Bad named entity: realine without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&realine" + ] + ] + }, + { + "input": "ℛ", + "description": "Named entity: realine; with a semi-colon", + "output": [ + [ + "Character", + "\u211b" + ] + ] + }, + { + "input": "&realpart", + "description": "Bad named entity: realpart without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&realpart" + ] + ] + }, + { + "input": "ℜ", + "description": "Named entity: realpart; with a semi-colon", + "output": [ + [ + "Character", + "\u211c" + ] + ] + }, + { + "input": "&reals", + "description": "Bad named entity: reals without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&reals" + ] + ] + }, + { + "input": "ℝ", + "description": "Named entity: reals; with a semi-colon", + "output": [ + [ + "Character", + "\u211d" + ] + ] + }, + { + "input": "&rect", + "description": "Bad named entity: rect without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rect" + ] + ] + }, + { + "input": "▭", + "description": "Named entity: rect; with a semi-colon", + "output": [ + [ + "Character", + "\u25ad" + ] + ] + }, + { + "input": "®", + "description": "Named entity: reg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ae" + ] + ] + }, + { + "input": "®", + "description": "Named entity: reg; with a semi-colon", + "output": [ + [ + "Character", + "\u00ae" + ] + ] + }, + { + "input": "&rfisht", + "description": "Bad named entity: rfisht without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rfisht" + ] + ] + }, + { + "input": "⥽", + "description": "Named entity: rfisht; with a semi-colon", + "output": [ + [ + "Character", + "\u297d" + ] + ] + }, + { + "input": "&rfloor", + "description": "Bad named entity: rfloor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rfloor" + ] + ] + }, + { + "input": "⌋", + "description": "Named entity: rfloor; with a semi-colon", + "output": [ + [ + "Character", + "\u230b" + ] + ] + }, + { + "input": "&rfr", + "description": "Bad named entity: rfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rfr" + ] + ] + }, + { + "input": "𝔯", + "description": "Named entity: rfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd2f" + ] + ] + }, + { + "input": "&rhard", + "description": "Bad named entity: rhard without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rhard" + ] + ] + }, + { + "input": "⇁", + "description": "Named entity: rhard; with a semi-colon", + "output": [ + [ + "Character", + "\u21c1" + ] + ] + }, + { + "input": "&rharu", + "description": "Bad named entity: rharu without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rharu" + ] + ] + }, + { + "input": "⇀", + "description": "Named entity: rharu; with a semi-colon", + "output": [ + [ + "Character", + "\u21c0" + ] + ] + }, + { + "input": "&rharul", + "description": "Bad named entity: rharul without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rharul" + ] + ] + }, + { + "input": "⥬", + "description": "Named entity: rharul; with a semi-colon", + "output": [ + [ + "Character", + "\u296c" + ] + ] + }, + { + "input": "&rho", + "description": "Bad named entity: rho without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rho" + ] + ] + }, + { + "input": "ρ", + "description": "Named entity: rho; with a semi-colon", + "output": [ + [ + "Character", + "\u03c1" + ] + ] + }, + { + "input": "&rhov", + "description": "Bad named entity: rhov without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rhov" + ] + ] + }, + { + "input": "ϱ", + "description": "Named entity: rhov; with a semi-colon", + "output": [ + [ + "Character", + "\u03f1" + ] + ] + }, + { + "input": "&rightarrow", + "description": "Bad named entity: rightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightarrow" + ] + ] + }, + { + "input": "→", + "description": "Named entity: rightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2192" + ] + ] + }, + { + "input": "&rightarrowtail", + "description": "Bad named entity: rightarrowtail without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightarrowtail" + ] + ] + }, + { + "input": "↣", + "description": "Named entity: rightarrowtail; with a semi-colon", + "output": [ + [ + "Character", + "\u21a3" + ] + ] + }, + { + "input": "&rightharpoondown", + "description": "Bad named entity: rightharpoondown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightharpoondown" + ] + ] + }, + { + "input": "⇁", + "description": "Named entity: rightharpoondown; with a semi-colon", + "output": [ + [ + "Character", + "\u21c1" + ] + ] + }, + { + "input": "&rightharpoonup", + "description": "Bad named entity: rightharpoonup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightharpoonup" + ] + ] + }, + { + "input": "⇀", + "description": "Named entity: rightharpoonup; with a semi-colon", + "output": [ + [ + "Character", + "\u21c0" + ] + ] + }, + { + "input": "&rightleftarrows", + "description": "Bad named entity: rightleftarrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightleftarrows" + ] + ] + }, + { + "input": "⇄", + "description": "Named entity: rightleftarrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21c4" + ] + ] + }, + { + "input": "&rightleftharpoons", + "description": "Bad named entity: rightleftharpoons without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightleftharpoons" + ] + ] + }, + { + "input": "⇌", + "description": "Named entity: rightleftharpoons; with a semi-colon", + "output": [ + [ + "Character", + "\u21cc" + ] + ] + }, + { + "input": "&rightrightarrows", + "description": "Bad named entity: rightrightarrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightrightarrows" + ] + ] + }, + { + "input": "⇉", + "description": "Named entity: rightrightarrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21c9" + ] + ] + }, + { + "input": "&rightsquigarrow", + "description": "Bad named entity: rightsquigarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightsquigarrow" + ] + ] + }, + { + "input": "↝", + "description": "Named entity: rightsquigarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u219d" + ] + ] + }, + { + "input": "&rightthreetimes", + "description": "Bad named entity: rightthreetimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rightthreetimes" + ] + ] + }, + { + "input": "⋌", + "description": "Named entity: rightthreetimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22cc" + ] + ] + }, + { + "input": "&ring", + "description": "Bad named entity: ring without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ring" + ] + ] + }, + { + "input": "˚", + "description": "Named entity: ring; with a semi-colon", + "output": [ + [ + "Character", + "\u02da" + ] + ] + }, + { + "input": "&risingdotseq", + "description": "Bad named entity: risingdotseq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&risingdotseq" + ] + ] + }, + { + "input": "≓", + "description": "Named entity: risingdotseq; with a semi-colon", + "output": [ + [ + "Character", + "\u2253" + ] + ] + }, + { + "input": "&rlarr", + "description": "Bad named entity: rlarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rlarr" + ] + ] + }, + { + "input": "⇄", + "description": "Named entity: rlarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c4" + ] + ] + }, + { + "input": "&rlhar", + "description": "Bad named entity: rlhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rlhar" + ] + ] + }, + { + "input": "⇌", + "description": "Named entity: rlhar; with a semi-colon", + "output": [ + [ + "Character", + "\u21cc" + ] + ] + }, + { + "input": "&rlm", + "description": "Bad named entity: rlm without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rlm" + ] + ] + }, + { + "input": "‏", + "description": "Named entity: rlm; with a semi-colon", + "output": [ + [ + "Character", + "\u200f" + ] + ] + }, + { + "input": "&rmoust", + "description": "Bad named entity: rmoust without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rmoust" + ] + ] + }, + { + "input": "⎱", + "description": "Named entity: rmoust; with a semi-colon", + "output": [ + [ + "Character", + "\u23b1" + ] + ] + }, + { + "input": "&rmoustache", + "description": "Bad named entity: rmoustache without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rmoustache" + ] + ] + }, + { + "input": "⎱", + "description": "Named entity: rmoustache; with a semi-colon", + "output": [ + [ + "Character", + "\u23b1" + ] + ] + }, + { + "input": "&rnmid", + "description": "Bad named entity: rnmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rnmid" + ] + ] + }, + { + "input": "⫮", + "description": "Named entity: rnmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2aee" + ] + ] + }, + { + "input": "&roang", + "description": "Bad named entity: roang without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&roang" + ] + ] + }, + { + "input": "⟭", + "description": "Named entity: roang; with a semi-colon", + "output": [ + [ + "Character", + "\u27ed" + ] + ] + }, + { + "input": "&roarr", + "description": "Bad named entity: roarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&roarr" + ] + ] + }, + { + "input": "⇾", + "description": "Named entity: roarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21fe" + ] + ] + }, + { + "input": "&robrk", + "description": "Bad named entity: robrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&robrk" + ] + ] + }, + { + "input": "⟧", + "description": "Named entity: robrk; with a semi-colon", + "output": [ + [ + "Character", + "\u27e7" + ] + ] + }, + { + "input": "&ropar", + "description": "Bad named entity: ropar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ropar" + ] + ] + }, + { + "input": "⦆", + "description": "Named entity: ropar; with a semi-colon", + "output": [ + [ + "Character", + "\u2986" + ] + ] + }, + { + "input": "&ropf", + "description": "Bad named entity: ropf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ropf" + ] + ] + }, + { + "input": "𝕣", + "description": "Named entity: ropf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd63" + ] + ] + }, + { + "input": "&roplus", + "description": "Bad named entity: roplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&roplus" + ] + ] + }, + { + "input": "⨮", + "description": "Named entity: roplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a2e" + ] + ] + }, + { + "input": "&rotimes", + "description": "Bad named entity: rotimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rotimes" + ] + ] + }, + { + "input": "⨵", + "description": "Named entity: rotimes; with a semi-colon", + "output": [ + [ + "Character", + "\u2a35" + ] + ] + }, + { + "input": "&rpar", + "description": "Bad named entity: rpar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rpar" + ] + ] + }, + { + "input": ")", + "description": "Named entity: rpar; with a semi-colon", + "output": [ + [ + "Character", + ")" + ] + ] + }, + { + "input": "&rpargt", + "description": "Bad named entity: rpargt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rpargt" + ] + ] + }, + { + "input": "⦔", + "description": "Named entity: rpargt; with a semi-colon", + "output": [ + [ + "Character", + "\u2994" + ] + ] + }, + { + "input": "&rppolint", + "description": "Bad named entity: rppolint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rppolint" + ] + ] + }, + { + "input": "⨒", + "description": "Named entity: rppolint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a12" + ] + ] + }, + { + "input": "&rrarr", + "description": "Bad named entity: rrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rrarr" + ] + ] + }, + { + "input": "⇉", + "description": "Named entity: rrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c9" + ] + ] + }, + { + "input": "&rsaquo", + "description": "Bad named entity: rsaquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rsaquo" + ] + ] + }, + { + "input": "›", + "description": "Named entity: rsaquo; with a semi-colon", + "output": [ + [ + "Character", + "\u203a" + ] + ] + }, + { + "input": "&rscr", + "description": "Bad named entity: rscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rscr" + ] + ] + }, + { + "input": "𝓇", + "description": "Named entity: rscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc7" + ] + ] + }, + { + "input": "&rsh", + "description": "Bad named entity: rsh without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rsh" + ] + ] + }, + { + "input": "↱", + "description": "Named entity: rsh; with a semi-colon", + "output": [ + [ + "Character", + "\u21b1" + ] + ] + }, + { + "input": "&rsqb", + "description": "Bad named entity: rsqb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rsqb" + ] + ] + }, + { + "input": "]", + "description": "Named entity: rsqb; with a semi-colon", + "output": [ + [ + "Character", + "]" + ] + ] + }, + { + "input": "&rsquo", + "description": "Bad named entity: rsquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rsquo" + ] + ] + }, + { + "input": "’", + "description": "Named entity: rsquo; with a semi-colon", + "output": [ + [ + "Character", + "\u2019" + ] + ] + }, + { + "input": "&rsquor", + "description": "Bad named entity: rsquor without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rsquor" + ] + ] + }, + { + "input": "’", + "description": "Named entity: rsquor; with a semi-colon", + "output": [ + [ + "Character", + "\u2019" + ] + ] + }, + { + "input": "&rthree", + "description": "Bad named entity: rthree without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rthree" + ] + ] + }, + { + "input": "⋌", + "description": "Named entity: rthree; with a semi-colon", + "output": [ + [ + "Character", + "\u22cc" + ] + ] + }, + { + "input": "&rtimes", + "description": "Bad named entity: rtimes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rtimes" + ] + ] + }, + { + "input": "⋊", + "description": "Named entity: rtimes; with a semi-colon", + "output": [ + [ + "Character", + "\u22ca" + ] + ] + }, + { + "input": "&rtri", + "description": "Bad named entity: rtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rtri" + ] + ] + }, + { + "input": "▹", + "description": "Named entity: rtri; with a semi-colon", + "output": [ + [ + "Character", + "\u25b9" + ] + ] + }, + { + "input": "&rtrie", + "description": "Bad named entity: rtrie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rtrie" + ] + ] + }, + { + "input": "⊵", + "description": "Named entity: rtrie; with a semi-colon", + "output": [ + [ + "Character", + "\u22b5" + ] + ] + }, + { + "input": "&rtrif", + "description": "Bad named entity: rtrif without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rtrif" + ] + ] + }, + { + "input": "▸", + "description": "Named entity: rtrif; with a semi-colon", + "output": [ + [ + "Character", + "\u25b8" + ] + ] + }, + { + "input": "&rtriltri", + "description": "Bad named entity: rtriltri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rtriltri" + ] + ] + }, + { + "input": "⧎", + "description": "Named entity: rtriltri; with a semi-colon", + "output": [ + [ + "Character", + "\u29ce" + ] + ] + }, + { + "input": "&ruluhar", + "description": "Bad named entity: ruluhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ruluhar" + ] + ] + }, + { + "input": "⥨", + "description": "Named entity: ruluhar; with a semi-colon", + "output": [ + [ + "Character", + "\u2968" + ] + ] + }, + { + "input": "&rx", + "description": "Bad named entity: rx without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&rx" + ] + ] + }, + { + "input": "℞", + "description": "Named entity: rx; with a semi-colon", + "output": [ + [ + "Character", + "\u211e" + ] + ] + }, + { + "input": "&sacute", + "description": "Bad named entity: sacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sacute" + ] + ] + }, + { + "input": "ś", + "description": "Named entity: sacute; with a semi-colon", + "output": [ + [ + "Character", + "\u015b" + ] + ] + }, + { + "input": "&sbquo", + "description": "Bad named entity: sbquo without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sbquo" + ] + ] + }, + { + "input": "‚", + "description": "Named entity: sbquo; with a semi-colon", + "output": [ + [ + "Character", + "\u201a" + ] + ] + }, + { + "input": "&sc", + "description": "Bad named entity: sc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sc" + ] + ] + }, + { + "input": "≻", + "description": "Named entity: sc; with a semi-colon", + "output": [ + [ + "Character", + "\u227b" + ] + ] + }, + { + "input": "&scE", + "description": "Bad named entity: scE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scE" + ] + ] + }, + { + "input": "⪴", + "description": "Named entity: scE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab4" + ] + ] + }, + { + "input": "&scap", + "description": "Bad named entity: scap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scap" + ] + ] + }, + { + "input": "⪸", + "description": "Named entity: scap; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab8" + ] + ] + }, + { + "input": "&scaron", + "description": "Bad named entity: scaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scaron" + ] + ] + }, + { + "input": "š", + "description": "Named entity: scaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0161" + ] + ] + }, + { + "input": "&sccue", + "description": "Bad named entity: sccue without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sccue" + ] + ] + }, + { + "input": "≽", + "description": "Named entity: sccue; with a semi-colon", + "output": [ + [ + "Character", + "\u227d" + ] + ] + }, + { + "input": "&sce", + "description": "Bad named entity: sce without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sce" + ] + ] + }, + { + "input": "⪰", + "description": "Named entity: sce; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0" + ] + ] + }, + { + "input": "&scedil", + "description": "Bad named entity: scedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scedil" + ] + ] + }, + { + "input": "ş", + "description": "Named entity: scedil; with a semi-colon", + "output": [ + [ + "Character", + "\u015f" + ] + ] + }, + { + "input": "&scirc", + "description": "Bad named entity: scirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scirc" + ] + ] + }, + { + "input": "ŝ", + "description": "Named entity: scirc; with a semi-colon", + "output": [ + [ + "Character", + "\u015d" + ] + ] + }, + { + "input": "&scnE", + "description": "Bad named entity: scnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scnE" + ] + ] + }, + { + "input": "⪶", + "description": "Named entity: scnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab6" + ] + ] + }, + { + "input": "&scnap", + "description": "Bad named entity: scnap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scnap" + ] + ] + }, + { + "input": "⪺", + "description": "Named entity: scnap; with a semi-colon", + "output": [ + [ + "Character", + "\u2aba" + ] + ] + }, + { + "input": "&scnsim", + "description": "Bad named entity: scnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scnsim" + ] + ] + }, + { + "input": "⋩", + "description": "Named entity: scnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e9" + ] + ] + }, + { + "input": "&scpolint", + "description": "Bad named entity: scpolint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scpolint" + ] + ] + }, + { + "input": "⨓", + "description": "Named entity: scpolint; with a semi-colon", + "output": [ + [ + "Character", + "\u2a13" + ] + ] + }, + { + "input": "&scsim", + "description": "Bad named entity: scsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scsim" + ] + ] + }, + { + "input": "≿", + "description": "Named entity: scsim; with a semi-colon", + "output": [ + [ + "Character", + "\u227f" + ] + ] + }, + { + "input": "&scy", + "description": "Bad named entity: scy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&scy" + ] + ] + }, + { + "input": "с", + "description": "Named entity: scy; with a semi-colon", + "output": [ + [ + "Character", + "\u0441" + ] + ] + }, + { + "input": "&sdot", + "description": "Bad named entity: sdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sdot" + ] + ] + }, + { + "input": "⋅", + "description": "Named entity: sdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22c5" + ] + ] + }, + { + "input": "&sdotb", + "description": "Bad named entity: sdotb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sdotb" + ] + ] + }, + { + "input": "⊡", + "description": "Named entity: sdotb; with a semi-colon", + "output": [ + [ + "Character", + "\u22a1" + ] + ] + }, + { + "input": "&sdote", + "description": "Bad named entity: sdote without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sdote" + ] + ] + }, + { + "input": "⩦", + "description": "Named entity: sdote; with a semi-colon", + "output": [ + [ + "Character", + "\u2a66" + ] + ] + }, + { + "input": "&seArr", + "description": "Bad named entity: seArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&seArr" + ] + ] + }, + { + "input": "⇘", + "description": "Named entity: seArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d8" + ] + ] + }, + { + "input": "&searhk", + "description": "Bad named entity: searhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&searhk" + ] + ] + }, + { + "input": "⤥", + "description": "Named entity: searhk; with a semi-colon", + "output": [ + [ + "Character", + "\u2925" + ] + ] + }, + { + "input": "&searr", + "description": "Bad named entity: searr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&searr" + ] + ] + }, + { + "input": "↘", + "description": "Named entity: searr; with a semi-colon", + "output": [ + [ + "Character", + "\u2198" + ] + ] + }, + { + "input": "&searrow", + "description": "Bad named entity: searrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&searrow" + ] + ] + }, + { + "input": "↘", + "description": "Named entity: searrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2198" + ] + ] + }, + { + "input": "§", + "description": "Named entity: sect without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a7" + ] + ] + }, + { + "input": "§", + "description": "Named entity: sect; with a semi-colon", + "output": [ + [ + "Character", + "\u00a7" + ] + ] + }, + { + "input": "&semi", + "description": "Bad named entity: semi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&semi" + ] + ] + }, + { + "input": ";", + "description": "Named entity: semi; with a semi-colon", + "output": [ + [ + "Character", + ";" + ] + ] + }, + { + "input": "&seswar", + "description": "Bad named entity: seswar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&seswar" + ] + ] + }, + { + "input": "⤩", + "description": "Named entity: seswar; with a semi-colon", + "output": [ + [ + "Character", + "\u2929" + ] + ] + }, + { + "input": "&setminus", + "description": "Bad named entity: setminus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&setminus" + ] + ] + }, + { + "input": "∖", + "description": "Named entity: setminus; with a semi-colon", + "output": [ + [ + "Character", + "\u2216" + ] + ] + }, + { + "input": "&setmn", + "description": "Bad named entity: setmn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&setmn" + ] + ] + }, + { + "input": "∖", + "description": "Named entity: setmn; with a semi-colon", + "output": [ + [ + "Character", + "\u2216" + ] + ] + }, + { + "input": "&sext", + "description": "Bad named entity: sext without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sext" + ] + ] + }, + { + "input": "✶", + "description": "Named entity: sext; with a semi-colon", + "output": [ + [ + "Character", + "\u2736" + ] + ] + }, + { + "input": "&sfr", + "description": "Bad named entity: sfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sfr" + ] + ] + }, + { + "input": "𝔰", + "description": "Named entity: sfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd30" + ] + ] + }, + { + "input": "&sfrown", + "description": "Bad named entity: sfrown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sfrown" + ] + ] + }, + { + "input": "⌢", + "description": "Named entity: sfrown; with a semi-colon", + "output": [ + [ + "Character", + "\u2322" + ] + ] + }, + { + "input": "&sharp", + "description": "Bad named entity: sharp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sharp" + ] + ] + }, + { + "input": "♯", + "description": "Named entity: sharp; with a semi-colon", + "output": [ + [ + "Character", + "\u266f" + ] + ] + }, + { + "input": "&shchcy", + "description": "Bad named entity: shchcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&shchcy" + ] + ] + }, + { + "input": "щ", + "description": "Named entity: shchcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0449" + ] + ] + }, + { + "input": "&shcy", + "description": "Bad named entity: shcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&shcy" + ] + ] + }, + { + "input": "ш", + "description": "Named entity: shcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0448" + ] + ] + }, + { + "input": "&shortmid", + "description": "Bad named entity: shortmid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&shortmid" + ] + ] + }, + { + "input": "∣", + "description": "Named entity: shortmid; with a semi-colon", + "output": [ + [ + "Character", + "\u2223" + ] + ] + }, + { + "input": "&shortparallel", + "description": "Bad named entity: shortparallel without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&shortparallel" + ] + ] + }, + { + "input": "∥", + "description": "Named entity: shortparallel; with a semi-colon", + "output": [ + [ + "Character", + "\u2225" + ] + ] + }, + { + "input": "­", + "description": "Named entity: shy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ad" + ] + ] + }, + { + "input": "­", + "description": "Named entity: shy; with a semi-colon", + "output": [ + [ + "Character", + "\u00ad" + ] + ] + }, + { + "input": "&sigma", + "description": "Bad named entity: sigma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sigma" + ] + ] + }, + { + "input": "σ", + "description": "Named entity: sigma; with a semi-colon", + "output": [ + [ + "Character", + "\u03c3" + ] + ] + }, + { + "input": "&sigmaf", + "description": "Bad named entity: sigmaf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sigmaf" + ] + ] + }, + { + "input": "ς", + "description": "Named entity: sigmaf; with a semi-colon", + "output": [ + [ + "Character", + "\u03c2" + ] + ] + }, + { + "input": "&sigmav", + "description": "Bad named entity: sigmav without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sigmav" + ] + ] + }, + { + "input": "ς", + "description": "Named entity: sigmav; with a semi-colon", + "output": [ + [ + "Character", + "\u03c2" + ] + ] + }, + { + "input": "&sim", + "description": "Bad named entity: sim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sim" + ] + ] + }, + { + "input": "∼", + "description": "Named entity: sim; with a semi-colon", + "output": [ + [ + "Character", + "\u223c" + ] + ] + }, + { + "input": "&simdot", + "description": "Bad named entity: simdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simdot" + ] + ] + }, + { + "input": "⩪", + "description": "Named entity: simdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a6a" + ] + ] + }, + { + "input": "&sime", + "description": "Bad named entity: sime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sime" + ] + ] + }, + { + "input": "≃", + "description": "Named entity: sime; with a semi-colon", + "output": [ + [ + "Character", + "\u2243" + ] + ] + }, + { + "input": "&simeq", + "description": "Bad named entity: simeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simeq" + ] + ] + }, + { + "input": "≃", + "description": "Named entity: simeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2243" + ] + ] + }, + { + "input": "&simg", + "description": "Bad named entity: simg without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simg" + ] + ] + }, + { + "input": "⪞", + "description": "Named entity: simg; with a semi-colon", + "output": [ + [ + "Character", + "\u2a9e" + ] + ] + }, + { + "input": "&simgE", + "description": "Bad named entity: simgE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simgE" + ] + ] + }, + { + "input": "⪠", + "description": "Named entity: simgE; with a semi-colon", + "output": [ + [ + "Character", + "\u2aa0" + ] + ] + }, + { + "input": "&siml", + "description": "Bad named entity: siml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&siml" + ] + ] + }, + { + "input": "⪝", + "description": "Named entity: siml; with a semi-colon", + "output": [ + [ + "Character", + "\u2a9d" + ] + ] + }, + { + "input": "&simlE", + "description": "Bad named entity: simlE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simlE" + ] + ] + }, + { + "input": "⪟", + "description": "Named entity: simlE; with a semi-colon", + "output": [ + [ + "Character", + "\u2a9f" + ] + ] + }, + { + "input": "&simne", + "description": "Bad named entity: simne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simne" + ] + ] + }, + { + "input": "≆", + "description": "Named entity: simne; with a semi-colon", + "output": [ + [ + "Character", + "\u2246" + ] + ] + }, + { + "input": "&simplus", + "description": "Bad named entity: simplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simplus" + ] + ] + }, + { + "input": "⨤", + "description": "Named entity: simplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a24" + ] + ] + }, + { + "input": "&simrarr", + "description": "Bad named entity: simrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&simrarr" + ] + ] + }, + { + "input": "⥲", + "description": "Named entity: simrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2972" + ] + ] + }, + { + "input": "&slarr", + "description": "Bad named entity: slarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&slarr" + ] + ] + }, + { + "input": "←", + "description": "Named entity: slarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2190" + ] + ] + }, + { + "input": "&smallsetminus", + "description": "Bad named entity: smallsetminus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smallsetminus" + ] + ] + }, + { + "input": "∖", + "description": "Named entity: smallsetminus; with a semi-colon", + "output": [ + [ + "Character", + "\u2216" + ] + ] + }, + { + "input": "&smashp", + "description": "Bad named entity: smashp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smashp" + ] + ] + }, + { + "input": "⨳", + "description": "Named entity: smashp; with a semi-colon", + "output": [ + [ + "Character", + "\u2a33" + ] + ] + }, + { + "input": "&smeparsl", + "description": "Bad named entity: smeparsl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smeparsl" + ] + ] + }, + { + "input": "⧤", + "description": "Named entity: smeparsl; with a semi-colon", + "output": [ + [ + "Character", + "\u29e4" + ] + ] + }, + { + "input": "&smid", + "description": "Bad named entity: smid without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smid" + ] + ] + }, + { + "input": "∣", + "description": "Named entity: smid; with a semi-colon", + "output": [ + [ + "Character", + "\u2223" + ] + ] + }, + { + "input": "&smile", + "description": "Bad named entity: smile without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smile" + ] + ] + }, + { + "input": "⌣", + "description": "Named entity: smile; with a semi-colon", + "output": [ + [ + "Character", + "\u2323" + ] + ] + }, + { + "input": "&smt", + "description": "Bad named entity: smt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smt" + ] + ] + }, + { + "input": "⪪", + "description": "Named entity: smt; with a semi-colon", + "output": [ + [ + "Character", + "\u2aaa" + ] + ] + }, + { + "input": "&smte", + "description": "Bad named entity: smte without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smte" + ] + ] + }, + { + "input": "⪬", + "description": "Named entity: smte; with a semi-colon", + "output": [ + [ + "Character", + "\u2aac" + ] + ] + }, + { + "input": "&smtes", + "description": "Bad named entity: smtes without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&smtes" + ] + ] + }, + { + "input": "⪬︀", + "description": "Named entity: smtes; with a semi-colon", + "output": [ + [ + "Character", + "\u2aac\ufe00" + ] + ] + }, + { + "input": "&softcy", + "description": "Bad named entity: softcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&softcy" + ] + ] + }, + { + "input": "ь", + "description": "Named entity: softcy; with a semi-colon", + "output": [ + [ + "Character", + "\u044c" + ] + ] + }, + { + "input": "&sol", + "description": "Bad named entity: sol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sol" + ] + ] + }, + { + "input": "/", + "description": "Named entity: sol; with a semi-colon", + "output": [ + [ + "Character", + "/" + ] + ] + }, + { + "input": "&solb", + "description": "Bad named entity: solb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&solb" + ] + ] + }, + { + "input": "⧄", + "description": "Named entity: solb; with a semi-colon", + "output": [ + [ + "Character", + "\u29c4" + ] + ] + }, + { + "input": "&solbar", + "description": "Bad named entity: solbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&solbar" + ] + ] + }, + { + "input": "⌿", + "description": "Named entity: solbar; with a semi-colon", + "output": [ + [ + "Character", + "\u233f" + ] + ] + }, + { + "input": "&sopf", + "description": "Bad named entity: sopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sopf" + ] + ] + }, + { + "input": "𝕤", + "description": "Named entity: sopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd64" + ] + ] + }, + { + "input": "&spades", + "description": "Bad named entity: spades without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&spades" + ] + ] + }, + { + "input": "♠", + "description": "Named entity: spades; with a semi-colon", + "output": [ + [ + "Character", + "\u2660" + ] + ] + }, + { + "input": "&spadesuit", + "description": "Bad named entity: spadesuit without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&spadesuit" + ] + ] + }, + { + "input": "♠", + "description": "Named entity: spadesuit; with a semi-colon", + "output": [ + [ + "Character", + "\u2660" + ] + ] + }, + { + "input": "&spar", + "description": "Bad named entity: spar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&spar" + ] + ] + }, + { + "input": "∥", + "description": "Named entity: spar; with a semi-colon", + "output": [ + [ + "Character", + "\u2225" + ] + ] + }, + { + "input": "&sqcap", + "description": "Bad named entity: sqcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqcap" + ] + ] + }, + { + "input": "⊓", + "description": "Named entity: sqcap; with a semi-colon", + "output": [ + [ + "Character", + "\u2293" + ] + ] + }, + { + "input": "&sqcaps", + "description": "Bad named entity: sqcaps without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqcaps" + ] + ] + }, + { + "input": "⊓︀", + "description": "Named entity: sqcaps; with a semi-colon", + "output": [ + [ + "Character", + "\u2293\ufe00" + ] + ] + }, + { + "input": "&sqcup", + "description": "Bad named entity: sqcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqcup" + ] + ] + }, + { + "input": "⊔", + "description": "Named entity: sqcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2294" + ] + ] + }, + { + "input": "&sqcups", + "description": "Bad named entity: sqcups without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqcups" + ] + ] + }, + { + "input": "⊔︀", + "description": "Named entity: sqcups; with a semi-colon", + "output": [ + [ + "Character", + "\u2294\ufe00" + ] + ] + }, + { + "input": "&sqsub", + "description": "Bad named entity: sqsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsub" + ] + ] + }, + { + "input": "⊏", + "description": "Named entity: sqsub; with a semi-colon", + "output": [ + [ + "Character", + "\u228f" + ] + ] + }, + { + "input": "&sqsube", + "description": "Bad named entity: sqsube without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsube" + ] + ] + }, + { + "input": "⊑", + "description": "Named entity: sqsube; with a semi-colon", + "output": [ + [ + "Character", + "\u2291" + ] + ] + }, + { + "input": "&sqsubset", + "description": "Bad named entity: sqsubset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsubset" + ] + ] + }, + { + "input": "⊏", + "description": "Named entity: sqsubset; with a semi-colon", + "output": [ + [ + "Character", + "\u228f" + ] + ] + }, + { + "input": "&sqsubseteq", + "description": "Bad named entity: sqsubseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsubseteq" + ] + ] + }, + { + "input": "⊑", + "description": "Named entity: sqsubseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2291" + ] + ] + }, + { + "input": "&sqsup", + "description": "Bad named entity: sqsup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsup" + ] + ] + }, + { + "input": "⊐", + "description": "Named entity: sqsup; with a semi-colon", + "output": [ + [ + "Character", + "\u2290" + ] + ] + }, + { + "input": "&sqsupe", + "description": "Bad named entity: sqsupe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsupe" + ] + ] + }, + { + "input": "⊒", + "description": "Named entity: sqsupe; with a semi-colon", + "output": [ + [ + "Character", + "\u2292" + ] + ] + }, + { + "input": "&sqsupset", + "description": "Bad named entity: sqsupset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsupset" + ] + ] + }, + { + "input": "⊐", + "description": "Named entity: sqsupset; with a semi-colon", + "output": [ + [ + "Character", + "\u2290" + ] + ] + }, + { + "input": "&sqsupseteq", + "description": "Bad named entity: sqsupseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sqsupseteq" + ] + ] + }, + { + "input": "⊒", + "description": "Named entity: sqsupseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2292" + ] + ] + }, + { + "input": "&squ", + "description": "Bad named entity: squ without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&squ" + ] + ] + }, + { + "input": "□", + "description": "Named entity: squ; with a semi-colon", + "output": [ + [ + "Character", + "\u25a1" + ] + ] + }, + { + "input": "&square", + "description": "Bad named entity: square without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&square" + ] + ] + }, + { + "input": "□", + "description": "Named entity: square; with a semi-colon", + "output": [ + [ + "Character", + "\u25a1" + ] + ] + }, + { + "input": "&squarf", + "description": "Bad named entity: squarf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&squarf" + ] + ] + }, + { + "input": "▪", + "description": "Named entity: squarf; with a semi-colon", + "output": [ + [ + "Character", + "\u25aa" + ] + ] + }, + { + "input": "&squf", + "description": "Bad named entity: squf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&squf" + ] + ] + }, + { + "input": "▪", + "description": "Named entity: squf; with a semi-colon", + "output": [ + [ + "Character", + "\u25aa" + ] + ] + }, + { + "input": "&srarr", + "description": "Bad named entity: srarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&srarr" + ] + ] + }, + { + "input": "→", + "description": "Named entity: srarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2192" + ] + ] + }, + { + "input": "&sscr", + "description": "Bad named entity: sscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sscr" + ] + ] + }, + { + "input": "𝓈", + "description": "Named entity: sscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc8" + ] + ] + }, + { + "input": "&ssetmn", + "description": "Bad named entity: ssetmn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ssetmn" + ] + ] + }, + { + "input": "∖", + "description": "Named entity: ssetmn; with a semi-colon", + "output": [ + [ + "Character", + "\u2216" + ] + ] + }, + { + "input": "&ssmile", + "description": "Bad named entity: ssmile without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ssmile" + ] + ] + }, + { + "input": "⌣", + "description": "Named entity: ssmile; with a semi-colon", + "output": [ + [ + "Character", + "\u2323" + ] + ] + }, + { + "input": "&sstarf", + "description": "Bad named entity: sstarf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sstarf" + ] + ] + }, + { + "input": "⋆", + "description": "Named entity: sstarf; with a semi-colon", + "output": [ + [ + "Character", + "\u22c6" + ] + ] + }, + { + "input": "&star", + "description": "Bad named entity: star without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&star" + ] + ] + }, + { + "input": "☆", + "description": "Named entity: star; with a semi-colon", + "output": [ + [ + "Character", + "\u2606" + ] + ] + }, + { + "input": "&starf", + "description": "Bad named entity: starf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&starf" + ] + ] + }, + { + "input": "★", + "description": "Named entity: starf; with a semi-colon", + "output": [ + [ + "Character", + "\u2605" + ] + ] + }, + { + "input": "&straightepsilon", + "description": "Bad named entity: straightepsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&straightepsilon" + ] + ] + }, + { + "input": "ϵ", + "description": "Named entity: straightepsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03f5" + ] + ] + }, + { + "input": "&straightphi", + "description": "Bad named entity: straightphi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&straightphi" + ] + ] + }, + { + "input": "ϕ", + "description": "Named entity: straightphi; with a semi-colon", + "output": [ + [ + "Character", + "\u03d5" + ] + ] + }, + { + "input": "&strns", + "description": "Bad named entity: strns without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&strns" + ] + ] + }, + { + "input": "¯", + "description": "Named entity: strns; with a semi-colon", + "output": [ + [ + "Character", + "\u00af" + ] + ] + }, + { + "input": "&sub", + "description": "Bad named entity: sub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sub" + ] + ] + }, + { + "input": "⊂", + "description": "Named entity: sub; with a semi-colon", + "output": [ + [ + "Character", + "\u2282" + ] + ] + }, + { + "input": "&subE", + "description": "Bad named entity: subE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subE" + ] + ] + }, + { + "input": "⫅", + "description": "Named entity: subE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac5" + ] + ] + }, + { + "input": "&subdot", + "description": "Bad named entity: subdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subdot" + ] + ] + }, + { + "input": "⪽", + "description": "Named entity: subdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2abd" + ] + ] + }, + { + "input": "&sube", + "description": "Bad named entity: sube without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sube" + ] + ] + }, + { + "input": "⊆", + "description": "Named entity: sube; with a semi-colon", + "output": [ + [ + "Character", + "\u2286" + ] + ] + }, + { + "input": "&subedot", + "description": "Bad named entity: subedot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subedot" + ] + ] + }, + { + "input": "⫃", + "description": "Named entity: subedot; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac3" + ] + ] + }, + { + "input": "&submult", + "description": "Bad named entity: submult without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&submult" + ] + ] + }, + { + "input": "⫁", + "description": "Named entity: submult; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac1" + ] + ] + }, + { + "input": "&subnE", + "description": "Bad named entity: subnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subnE" + ] + ] + }, + { + "input": "⫋", + "description": "Named entity: subnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2acb" + ] + ] + }, + { + "input": "&subne", + "description": "Bad named entity: subne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subne" + ] + ] + }, + { + "input": "⊊", + "description": "Named entity: subne; with a semi-colon", + "output": [ + [ + "Character", + "\u228a" + ] + ] + }, + { + "input": "&subplus", + "description": "Bad named entity: subplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subplus" + ] + ] + }, + { + "input": "⪿", + "description": "Named entity: subplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2abf" + ] + ] + }, + { + "input": "&subrarr", + "description": "Bad named entity: subrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subrarr" + ] + ] + }, + { + "input": "⥹", + "description": "Named entity: subrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2979" + ] + ] + }, + { + "input": "&subset", + "description": "Bad named entity: subset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subset" + ] + ] + }, + { + "input": "⊂", + "description": "Named entity: subset; with a semi-colon", + "output": [ + [ + "Character", + "\u2282" + ] + ] + }, + { + "input": "&subseteq", + "description": "Bad named entity: subseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subseteq" + ] + ] + }, + { + "input": "⊆", + "description": "Named entity: subseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2286" + ] + ] + }, + { + "input": "&subseteqq", + "description": "Bad named entity: subseteqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subseteqq" + ] + ] + }, + { + "input": "⫅", + "description": "Named entity: subseteqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac5" + ] + ] + }, + { + "input": "&subsetneq", + "description": "Bad named entity: subsetneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subsetneq" + ] + ] + }, + { + "input": "⊊", + "description": "Named entity: subsetneq; with a semi-colon", + "output": [ + [ + "Character", + "\u228a" + ] + ] + }, + { + "input": "&subsetneqq", + "description": "Bad named entity: subsetneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subsetneqq" + ] + ] + }, + { + "input": "⫋", + "description": "Named entity: subsetneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2acb" + ] + ] + }, + { + "input": "&subsim", + "description": "Bad named entity: subsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subsim" + ] + ] + }, + { + "input": "⫇", + "description": "Named entity: subsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac7" + ] + ] + }, + { + "input": "&subsub", + "description": "Bad named entity: subsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subsub" + ] + ] + }, + { + "input": "⫕", + "description": "Named entity: subsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad5" + ] + ] + }, + { + "input": "&subsup", + "description": "Bad named entity: subsup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&subsup" + ] + ] + }, + { + "input": "⫓", + "description": "Named entity: subsup; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad3" + ] + ] + }, + { + "input": "&succ", + "description": "Bad named entity: succ without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succ" + ] + ] + }, + { + "input": "≻", + "description": "Named entity: succ; with a semi-colon", + "output": [ + [ + "Character", + "\u227b" + ] + ] + }, + { + "input": "&succapprox", + "description": "Bad named entity: succapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succapprox" + ] + ] + }, + { + "input": "⪸", + "description": "Named entity: succapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab8" + ] + ] + }, + { + "input": "&succcurlyeq", + "description": "Bad named entity: succcurlyeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succcurlyeq" + ] + ] + }, + { + "input": "≽", + "description": "Named entity: succcurlyeq; with a semi-colon", + "output": [ + [ + "Character", + "\u227d" + ] + ] + }, + { + "input": "&succeq", + "description": "Bad named entity: succeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succeq" + ] + ] + }, + { + "input": "⪰", + "description": "Named entity: succeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab0" + ] + ] + }, + { + "input": "&succnapprox", + "description": "Bad named entity: succnapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succnapprox" + ] + ] + }, + { + "input": "⪺", + "description": "Named entity: succnapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2aba" + ] + ] + }, + { + "input": "&succneqq", + "description": "Bad named entity: succneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succneqq" + ] + ] + }, + { + "input": "⪶", + "description": "Named entity: succneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ab6" + ] + ] + }, + { + "input": "&succnsim", + "description": "Bad named entity: succnsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succnsim" + ] + ] + }, + { + "input": "⋩", + "description": "Named entity: succnsim; with a semi-colon", + "output": [ + [ + "Character", + "\u22e9" + ] + ] + }, + { + "input": "&succsim", + "description": "Bad named entity: succsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&succsim" + ] + ] + }, + { + "input": "≿", + "description": "Named entity: succsim; with a semi-colon", + "output": [ + [ + "Character", + "\u227f" + ] + ] + }, + { + "input": "&sum", + "description": "Bad named entity: sum without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sum" + ] + ] + }, + { + "input": "∑", + "description": "Named entity: sum; with a semi-colon", + "output": [ + [ + "Character", + "\u2211" + ] + ] + }, + { + "input": "&sung", + "description": "Bad named entity: sung without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sung" + ] + ] + }, + { + "input": "♪", + "description": "Named entity: sung; with a semi-colon", + "output": [ + [ + "Character", + "\u266a" + ] + ] + }, + { + "input": "&sup", + "description": "Bad named entity: sup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&sup" + ] + ] + }, + { + "input": "¹", + "description": "Named entity: sup1 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b9" + ] + ] + }, + { + "input": "¹", + "description": "Named entity: sup1; with a semi-colon", + "output": [ + [ + "Character", + "\u00b9" + ] + ] + }, + { + "input": "²", + "description": "Named entity: sup2 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b2" + ] + ] + }, + { + "input": "²", + "description": "Named entity: sup2; with a semi-colon", + "output": [ + [ + "Character", + "\u00b2" + ] + ] + }, + { + "input": "³", + "description": "Named entity: sup3 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00b3" + ] + ] + }, + { + "input": "³", + "description": "Named entity: sup3; with a semi-colon", + "output": [ + [ + "Character", + "\u00b3" + ] + ] + }, + { + "input": "⊃", + "description": "Named entity: sup; with a semi-colon", + "output": [ + [ + "Character", + "\u2283" + ] + ] + }, + { + "input": "&supE", + "description": "Bad named entity: supE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supE" + ] + ] + }, + { + "input": "⫆", + "description": "Named entity: supE; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac6" + ] + ] + }, + { + "input": "&supdot", + "description": "Bad named entity: supdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supdot" + ] + ] + }, + { + "input": "⪾", + "description": "Named entity: supdot; with a semi-colon", + "output": [ + [ + "Character", + "\u2abe" + ] + ] + }, + { + "input": "&supdsub", + "description": "Bad named entity: supdsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supdsub" + ] + ] + }, + { + "input": "⫘", + "description": "Named entity: supdsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad8" + ] + ] + }, + { + "input": "&supe", + "description": "Bad named entity: supe without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supe" + ] + ] + }, + { + "input": "⊇", + "description": "Named entity: supe; with a semi-colon", + "output": [ + [ + "Character", + "\u2287" + ] + ] + }, + { + "input": "&supedot", + "description": "Bad named entity: supedot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supedot" + ] + ] + }, + { + "input": "⫄", + "description": "Named entity: supedot; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac4" + ] + ] + }, + { + "input": "&suphsol", + "description": "Bad named entity: suphsol without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&suphsol" + ] + ] + }, + { + "input": "⟉", + "description": "Named entity: suphsol; with a semi-colon", + "output": [ + [ + "Character", + "\u27c9" + ] + ] + }, + { + "input": "&suphsub", + "description": "Bad named entity: suphsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&suphsub" + ] + ] + }, + { + "input": "⫗", + "description": "Named entity: suphsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad7" + ] + ] + }, + { + "input": "&suplarr", + "description": "Bad named entity: suplarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&suplarr" + ] + ] + }, + { + "input": "⥻", + "description": "Named entity: suplarr; with a semi-colon", + "output": [ + [ + "Character", + "\u297b" + ] + ] + }, + { + "input": "&supmult", + "description": "Bad named entity: supmult without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supmult" + ] + ] + }, + { + "input": "⫂", + "description": "Named entity: supmult; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac2" + ] + ] + }, + { + "input": "&supnE", + "description": "Bad named entity: supnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supnE" + ] + ] + }, + { + "input": "⫌", + "description": "Named entity: supnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2acc" + ] + ] + }, + { + "input": "&supne", + "description": "Bad named entity: supne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supne" + ] + ] + }, + { + "input": "⊋", + "description": "Named entity: supne; with a semi-colon", + "output": [ + [ + "Character", + "\u228b" + ] + ] + }, + { + "input": "&supplus", + "description": "Bad named entity: supplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supplus" + ] + ] + }, + { + "input": "⫀", + "description": "Named entity: supplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac0" + ] + ] + }, + { + "input": "&supset", + "description": "Bad named entity: supset without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supset" + ] + ] + }, + { + "input": "⊃", + "description": "Named entity: supset; with a semi-colon", + "output": [ + [ + "Character", + "\u2283" + ] + ] + }, + { + "input": "&supseteq", + "description": "Bad named entity: supseteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supseteq" + ] + ] + }, + { + "input": "⊇", + "description": "Named entity: supseteq; with a semi-colon", + "output": [ + [ + "Character", + "\u2287" + ] + ] + }, + { + "input": "&supseteqq", + "description": "Bad named entity: supseteqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supseteqq" + ] + ] + }, + { + "input": "⫆", + "description": "Named entity: supseteqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac6" + ] + ] + }, + { + "input": "&supsetneq", + "description": "Bad named entity: supsetneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supsetneq" + ] + ] + }, + { + "input": "⊋", + "description": "Named entity: supsetneq; with a semi-colon", + "output": [ + [ + "Character", + "\u228b" + ] + ] + }, + { + "input": "&supsetneqq", + "description": "Bad named entity: supsetneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supsetneqq" + ] + ] + }, + { + "input": "⫌", + "description": "Named entity: supsetneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2acc" + ] + ] + }, + { + "input": "&supsim", + "description": "Bad named entity: supsim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supsim" + ] + ] + }, + { + "input": "⫈", + "description": "Named entity: supsim; with a semi-colon", + "output": [ + [ + "Character", + "\u2ac8" + ] + ] + }, + { + "input": "&supsub", + "description": "Bad named entity: supsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supsub" + ] + ] + }, + { + "input": "⫔", + "description": "Named entity: supsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad4" + ] + ] + }, + { + "input": "&supsup", + "description": "Bad named entity: supsup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&supsup" + ] + ] + }, + { + "input": "⫖", + "description": "Named entity: supsup; with a semi-colon", + "output": [ + [ + "Character", + "\u2ad6" + ] + ] + }, + { + "input": "&swArr", + "description": "Bad named entity: swArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&swArr" + ] + ] + }, + { + "input": "⇙", + "description": "Named entity: swArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d9" + ] + ] + }, + { + "input": "&swarhk", + "description": "Bad named entity: swarhk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&swarhk" + ] + ] + }, + { + "input": "⤦", + "description": "Named entity: swarhk; with a semi-colon", + "output": [ + [ + "Character", + "\u2926" + ] + ] + }, + { + "input": "&swarr", + "description": "Bad named entity: swarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&swarr" + ] + ] + }, + { + "input": "↙", + "description": "Named entity: swarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2199" + ] + ] + }, + { + "input": "&swarrow", + "description": "Bad named entity: swarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&swarrow" + ] + ] + }, + { + "input": "↙", + "description": "Named entity: swarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2199" + ] + ] + }, + { + "input": "&swnwar", + "description": "Bad named entity: swnwar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&swnwar" + ] + ] + }, + { + "input": "⤪", + "description": "Named entity: swnwar; with a semi-colon", + "output": [ + [ + "Character", + "\u292a" + ] + ] + }, + { + "input": "ß", + "description": "Named entity: szlig without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00df" + ] + ] + }, + { + "input": "ß", + "description": "Named entity: szlig; with a semi-colon", + "output": [ + [ + "Character", + "\u00df" + ] + ] + }, + { + "input": "&target", + "description": "Bad named entity: target without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&target" + ] + ] + }, + { + "input": "⌖", + "description": "Named entity: target; with a semi-colon", + "output": [ + [ + "Character", + "\u2316" + ] + ] + }, + { + "input": "&tau", + "description": "Bad named entity: tau without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tau" + ] + ] + }, + { + "input": "τ", + "description": "Named entity: tau; with a semi-colon", + "output": [ + [ + "Character", + "\u03c4" + ] + ] + }, + { + "input": "&tbrk", + "description": "Bad named entity: tbrk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tbrk" + ] + ] + }, + { + "input": "⎴", + "description": "Named entity: tbrk; with a semi-colon", + "output": [ + [ + "Character", + "\u23b4" + ] + ] + }, + { + "input": "&tcaron", + "description": "Bad named entity: tcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tcaron" + ] + ] + }, + { + "input": "ť", + "description": "Named entity: tcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u0165" + ] + ] + }, + { + "input": "&tcedil", + "description": "Bad named entity: tcedil without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tcedil" + ] + ] + }, + { + "input": "ţ", + "description": "Named entity: tcedil; with a semi-colon", + "output": [ + [ + "Character", + "\u0163" + ] + ] + }, + { + "input": "&tcy", + "description": "Bad named entity: tcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tcy" + ] + ] + }, + { + "input": "т", + "description": "Named entity: tcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0442" + ] + ] + }, + { + "input": "&tdot", + "description": "Bad named entity: tdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tdot" + ] + ] + }, + { + "input": "⃛", + "description": "Named entity: tdot; with a semi-colon", + "output": [ + [ + "Character", + "\u20db" + ] + ] + }, + { + "input": "&telrec", + "description": "Bad named entity: telrec without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&telrec" + ] + ] + }, + { + "input": "⌕", + "description": "Named entity: telrec; with a semi-colon", + "output": [ + [ + "Character", + "\u2315" + ] + ] + }, + { + "input": "&tfr", + "description": "Bad named entity: tfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tfr" + ] + ] + }, + { + "input": "𝔱", + "description": "Named entity: tfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd31" + ] + ] + }, + { + "input": "&there4", + "description": "Bad named entity: there4 without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&there4" + ] + ] + }, + { + "input": "∴", + "description": "Named entity: there4; with a semi-colon", + "output": [ + [ + "Character", + "\u2234" + ] + ] + }, + { + "input": "&therefore", + "description": "Bad named entity: therefore without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&therefore" + ] + ] + }, + { + "input": "∴", + "description": "Named entity: therefore; with a semi-colon", + "output": [ + [ + "Character", + "\u2234" + ] + ] + }, + { + "input": "&theta", + "description": "Bad named entity: theta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&theta" + ] + ] + }, + { + "input": "θ", + "description": "Named entity: theta; with a semi-colon", + "output": [ + [ + "Character", + "\u03b8" + ] + ] + }, + { + "input": "&thetasym", + "description": "Bad named entity: thetasym without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thetasym" + ] + ] + }, + { + "input": "ϑ", + "description": "Named entity: thetasym; with a semi-colon", + "output": [ + [ + "Character", + "\u03d1" + ] + ] + }, + { + "input": "&thetav", + "description": "Bad named entity: thetav without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thetav" + ] + ] + }, + { + "input": "ϑ", + "description": "Named entity: thetav; with a semi-colon", + "output": [ + [ + "Character", + "\u03d1" + ] + ] + }, + { + "input": "&thickapprox", + "description": "Bad named entity: thickapprox without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thickapprox" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: thickapprox; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&thicksim", + "description": "Bad named entity: thicksim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thicksim" + ] + ] + }, + { + "input": "∼", + "description": "Named entity: thicksim; with a semi-colon", + "output": [ + [ + "Character", + "\u223c" + ] + ] + }, + { + "input": "&thinsp", + "description": "Bad named entity: thinsp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thinsp" + ] + ] + }, + { + "input": " ", + "description": "Named entity: thinsp; with a semi-colon", + "output": [ + [ + "Character", + "\u2009" + ] + ] + }, + { + "input": "&thkap", + "description": "Bad named entity: thkap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thkap" + ] + ] + }, + { + "input": "≈", + "description": "Named entity: thkap; with a semi-colon", + "output": [ + [ + "Character", + "\u2248" + ] + ] + }, + { + "input": "&thksim", + "description": "Bad named entity: thksim without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&thksim" + ] + ] + }, + { + "input": "∼", + "description": "Named entity: thksim; with a semi-colon", + "output": [ + [ + "Character", + "\u223c" + ] + ] + }, + { + "input": "þ", + "description": "Named entity: thorn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00fe" + ] + ] + }, + { + "input": "þ", + "description": "Named entity: thorn; with a semi-colon", + "output": [ + [ + "Character", + "\u00fe" + ] + ] + }, + { + "input": "&tilde", + "description": "Bad named entity: tilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tilde" + ] + ] + }, + { + "input": "˜", + "description": "Named entity: tilde; with a semi-colon", + "output": [ + [ + "Character", + "\u02dc" + ] + ] + }, + { + "input": "×", + "description": "Named entity: times without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00d7" + ] + ] + }, + { + "input": "×", + "description": "Named entity: times; with a semi-colon", + "output": [ + [ + "Character", + "\u00d7" + ] + ] + }, + { + "input": "⊠", + "description": "Named entity: timesb; with a semi-colon", + "output": [ + [ + "Character", + "\u22a0" + ] + ] + }, + { + "input": "⨱", + "description": "Named entity: timesbar; with a semi-colon", + "output": [ + [ + "Character", + "\u2a31" + ] + ] + }, + { + "input": "⨰", + "description": "Named entity: timesd; with a semi-colon", + "output": [ + [ + "Character", + "\u2a30" + ] + ] + }, + { + "input": "&tint", + "description": "Bad named entity: tint without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tint" + ] + ] + }, + { + "input": "∭", + "description": "Named entity: tint; with a semi-colon", + "output": [ + [ + "Character", + "\u222d" + ] + ] + }, + { + "input": "&toea", + "description": "Bad named entity: toea without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&toea" + ] + ] + }, + { + "input": "⤨", + "description": "Named entity: toea; with a semi-colon", + "output": [ + [ + "Character", + "\u2928" + ] + ] + }, + { + "input": "&top", + "description": "Bad named entity: top without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&top" + ] + ] + }, + { + "input": "⊤", + "description": "Named entity: top; with a semi-colon", + "output": [ + [ + "Character", + "\u22a4" + ] + ] + }, + { + "input": "&topbot", + "description": "Bad named entity: topbot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&topbot" + ] + ] + }, + { + "input": "⌶", + "description": "Named entity: topbot; with a semi-colon", + "output": [ + [ + "Character", + "\u2336" + ] + ] + }, + { + "input": "&topcir", + "description": "Bad named entity: topcir without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&topcir" + ] + ] + }, + { + "input": "⫱", + "description": "Named entity: topcir; with a semi-colon", + "output": [ + [ + "Character", + "\u2af1" + ] + ] + }, + { + "input": "&topf", + "description": "Bad named entity: topf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&topf" + ] + ] + }, + { + "input": "𝕥", + "description": "Named entity: topf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd65" + ] + ] + }, + { + "input": "&topfork", + "description": "Bad named entity: topfork without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&topfork" + ] + ] + }, + { + "input": "⫚", + "description": "Named entity: topfork; with a semi-colon", + "output": [ + [ + "Character", + "\u2ada" + ] + ] + }, + { + "input": "&tosa", + "description": "Bad named entity: tosa without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tosa" + ] + ] + }, + { + "input": "⤩", + "description": "Named entity: tosa; with a semi-colon", + "output": [ + [ + "Character", + "\u2929" + ] + ] + }, + { + "input": "&tprime", + "description": "Bad named entity: tprime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tprime" + ] + ] + }, + { + "input": "‴", + "description": "Named entity: tprime; with a semi-colon", + "output": [ + [ + "Character", + "\u2034" + ] + ] + }, + { + "input": "&trade", + "description": "Bad named entity: trade without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trade" + ] + ] + }, + { + "input": "™", + "description": "Named entity: trade; with a semi-colon", + "output": [ + [ + "Character", + "\u2122" + ] + ] + }, + { + "input": "&triangle", + "description": "Bad named entity: triangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triangle" + ] + ] + }, + { + "input": "▵", + "description": "Named entity: triangle; with a semi-colon", + "output": [ + [ + "Character", + "\u25b5" + ] + ] + }, + { + "input": "&triangledown", + "description": "Bad named entity: triangledown without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triangledown" + ] + ] + }, + { + "input": "▿", + "description": "Named entity: triangledown; with a semi-colon", + "output": [ + [ + "Character", + "\u25bf" + ] + ] + }, + { + "input": "&triangleleft", + "description": "Bad named entity: triangleleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triangleleft" + ] + ] + }, + { + "input": "◃", + "description": "Named entity: triangleleft; with a semi-colon", + "output": [ + [ + "Character", + "\u25c3" + ] + ] + }, + { + "input": "&trianglelefteq", + "description": "Bad named entity: trianglelefteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trianglelefteq" + ] + ] + }, + { + "input": "⊴", + "description": "Named entity: trianglelefteq; with a semi-colon", + "output": [ + [ + "Character", + "\u22b4" + ] + ] + }, + { + "input": "&triangleq", + "description": "Bad named entity: triangleq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triangleq" + ] + ] + }, + { + "input": "≜", + "description": "Named entity: triangleq; with a semi-colon", + "output": [ + [ + "Character", + "\u225c" + ] + ] + }, + { + "input": "&triangleright", + "description": "Bad named entity: triangleright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triangleright" + ] + ] + }, + { + "input": "▹", + "description": "Named entity: triangleright; with a semi-colon", + "output": [ + [ + "Character", + "\u25b9" + ] + ] + }, + { + "input": "&trianglerighteq", + "description": "Bad named entity: trianglerighteq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trianglerighteq" + ] + ] + }, + { + "input": "⊵", + "description": "Named entity: trianglerighteq; with a semi-colon", + "output": [ + [ + "Character", + "\u22b5" + ] + ] + }, + { + "input": "&tridot", + "description": "Bad named entity: tridot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tridot" + ] + ] + }, + { + "input": "◬", + "description": "Named entity: tridot; with a semi-colon", + "output": [ + [ + "Character", + "\u25ec" + ] + ] + }, + { + "input": "&trie", + "description": "Bad named entity: trie without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trie" + ] + ] + }, + { + "input": "≜", + "description": "Named entity: trie; with a semi-colon", + "output": [ + [ + "Character", + "\u225c" + ] + ] + }, + { + "input": "&triminus", + "description": "Bad named entity: triminus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triminus" + ] + ] + }, + { + "input": "⨺", + "description": "Named entity: triminus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a3a" + ] + ] + }, + { + "input": "&triplus", + "description": "Bad named entity: triplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&triplus" + ] + ] + }, + { + "input": "⨹", + "description": "Named entity: triplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a39" + ] + ] + }, + { + "input": "&trisb", + "description": "Bad named entity: trisb without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trisb" + ] + ] + }, + { + "input": "⧍", + "description": "Named entity: trisb; with a semi-colon", + "output": [ + [ + "Character", + "\u29cd" + ] + ] + }, + { + "input": "&tritime", + "description": "Bad named entity: tritime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tritime" + ] + ] + }, + { + "input": "⨻", + "description": "Named entity: tritime; with a semi-colon", + "output": [ + [ + "Character", + "\u2a3b" + ] + ] + }, + { + "input": "&trpezium", + "description": "Bad named entity: trpezium without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&trpezium" + ] + ] + }, + { + "input": "⏢", + "description": "Named entity: trpezium; with a semi-colon", + "output": [ + [ + "Character", + "\u23e2" + ] + ] + }, + { + "input": "&tscr", + "description": "Bad named entity: tscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tscr" + ] + ] + }, + { + "input": "𝓉", + "description": "Named entity: tscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcc9" + ] + ] + }, + { + "input": "&tscy", + "description": "Bad named entity: tscy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tscy" + ] + ] + }, + { + "input": "ц", + "description": "Named entity: tscy; with a semi-colon", + "output": [ + [ + "Character", + "\u0446" + ] + ] + }, + { + "input": "&tshcy", + "description": "Bad named entity: tshcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tshcy" + ] + ] + }, + { + "input": "ћ", + "description": "Named entity: tshcy; with a semi-colon", + "output": [ + [ + "Character", + "\u045b" + ] + ] + }, + { + "input": "&tstrok", + "description": "Bad named entity: tstrok without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&tstrok" + ] + ] + }, + { + "input": "ŧ", + "description": "Named entity: tstrok; with a semi-colon", + "output": [ + [ + "Character", + "\u0167" + ] + ] + }, + { + "input": "&twixt", + "description": "Bad named entity: twixt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&twixt" + ] + ] + }, + { + "input": "≬", + "description": "Named entity: twixt; with a semi-colon", + "output": [ + [ + "Character", + "\u226c" + ] + ] + }, + { + "input": "&twoheadleftarrow", + "description": "Bad named entity: twoheadleftarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&twoheadleftarrow" + ] + ] + }, + { + "input": "↞", + "description": "Named entity: twoheadleftarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u219e" + ] + ] + }, + { + "input": "&twoheadrightarrow", + "description": "Bad named entity: twoheadrightarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&twoheadrightarrow" + ] + ] + }, + { + "input": "↠", + "description": "Named entity: twoheadrightarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u21a0" + ] + ] + }, + { + "input": "&uArr", + "description": "Bad named entity: uArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uArr" + ] + ] + }, + { + "input": "⇑", + "description": "Named entity: uArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d1" + ] + ] + }, + { + "input": "&uHar", + "description": "Bad named entity: uHar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uHar" + ] + ] + }, + { + "input": "⥣", + "description": "Named entity: uHar; with a semi-colon", + "output": [ + [ + "Character", + "\u2963" + ] + ] + }, + { + "input": "ú", + "description": "Named entity: uacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00fa" + ] + ] + }, + { + "input": "ú", + "description": "Named entity: uacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00fa" + ] + ] + }, + { + "input": "&uarr", + "description": "Bad named entity: uarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uarr" + ] + ] + }, + { + "input": "↑", + "description": "Named entity: uarr; with a semi-colon", + "output": [ + [ + "Character", + "\u2191" + ] + ] + }, + { + "input": "&ubrcy", + "description": "Bad named entity: ubrcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ubrcy" + ] + ] + }, + { + "input": "ў", + "description": "Named entity: ubrcy; with a semi-colon", + "output": [ + [ + "Character", + "\u045e" + ] + ] + }, + { + "input": "&ubreve", + "description": "Bad named entity: ubreve without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ubreve" + ] + ] + }, + { + "input": "ŭ", + "description": "Named entity: ubreve; with a semi-colon", + "output": [ + [ + "Character", + "\u016d" + ] + ] + }, + { + "input": "û", + "description": "Named entity: ucirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00fb" + ] + ] + }, + { + "input": "û", + "description": "Named entity: ucirc; with a semi-colon", + "output": [ + [ + "Character", + "\u00fb" + ] + ] + }, + { + "input": "&ucy", + "description": "Bad named entity: ucy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ucy" + ] + ] + }, + { + "input": "у", + "description": "Named entity: ucy; with a semi-colon", + "output": [ + [ + "Character", + "\u0443" + ] + ] + }, + { + "input": "&udarr", + "description": "Bad named entity: udarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&udarr" + ] + ] + }, + { + "input": "⇅", + "description": "Named entity: udarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c5" + ] + ] + }, + { + "input": "&udblac", + "description": "Bad named entity: udblac without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&udblac" + ] + ] + }, + { + "input": "ű", + "description": "Named entity: udblac; with a semi-colon", + "output": [ + [ + "Character", + "\u0171" + ] + ] + }, + { + "input": "&udhar", + "description": "Bad named entity: udhar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&udhar" + ] + ] + }, + { + "input": "⥮", + "description": "Named entity: udhar; with a semi-colon", + "output": [ + [ + "Character", + "\u296e" + ] + ] + }, + { + "input": "&ufisht", + "description": "Bad named entity: ufisht without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ufisht" + ] + ] + }, + { + "input": "⥾", + "description": "Named entity: ufisht; with a semi-colon", + "output": [ + [ + "Character", + "\u297e" + ] + ] + }, + { + "input": "&ufr", + "description": "Bad named entity: ufr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ufr" + ] + ] + }, + { + "input": "𝔲", + "description": "Named entity: ufr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd32" + ] + ] + }, + { + "input": "ù", + "description": "Named entity: ugrave without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00f9" + ] + ] + }, + { + "input": "ù", + "description": "Named entity: ugrave; with a semi-colon", + "output": [ + [ + "Character", + "\u00f9" + ] + ] + }, + { + "input": "&uharl", + "description": "Bad named entity: uharl without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uharl" + ] + ] + }, + { + "input": "↿", + "description": "Named entity: uharl; with a semi-colon", + "output": [ + [ + "Character", + "\u21bf" + ] + ] + }, + { + "input": "&uharr", + "description": "Bad named entity: uharr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uharr" + ] + ] + }, + { + "input": "↾", + "description": "Named entity: uharr; with a semi-colon", + "output": [ + [ + "Character", + "\u21be" + ] + ] + }, + { + "input": "&uhblk", + "description": "Bad named entity: uhblk without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uhblk" + ] + ] + }, + { + "input": "▀", + "description": "Named entity: uhblk; with a semi-colon", + "output": [ + [ + "Character", + "\u2580" + ] + ] + }, + { + "input": "&ulcorn", + "description": "Bad named entity: ulcorn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ulcorn" + ] + ] + }, + { + "input": "⌜", + "description": "Named entity: ulcorn; with a semi-colon", + "output": [ + [ + "Character", + "\u231c" + ] + ] + }, + { + "input": "&ulcorner", + "description": "Bad named entity: ulcorner without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ulcorner" + ] + ] + }, + { + "input": "⌜", + "description": "Named entity: ulcorner; with a semi-colon", + "output": [ + [ + "Character", + "\u231c" + ] + ] + }, + { + "input": "&ulcrop", + "description": "Bad named entity: ulcrop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ulcrop" + ] + ] + }, + { + "input": "⌏", + "description": "Named entity: ulcrop; with a semi-colon", + "output": [ + [ + "Character", + "\u230f" + ] + ] + }, + { + "input": "&ultri", + "description": "Bad named entity: ultri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ultri" + ] + ] + }, + { + "input": "◸", + "description": "Named entity: ultri; with a semi-colon", + "output": [ + [ + "Character", + "\u25f8" + ] + ] + }, + { + "input": "&umacr", + "description": "Bad named entity: umacr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&umacr" + ] + ] + }, + { + "input": "ū", + "description": "Named entity: umacr; with a semi-colon", + "output": [ + [ + "Character", + "\u016b" + ] + ] + }, + { + "input": "¨", + "description": "Named entity: uml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a8" + ] + ] + }, + { + "input": "¨", + "description": "Named entity: uml; with a semi-colon", + "output": [ + [ + "Character", + "\u00a8" + ] + ] + }, + { + "input": "&uogon", + "description": "Bad named entity: uogon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uogon" + ] + ] + }, + { + "input": "ų", + "description": "Named entity: uogon; with a semi-colon", + "output": [ + [ + "Character", + "\u0173" + ] + ] + }, + { + "input": "&uopf", + "description": "Bad named entity: uopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uopf" + ] + ] + }, + { + "input": "𝕦", + "description": "Named entity: uopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd66" + ] + ] + }, + { + "input": "&uparrow", + "description": "Bad named entity: uparrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uparrow" + ] + ] + }, + { + "input": "↑", + "description": "Named entity: uparrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2191" + ] + ] + }, + { + "input": "&updownarrow", + "description": "Bad named entity: updownarrow without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&updownarrow" + ] + ] + }, + { + "input": "↕", + "description": "Named entity: updownarrow; with a semi-colon", + "output": [ + [ + "Character", + "\u2195" + ] + ] + }, + { + "input": "&upharpoonleft", + "description": "Bad named entity: upharpoonleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upharpoonleft" + ] + ] + }, + { + "input": "↿", + "description": "Named entity: upharpoonleft; with a semi-colon", + "output": [ + [ + "Character", + "\u21bf" + ] + ] + }, + { + "input": "&upharpoonright", + "description": "Bad named entity: upharpoonright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upharpoonright" + ] + ] + }, + { + "input": "↾", + "description": "Named entity: upharpoonright; with a semi-colon", + "output": [ + [ + "Character", + "\u21be" + ] + ] + }, + { + "input": "&uplus", + "description": "Bad named entity: uplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uplus" + ] + ] + }, + { + "input": "⊎", + "description": "Named entity: uplus; with a semi-colon", + "output": [ + [ + "Character", + "\u228e" + ] + ] + }, + { + "input": "&upsi", + "description": "Bad named entity: upsi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upsi" + ] + ] + }, + { + "input": "υ", + "description": "Named entity: upsi; with a semi-colon", + "output": [ + [ + "Character", + "\u03c5" + ] + ] + }, + { + "input": "&upsih", + "description": "Bad named entity: upsih without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upsih" + ] + ] + }, + { + "input": "ϒ", + "description": "Named entity: upsih; with a semi-colon", + "output": [ + [ + "Character", + "\u03d2" + ] + ] + }, + { + "input": "&upsilon", + "description": "Bad named entity: upsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upsilon" + ] + ] + }, + { + "input": "υ", + "description": "Named entity: upsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03c5" + ] + ] + }, + { + "input": "&upuparrows", + "description": "Bad named entity: upuparrows without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&upuparrows" + ] + ] + }, + { + "input": "⇈", + "description": "Named entity: upuparrows; with a semi-colon", + "output": [ + [ + "Character", + "\u21c8" + ] + ] + }, + { + "input": "&urcorn", + "description": "Bad named entity: urcorn without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&urcorn" + ] + ] + }, + { + "input": "⌝", + "description": "Named entity: urcorn; with a semi-colon", + "output": [ + [ + "Character", + "\u231d" + ] + ] + }, + { + "input": "&urcorner", + "description": "Bad named entity: urcorner without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&urcorner" + ] + ] + }, + { + "input": "⌝", + "description": "Named entity: urcorner; with a semi-colon", + "output": [ + [ + "Character", + "\u231d" + ] + ] + }, + { + "input": "&urcrop", + "description": "Bad named entity: urcrop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&urcrop" + ] + ] + }, + { + "input": "⌎", + "description": "Named entity: urcrop; with a semi-colon", + "output": [ + [ + "Character", + "\u230e" + ] + ] + }, + { + "input": "&uring", + "description": "Bad named entity: uring without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uring" + ] + ] + }, + { + "input": "ů", + "description": "Named entity: uring; with a semi-colon", + "output": [ + [ + "Character", + "\u016f" + ] + ] + }, + { + "input": "&urtri", + "description": "Bad named entity: urtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&urtri" + ] + ] + }, + { + "input": "◹", + "description": "Named entity: urtri; with a semi-colon", + "output": [ + [ + "Character", + "\u25f9" + ] + ] + }, + { + "input": "&uscr", + "description": "Bad named entity: uscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uscr" + ] + ] + }, + { + "input": "𝓊", + "description": "Named entity: uscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcca" + ] + ] + }, + { + "input": "&utdot", + "description": "Bad named entity: utdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&utdot" + ] + ] + }, + { + "input": "⋰", + "description": "Named entity: utdot; with a semi-colon", + "output": [ + [ + "Character", + "\u22f0" + ] + ] + }, + { + "input": "&utilde", + "description": "Bad named entity: utilde without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&utilde" + ] + ] + }, + { + "input": "ũ", + "description": "Named entity: utilde; with a semi-colon", + "output": [ + [ + "Character", + "\u0169" + ] + ] + }, + { + "input": "&utri", + "description": "Bad named entity: utri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&utri" + ] + ] + }, + { + "input": "▵", + "description": "Named entity: utri; with a semi-colon", + "output": [ + [ + "Character", + "\u25b5" + ] + ] + }, + { + "input": "&utrif", + "description": "Bad named entity: utrif without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&utrif" + ] + ] + }, + { + "input": "▴", + "description": "Named entity: utrif; with a semi-colon", + "output": [ + [ + "Character", + "\u25b4" + ] + ] + }, + { + "input": "&uuarr", + "description": "Bad named entity: uuarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uuarr" + ] + ] + }, + { + "input": "⇈", + "description": "Named entity: uuarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21c8" + ] + ] + }, + { + "input": "ü", + "description": "Named entity: uuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00fc" + ] + ] + }, + { + "input": "ü", + "description": "Named entity: uuml; with a semi-colon", + "output": [ + [ + "Character", + "\u00fc" + ] + ] + }, + { + "input": "&uwangle", + "description": "Bad named entity: uwangle without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&uwangle" + ] + ] + }, + { + "input": "⦧", + "description": "Named entity: uwangle; with a semi-colon", + "output": [ + [ + "Character", + "\u29a7" + ] + ] + }, + { + "input": "&vArr", + "description": "Bad named entity: vArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vArr" + ] + ] + }, + { + "input": "⇕", + "description": "Named entity: vArr; with a semi-colon", + "output": [ + [ + "Character", + "\u21d5" + ] + ] + }, + { + "input": "&vBar", + "description": "Bad named entity: vBar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vBar" + ] + ] + }, + { + "input": "⫨", + "description": "Named entity: vBar; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae8" + ] + ] + }, + { + "input": "&vBarv", + "description": "Bad named entity: vBarv without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vBarv" + ] + ] + }, + { + "input": "⫩", + "description": "Named entity: vBarv; with a semi-colon", + "output": [ + [ + "Character", + "\u2ae9" + ] + ] + }, + { + "input": "&vDash", + "description": "Bad named entity: vDash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vDash" + ] + ] + }, + { + "input": "⊨", + "description": "Named entity: vDash; with a semi-colon", + "output": [ + [ + "Character", + "\u22a8" + ] + ] + }, + { + "input": "&vangrt", + "description": "Bad named entity: vangrt without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vangrt" + ] + ] + }, + { + "input": "⦜", + "description": "Named entity: vangrt; with a semi-colon", + "output": [ + [ + "Character", + "\u299c" + ] + ] + }, + { + "input": "&varepsilon", + "description": "Bad named entity: varepsilon without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varepsilon" + ] + ] + }, + { + "input": "ϵ", + "description": "Named entity: varepsilon; with a semi-colon", + "output": [ + [ + "Character", + "\u03f5" + ] + ] + }, + { + "input": "&varkappa", + "description": "Bad named entity: varkappa without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varkappa" + ] + ] + }, + { + "input": "ϰ", + "description": "Named entity: varkappa; with a semi-colon", + "output": [ + [ + "Character", + "\u03f0" + ] + ] + }, + { + "input": "&varnothing", + "description": "Bad named entity: varnothing without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varnothing" + ] + ] + }, + { + "input": "∅", + "description": "Named entity: varnothing; with a semi-colon", + "output": [ + [ + "Character", + "\u2205" + ] + ] + }, + { + "input": "&varphi", + "description": "Bad named entity: varphi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varphi" + ] + ] + }, + { + "input": "ϕ", + "description": "Named entity: varphi; with a semi-colon", + "output": [ + [ + "Character", + "\u03d5" + ] + ] + }, + { + "input": "&varpi", + "description": "Bad named entity: varpi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varpi" + ] + ] + }, + { + "input": "ϖ", + "description": "Named entity: varpi; with a semi-colon", + "output": [ + [ + "Character", + "\u03d6" + ] + ] + }, + { + "input": "&varpropto", + "description": "Bad named entity: varpropto without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varpropto" + ] + ] + }, + { + "input": "∝", + "description": "Named entity: varpropto; with a semi-colon", + "output": [ + [ + "Character", + "\u221d" + ] + ] + }, + { + "input": "&varr", + "description": "Bad named entity: varr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varr" + ] + ] + }, + { + "input": "↕", + "description": "Named entity: varr; with a semi-colon", + "output": [ + [ + "Character", + "\u2195" + ] + ] + }, + { + "input": "&varrho", + "description": "Bad named entity: varrho without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varrho" + ] + ] + }, + { + "input": "ϱ", + "description": "Named entity: varrho; with a semi-colon", + "output": [ + [ + "Character", + "\u03f1" + ] + ] + }, + { + "input": "&varsigma", + "description": "Bad named entity: varsigma without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varsigma" + ] + ] + }, + { + "input": "ς", + "description": "Named entity: varsigma; with a semi-colon", + "output": [ + [ + "Character", + "\u03c2" + ] + ] + }, + { + "input": "&varsubsetneq", + "description": "Bad named entity: varsubsetneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varsubsetneq" + ] + ] + }, + { + "input": "⊊︀", + "description": "Named entity: varsubsetneq; with a semi-colon", + "output": [ + [ + "Character", + "\u228a\ufe00" + ] + ] + }, + { + "input": "&varsubsetneqq", + "description": "Bad named entity: varsubsetneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varsubsetneqq" + ] + ] + }, + { + "input": "⫋︀", + "description": "Named entity: varsubsetneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2acb\ufe00" + ] + ] + }, + { + "input": "&varsupsetneq", + "description": "Bad named entity: varsupsetneq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varsupsetneq" + ] + ] + }, + { + "input": "⊋︀", + "description": "Named entity: varsupsetneq; with a semi-colon", + "output": [ + [ + "Character", + "\u228b\ufe00" + ] + ] + }, + { + "input": "&varsupsetneqq", + "description": "Bad named entity: varsupsetneqq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&varsupsetneqq" + ] + ] + }, + { + "input": "⫌︀", + "description": "Named entity: varsupsetneqq; with a semi-colon", + "output": [ + [ + "Character", + "\u2acc\ufe00" + ] + ] + }, + { + "input": "&vartheta", + "description": "Bad named entity: vartheta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vartheta" + ] + ] + }, + { + "input": "ϑ", + "description": "Named entity: vartheta; with a semi-colon", + "output": [ + [ + "Character", + "\u03d1" + ] + ] + }, + { + "input": "&vartriangleleft", + "description": "Bad named entity: vartriangleleft without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vartriangleleft" + ] + ] + }, + { + "input": "⊲", + "description": "Named entity: vartriangleleft; with a semi-colon", + "output": [ + [ + "Character", + "\u22b2" + ] + ] + }, + { + "input": "&vartriangleright", + "description": "Bad named entity: vartriangleright without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vartriangleright" + ] + ] + }, + { + "input": "⊳", + "description": "Named entity: vartriangleright; with a semi-colon", + "output": [ + [ + "Character", + "\u22b3" + ] + ] + }, + { + "input": "&vcy", + "description": "Bad named entity: vcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vcy" + ] + ] + }, + { + "input": "в", + "description": "Named entity: vcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0432" + ] + ] + }, + { + "input": "&vdash", + "description": "Bad named entity: vdash without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vdash" + ] + ] + }, + { + "input": "⊢", + "description": "Named entity: vdash; with a semi-colon", + "output": [ + [ + "Character", + "\u22a2" + ] + ] + }, + { + "input": "&vee", + "description": "Bad named entity: vee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vee" + ] + ] + }, + { + "input": "∨", + "description": "Named entity: vee; with a semi-colon", + "output": [ + [ + "Character", + "\u2228" + ] + ] + }, + { + "input": "&veebar", + "description": "Bad named entity: veebar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&veebar" + ] + ] + }, + { + "input": "⊻", + "description": "Named entity: veebar; with a semi-colon", + "output": [ + [ + "Character", + "\u22bb" + ] + ] + }, + { + "input": "&veeeq", + "description": "Bad named entity: veeeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&veeeq" + ] + ] + }, + { + "input": "≚", + "description": "Named entity: veeeq; with a semi-colon", + "output": [ + [ + "Character", + "\u225a" + ] + ] + }, + { + "input": "&vellip", + "description": "Bad named entity: vellip without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vellip" + ] + ] + }, + { + "input": "⋮", + "description": "Named entity: vellip; with a semi-colon", + "output": [ + [ + "Character", + "\u22ee" + ] + ] + }, + { + "input": "&verbar", + "description": "Bad named entity: verbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&verbar" + ] + ] + }, + { + "input": "|", + "description": "Named entity: verbar; with a semi-colon", + "output": [ + [ + "Character", + "|" + ] + ] + }, + { + "input": "&vert", + "description": "Bad named entity: vert without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vert" + ] + ] + }, + { + "input": "|", + "description": "Named entity: vert; with a semi-colon", + "output": [ + [ + "Character", + "|" + ] + ] + }, + { + "input": "&vfr", + "description": "Bad named entity: vfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vfr" + ] + ] + }, + { + "input": "𝔳", + "description": "Named entity: vfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd33" + ] + ] + }, + { + "input": "&vltri", + "description": "Bad named entity: vltri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vltri" + ] + ] + }, + { + "input": "⊲", + "description": "Named entity: vltri; with a semi-colon", + "output": [ + [ + "Character", + "\u22b2" + ] + ] + }, + { + "input": "&vnsub", + "description": "Bad named entity: vnsub without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vnsub" + ] + ] + }, + { + "input": "⊂⃒", + "description": "Named entity: vnsub; with a semi-colon", + "output": [ + [ + "Character", + "\u2282\u20d2" + ] + ] + }, + { + "input": "&vnsup", + "description": "Bad named entity: vnsup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vnsup" + ] + ] + }, + { + "input": "⊃⃒", + "description": "Named entity: vnsup; with a semi-colon", + "output": [ + [ + "Character", + "\u2283\u20d2" + ] + ] + }, + { + "input": "&vopf", + "description": "Bad named entity: vopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vopf" + ] + ] + }, + { + "input": "𝕧", + "description": "Named entity: vopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd67" + ] + ] + }, + { + "input": "&vprop", + "description": "Bad named entity: vprop without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vprop" + ] + ] + }, + { + "input": "∝", + "description": "Named entity: vprop; with a semi-colon", + "output": [ + [ + "Character", + "\u221d" + ] + ] + }, + { + "input": "&vrtri", + "description": "Bad named entity: vrtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vrtri" + ] + ] + }, + { + "input": "⊳", + "description": "Named entity: vrtri; with a semi-colon", + "output": [ + [ + "Character", + "\u22b3" + ] + ] + }, + { + "input": "&vscr", + "description": "Bad named entity: vscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vscr" + ] + ] + }, + { + "input": "𝓋", + "description": "Named entity: vscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udccb" + ] + ] + }, + { + "input": "&vsubnE", + "description": "Bad named entity: vsubnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vsubnE" + ] + ] + }, + { + "input": "⫋︀", + "description": "Named entity: vsubnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2acb\ufe00" + ] + ] + }, + { + "input": "&vsubne", + "description": "Bad named entity: vsubne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vsubne" + ] + ] + }, + { + "input": "⊊︀", + "description": "Named entity: vsubne; with a semi-colon", + "output": [ + [ + "Character", + "\u228a\ufe00" + ] + ] + }, + { + "input": "&vsupnE", + "description": "Bad named entity: vsupnE without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vsupnE" + ] + ] + }, + { + "input": "⫌︀", + "description": "Named entity: vsupnE; with a semi-colon", + "output": [ + [ + "Character", + "\u2acc\ufe00" + ] + ] + }, + { + "input": "&vsupne", + "description": "Bad named entity: vsupne without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vsupne" + ] + ] + }, + { + "input": "⊋︀", + "description": "Named entity: vsupne; with a semi-colon", + "output": [ + [ + "Character", + "\u228b\ufe00" + ] + ] + }, + { + "input": "&vzigzag", + "description": "Bad named entity: vzigzag without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&vzigzag" + ] + ] + }, + { + "input": "⦚", + "description": "Named entity: vzigzag; with a semi-colon", + "output": [ + [ + "Character", + "\u299a" + ] + ] + }, + { + "input": "&wcirc", + "description": "Bad named entity: wcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wcirc" + ] + ] + }, + { + "input": "ŵ", + "description": "Named entity: wcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0175" + ] + ] + }, + { + "input": "&wedbar", + "description": "Bad named entity: wedbar without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wedbar" + ] + ] + }, + { + "input": "⩟", + "description": "Named entity: wedbar; with a semi-colon", + "output": [ + [ + "Character", + "\u2a5f" + ] + ] + }, + { + "input": "&wedge", + "description": "Bad named entity: wedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wedge" + ] + ] + }, + { + "input": "∧", + "description": "Named entity: wedge; with a semi-colon", + "output": [ + [ + "Character", + "\u2227" + ] + ] + }, + { + "input": "&wedgeq", + "description": "Bad named entity: wedgeq without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wedgeq" + ] + ] + }, + { + "input": "≙", + "description": "Named entity: wedgeq; with a semi-colon", + "output": [ + [ + "Character", + "\u2259" + ] + ] + }, + { + "input": "&weierp", + "description": "Bad named entity: weierp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&weierp" + ] + ] + }, + { + "input": "℘", + "description": "Named entity: weierp; with a semi-colon", + "output": [ + [ + "Character", + "\u2118" + ] + ] + }, + { + "input": "&wfr", + "description": "Bad named entity: wfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wfr" + ] + ] + }, + { + "input": "𝔴", + "description": "Named entity: wfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd34" + ] + ] + }, + { + "input": "&wopf", + "description": "Bad named entity: wopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wopf" + ] + ] + }, + { + "input": "𝕨", + "description": "Named entity: wopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd68" + ] + ] + }, + { + "input": "&wp", + "description": "Bad named entity: wp without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wp" + ] + ] + }, + { + "input": "℘", + "description": "Named entity: wp; with a semi-colon", + "output": [ + [ + "Character", + "\u2118" + ] + ] + }, + { + "input": "&wr", + "description": "Bad named entity: wr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wr" + ] + ] + }, + { + "input": "≀", + "description": "Named entity: wr; with a semi-colon", + "output": [ + [ + "Character", + "\u2240" + ] + ] + }, + { + "input": "&wreath", + "description": "Bad named entity: wreath without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wreath" + ] + ] + }, + { + "input": "≀", + "description": "Named entity: wreath; with a semi-colon", + "output": [ + [ + "Character", + "\u2240" + ] + ] + }, + { + "input": "&wscr", + "description": "Bad named entity: wscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&wscr" + ] + ] + }, + { + "input": "𝓌", + "description": "Named entity: wscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udccc" + ] + ] + }, + { + "input": "&xcap", + "description": "Bad named entity: xcap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xcap" + ] + ] + }, + { + "input": "⋂", + "description": "Named entity: xcap; with a semi-colon", + "output": [ + [ + "Character", + "\u22c2" + ] + ] + }, + { + "input": "&xcirc", + "description": "Bad named entity: xcirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xcirc" + ] + ] + }, + { + "input": "◯", + "description": "Named entity: xcirc; with a semi-colon", + "output": [ + [ + "Character", + "\u25ef" + ] + ] + }, + { + "input": "&xcup", + "description": "Bad named entity: xcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xcup" + ] + ] + }, + { + "input": "⋃", + "description": "Named entity: xcup; with a semi-colon", + "output": [ + [ + "Character", + "\u22c3" + ] + ] + }, + { + "input": "&xdtri", + "description": "Bad named entity: xdtri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xdtri" + ] + ] + }, + { + "input": "▽", + "description": "Named entity: xdtri; with a semi-colon", + "output": [ + [ + "Character", + "\u25bd" + ] + ] + }, + { + "input": "&xfr", + "description": "Bad named entity: xfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xfr" + ] + ] + }, + { + "input": "𝔵", + "description": "Named entity: xfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd35" + ] + ] + }, + { + "input": "&xhArr", + "description": "Bad named entity: xhArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xhArr" + ] + ] + }, + { + "input": "⟺", + "description": "Named entity: xhArr; with a semi-colon", + "output": [ + [ + "Character", + "\u27fa" + ] + ] + }, + { + "input": "&xharr", + "description": "Bad named entity: xharr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xharr" + ] + ] + }, + { + "input": "⟷", + "description": "Named entity: xharr; with a semi-colon", + "output": [ + [ + "Character", + "\u27f7" + ] + ] + }, + { + "input": "&xi", + "description": "Bad named entity: xi without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xi" + ] + ] + }, + { + "input": "ξ", + "description": "Named entity: xi; with a semi-colon", + "output": [ + [ + "Character", + "\u03be" + ] + ] + }, + { + "input": "&xlArr", + "description": "Bad named entity: xlArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xlArr" + ] + ] + }, + { + "input": "⟸", + "description": "Named entity: xlArr; with a semi-colon", + "output": [ + [ + "Character", + "\u27f8" + ] + ] + }, + { + "input": "&xlarr", + "description": "Bad named entity: xlarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xlarr" + ] + ] + }, + { + "input": "⟵", + "description": "Named entity: xlarr; with a semi-colon", + "output": [ + [ + "Character", + "\u27f5" + ] + ] + }, + { + "input": "&xmap", + "description": "Bad named entity: xmap without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xmap" + ] + ] + }, + { + "input": "⟼", + "description": "Named entity: xmap; with a semi-colon", + "output": [ + [ + "Character", + "\u27fc" + ] + ] + }, + { + "input": "&xnis", + "description": "Bad named entity: xnis without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xnis" + ] + ] + }, + { + "input": "⋻", + "description": "Named entity: xnis; with a semi-colon", + "output": [ + [ + "Character", + "\u22fb" + ] + ] + }, + { + "input": "&xodot", + "description": "Bad named entity: xodot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xodot" + ] + ] + }, + { + "input": "⨀", + "description": "Named entity: xodot; with a semi-colon", + "output": [ + [ + "Character", + "\u2a00" + ] + ] + }, + { + "input": "&xopf", + "description": "Bad named entity: xopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xopf" + ] + ] + }, + { + "input": "𝕩", + "description": "Named entity: xopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd69" + ] + ] + }, + { + "input": "&xoplus", + "description": "Bad named entity: xoplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xoplus" + ] + ] + }, + { + "input": "⨁", + "description": "Named entity: xoplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a01" + ] + ] + }, + { + "input": "&xotime", + "description": "Bad named entity: xotime without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xotime" + ] + ] + }, + { + "input": "⨂", + "description": "Named entity: xotime; with a semi-colon", + "output": [ + [ + "Character", + "\u2a02" + ] + ] + }, + { + "input": "&xrArr", + "description": "Bad named entity: xrArr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xrArr" + ] + ] + }, + { + "input": "⟹", + "description": "Named entity: xrArr; with a semi-colon", + "output": [ + [ + "Character", + "\u27f9" + ] + ] + }, + { + "input": "&xrarr", + "description": "Bad named entity: xrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xrarr" + ] + ] + }, + { + "input": "⟶", + "description": "Named entity: xrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u27f6" + ] + ] + }, + { + "input": "&xscr", + "description": "Bad named entity: xscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xscr" + ] + ] + }, + { + "input": "𝓍", + "description": "Named entity: xscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udccd" + ] + ] + }, + { + "input": "&xsqcup", + "description": "Bad named entity: xsqcup without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xsqcup" + ] + ] + }, + { + "input": "⨆", + "description": "Named entity: xsqcup; with a semi-colon", + "output": [ + [ + "Character", + "\u2a06" + ] + ] + }, + { + "input": "&xuplus", + "description": "Bad named entity: xuplus without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xuplus" + ] + ] + }, + { + "input": "⨄", + "description": "Named entity: xuplus; with a semi-colon", + "output": [ + [ + "Character", + "\u2a04" + ] + ] + }, + { + "input": "&xutri", + "description": "Bad named entity: xutri without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xutri" + ] + ] + }, + { + "input": "△", + "description": "Named entity: xutri; with a semi-colon", + "output": [ + [ + "Character", + "\u25b3" + ] + ] + }, + { + "input": "&xvee", + "description": "Bad named entity: xvee without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xvee" + ] + ] + }, + { + "input": "⋁", + "description": "Named entity: xvee; with a semi-colon", + "output": [ + [ + "Character", + "\u22c1" + ] + ] + }, + { + "input": "&xwedge", + "description": "Bad named entity: xwedge without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&xwedge" + ] + ] + }, + { + "input": "⋀", + "description": "Named entity: xwedge; with a semi-colon", + "output": [ + [ + "Character", + "\u22c0" + ] + ] + }, + { + "input": "ý", + "description": "Named entity: yacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00fd" + ] + ] + }, + { + "input": "ý", + "description": "Named entity: yacute; with a semi-colon", + "output": [ + [ + "Character", + "\u00fd" + ] + ] + }, + { + "input": "&yacy", + "description": "Bad named entity: yacy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yacy" + ] + ] + }, + { + "input": "я", + "description": "Named entity: yacy; with a semi-colon", + "output": [ + [ + "Character", + "\u044f" + ] + ] + }, + { + "input": "&ycirc", + "description": "Bad named entity: ycirc without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ycirc" + ] + ] + }, + { + "input": "ŷ", + "description": "Named entity: ycirc; with a semi-colon", + "output": [ + [ + "Character", + "\u0177" + ] + ] + }, + { + "input": "&ycy", + "description": "Bad named entity: ycy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&ycy" + ] + ] + }, + { + "input": "ы", + "description": "Named entity: ycy; with a semi-colon", + "output": [ + [ + "Character", + "\u044b" + ] + ] + }, + { + "input": "¥", + "description": "Named entity: yen without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00a5" + ] + ] + }, + { + "input": "¥", + "description": "Named entity: yen; with a semi-colon", + "output": [ + [ + "Character", + "\u00a5" + ] + ] + }, + { + "input": "&yfr", + "description": "Bad named entity: yfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yfr" + ] + ] + }, + { + "input": "𝔶", + "description": "Named entity: yfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd36" + ] + ] + }, + { + "input": "&yicy", + "description": "Bad named entity: yicy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yicy" + ] + ] + }, + { + "input": "ї", + "description": "Named entity: yicy; with a semi-colon", + "output": [ + [ + "Character", + "\u0457" + ] + ] + }, + { + "input": "&yopf", + "description": "Bad named entity: yopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yopf" + ] + ] + }, + { + "input": "𝕪", + "description": "Named entity: yopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd6a" + ] + ] + }, + { + "input": "&yscr", + "description": "Bad named entity: yscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yscr" + ] + ] + }, + { + "input": "𝓎", + "description": "Named entity: yscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udcce" + ] + ] + }, + { + "input": "&yucy", + "description": "Bad named entity: yucy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&yucy" + ] + ] + }, + { + "input": "ю", + "description": "Named entity: yucy; with a semi-colon", + "output": [ + [ + "Character", + "\u044e" + ] + ] + }, + { + "input": "ÿ", + "description": "Named entity: yuml without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "\u00ff" + ] + ] + }, + { + "input": "ÿ", + "description": "Named entity: yuml; with a semi-colon", + "output": [ + [ + "Character", + "\u00ff" + ] + ] + }, + { + "input": "&zacute", + "description": "Bad named entity: zacute without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zacute" + ] + ] + }, + { + "input": "ź", + "description": "Named entity: zacute; with a semi-colon", + "output": [ + [ + "Character", + "\u017a" + ] + ] + }, + { + "input": "&zcaron", + "description": "Bad named entity: zcaron without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zcaron" + ] + ] + }, + { + "input": "ž", + "description": "Named entity: zcaron; with a semi-colon", + "output": [ + [ + "Character", + "\u017e" + ] + ] + }, + { + "input": "&zcy", + "description": "Bad named entity: zcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zcy" + ] + ] + }, + { + "input": "з", + "description": "Named entity: zcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0437" + ] + ] + }, + { + "input": "&zdot", + "description": "Bad named entity: zdot without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zdot" + ] + ] + }, + { + "input": "ż", + "description": "Named entity: zdot; with a semi-colon", + "output": [ + [ + "Character", + "\u017c" + ] + ] + }, + { + "input": "&zeetrf", + "description": "Bad named entity: zeetrf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zeetrf" + ] + ] + }, + { + "input": "ℨ", + "description": "Named entity: zeetrf; with a semi-colon", + "output": [ + [ + "Character", + "\u2128" + ] + ] + }, + { + "input": "&zeta", + "description": "Bad named entity: zeta without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zeta" + ] + ] + }, + { + "input": "ζ", + "description": "Named entity: zeta; with a semi-colon", + "output": [ + [ + "Character", + "\u03b6" + ] + ] + }, + { + "input": "&zfr", + "description": "Bad named entity: zfr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zfr" + ] + ] + }, + { + "input": "𝔷", + "description": "Named entity: zfr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd37" + ] + ] + }, + { + "input": "&zhcy", + "description": "Bad named entity: zhcy without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zhcy" + ] + ] + }, + { + "input": "ж", + "description": "Named entity: zhcy; with a semi-colon", + "output": [ + [ + "Character", + "\u0436" + ] + ] + }, + { + "input": "&zigrarr", + "description": "Bad named entity: zigrarr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zigrarr" + ] + ] + }, + { + "input": "⇝", + "description": "Named entity: zigrarr; with a semi-colon", + "output": [ + [ + "Character", + "\u21dd" + ] + ] + }, + { + "input": "&zopf", + "description": "Bad named entity: zopf without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zopf" + ] + ] + }, + { + "input": "𝕫", + "description": "Named entity: zopf; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udd6b" + ] + ] + }, + { + "input": "&zscr", + "description": "Bad named entity: zscr without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zscr" + ] + ] + }, + { + "input": "𝓏", + "description": "Named entity: zscr; with a semi-colon", + "output": [ + [ + "Character", + "\ud835\udccf" + ] + ] + }, + { + "input": "&zwj", + "description": "Bad named entity: zwj without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zwj" + ] + ] + }, + { + "input": "‍", + "description": "Named entity: zwj; with a semi-colon", + "output": [ + [ + "Character", + "\u200d" + ] + ] + }, + { + "input": "&zwnj", + "description": "Bad named entity: zwnj without a semi-colon", + "output": [ + "ParseError", + [ + "Character", + "&zwnj" + ] + ] + }, + { + "input": "‌", + "description": "Named entity: zwnj; with a semi-colon", + "output": [ + [ + "Character", + "\u200c" + ] + ] + } + ] +} \ No newline at end of file diff --git a/pkgs/html/test/data/tokenizer/numericEntities.test b/pkgs/html/test/data/tokenizer/numericEntities.test new file mode 100644 index 000000000..36c82281c --- /dev/null +++ b/pkgs/html/test/data/tokenizer/numericEntities.test @@ -0,0 +1,1313 @@ +{"tests": [ + +{"description": "Invalid numeric entity character U+0000", +"input": "�", +"output": ["ParseError", ["Character", "\uFFFD"]]}, + +{"description": "Invalid numeric entity character U+0001", +"input": "", +"output": ["ParseError", ["Character", "\u0001"]]}, + +{"description": "Invalid numeric entity character U+0002", +"input": "", +"output": ["ParseError", ["Character", "\u0002"]]}, + +{"description": "Invalid numeric entity character U+0003", +"input": "", +"output": ["ParseError", ["Character", "\u0003"]]}, + +{"description": "Invalid numeric entity character U+0004", +"input": "", +"output": ["ParseError", ["Character", "\u0004"]]}, + +{"description": "Invalid numeric entity character U+0005", +"input": "", +"output": ["ParseError", ["Character", "\u0005"]]}, + +{"description": "Invalid numeric entity character U+0006", +"input": "", +"output": ["ParseError", ["Character", "\u0006"]]}, + +{"description": "Invalid numeric entity character U+0007", +"input": "", +"output": ["ParseError", ["Character", "\u0007"]]}, + +{"description": "Invalid numeric entity character U+0008", +"input": "", +"output": ["ParseError", ["Character", "\u0008"]]}, + +{"description": "Invalid numeric entity character U+000B", +"input": " ", +"output": ["ParseError", ["Character", "\u000b"]]}, + +{"description": "Invalid numeric entity character U+000E", +"input": "", +"output": ["ParseError", ["Character", "\u000e"]]}, + +{"description": "Invalid numeric entity character U+000F", +"input": "", +"output": ["ParseError", ["Character", "\u000f"]]}, + +{"description": "Invalid numeric entity character U+0010", +"input": "", +"output": ["ParseError", ["Character", "\u0010"]]}, + +{"description": "Invalid numeric entity character U+0011", +"input": "", +"output": ["ParseError", ["Character", "\u0011"]]}, + +{"description": "Invalid numeric entity character U+0012", +"input": "", +"output": ["ParseError", ["Character", "\u0012"]]}, + +{"description": "Invalid numeric entity character U+0013", +"input": "", +"output": ["ParseError", ["Character", "\u0013"]]}, + +{"description": "Invalid numeric entity character U+0014", +"input": "", +"output": ["ParseError", ["Character", "\u0014"]]}, + +{"description": "Invalid numeric entity character U+0015", +"input": "", +"output": ["ParseError", ["Character", "\u0015"]]}, + +{"description": "Invalid numeric entity character U+0016", +"input": "", +"output": ["ParseError", ["Character", "\u0016"]]}, + +{"description": "Invalid numeric entity character U+0017", +"input": "", +"output": ["ParseError", ["Character", "\u0017"]]}, + +{"description": "Invalid numeric entity character U+0018", +"input": "", +"output": ["ParseError", ["Character", "\u0018"]]}, + +{"description": "Invalid numeric entity character U+0019", +"input": "", +"output": ["ParseError", ["Character", "\u0019"]]}, + +{"description": "Invalid numeric entity character U+001A", +"input": "", +"output": ["ParseError", ["Character", "\u001a"]]}, + +{"description": "Invalid numeric entity character U+001B", +"input": "", +"output": ["ParseError", ["Character", "\u001b"]]}, + +{"description": "Invalid numeric entity character U+001C", +"input": "", +"output": ["ParseError", ["Character", "\u001c"]]}, + +{"description": "Invalid numeric entity character U+001D", +"input": "", +"output": ["ParseError", ["Character", "\u001d"]]}, + +{"description": "Invalid numeric entity character U+001E", +"input": "", +"output": ["ParseError", ["Character", "\u001e"]]}, + +{"description": "Invalid numeric entity character U+001F", +"input": "", +"output": ["ParseError", ["Character", "\u001f"]]}, + +{"description": "Invalid numeric entity character U+007F", +"input": "", +"output": ["ParseError", ["Character", "\u007f"]]}, + +{"description": "Invalid numeric entity character U+D800", +"input": "�", +"output": ["ParseError", ["Character", "\uFFFD"]]}, + +{"description": "Invalid numeric entity character U+DFFF", +"input": "�", +"output": ["ParseError", ["Character", "\uFFFD"]]}, + +{"description": "Invalid numeric entity character U+FDD0", +"input": "﷐", +"output": ["ParseError", ["Character", "\ufdd0"]]}, + +{"description": "Invalid numeric entity character U+FDD1", +"input": "﷑", +"output": ["ParseError", ["Character", "\ufdd1"]]}, + +{"description": "Invalid numeric entity character U+FDD2", +"input": "﷒", +"output": ["ParseError", ["Character", "\ufdd2"]]}, + +{"description": "Invalid numeric entity character U+FDD3", +"input": "﷓", +"output": ["ParseError", ["Character", "\ufdd3"]]}, + +{"description": "Invalid numeric entity character U+FDD4", +"input": "﷔", +"output": ["ParseError", ["Character", "\ufdd4"]]}, + +{"description": "Invalid numeric entity character U+FDD5", +"input": "﷕", +"output": ["ParseError", ["Character", "\ufdd5"]]}, + +{"description": "Invalid numeric entity character U+FDD6", +"input": "﷖", +"output": ["ParseError", ["Character", "\ufdd6"]]}, + +{"description": "Invalid numeric entity character U+FDD7", +"input": "﷗", +"output": ["ParseError", ["Character", "\ufdd7"]]}, + +{"description": "Invalid numeric entity character U+FDD8", +"input": "﷘", +"output": ["ParseError", ["Character", "\ufdd8"]]}, + +{"description": "Invalid numeric entity character U+FDD9", +"input": "﷙", +"output": ["ParseError", ["Character", "\ufdd9"]]}, + +{"description": "Invalid numeric entity character U+FDDA", +"input": "﷚", +"output": ["ParseError", ["Character", "\ufdda"]]}, + +{"description": "Invalid numeric entity character U+FDDB", +"input": "﷛", +"output": ["ParseError", ["Character", "\ufddb"]]}, + +{"description": "Invalid numeric entity character U+FDDC", +"input": "﷜", +"output": ["ParseError", ["Character", "\ufddc"]]}, + +{"description": "Invalid numeric entity character U+FDDD", +"input": "﷝", +"output": ["ParseError", ["Character", "\ufddd"]]}, + +{"description": "Invalid numeric entity character U+FDDE", +"input": "﷞", +"output": ["ParseError", ["Character", "\ufdde"]]}, + +{"description": "Invalid numeric entity character U+FDDF", +"input": "﷟", +"output": ["ParseError", ["Character", "\ufddf"]]}, + +{"description": "Invalid numeric entity character U+FDE0", +"input": "﷠", +"output": ["ParseError", ["Character", "\ufde0"]]}, + +{"description": "Invalid numeric entity character U+FDE1", +"input": "﷡", +"output": ["ParseError", ["Character", "\ufde1"]]}, + +{"description": "Invalid numeric entity character U+FDE2", +"input": "﷢", +"output": ["ParseError", ["Character", "\ufde2"]]}, + +{"description": "Invalid numeric entity character U+FDE3", +"input": "﷣", +"output": ["ParseError", ["Character", "\ufde3"]]}, + +{"description": "Invalid numeric entity character U+FDE4", +"input": "﷤", +"output": ["ParseError", ["Character", "\ufde4"]]}, + +{"description": "Invalid numeric entity character U+FDE5", +"input": "﷥", +"output": ["ParseError", ["Character", "\ufde5"]]}, + +{"description": "Invalid numeric entity character U+FDE6", +"input": "﷦", +"output": ["ParseError", ["Character", "\ufde6"]]}, + +{"description": "Invalid numeric entity character U+FDE7", +"input": "﷧", +"output": ["ParseError", ["Character", "\ufde7"]]}, + +{"description": "Invalid numeric entity character U+FDE8", +"input": "﷨", +"output": ["ParseError", ["Character", "\ufde8"]]}, + +{"description": "Invalid numeric entity character U+FDE9", +"input": "﷩", +"output": ["ParseError", ["Character", "\ufde9"]]}, + +{"description": "Invalid numeric entity character U+FDEA", +"input": "﷪", +"output": ["ParseError", ["Character", "\ufdea"]]}, + +{"description": "Invalid numeric entity character U+FDEB", +"input": "﷫", +"output": ["ParseError", ["Character", "\ufdeb"]]}, + +{"description": "Invalid numeric entity character U+FDEC", +"input": "﷬", +"output": ["ParseError", ["Character", "\ufdec"]]}, + +{"description": "Invalid numeric entity character U+FDED", +"input": "﷭", +"output": ["ParseError", ["Character", "\ufded"]]}, + +{"description": "Invalid numeric entity character U+FDEE", +"input": "﷮", +"output": ["ParseError", ["Character", "\ufdee"]]}, + +{"description": "Invalid numeric entity character U+FDEF", +"input": "﷯", +"output": ["ParseError", ["Character", "\ufdef"]]}, + +{"description": "Invalid numeric entity character U+FFFE", +"input": "￾", +"output": ["ParseError", ["Character", "\ufffe"]]}, + +{"description": "Invalid numeric entity character U+FFFF", +"input": "￿", +"output": ["ParseError", ["Character", "\uffff"]]}, + +{"description": "Invalid numeric entity character U+1FFFE", +"input": "🿾", +"output": ["ParseError", ["Character", "\uD83F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+1FFFF", +"input": "🿿", +"output": ["ParseError", ["Character", "\uD83F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+2FFFE", +"input": "𯿾", +"output": ["ParseError", ["Character", "\uD87F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+2FFFF", +"input": "𯿿", +"output": ["ParseError", ["Character", "\uD87F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+3FFFE", +"input": "𿿾", +"output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+3FFFF", +"input": "𿿿", +"output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+4FFFE", +"input": "񏿾", +"output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+4FFFF", +"input": "񏿿", +"output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+5FFFE", +"input": "񟿾", +"output": ["ParseError", ["Character", "\uD93F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+5FFFF", +"input": "񟿿", +"output": ["ParseError", ["Character", "\uD93F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+6FFFE", +"input": "񯿾", +"output": ["ParseError", ["Character", "\uD97F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+6FFFF", +"input": "񯿿", +"output": ["ParseError", ["Character", "\uD97F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+7FFFE", +"input": "񿿾", +"output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+7FFFF", +"input": "񿿿", +"output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+8FFFE", +"input": "򏿾", +"output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+8FFFF", +"input": "򏿿", +"output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+9FFFE", +"input": "򟿾", +"output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+9FFFF", +"input": "򟿿", +"output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+AFFFE", +"input": "򯿾", +"output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+AFFFF", +"input": "򯿿", +"output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+BFFFE", +"input": "򿿾", +"output": ["ParseError", ["Character", "\uDABF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+BFFFF", +"input": "򿿿", +"output": ["ParseError", ["Character", "\uDABF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+CFFFE", +"input": "󏿾", +"output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+CFFFF", +"input": "󏿿", +"output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+DFFFE", +"input": "󟿾", +"output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+DFFFF", +"input": "󟿿", +"output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+EFFFE", +"input": "󯿾", +"output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+EFFFF", +"input": "󯿿", +"output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+FFFFE", +"input": "󿿾", +"output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+FFFFF", +"input": "󿿿", +"output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]}, + +{"description": "Invalid numeric entity character U+10FFFE", +"input": "􏿾", +"output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]}, + +{"description": "Invalid numeric entity character U+10FFFF", +"input": "􏿿", +"output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]}, + +{"description": "Valid numeric entity character U+0009", +"input": " ", +"output": [["Character", "\u0009"]]}, + +{"description": "Valid numeric entity character U+000A", +"input": " ", +"output": [["Character", "\u000A"]]}, + +{"description": "Valid numeric entity character U+0020", +"input": " ", +"output": [["Character", "\u0020"]]}, + +{"description": "Valid numeric entity character U+0021", +"input": "!", +"output": [["Character", "\u0021"]]}, + +{"description": "Valid numeric entity character U+0022", +"input": """, +"output": [["Character", "\u0022"]]}, + +{"description": "Valid numeric entity character U+0023", +"input": "#", +"output": [["Character", "\u0023"]]}, + +{"description": "Valid numeric entity character U+0024", +"input": "$", +"output": [["Character", "\u0024"]]}, + +{"description": "Valid numeric entity character U+0025", +"input": "%", +"output": [["Character", "\u0025"]]}, + +{"description": "Valid numeric entity character U+0026", +"input": "&", +"output": [["Character", "\u0026"]]}, + +{"description": "Valid numeric entity character U+0027", +"input": "'", +"output": [["Character", "\u0027"]]}, + +{"description": "Valid numeric entity character U+0028", +"input": "(", +"output": [["Character", "\u0028"]]}, + +{"description": "Valid numeric entity character U+0029", +"input": ")", +"output": [["Character", "\u0029"]]}, + +{"description": "Valid numeric entity character U+002A", +"input": "*", +"output": [["Character", "\u002A"]]}, + +{"description": "Valid numeric entity character U+002B", +"input": "+", +"output": [["Character", "\u002B"]]}, + +{"description": "Valid numeric entity character U+002C", +"input": ",", +"output": [["Character", "\u002C"]]}, + +{"description": "Valid numeric entity character U+002D", +"input": "-", +"output": [["Character", "\u002D"]]}, + +{"description": "Valid numeric entity character U+002E", +"input": ".", +"output": [["Character", "\u002E"]]}, + +{"description": "Valid numeric entity character U+002F", +"input": "/", +"output": [["Character", "\u002F"]]}, + +{"description": "Valid numeric entity character U+0030", +"input": "0", +"output": [["Character", "\u0030"]]}, + +{"description": "Valid numeric entity character U+0031", +"input": "1", +"output": [["Character", "\u0031"]]}, + +{"description": "Valid numeric entity character U+0032", +"input": "2", +"output": [["Character", "\u0032"]]}, + +{"description": "Valid numeric entity character U+0033", +"input": "3", +"output": [["Character", "\u0033"]]}, + +{"description": "Valid numeric entity character U+0034", +"input": "4", +"output": [["Character", "\u0034"]]}, + +{"description": "Valid numeric entity character U+0035", +"input": "5", +"output": [["Character", "\u0035"]]}, + +{"description": "Valid numeric entity character U+0036", +"input": "6", +"output": [["Character", "\u0036"]]}, + +{"description": "Valid numeric entity character U+0037", +"input": "7", +"output": [["Character", "\u0037"]]}, + +{"description": "Valid numeric entity character U+0038", +"input": "8", +"output": [["Character", "\u0038"]]}, + +{"description": "Valid numeric entity character U+0039", +"input": "9", +"output": [["Character", "\u0039"]]}, + +{"description": "Valid numeric entity character U+003A", +"input": ":", +"output": [["Character", "\u003A"]]}, + +{"description": "Valid numeric entity character U+003B", +"input": ";", +"output": [["Character", "\u003B"]]}, + +{"description": "Valid numeric entity character U+003C", +"input": "<", +"output": [["Character", "\u003C"]]}, + +{"description": "Valid numeric entity character U+003D", +"input": "=", +"output": [["Character", "\u003D"]]}, + +{"description": "Valid numeric entity character U+003E", +"input": ">", +"output": [["Character", "\u003E"]]}, + +{"description": "Valid numeric entity character U+003F", +"input": "?", +"output": [["Character", "\u003F"]]}, + +{"description": "Valid numeric entity character U+0040", +"input": "@", +"output": [["Character", "\u0040"]]}, + +{"description": "Valid numeric entity character U+0041", +"input": "A", +"output": [["Character", "\u0041"]]}, + +{"description": "Valid numeric entity character U+0042", +"input": "B", +"output": [["Character", "\u0042"]]}, + +{"description": "Valid numeric entity character U+0043", +"input": "C", +"output": [["Character", "\u0043"]]}, + +{"description": "Valid numeric entity character U+0044", +"input": "D", +"output": [["Character", "\u0044"]]}, + +{"description": "Valid numeric entity character U+0045", +"input": "E", +"output": [["Character", "\u0045"]]}, + +{"description": "Valid numeric entity character U+0046", +"input": "F", +"output": [["Character", "\u0046"]]}, + +{"description": "Valid numeric entity character U+0047", +"input": "G", +"output": [["Character", "\u0047"]]}, + +{"description": "Valid numeric entity character U+0048", +"input": "H", +"output": [["Character", "\u0048"]]}, + +{"description": "Valid numeric entity character U+0049", +"input": "I", +"output": [["Character", "\u0049"]]}, + +{"description": "Valid numeric entity character U+004A", +"input": "J", +"output": [["Character", "\u004A"]]}, + +{"description": "Valid numeric entity character U+004B", +"input": "K", +"output": [["Character", "\u004B"]]}, + +{"description": "Valid numeric entity character U+004C", +"input": "L", +"output": [["Character", "\u004C"]]}, + +{"description": "Valid numeric entity character U+004D", +"input": "M", +"output": [["Character", "\u004D"]]}, + +{"description": "Valid numeric entity character U+004E", +"input": "N", +"output": [["Character", "\u004E"]]}, + +{"description": "Valid numeric entity character U+004F", +"input": "O", +"output": [["Character", "\u004F"]]}, + +{"description": "Valid numeric entity character U+0050", +"input": "P", +"output": [["Character", "\u0050"]]}, + +{"description": "Valid numeric entity character U+0051", +"input": "Q", +"output": [["Character", "\u0051"]]}, + +{"description": "Valid numeric entity character U+0052", +"input": "R", +"output": [["Character", "\u0052"]]}, + +{"description": "Valid numeric entity character U+0053", +"input": "S", +"output": [["Character", "\u0053"]]}, + +{"description": "Valid numeric entity character U+0054", +"input": "T", +"output": [["Character", "\u0054"]]}, + +{"description": "Valid numeric entity character U+0055", +"input": "U", +"output": [["Character", "\u0055"]]}, + +{"description": "Valid numeric entity character U+0056", +"input": "V", +"output": [["Character", "\u0056"]]}, + +{"description": "Valid numeric entity character U+0057", +"input": "W", +"output": [["Character", "\u0057"]]}, + +{"description": "Valid numeric entity character U+0058", +"input": "X", +"output": [["Character", "\u0058"]]}, + +{"description": "Valid numeric entity character U+0059", +"input": "Y", +"output": [["Character", "\u0059"]]}, + +{"description": "Valid numeric entity character U+005A", +"input": "Z", +"output": [["Character", "\u005A"]]}, + +{"description": "Valid numeric entity character U+005B", +"input": "[", +"output": [["Character", "\u005B"]]}, + +{"description": "Valid numeric entity character U+005C", +"input": "\", +"output": [["Character", "\u005C"]]}, + +{"description": "Valid numeric entity character U+005D", +"input": "]", +"output": [["Character", "\u005D"]]}, + +{"description": "Valid numeric entity character U+005E", +"input": "^", +"output": [["Character", "\u005E"]]}, + +{"description": "Valid numeric entity character U+005F", +"input": "_", +"output": [["Character", "\u005F"]]}, + +{"description": "Valid numeric entity character U+0060", +"input": "`", +"output": [["Character", "\u0060"]]}, + +{"description": "Valid numeric entity character U+0061", +"input": "a", +"output": [["Character", "\u0061"]]}, + +{"description": "Valid numeric entity character U+0062", +"input": "b", +"output": [["Character", "\u0062"]]}, + +{"description": "Valid numeric entity character U+0063", +"input": "c", +"output": [["Character", "\u0063"]]}, + +{"description": "Valid numeric entity character U+0064", +"input": "d", +"output": [["Character", "\u0064"]]}, + +{"description": "Valid numeric entity character U+0065", +"input": "e", +"output": [["Character", "\u0065"]]}, + +{"description": "Valid numeric entity character U+0066", +"input": "f", +"output": [["Character", "\u0066"]]}, + +{"description": "Valid numeric entity character U+0067", +"input": "g", +"output": [["Character", "\u0067"]]}, + +{"description": "Valid numeric entity character U+0068", +"input": "h", +"output": [["Character", "\u0068"]]}, + +{"description": "Valid numeric entity character U+0069", +"input": "i", +"output": [["Character", "\u0069"]]}, + +{"description": "Valid numeric entity character U+006A", +"input": "j", +"output": [["Character", "\u006A"]]}, + +{"description": "Valid numeric entity character U+006B", +"input": "k", +"output": [["Character", "\u006B"]]}, + +{"description": "Valid numeric entity character U+006C", +"input": "l", +"output": [["Character", "\u006C"]]}, + +{"description": "Valid numeric entity character U+006D", +"input": "m", +"output": [["Character", "\u006D"]]}, + +{"description": "Valid numeric entity character U+006E", +"input": "n", +"output": [["Character", "\u006E"]]}, + +{"description": "Valid numeric entity character U+006F", +"input": "o", +"output": [["Character", "\u006F"]]}, + +{"description": "Valid numeric entity character U+0070", +"input": "p", +"output": [["Character", "\u0070"]]}, + +{"description": "Valid numeric entity character U+0071", +"input": "q", +"output": [["Character", "\u0071"]]}, + +{"description": "Valid numeric entity character U+0072", +"input": "r", +"output": [["Character", "\u0072"]]}, + +{"description": "Valid numeric entity character U+0073", +"input": "s", +"output": [["Character", "\u0073"]]}, + +{"description": "Valid numeric entity character U+0074", +"input": "t", +"output": [["Character", "\u0074"]]}, + +{"description": "Valid numeric entity character U+0075", +"input": "u", +"output": [["Character", "\u0075"]]}, + +{"description": "Valid numeric entity character U+0076", +"input": "v", +"output": [["Character", "\u0076"]]}, + +{"description": "Valid numeric entity character U+0077", +"input": "w", +"output": [["Character", "\u0077"]]}, + +{"description": "Valid numeric entity character U+0078", +"input": "x", +"output": [["Character", "\u0078"]]}, + +{"description": "Valid numeric entity character U+0079", +"input": "y", +"output": [["Character", "\u0079"]]}, + +{"description": "Valid numeric entity character U+007A", +"input": "z", +"output": [["Character", "\u007A"]]}, + +{"description": "Valid numeric entity character U+007B", +"input": "{", +"output": [["Character", "\u007B"]]}, + +{"description": "Valid numeric entity character U+007C", +"input": "|", +"output": [["Character", "\u007C"]]}, + +{"description": "Valid numeric entity character U+007D", +"input": "}", +"output": [["Character", "\u007D"]]}, + +{"description": "Valid numeric entity character U+007E", +"input": "~", +"output": [["Character", "\u007E"]]}, + +{"description": "Valid numeric entity character U+00A0", +"input": " ", +"output": [["Character", "\u00A0"]]}, + +{"description": "Valid numeric entity character U+00A1", +"input": "¡", +"output": [["Character", "\u00A1"]]}, + +{"description": "Valid numeric entity character U+00A2", +"input": "¢", +"output": [["Character", "\u00A2"]]}, + +{"description": "Valid numeric entity character U+00A3", +"input": "£", +"output": [["Character", "\u00A3"]]}, + +{"description": "Valid numeric entity character U+00A4", +"input": "¤", +"output": [["Character", "\u00A4"]]}, + +{"description": "Valid numeric entity character U+00A5", +"input": "¥", +"output": [["Character", "\u00A5"]]}, + +{"description": "Valid numeric entity character U+00A6", +"input": "¦", +"output": [["Character", "\u00A6"]]}, + +{"description": "Valid numeric entity character U+00A7", +"input": "§", +"output": [["Character", "\u00A7"]]}, + +{"description": "Valid numeric entity character U+00A8", +"input": "¨", +"output": [["Character", "\u00A8"]]}, + +{"description": "Valid numeric entity character U+00A9", +"input": "©", +"output": [["Character", "\u00A9"]]}, + +{"description": "Valid numeric entity character U+00AA", +"input": "ª", +"output": [["Character", "\u00AA"]]}, + +{"description": "Valid numeric entity character U+00AB", +"input": "«", +"output": [["Character", "\u00AB"]]}, + +{"description": "Valid numeric entity character U+00AC", +"input": "¬", +"output": [["Character", "\u00AC"]]}, + +{"description": "Valid numeric entity character U+00AD", +"input": "­", +"output": [["Character", "\u00AD"]]}, + +{"description": "Valid numeric entity character U+00AE", +"input": "®", +"output": [["Character", "\u00AE"]]}, + +{"description": "Valid numeric entity character U+00AF", +"input": "¯", +"output": [["Character", "\u00AF"]]}, + +{"description": "Valid numeric entity character U+00B0", +"input": "°", +"output": [["Character", "\u00B0"]]}, + +{"description": "Valid numeric entity character U+00B1", +"input": "±", +"output": [["Character", "\u00B1"]]}, + +{"description": "Valid numeric entity character U+00B2", +"input": "²", +"output": [["Character", "\u00B2"]]}, + +{"description": "Valid numeric entity character U+00B3", +"input": "³", +"output": [["Character", "\u00B3"]]}, + +{"description": "Valid numeric entity character U+00B4", +"input": "´", +"output": [["Character", "\u00B4"]]}, + +{"description": "Valid numeric entity character U+00B5", +"input": "µ", +"output": [["Character", "\u00B5"]]}, + +{"description": "Valid numeric entity character U+00B6", +"input": "¶", +"output": [["Character", "\u00B6"]]}, + +{"description": "Valid numeric entity character U+00B7", +"input": "·", +"output": [["Character", "\u00B7"]]}, + +{"description": "Valid numeric entity character U+00B8", +"input": "¸", +"output": [["Character", "\u00B8"]]}, + +{"description": "Valid numeric entity character U+00B9", +"input": "¹", +"output": [["Character", "\u00B9"]]}, + +{"description": "Valid numeric entity character U+00BA", +"input": "º", +"output": [["Character", "\u00BA"]]}, + +{"description": "Valid numeric entity character U+00BB", +"input": "»", +"output": [["Character", "\u00BB"]]}, + +{"description": "Valid numeric entity character U+00BC", +"input": "¼", +"output": [["Character", "\u00BC"]]}, + +{"description": "Valid numeric entity character U+00BD", +"input": "½", +"output": [["Character", "\u00BD"]]}, + +{"description": "Valid numeric entity character U+00BE", +"input": "¾", +"output": [["Character", "\u00BE"]]}, + +{"description": "Valid numeric entity character U+00BF", +"input": "¿", +"output": [["Character", "\u00BF"]]}, + +{"description": "Valid numeric entity character U+00C0", +"input": "À", +"output": [["Character", "\u00C0"]]}, + +{"description": "Valid numeric entity character U+00C1", +"input": "Á", +"output": [["Character", "\u00C1"]]}, + +{"description": "Valid numeric entity character U+00C2", +"input": "Â", +"output": [["Character", "\u00C2"]]}, + +{"description": "Valid numeric entity character U+00C3", +"input": "Ã", +"output": [["Character", "\u00C3"]]}, + +{"description": "Valid numeric entity character U+00C4", +"input": "Ä", +"output": [["Character", "\u00C4"]]}, + +{"description": "Valid numeric entity character U+00C5", +"input": "Å", +"output": [["Character", "\u00C5"]]}, + +{"description": "Valid numeric entity character U+00C6", +"input": "Æ", +"output": [["Character", "\u00C6"]]}, + +{"description": "Valid numeric entity character U+00C7", +"input": "Ç", +"output": [["Character", "\u00C7"]]}, + +{"description": "Valid numeric entity character U+00C8", +"input": "È", +"output": [["Character", "\u00C8"]]}, + +{"description": "Valid numeric entity character U+00C9", +"input": "É", +"output": [["Character", "\u00C9"]]}, + +{"description": "Valid numeric entity character U+00CA", +"input": "Ê", +"output": [["Character", "\u00CA"]]}, + +{"description": "Valid numeric entity character U+00CB", +"input": "Ë", +"output": [["Character", "\u00CB"]]}, + +{"description": "Valid numeric entity character U+00CC", +"input": "Ì", +"output": [["Character", "\u00CC"]]}, + +{"description": "Valid numeric entity character U+00CD", +"input": "Í", +"output": [["Character", "\u00CD"]]}, + +{"description": "Valid numeric entity character U+00CE", +"input": "Î", +"output": [["Character", "\u00CE"]]}, + +{"description": "Valid numeric entity character U+00CF", +"input": "Ï", +"output": [["Character", "\u00CF"]]}, + +{"description": "Valid numeric entity character U+00D0", +"input": "Ð", +"output": [["Character", "\u00D0"]]}, + +{"description": "Valid numeric entity character U+00D1", +"input": "Ñ", +"output": [["Character", "\u00D1"]]}, + +{"description": "Valid numeric entity character U+00D2", +"input": "Ò", +"output": [["Character", "\u00D2"]]}, + +{"description": "Valid numeric entity character U+00D3", +"input": "Ó", +"output": [["Character", "\u00D3"]]}, + +{"description": "Valid numeric entity character U+00D4", +"input": "Ô", +"output": [["Character", "\u00D4"]]}, + +{"description": "Valid numeric entity character U+00D5", +"input": "Õ", +"output": [["Character", "\u00D5"]]}, + +{"description": "Valid numeric entity character U+00D6", +"input": "Ö", +"output": [["Character", "\u00D6"]]}, + +{"description": "Valid numeric entity character U+00D7", +"input": "×", +"output": [["Character", "\u00D7"]]}, + +{"description": "Valid numeric entity character U+00D8", +"input": "Ø", +"output": [["Character", "\u00D8"]]}, + +{"description": "Valid numeric entity character U+00D9", +"input": "Ù", +"output": [["Character", "\u00D9"]]}, + +{"description": "Valid numeric entity character U+00DA", +"input": "Ú", +"output": [["Character", "\u00DA"]]}, + +{"description": "Valid numeric entity character U+00DB", +"input": "Û", +"output": [["Character", "\u00DB"]]}, + +{"description": "Valid numeric entity character U+00DC", +"input": "Ü", +"output": [["Character", "\u00DC"]]}, + +{"description": "Valid numeric entity character U+00DD", +"input": "Ý", +"output": [["Character", "\u00DD"]]}, + +{"description": "Valid numeric entity character U+00DE", +"input": "Þ", +"output": [["Character", "\u00DE"]]}, + +{"description": "Valid numeric entity character U+00DF", +"input": "ß", +"output": [["Character", "\u00DF"]]}, + +{"description": "Valid numeric entity character U+00E0", +"input": "à", +"output": [["Character", "\u00E0"]]}, + +{"description": "Valid numeric entity character U+00E1", +"input": "á", +"output": [["Character", "\u00E1"]]}, + +{"description": "Valid numeric entity character U+00E2", +"input": "â", +"output": [["Character", "\u00E2"]]}, + +{"description": "Valid numeric entity character U+00E3", +"input": "ã", +"output": [["Character", "\u00E3"]]}, + +{"description": "Valid numeric entity character U+00E4", +"input": "ä", +"output": [["Character", "\u00E4"]]}, + +{"description": "Valid numeric entity character U+00E5", +"input": "å", +"output": [["Character", "\u00E5"]]}, + +{"description": "Valid numeric entity character U+00E6", +"input": "æ", +"output": [["Character", "\u00E6"]]}, + +{"description": "Valid numeric entity character U+00E7", +"input": "ç", +"output": [["Character", "\u00E7"]]}, + +{"description": "Valid numeric entity character U+00E8", +"input": "è", +"output": [["Character", "\u00E8"]]}, + +{"description": "Valid numeric entity character U+00E9", +"input": "é", +"output": [["Character", "\u00E9"]]}, + +{"description": "Valid numeric entity character U+00EA", +"input": "ê", +"output": [["Character", "\u00EA"]]}, + +{"description": "Valid numeric entity character U+00EB", +"input": "ë", +"output": [["Character", "\u00EB"]]}, + +{"description": "Valid numeric entity character U+00EC", +"input": "ì", +"output": [["Character", "\u00EC"]]}, + +{"description": "Valid numeric entity character U+00ED", +"input": "í", +"output": [["Character", "\u00ED"]]}, + +{"description": "Valid numeric entity character U+00EE", +"input": "î", +"output": [["Character", "\u00EE"]]}, + +{"description": "Valid numeric entity character U+00EF", +"input": "ï", +"output": [["Character", "\u00EF"]]}, + +{"description": "Valid numeric entity character U+00F0", +"input": "ð", +"output": [["Character", "\u00F0"]]}, + +{"description": "Valid numeric entity character U+00F1", +"input": "ñ", +"output": [["Character", "\u00F1"]]}, + +{"description": "Valid numeric entity character U+00F2", +"input": "ò", +"output": [["Character", "\u00F2"]]}, + +{"description": "Valid numeric entity character U+00F3", +"input": "ó", +"output": [["Character", "\u00F3"]]}, + +{"description": "Valid numeric entity character U+00F4", +"input": "ô", +"output": [["Character", "\u00F4"]]}, + +{"description": "Valid numeric entity character U+00F5", +"input": "õ", +"output": [["Character", "\u00F5"]]}, + +{"description": "Valid numeric entity character U+00F6", +"input": "ö", +"output": [["Character", "\u00F6"]]}, + +{"description": "Valid numeric entity character U+00F7", +"input": "÷", +"output": [["Character", "\u00F7"]]}, + +{"description": "Valid numeric entity character U+00F8", +"input": "ø", +"output": [["Character", "\u00F8"]]}, + +{"description": "Valid numeric entity character U+00F9", +"input": "ù", +"output": [["Character", "\u00F9"]]}, + +{"description": "Valid numeric entity character U+00FA", +"input": "ú", +"output": [["Character", "\u00FA"]]}, + +{"description": "Valid numeric entity character U+00FB", +"input": "û", +"output": [["Character", "\u00FB"]]}, + +{"description": "Valid numeric entity character U+00FC", +"input": "ü", +"output": [["Character", "\u00FC"]]}, + +{"description": "Valid numeric entity character U+00FD", +"input": "ý", +"output": [["Character", "\u00FD"]]}, + +{"description": "Valid numeric entity character U+00FE", +"input": "þ", +"output": [["Character", "\u00FE"]]}, + +{"description": "Valid numeric entity character U+00FF", +"input": "ÿ", +"output": [["Character", "\u00FF"]]}, + +{"description": "Valid numeric entity character U+D7FF", +"input": "퟿", +"output": [["Character", "\uD7FF"]]}, + +{"description": "Valid numeric entity character U+E000", +"input": "", +"output": [["Character", "\uE000"]]}, + +{"description": "Valid numeric entity character U+FDCF", +"input": "﷏", +"output": [["Character", "\uFDCF"]]}, + +{"description": "Valid numeric entity character U+FDF0", +"input": "ﷰ", +"output": [["Character", "\uFDF0"]]}, + +{"description": "Valid numeric entity character U+FFFD", +"input": "�", +"output": [["Character", "\uFFFD"]]}, + +{"description": "Valid numeric entity character U+10000", +"input": "𐀀", +"output": [["Character", "\uD800\uDC00"]]}, + +{"description": "Valid numeric entity character U+1FFFD", +"input": "🿽", +"output": [["Character", "\uD83F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+20000", +"input": "𠀀", +"output": [["Character", "\uD840\uDC00"]]}, + +{"description": "Valid numeric entity character U+2FFFD", +"input": "𯿽", +"output": [["Character", "\uD87F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+30000", +"input": "𰀀", +"output": [["Character", "\uD880\uDC00"]]}, + +{"description": "Valid numeric entity character U+3FFFD", +"input": "𿿽", +"output": [["Character", "\uD8BF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+40000", +"input": "񀀀", +"output": [["Character", "\uD8C0\uDC00"]]}, + +{"description": "Valid numeric entity character U+4FFFD", +"input": "񏿽", +"output": [["Character", "\uD8FF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+50000", +"input": "񐀀", +"output": [["Character", "\uD900\uDC00"]]}, + +{"description": "Valid numeric entity character U+5FFFD", +"input": "񟿽", +"output": [["Character", "\uD93F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+60000", +"input": "񠀀", +"output": [["Character", "\uD940\uDC00"]]}, + +{"description": "Valid numeric entity character U+6FFFD", +"input": "񯿽", +"output": [["Character", "\uD97F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+70000", +"input": "񰀀", +"output": [["Character", "\uD980\uDC00"]]}, + +{"description": "Valid numeric entity character U+7FFFD", +"input": "񿿽", +"output": [["Character", "\uD9BF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+80000", +"input": "򀀀", +"output": [["Character", "\uD9C0\uDC00"]]}, + +{"description": "Valid numeric entity character U+8FFFD", +"input": "򏿽", +"output": [["Character", "\uD9FF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+90000", +"input": "򐀀", +"output": [["Character", "\uDA00\uDC00"]]}, + +{"description": "Valid numeric entity character U+9FFFD", +"input": "򟿽", +"output": [["Character", "\uDA3F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+A0000", +"input": "򠀀", +"output": [["Character", "\uDA40\uDC00"]]}, + +{"description": "Valid numeric entity character U+AFFFD", +"input": "򯿽", +"output": [["Character", "\uDA7F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+B0000", +"input": "򰀀", +"output": [["Character", "\uDA80\uDC00"]]}, + +{"description": "Valid numeric entity character U+BFFFD", +"input": "򿿽", +"output": [["Character", "\uDABF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+C0000", +"input": "󀀀", +"output": [["Character", "\uDAC0\uDC00"]]}, + +{"description": "Valid numeric entity character U+CFFFD", +"input": "󏿽", +"output": [["Character", "\uDAFF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+D0000", +"input": "󐀀", +"output": [["Character", "\uDB00\uDC00"]]}, + +{"description": "Valid numeric entity character U+DFFFD", +"input": "󟿽", +"output": [["Character", "\uDB3F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+E0000", +"input": "󠀀", +"output": [["Character", "\uDB40\uDC00"]]}, + +{"description": "Valid numeric entity character U+EFFFD", +"input": "󯿽", +"output": [["Character", "\uDB7F\uDFFD"]]}, + +{"description": "Valid numeric entity character U+F0000", +"input": "󰀀", +"output": [["Character", "\uDB80\uDC00"]]}, + +{"description": "Valid numeric entity character U+FFFFD", +"input": "󿿽", +"output": [["Character", "\uDBBF\uDFFD"]]}, + +{"description": "Valid numeric entity character U+100000", +"input": "􀀀", +"output": [["Character", "\uDBC0\uDC00"]]}, + +{"description": "Valid numeric entity character U+10FFFD", +"input": "􏿽", +"output": [["Character", "\uDBFF\uDFFD"]]} + +]} + + diff --git a/pkgs/html/test/data/tokenizer/pendingSpecChanges.test b/pkgs/html/test/data/tokenizer/pendingSpecChanges.test new file mode 100644 index 000000000..1b7dc3c72 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/pendingSpecChanges.test @@ -0,0 +1,7 @@ +{"tests": [ + +{"description":"", + "output":[["Comment", "comment"]]}, + +{"description":"Comment, Central dash no space", + "input":"", + "output":["ParseError", ["Comment", "-"]]}, + +{"description":"Comment, two central dashes", +"input":"", +"output":["ParseError", ["Comment", " --comment "]]}, + +{"description":"Unfinished comment", +"input":"", + "output":["ParseError", ["Comment", ""]]}, + +{"description":"Short comment two", + "input":"", + "output":["ParseError", ["Comment", ""]]}, + +{"description":"Short comment three", + "input":"", + "output":[["Comment", ""]]}, + + +{"description":"Ampersand EOF", +"input":"&", +"output":[["Character", "&"]]}, + +{"description":"Ampersand ampersand EOF", +"input":"&&", +"output":[["Character", "&&"]]}, + +{"description":"Ampersand space EOF", +"input":"& ", +"output":[["Character", "& "]]}, + +{"description":"Unfinished entity", +"input":"&f", +"output":["ParseError", ["Character", "&f"]]}, + +{"description":"Ampersand, number sign", +"input":"&#", +"output":["ParseError", ["Character", "&#"]]}, + +{"description":"Unfinished numeric entity", +"input":"&#x", +"output":["ParseError", ["Character", "&#x"]]}, + +{"description":"Entity with trailing semicolon (1)", +"input":"I'm ¬it", +"output":[["Character","I'm \u00ACit"]]}, + +{"description":"Entity with trailing semicolon (2)", +"input":"I'm ∉", +"output":[["Character","I'm \u2209"]]}, + +{"description":"Entity without trailing semicolon (1)", +"input":"I'm ¬it", +"output":[["Character","I'm "], "ParseError", ["Character", "\u00ACit"]]}, + +{"description":"Entity without trailing semicolon (2)", +"input":"I'm ¬in", +"output":[["Character","I'm "], "ParseError", ["Character", "\u00ACin"]]}, + +{"description":"Partial entity match at end of file", +"input":"I'm &no", +"output":[["Character","I'm "], "ParseError", ["Character", "&no"]]}, + +{"description":"Non-ASCII character reference name", +"input":"&\u00AC;", +"output":["ParseError", ["Character", "&\u00AC;"]]}, + +{"description":"ASCII decimal entity", +"input":"$", +"output":[["Character","$"]]}, + +{"description":"ASCII hexadecimal entity", +"input":"?", +"output":[["Character","?"]]}, + +{"description":"Hexadecimal entity in attribute", +"input":"", +"output":[["StartTag", "h", {"a":"?"}], ["EndTag", "h"]]}, + +{"description":"Entity in attribute without semicolon ending in x", +"input":"", +"output":["ParseError", ["StartTag", "h", {"a":"¬x"}]]}, + +{"description":"Entity in attribute without semicolon ending in 1", +"input":"", +"output":["ParseError", ["StartTag", "h", {"a":"¬1"}]]}, + +{"description":"Entity in attribute without semicolon ending in i", +"input":"", +"output":["ParseError", ["StartTag", "h", {"a":"¬i"}]]}, + +{"description":"Entity in attribute without semicolon", +"input":"", +"output":["ParseError", ["StartTag", "h", {"a":"\u00A9"}]]}, + +{"description":"Unquoted attribute ending in ampersand", +"input":"", +"output":[["StartTag","s",{"o":"&","t":""}]]}, + +{"description":"Unquoted attribute at end of tag with final character of &, with tag followed by characters", +"input":"foo", +"output":[["StartTag", "a", {"a":"a&"}], ["Character", "foo"]]}, + +{"description":"plaintext element", + "input":"foobar", + "output":[["StartTag","plaintext",{}], ["Character","foobar"]]}, + +{"description":"Open angled bracket in unquoted attribute value state", + "input":"<a a=f<>", + "output":["ParseError", ["StartTag", "a", {"a":"f<"}]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/test2.test b/pkgs/html/test/data/tokenizer/test2.test new file mode 100644 index 000000000..e15751432 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/test2.test @@ -0,0 +1,179 @@ +{"tests": [ + +{"description":"DOCTYPE without name", +"input":"<!DOCTYPE>", +"output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"DOCTYPE without space before name", +"input":"<!DOCTYPEhtml>", +"output":["ParseError", ["DOCTYPE", "html", null, null, true]]}, + +{"description":"Incorrect DOCTYPE without a space before name", +"input":"<!DOCTYPEfoo>", +"output":["ParseError", ["DOCTYPE", "foo", null, null, true]]}, + +{"description":"DOCTYPE with publicId", +"input":"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML Transitional 4.01//EN\">", +"output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", null, true]]}, + +{"description":"DOCTYPE with EOF after PUBLIC", +"input":"<!DOCTYPE html PUBLIC", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"DOCTYPE with EOF after PUBLIC '", +"input":"<!DOCTYPE html PUBLIC '", +"output":["ParseError", ["DOCTYPE", "html", "", null, false]]}, + +{"description":"DOCTYPE with EOF after PUBLIC 'x", +"input":"<!DOCTYPE html PUBLIC 'x", +"output":["ParseError", ["DOCTYPE", "html", "x", null, false]]}, + +{"description":"DOCTYPE with systemId", +"input":"<!DOCTYPE html SYSTEM \"-//W3C//DTD HTML Transitional 4.01//EN\">", +"output":[["DOCTYPE", "html", null, "-//W3C//DTD HTML Transitional 4.01//EN", true]]}, + +{"description":"DOCTYPE with publicId and systemId", +"input":"<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML Transitional 4.01//EN\" \"-//W3C//DTD HTML Transitional 4.01//EN\">", +"output":[["DOCTYPE", "html", "-//W3C//DTD HTML Transitional 4.01//EN", "-//W3C//DTD HTML Transitional 4.01//EN", true]]}, + +{"description":"DOCTYPE with > in double-quoted publicId", +"input":"<!DOCTYPE html PUBLIC \">x", +"output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]}, + +{"description":"DOCTYPE with > in single-quoted publicId", +"input":"<!DOCTYPE html PUBLIC '>x", +"output":["ParseError", ["DOCTYPE", "html", "", null, false], ["Character", "x"]]}, + +{"description":"DOCTYPE with > in double-quoted systemId", +"input":"<!DOCTYPE html PUBLIC \"foo\" \">x", +"output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]}, + +{"description":"DOCTYPE with > in single-quoted systemId", +"input":"<!DOCTYPE html PUBLIC 'foo' '>x", +"output":["ParseError", ["DOCTYPE", "html", "foo", "", false], ["Character", "x"]]}, + +{"description":"Incomplete doctype", +"input":"<!DOCTYPE html ", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"Numeric entity representing the NUL character", +"input":"&#0000;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Hexadecimal entity representing the NUL character", +"input":"&#x0000;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Numeric entity representing a codepoint after 1114111 (U+10FFFF)", +"input":"&#2225222;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Hexadecimal entity representing a codepoint after 1114111 (U+10FFFF)", +"input":"&#x1010FFFF;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Hexadecimal entity pair representing a surrogate pair", +"input":"&#xD869;&#xDED6;", +"output":["ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Hexadecimal entity with mixed uppercase and lowercase", +"input":"&#xaBcD;", +"output":[["Character", "\uABCD"]]}, + +{"description":"Entity without a name", +"input":"&;", +"output":["ParseError", ["Character", "&;"]]}, + +{"description":"Unescaped ampersand in attribute value", +"input":"<h a='&'>", +"output":[["StartTag", "h", { "a":"&" }]]}, + +{"description":"StartTag containing <", +"input":"<a<b>", +"output":[["StartTag", "a<b", { }]]}, + +{"description":"Non-void element containing trailing /", +"input":"<h/>", +"output":[["StartTag","h",{},true]]}, + +{"description":"Void element with permitted slash", +"input":"<br/>", +"output":[["StartTag","br",{},true]]}, + +{"description":"Void element with permitted slash (with attribute)", +"input":"<br foo='bar'/>", +"output":[["StartTag","br",{"foo":"bar"},true]]}, + +{"description":"StartTag containing /", +"input":"<h/a='b'>", +"output":["ParseError", ["StartTag", "h", { "a":"b" }]]}, + +{"description":"Double-quoted attribute value", +"input":"<h a=\"b\">", +"output":[["StartTag", "h", { "a":"b" }]]}, + +{"description":"Unescaped </", +"input":"</", +"output":["ParseError", ["Character", "</"]]}, + +{"description":"Illegal end tag name", +"input":"</1>", +"output":["ParseError", ["Comment", "1"]]}, + +{"description":"Simili processing instruction", +"input":"<?namespace>", +"output":["ParseError", ["Comment", "?namespace"]]}, + +{"description":"A bogus comment stops at >, even if preceeded by two dashes", +"input":"<?foo-->", +"output":["ParseError", ["Comment", "?foo--"]]}, + +{"description":"Unescaped <", +"input":"foo < bar", +"output":[["Character", "foo "], "ParseError", ["Character", "< bar"]]}, + +{"description":"Null Byte Replacement", +"input":"\u0000", +"output":["ParseError", ["Character", "\u0000"]]}, + +{"description":"Comment with dash", +"input":"<!---x", +"output":["ParseError", ["Comment", "-x"]]}, + +{"description":"Entity + newline", +"input":"\nx\n&gt;\n", +"output":[["Character","\nx\n>\n"]]}, + +{"description":"Start tag with no attributes but space before the greater-than sign", +"input":"<h >", +"output":[["StartTag", "h", {}]]}, + +{"description":"Empty attribute followed by uppercase attribute", +"input":"<h a B=''>", +"output":[["StartTag", "h", {"a":"", "b":""}]]}, + +{"description":"Double-quote after attribute name", +"input":"<h a \">", +"output":["ParseError", ["StartTag", "h", {"a":"", "\"":""}]]}, + +{"description":"Single-quote after attribute name", +"input":"<h a '>", +"output":["ParseError", ["StartTag", "h", {"a":"", "'":""}]]}, + +{"description":"Empty end tag with following characters", +"input":"a</>bc", +"output":[["Character", "a"], "ParseError", ["Character", "bc"]]}, + +{"description":"Empty end tag with following tag", +"input":"a</><b>c", +"output":[["Character", "a"], "ParseError", ["StartTag", "b", {}], ["Character", "c"]]}, + +{"description":"Empty end tag with following comment", +"input":"a</><!--b-->c", +"output":[["Character", "a"], "ParseError", ["Comment", "b"], ["Character", "c"]]}, + +{"description":"Empty end tag with following end tag", +"input":"a</></b>c", +"output":[["Character", "a"], "ParseError", ["EndTag", "b"], ["Character", "c"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/test3.test b/pkgs/html/test/data/tokenizer/test3.test new file mode 100644 index 000000000..58519e8ad --- /dev/null +++ b/pkgs/html/test/data/tokenizer/test3.test @@ -0,0 +1,6047 @@ +{"tests": [ + +{"description":"", +"input":"", +"output":[]}, + +{"description":"\\u0009", +"input":"\u0009", +"output":[["Character", "\u0009"]]}, + +{"description":"\\u000A", +"input":"\u000A", +"output":[["Character", "\u000A"]]}, + +{"description":"\\u000B", +"input":"\u000B", +"output":["ParseError", ["Character", "\u000B"]]}, + +{"description":"\\u000C", +"input":"\u000C", +"output":[["Character", "\u000C"]]}, + +{"description":" ", +"input":" ", +"output":[["Character", " "]]}, + +{"description":"!", +"input":"!", +"output":[["Character", "!"]]}, + +{"description":"\"", +"input":"\"", +"output":[["Character", "\""]]}, + +{"description":"%", +"input":"%", +"output":[["Character", "%"]]}, + +{"description":"&", +"input":"&", +"output":[["Character", "&"]]}, + +{"description":"'", +"input":"'", +"output":[["Character", "'"]]}, + +{"description":",", +"input":",", +"output":[["Character", ","]]}, + +{"description":"-", +"input":"-", +"output":[["Character", "-"]]}, + +{"description":".", +"input":".", +"output":[["Character", "."]]}, + +{"description":"/", +"input":"/", +"output":[["Character", "/"]]}, + +{"description":"0", +"input":"0", +"output":[["Character", "0"]]}, + +{"description":"1", +"input":"1", +"output":[["Character", "1"]]}, + +{"description":"9", +"input":"9", +"output":[["Character", "9"]]}, + +{"description":";", +"input":";", +"output":[["Character", ";"]]}, + +{"description":"<", +"input":"<", +"output":["ParseError", ["Character", "<"]]}, + +{"description":"<\\u0000", +"input":"<\u0000", +"output":["ParseError", ["Character", "<"], "ParseError", ["Character", "\u0000"]]}, + +{"description":"<\\u0009", +"input":"<\u0009", +"output":["ParseError", ["Character", "<\u0009"]]}, + +{"description":"<\\u000A", +"input":"<\u000A", +"output":["ParseError", ["Character", "<\u000A"]]}, + +{"description":"<\\u000B", +"input":"<\u000B", +"output":["ParseError", "ParseError", ["Character", "<\u000B"]]}, + +{"description":"<\\u000C", +"input":"<\u000C", +"output":["ParseError", ["Character", "<\u000C"]]}, + +{"description":"< ", +"input":"< ", +"output":["ParseError", ["Character", "< "]]}, + +{"description":"<!", +"input":"<!", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!\\u0000", +"input":"<!\u0000", +"output":["ParseError", ["Comment", "\uFFFD"]]}, + +{"description":"<!\\u0009", +"input":"<!\u0009", +"output":["ParseError", ["Comment", "\u0009"]]}, + +{"description":"<!\\u000A", +"input":"<!\u000A", +"output":["ParseError", ["Comment", "\u000A"]]}, + +{"description":"<!\\u000B", +"input":"<!\u000B", +"output":["ParseError", "ParseError", ["Comment", "\u000B"]]}, + +{"description":"<!\\u000C", +"input":"<!\u000C", +"output":["ParseError", ["Comment", "\u000C"]]}, + +{"description":"<! ", +"input":"<! ", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"<!!", +"input":"<!!", +"output":["ParseError", ["Comment", "!"]]}, + +{"description":"<!\"", +"input":"<!\"", +"output":["ParseError", ["Comment", "\""]]}, + +{"description":"<!&", +"input":"<!&", +"output":["ParseError", ["Comment", "&"]]}, + +{"description":"<!'", +"input":"<!'", +"output":["ParseError", ["Comment", "'"]]}, + +{"description":"<!-", +"input":"<!-", +"output":["ParseError", ["Comment", "-"]]}, + +{"description":"<!--", +"input":"<!--", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!--\\u0000", +"input":"<!--\u0000", +"output":["ParseError", "ParseError", ["Comment", "\uFFFD"]]}, + +{"description":"<!--\\u0009", +"input":"<!--\u0009", +"output":["ParseError", ["Comment", "\u0009"]]}, + +{"description":"<!--\\u000A", +"input":"<!--\u000A", +"output":["ParseError", ["Comment", "\u000A"]]}, + +{"description":"<!--\\u000B", +"input":"<!--\u000B", +"output":["ParseError", "ParseError", ["Comment", "\u000B"]]}, + +{"description":"<!--\\u000C", +"input":"<!--\u000C", +"output":["ParseError", ["Comment", "\u000C"]]}, + +{"description":"<!-- ", +"input":"<!-- ", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"<!-- \\u0000", +"input":"<!-- \u0000", +"output":["ParseError", "ParseError", ["Comment", " \uFFFD"]]}, + +{"description":"<!-- \\u0009", +"input":"<!-- \u0009", +"output":["ParseError", ["Comment", " \u0009"]]}, + +{"description":"<!-- \\u000A", +"input":"<!-- \u000A", +"output":["ParseError", ["Comment", " \u000A"]]}, + +{"description":"<!-- \\u000B", +"input":"<!-- \u000B", +"output":["ParseError", "ParseError", ["Comment", " \u000B"]]}, + +{"description":"<!-- \\u000C", +"input":"<!-- \u000C", +"output":["ParseError", ["Comment", " \u000C"]]}, + +{"description":"<!-- ", +"input":"<!-- ", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"<!-- !", +"input":"<!-- !", +"output":["ParseError", ["Comment", " !"]]}, + +{"description":"<!-- \"", +"input":"<!-- \"", +"output":["ParseError", ["Comment", " \""]]}, + +{"description":"<!-- &", +"input":"<!-- &", +"output":["ParseError", ["Comment", " &"]]}, + +{"description":"<!-- '", +"input":"<!-- '", +"output":["ParseError", ["Comment", " '"]]}, + +{"description":"<!-- ,", +"input":"<!-- ,", +"output":["ParseError", ["Comment", " ,"]]}, + +{"description":"<!-- -", +"input":"<!-- -", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"<!-- -\\u0000", +"input":"<!-- -\u0000", +"output":["ParseError", "ParseError", ["Comment", " -\uFFFD"]]}, + +{"description":"<!-- -\\u0009", +"input":"<!-- -\u0009", +"output":["ParseError", ["Comment", " -\u0009"]]}, + +{"description":"<!-- -\\u000A", +"input":"<!-- -\u000A", +"output":["ParseError", ["Comment", " -\u000A"]]}, + +{"description":"<!-- -\\u000B", +"input":"<!-- -\u000B", +"output":["ParseError", "ParseError", ["Comment", " -\u000B"]]}, + +{"description":"<!-- -\\u000C", +"input":"<!-- -\u000C", +"output":["ParseError", ["Comment", " -\u000C"]]}, + +{"description":"<!-- - ", +"input":"<!-- - ", +"output":["ParseError", ["Comment", " - "]]}, + +{"description":"<!-- -!", +"input":"<!-- -!", +"output":["ParseError", ["Comment", " -!"]]}, + +{"description":"<!-- -\"", +"input":"<!-- -\"", +"output":["ParseError", ["Comment", " -\""]]}, + +{"description":"<!-- -&", +"input":"<!-- -&", +"output":["ParseError", ["Comment", " -&"]]}, + +{"description":"<!-- -'", +"input":"<!-- -'", +"output":["ParseError", ["Comment", " -'"]]}, + +{"description":"<!-- -,", +"input":"<!-- -,", +"output":["ParseError", ["Comment", " -,"]]}, + +{"description":"<!-- --", +"input":"<!-- --", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"<!-- -.", +"input":"<!-- -.", +"output":["ParseError", ["Comment", " -."]]}, + +{"description":"<!-- -/", +"input":"<!-- -/", +"output":["ParseError", ["Comment", " -/"]]}, + +{"description":"<!-- -0", +"input":"<!-- -0", +"output":["ParseError", ["Comment", " -0"]]}, + +{"description":"<!-- -1", +"input":"<!-- -1", +"output":["ParseError", ["Comment", " -1"]]}, + +{"description":"<!-- -9", +"input":"<!-- -9", +"output":["ParseError", ["Comment", " -9"]]}, + +{"description":"<!-- -<", +"input":"<!-- -<", +"output":["ParseError", ["Comment", " -<"]]}, + +{"description":"<!-- -=", +"input":"<!-- -=", +"output":["ParseError", ["Comment", " -="]]}, + +{"description":"<!-- ->", +"input":"<!-- ->", +"output":["ParseError", ["Comment", " ->"]]}, + +{"description":"<!-- -?", +"input":"<!-- -?", +"output":["ParseError", ["Comment", " -?"]]}, + +{"description":"<!-- -@", +"input":"<!-- -@", +"output":["ParseError", ["Comment", " -@"]]}, + +{"description":"<!-- -A", +"input":"<!-- -A", +"output":["ParseError", ["Comment", " -A"]]}, + +{"description":"<!-- -B", +"input":"<!-- -B", +"output":["ParseError", ["Comment", " -B"]]}, + +{"description":"<!-- -Y", +"input":"<!-- -Y", +"output":["ParseError", ["Comment", " -Y"]]}, + +{"description":"<!-- -Z", +"input":"<!-- -Z", +"output":["ParseError", ["Comment", " -Z"]]}, + +{"description":"<!-- -`", +"input":"<!-- -`", +"output":["ParseError", ["Comment", " -`"]]}, + +{"description":"<!-- -a", +"input":"<!-- -a", +"output":["ParseError", ["Comment", " -a"]]}, + +{"description":"<!-- -b", +"input":"<!-- -b", +"output":["ParseError", ["Comment", " -b"]]}, + +{"description":"<!-- -y", +"input":"<!-- -y", +"output":["ParseError", ["Comment", " -y"]]}, + +{"description":"<!-- -z", +"input":"<!-- -z", +"output":["ParseError", ["Comment", " -z"]]}, + +{"description":"<!-- -{", +"input":"<!-- -{", +"output":["ParseError", ["Comment", " -{"]]}, + +{"description":"<!-- -\\uDBC0\\uDC00", +"input":"<!-- -\uDBC0\uDC00", +"output":["ParseError", ["Comment", " -\uDBC0\uDC00"]]}, + +{"description":"<!-- .", +"input":"<!-- .", +"output":["ParseError", ["Comment", " ."]]}, + +{"description":"<!-- /", +"input":"<!-- /", +"output":["ParseError", ["Comment", " /"]]}, + +{"description":"<!-- 0", +"input":"<!-- 0", +"output":["ParseError", ["Comment", " 0"]]}, + +{"description":"<!-- 1", +"input":"<!-- 1", +"output":["ParseError", ["Comment", " 1"]]}, + +{"description":"<!-- 9", +"input":"<!-- 9", +"output":["ParseError", ["Comment", " 9"]]}, + +{"description":"<!-- <", +"input":"<!-- <", +"output":["ParseError", ["Comment", " <"]]}, + +{"description":"<!-- =", +"input":"<!-- =", +"output":["ParseError", ["Comment", " ="]]}, + +{"description":"<!-- >", +"input":"<!-- >", +"output":["ParseError", ["Comment", " >"]]}, + +{"description":"<!-- ?", +"input":"<!-- ?", +"output":["ParseError", ["Comment", " ?"]]}, + +{"description":"<!-- @", +"input":"<!-- @", +"output":["ParseError", ["Comment", " @"]]}, + +{"description":"<!-- A", +"input":"<!-- A", +"output":["ParseError", ["Comment", " A"]]}, + +{"description":"<!-- B", +"input":"<!-- B", +"output":["ParseError", ["Comment", " B"]]}, + +{"description":"<!-- Y", +"input":"<!-- Y", +"output":["ParseError", ["Comment", " Y"]]}, + +{"description":"<!-- Z", +"input":"<!-- Z", +"output":["ParseError", ["Comment", " Z"]]}, + +{"description":"<!-- `", +"input":"<!-- `", +"output":["ParseError", ["Comment", " `"]]}, + +{"description":"<!-- a", +"input":"<!-- a", +"output":["ParseError", ["Comment", " a"]]}, + +{"description":"<!-- b", +"input":"<!-- b", +"output":["ParseError", ["Comment", " b"]]}, + +{"description":"<!-- y", +"input":"<!-- y", +"output":["ParseError", ["Comment", " y"]]}, + +{"description":"<!-- z", +"input":"<!-- z", +"output":["ParseError", ["Comment", " z"]]}, + +{"description":"<!-- {", +"input":"<!-- {", +"output":["ParseError", ["Comment", " {"]]}, + +{"description":"<!-- \\uDBC0\\uDC00", +"input":"<!-- \uDBC0\uDC00", +"output":["ParseError", ["Comment", " \uDBC0\uDC00"]]}, + +{"description":"<!--!", +"input":"<!--!", +"output":["ParseError", ["Comment", "!"]]}, + +{"description":"<!--\"", +"input":"<!--\"", +"output":["ParseError", ["Comment", "\""]]}, + +{"description":"<!--&", +"input":"<!--&", +"output":["ParseError", ["Comment", "&"]]}, + +{"description":"<!--'", +"input":"<!--'", +"output":["ParseError", ["Comment", "'"]]}, + +{"description":"<!--,", +"input":"<!--,", +"output":["ParseError", ["Comment", ","]]}, + +{"description":"<!---", +"input":"<!---", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!---\\u0000", +"input":"<!---\u0000", +"output":["ParseError", "ParseError", ["Comment", "-\uFFFD"]]}, + +{"description":"<!---\\u0009", +"input":"<!---\u0009", +"output":["ParseError", ["Comment", "-\u0009"]]}, + +{"description":"<!---\\u000A", +"input":"<!---\u000A", +"output":["ParseError", ["Comment", "-\u000A"]]}, + +{"description":"<!---\\u000B", +"input":"<!---\u000B", +"output":["ParseError", "ParseError", ["Comment", "-\u000B"]]}, + +{"description":"<!---\\u000C", +"input":"<!---\u000C", +"output":["ParseError", ["Comment", "-\u000C"]]}, + +{"description":"<!--- ", +"input":"<!--- ", +"output":["ParseError", ["Comment", "- "]]}, + +{"description":"<!---!", +"input":"<!---!", +"output":["ParseError", ["Comment", "-!"]]}, + +{"description":"<!---\"", +"input":"<!---\"", +"output":["ParseError", ["Comment", "-\""]]}, + +{"description":"<!---&", +"input":"<!---&", +"output":["ParseError", ["Comment", "-&"]]}, + +{"description":"<!---'", +"input":"<!---'", +"output":["ParseError", ["Comment", "-'"]]}, + +{"description":"<!---,", +"input":"<!---,", +"output":["ParseError", ["Comment", "-,"]]}, + +{"description":"<!----", +"input":"<!----", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!----\\u0000", +"input":"<!----\u0000", +"output":["ParseError", "ParseError", ["Comment", "--\uFFFD"]]}, + +{"description":"<!----\\u0009", +"input":"<!----\u0009", +"output":["ParseError", "ParseError", ["Comment", "--\u0009"]]}, + +{"description":"<!----\\u000A", +"input":"<!----\u000A", +"output":["ParseError", "ParseError", ["Comment", "--\u000A"]]}, + +{"description":"<!----\\u000B", +"input":"<!----\u000B", +"output":["ParseError", "ParseError", "ParseError", ["Comment", "--\u000B"]]}, + +{"description":"<!----\\u000C", +"input":"<!----\u000C", +"output":["ParseError", "ParseError", ["Comment", "--\u000C"]]}, + +{"description":"<!---- ", +"input":"<!---- ", +"output":["ParseError", "ParseError", ["Comment", "-- "]]}, + +{"description":"<!---- -", +"input":"<!---- -", +"output":["ParseError", "ParseError", ["Comment", "-- "]]}, + +{"description":"<!---- --", +"input":"<!---- --", +"output":["ParseError", "ParseError", ["Comment", "-- "]]}, + +{"description":"<!---- -->", +"input":"<!---- -->", +"output":["ParseError", ["Comment", "-- "]]}, + +{"description":"<!---- -->", +"input":"<!---- -->", +"output":["ParseError", ["Comment", "-- "]]}, + +{"description":"<!---- a-->", +"input":"<!---- a-->", +"output":["ParseError", ["Comment", "-- a"]]}, + +{"description":"<!----!", +"input":"<!----!", +"output":["ParseError", "ParseError", ["Comment", ""]]}, + +{"description":"<!----!>", +"input":"<!----!>", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!----!a", +"input":"<!----!a", +"output":["ParseError", "ParseError", ["Comment", "--!a"]]}, + +{"description":"<!----!a-", +"input":"<!----!a-", +"output":["ParseError", "ParseError", ["Comment", "--!a"]]}, + +{"description":"<!----!a--", +"input":"<!----!a--", +"output":["ParseError", "ParseError", ["Comment", "--!a"]]}, + +{"description":"<!----!a-->", +"input":"<!----!a-->", +"output":["ParseError", ["Comment", "--!a"]]}, + +{"description":"<!----!-", +"input":"<!----!-", +"output":["ParseError", "ParseError", ["Comment", "--!"]]}, + +{"description":"<!----!--", +"input":"<!----!--", +"output":["ParseError", "ParseError", ["Comment", "--!"]]}, + +{"description":"<!----!-->", +"input":"<!----!-->", +"output":["ParseError", ["Comment", "--!"]]}, + +{"description":"<!----\"", +"input":"<!----\"", +"output":["ParseError", "ParseError", ["Comment", "--\""]]}, + +{"description":"<!----&", +"input":"<!----&", +"output":["ParseError", "ParseError", ["Comment", "--&"]]}, + +{"description":"<!----'", +"input":"<!----'", +"output":["ParseError", "ParseError", ["Comment", "--'"]]}, + +{"description":"<!----,", +"input":"<!----,", +"output":["ParseError", "ParseError", ["Comment", "--,"]]}, + +{"description":"<!-----", +"input":"<!-----", +"output":["ParseError", "ParseError", ["Comment", "-"]]}, + +{"description":"<!----.", +"input":"<!----.", +"output":["ParseError", "ParseError", ["Comment", "--."]]}, + +{"description":"<!----/", +"input":"<!----/", +"output":["ParseError", "ParseError", ["Comment", "--/"]]}, + +{"description":"<!----0", +"input":"<!----0", +"output":["ParseError", "ParseError", ["Comment", "--0"]]}, + +{"description":"<!----1", +"input":"<!----1", +"output":["ParseError", "ParseError", ["Comment", "--1"]]}, + +{"description":"<!----9", +"input":"<!----9", +"output":["ParseError", "ParseError", ["Comment", "--9"]]}, + +{"description":"<!----<", +"input":"<!----<", +"output":["ParseError", "ParseError", ["Comment", "--<"]]}, + +{"description":"<!----=", +"input":"<!----=", +"output":["ParseError", "ParseError", ["Comment", "--="]]}, + +{"description":"<!---->", +"input":"<!---->", +"output":[["Comment", ""]]}, + +{"description":"<!----?", +"input":"<!----?", +"output":["ParseError", "ParseError", ["Comment", "--?"]]}, + +{"description":"<!----@", +"input":"<!----@", +"output":["ParseError", "ParseError", ["Comment", "--@"]]}, + +{"description":"<!----A", +"input":"<!----A", +"output":["ParseError", "ParseError", ["Comment", "--A"]]}, + +{"description":"<!----B", +"input":"<!----B", +"output":["ParseError", "ParseError", ["Comment", "--B"]]}, + +{"description":"<!----Y", +"input":"<!----Y", +"output":["ParseError", "ParseError", ["Comment", "--Y"]]}, + +{"description":"<!----Z", +"input":"<!----Z", +"output":["ParseError", "ParseError", ["Comment", "--Z"]]}, + +{"description":"<!----`", +"input":"<!----`", +"output":["ParseError", "ParseError", ["Comment", "--`"]]}, + +{"description":"<!----a", +"input":"<!----a", +"output":["ParseError", "ParseError", ["Comment", "--a"]]}, + +{"description":"<!----b", +"input":"<!----b", +"output":["ParseError", "ParseError", ["Comment", "--b"]]}, + +{"description":"<!----y", +"input":"<!----y", +"output":["ParseError", "ParseError", ["Comment", "--y"]]}, + +{"description":"<!----z", +"input":"<!----z", +"output":["ParseError", "ParseError", ["Comment", "--z"]]}, + +{"description":"<!----{", +"input":"<!----{", +"output":["ParseError", "ParseError", ["Comment", "--{"]]}, + +{"description":"<!----\\uDBC0\\uDC00", +"input":"<!----\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["Comment", "--\uDBC0\uDC00"]]}, + +{"description":"<!---.", +"input":"<!---.", +"output":["ParseError", ["Comment", "-."]]}, + +{"description":"<!---/", +"input":"<!---/", +"output":["ParseError", ["Comment", "-/"]]}, + +{"description":"<!---0", +"input":"<!---0", +"output":["ParseError", ["Comment", "-0"]]}, + +{"description":"<!---1", +"input":"<!---1", +"output":["ParseError", ["Comment", "-1"]]}, + +{"description":"<!---9", +"input":"<!---9", +"output":["ParseError", ["Comment", "-9"]]}, + +{"description":"<!---<", +"input":"<!---<", +"output":["ParseError", ["Comment", "-<"]]}, + +{"description":"<!---=", +"input":"<!---=", +"output":["ParseError", ["Comment", "-="]]}, + +{"description":"<!--->", +"input":"<!--->", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!---?", +"input":"<!---?", +"output":["ParseError", ["Comment", "-?"]]}, + +{"description":"<!---@", +"input":"<!---@", +"output":["ParseError", ["Comment", "-@"]]}, + +{"description":"<!---A", +"input":"<!---A", +"output":["ParseError", ["Comment", "-A"]]}, + +{"description":"<!---B", +"input":"<!---B", +"output":["ParseError", ["Comment", "-B"]]}, + +{"description":"<!---Y", +"input":"<!---Y", +"output":["ParseError", ["Comment", "-Y"]]}, + +{"description":"<!---Z", +"input":"<!---Z", +"output":["ParseError", ["Comment", "-Z"]]}, + +{"description":"<!---`", +"input":"<!---`", +"output":["ParseError", ["Comment", "-`"]]}, + +{"description":"<!---a", +"input":"<!---a", +"output":["ParseError", ["Comment", "-a"]]}, + +{"description":"<!---b", +"input":"<!---b", +"output":["ParseError", ["Comment", "-b"]]}, + +{"description":"<!---y", +"input":"<!---y", +"output":["ParseError", ["Comment", "-y"]]}, + +{"description":"<!---z", +"input":"<!---z", +"output":["ParseError", ["Comment", "-z"]]}, + +{"description":"<!---{", +"input":"<!---{", +"output":["ParseError", ["Comment", "-{"]]}, + +{"description":"<!---\\uDBC0\\uDC00", +"input":"<!---\uDBC0\uDC00", +"output":["ParseError", ["Comment", "-\uDBC0\uDC00"]]}, + +{"description":"<!--.", +"input":"<!--.", +"output":["ParseError", ["Comment", "."]]}, + +{"description":"<!--/", +"input":"<!--/", +"output":["ParseError", ["Comment", "/"]]}, + +{"description":"<!--0", +"input":"<!--0", +"output":["ParseError", ["Comment", "0"]]}, + +{"description":"<!--1", +"input":"<!--1", +"output":["ParseError", ["Comment", "1"]]}, + +{"description":"<!--9", +"input":"<!--9", +"output":["ParseError", ["Comment", "9"]]}, + +{"description":"<!--<", +"input":"<!--<", +"output":["ParseError", ["Comment", "<"]]}, + +{"description":"<!--=", +"input":"<!--=", +"output":["ParseError", ["Comment", "="]]}, + +{"description":"<!-->", +"input":"<!-->", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!--?", +"input":"<!--?", +"output":["ParseError", ["Comment", "?"]]}, + +{"description":"<!--@", +"input":"<!--@", +"output":["ParseError", ["Comment", "@"]]}, + +{"description":"<!--A", +"input":"<!--A", +"output":["ParseError", ["Comment", "A"]]}, + +{"description":"<!--B", +"input":"<!--B", +"output":["ParseError", ["Comment", "B"]]}, + +{"description":"<!--Y", +"input":"<!--Y", +"output":["ParseError", ["Comment", "Y"]]}, + +{"description":"<!--Z", +"input":"<!--Z", +"output":["ParseError", ["Comment", "Z"]]}, + +{"description":"<!--`", +"input":"<!--`", +"output":["ParseError", ["Comment", "`"]]}, + +{"description":"<!--a", +"input":"<!--a", +"output":["ParseError", ["Comment", "a"]]}, + +{"description":"<!--b", +"input":"<!--b", +"output":["ParseError", ["Comment", "b"]]}, + +{"description":"<!--y", +"input":"<!--y", +"output":["ParseError", ["Comment", "y"]]}, + +{"description":"<!--z", +"input":"<!--z", +"output":["ParseError", ["Comment", "z"]]}, + +{"description":"<!--{", +"input":"<!--{", +"output":["ParseError", ["Comment", "{"]]}, + +{"description":"<!--\\uDBC0\\uDC00", +"input":"<!--\uDBC0\uDC00", +"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]}, + +{"description":"<!/", +"input":"<!/", +"output":["ParseError", ["Comment", "/"]]}, + +{"description":"<!0", +"input":"<!0", +"output":["ParseError", ["Comment", "0"]]}, + +{"description":"<!1", +"input":"<!1", +"output":["ParseError", ["Comment", "1"]]}, + +{"description":"<!9", +"input":"<!9", +"output":["ParseError", ["Comment", "9"]]}, + +{"description":"<!<", +"input":"<!<", +"output":["ParseError", ["Comment", "<"]]}, + +{"description":"<!=", +"input":"<!=", +"output":["ParseError", ["Comment", "="]]}, + +{"description":"<!>", +"input":"<!>", +"output":["ParseError", ["Comment", ""]]}, + +{"description":"<!?", +"input":"<!?", +"output":["ParseError", ["Comment", "?"]]}, + +{"description":"<!@", +"input":"<!@", +"output":["ParseError", ["Comment", "@"]]}, + +{"description":"<!A", +"input":"<!A", +"output":["ParseError", ["Comment", "A"]]}, + +{"description":"<!B", +"input":"<!B", +"output":["ParseError", ["Comment", "B"]]}, + +{"description":"<!DOCTYPE", +"input":"<!DOCTYPE", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE\\u0000", +"input":"<!DOCTYPE\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\uFFFD", null, null, false]]}, + +{"description":"<!DOCTYPE\\u0008", +"input":"<!DOCTYPE\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u0008", null, null, false]]}, + +{"description":"<!DOCTYPE\\u0009", +"input":"<!DOCTYPE\u0009", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE\\u000A", +"input":"<!DOCTYPE\u000A", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE\\u000B", +"input":"<!DOCTYPE\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u000B", null, null, false]]}, + +{"description":"<!DOCTYPE\\u000C", +"input":"<!DOCTYPE\u000C", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE\\u000D", +"input":"<!DOCTYPE\u000D", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE\\u001F", +"input":"<!DOCTYPE\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "\u001F", null, null, false]]}, + +{"description":"<!DOCTYPE ", +"input":"<!DOCTYPE ", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE \\u0000", +"input":"<!DOCTYPE \u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "\uFFFD", null, null, false]]}, + +{"description":"<!DOCTYPE \\u0008", +"input":"<!DOCTYPE \u0008", +"output":["ParseError", "ParseError", ["DOCTYPE", "\u0008", null, null, false]]}, + +{"description":"<!DOCTYPE \\u0009", +"input":"<!DOCTYPE \u0009", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE \\u000A", +"input":"<!DOCTYPE \u000A", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE \\u000B", +"input":"<!DOCTYPE \u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "\u000B", null, null, false]]}, + +{"description":"<!DOCTYPE \\u000C", +"input":"<!DOCTYPE \u000C", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE \\u000D", +"input":"<!DOCTYPE \u000D", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE \\u001F", +"input":"<!DOCTYPE \u001F", +"output":["ParseError", "ParseError", ["DOCTYPE", "\u001F", null, null, false]]}, + +{"description":"<!DOCTYPE ", +"input":"<!DOCTYPE ", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE !", +"input":"<!DOCTYPE !", +"output":["ParseError", ["DOCTYPE", "!", null, null, false]]}, + +{"description":"<!DOCTYPE \"", +"input":"<!DOCTYPE \"", +"output":["ParseError", ["DOCTYPE", "\"", null, null, false]]}, + +{"description":"<!DOCTYPE &", +"input":"<!DOCTYPE &", +"output":["ParseError", ["DOCTYPE", "&", null, null, false]]}, + +{"description":"<!DOCTYPE '", +"input":"<!DOCTYPE '", +"output":["ParseError", ["DOCTYPE", "'", null, null, false]]}, + +{"description":"<!DOCTYPE -", +"input":"<!DOCTYPE -", +"output":["ParseError", ["DOCTYPE", "-", null, null, false]]}, + +{"description":"<!DOCTYPE /", +"input":"<!DOCTYPE /", +"output":["ParseError", ["DOCTYPE", "/", null, null, false]]}, + +{"description":"<!DOCTYPE 0", +"input":"<!DOCTYPE 0", +"output":["ParseError", ["DOCTYPE", "0", null, null, false]]}, + +{"description":"<!DOCTYPE 1", +"input":"<!DOCTYPE 1", +"output":["ParseError", ["DOCTYPE", "1", null, null, false]]}, + +{"description":"<!DOCTYPE 9", +"input":"<!DOCTYPE 9", +"output":["ParseError", ["DOCTYPE", "9", null, null, false]]}, + +{"description":"<!DOCTYPE <", +"input":"<!DOCTYPE <", +"output":["ParseError", ["DOCTYPE", "<", null, null, false]]}, + +{"description":"<!DOCTYPE =", +"input":"<!DOCTYPE =", +"output":["ParseError", ["DOCTYPE", "=", null, null, false]]}, + +{"description":"<!DOCTYPE >", +"input":"<!DOCTYPE >", +"output":["ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE ?", +"input":"<!DOCTYPE ?", +"output":["ParseError", ["DOCTYPE", "?", null, null, false]]}, + +{"description":"<!DOCTYPE @", +"input":"<!DOCTYPE @", +"output":["ParseError", ["DOCTYPE", "@", null, null, false]]}, + +{"description":"<!DOCTYPE A", +"input":"<!DOCTYPE A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE B", +"input":"<!DOCTYPE B", +"output":["ParseError", ["DOCTYPE", "b", null, null, false]]}, + +{"description":"<!DOCTYPE Y", +"input":"<!DOCTYPE Y", +"output":["ParseError", ["DOCTYPE", "y", null, null, false]]}, + +{"description":"<!DOCTYPE Z", +"input":"<!DOCTYPE Z", +"output":["ParseError", ["DOCTYPE", "z", null, null, false]]}, + +{"description":"<!DOCTYPE [", +"input":"<!DOCTYPE [", +"output":["ParseError", ["DOCTYPE", "[", null, null, false]]}, + +{"description":"<!DOCTYPE `", +"input":"<!DOCTYPE `", +"output":["ParseError", ["DOCTYPE", "`", null, null, false]]}, + +{"description":"<!DOCTYPE a", +"input":"<!DOCTYPE a", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u0000", +"input":"<!DOCTYPE a\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\uFFFD", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u0008", +"input":"<!DOCTYPE a\u0008", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\u0008", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u0009", +"input":"<!DOCTYPE a\u0009", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u000A", +"input":"<!DOCTYPE a\u000A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u000B", +"input":"<!DOCTYPE a\u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\u000B", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u000C", +"input":"<!DOCTYPE a\u000C", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u000D", +"input":"<!DOCTYPE a\u000D", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a\\u001F", +"input":"<!DOCTYPE a\u001F", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\u001F", null, null, false]]}, + +{"description":"<!DOCTYPE a ", +"input":"<!DOCTYPE a ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u0000", +"input":"<!DOCTYPE a \u0000", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u0008", +"input":"<!DOCTYPE a \u0008", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u0009", +"input":"<!DOCTYPE a \u0009", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u000A", +"input":"<!DOCTYPE a \u000A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u000B", +"input":"<!DOCTYPE a \u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u000C", +"input":"<!DOCTYPE a \u000C", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u000D", +"input":"<!DOCTYPE a \u000D", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\u001F", +"input":"<!DOCTYPE a \u001F", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a ", +"input":"<!DOCTYPE a ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a !", +"input":"<!DOCTYPE a !", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \"", +"input":"<!DOCTYPE a \"", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a &", +"input":"<!DOCTYPE a &", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a '", +"input":"<!DOCTYPE a '", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a -", +"input":"<!DOCTYPE a -", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a /", +"input":"<!DOCTYPE a /", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a 0", +"input":"<!DOCTYPE a 0", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a 1", +"input":"<!DOCTYPE a 1", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a 9", +"input":"<!DOCTYPE a 9", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a <", +"input":"<!DOCTYPE a <", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a =", +"input":"<!DOCTYPE a =", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a >", +"input":"<!DOCTYPE a >", +"output":[["DOCTYPE", "a", null, null, true]]}, + +{"description":"<!DOCTYPE a ?", +"input":"<!DOCTYPE a ?", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a @", +"input":"<!DOCTYPE a @", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a A", +"input":"<!DOCTYPE a A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a B", +"input":"<!DOCTYPE a B", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC", +"input":"<!DOCTYPE a PUBLIC", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u0000", +"input":"<!DOCTYPE a PUBLIC\u0000", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u0008", +"input":"<!DOCTYPE a PUBLIC\u0008", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u0009", +"input":"<!DOCTYPE a PUBLIC\u0009", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u000A", +"input":"<!DOCTYPE a PUBLIC\u000A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u000B", +"input":"<!DOCTYPE a PUBLIC\u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u000C", +"input":"<!DOCTYPE a PUBLIC\u000C", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u000D", +"input":"<!DOCTYPE a PUBLIC\u000D", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\u001F", +"input":"<!DOCTYPE a PUBLIC\u001F", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC ", +"input":"<!DOCTYPE a PUBLIC ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC!", +"input":"<!DOCTYPE a PUBLIC!", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"", +"input":"<!DOCTYPE a PUBLIC\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\u0000", +"input":"<!DOCTYPE a PUBLIC\"\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\u0009", +"input":"<!DOCTYPE a PUBLIC\"\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\u000A", +"input":"<!DOCTYPE a PUBLIC\"\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\u000B", +"input":"<!DOCTYPE a PUBLIC\"\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\u000C", +"input":"<!DOCTYPE a PUBLIC\"\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\" ", +"input":"<!DOCTYPE a PUBLIC\" ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"!", +"input":"<!DOCTYPE a PUBLIC\"!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\"", +"input":"<!DOCTYPE a PUBLIC\"\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"#", +"input":"<!DOCTYPE a PUBLIC\"#", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"&", +"input":"<!DOCTYPE a PUBLIC\"&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"'", +"input":"<!DOCTYPE a PUBLIC\"'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"-", +"input":"<!DOCTYPE a PUBLIC\"-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"/", +"input":"<!DOCTYPE a PUBLIC\"/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"0", +"input":"<!DOCTYPE a PUBLIC\"0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"1", +"input":"<!DOCTYPE a PUBLIC\"1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"9", +"input":"<!DOCTYPE a PUBLIC\"9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"<", +"input":"<!DOCTYPE a PUBLIC\"<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"=", +"input":"<!DOCTYPE a PUBLIC\"=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\">", +"input":"<!DOCTYPE a PUBLIC\">", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"?", +"input":"<!DOCTYPE a PUBLIC\"?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"@", +"input":"<!DOCTYPE a PUBLIC\"@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"A", +"input":"<!DOCTYPE a PUBLIC\"A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"B", +"input":"<!DOCTYPE a PUBLIC\"B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"Y", +"input":"<!DOCTYPE a PUBLIC\"Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"Z", +"input":"<!DOCTYPE a PUBLIC\"Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"`", +"input":"<!DOCTYPE a PUBLIC\"`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"a", +"input":"<!DOCTYPE a PUBLIC\"a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"b", +"input":"<!DOCTYPE a PUBLIC\"b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"y", +"input":"<!DOCTYPE a PUBLIC\"y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"z", +"input":"<!DOCTYPE a PUBLIC\"z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"{", +"input":"<!DOCTYPE a PUBLIC\"{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\"\\uDBC0\\uDC00", +"input":"<!DOCTYPE a PUBLIC\"\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC#", +"input":"<!DOCTYPE a PUBLIC#", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC&", +"input":"<!DOCTYPE a PUBLIC&", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'", +"input":"<!DOCTYPE a PUBLIC'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\u0000", +"input":"<!DOCTYPE a PUBLIC'\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\u0009", +"input":"<!DOCTYPE a PUBLIC'\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\u000A", +"input":"<!DOCTYPE a PUBLIC'\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\u000B", +"input":"<!DOCTYPE a PUBLIC'\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\u000C", +"input":"<!DOCTYPE a PUBLIC'\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC' ", +"input":"<!DOCTYPE a PUBLIC' ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'!", +"input":"<!DOCTYPE a PUBLIC'!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\"", +"input":"<!DOCTYPE a PUBLIC'\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'&", +"input":"<!DOCTYPE a PUBLIC'&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''", +"input":"<!DOCTYPE a PUBLIC''", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u0000", +"input":"<!DOCTYPE a PUBLIC''\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u0008", +"input":"<!DOCTYPE a PUBLIC''\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u0009", +"input":"<!DOCTYPE a PUBLIC''\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u000A", +"input":"<!DOCTYPE a PUBLIC''\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u000B", +"input":"<!DOCTYPE a PUBLIC''\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u000C", +"input":"<!DOCTYPE a PUBLIC''\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u000D", +"input":"<!DOCTYPE a PUBLIC''\u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\u001F", +"input":"<!DOCTYPE a PUBLIC''\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'' ", +"input":"<!DOCTYPE a PUBLIC'' ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''!", +"input":"<!DOCTYPE a PUBLIC''!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\"", +"input":"<!DOCTYPE a PUBLIC''\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]}, + +{"description":"<!DOCTYPE a PUBLIC''#", +"input":"<!DOCTYPE a PUBLIC''#", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''&", +"input":"<!DOCTYPE a PUBLIC''&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'''", +"input":"<!DOCTYPE a PUBLIC'''", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]}, + +{"description":"<!DOCTYPE a PUBLIC''(", +"input":"<!DOCTYPE a PUBLIC''(", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''-", +"input":"<!DOCTYPE a PUBLIC''-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''/", +"input":"<!DOCTYPE a PUBLIC''/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''0", +"input":"<!DOCTYPE a PUBLIC''0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''1", +"input":"<!DOCTYPE a PUBLIC''1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''9", +"input":"<!DOCTYPE a PUBLIC''9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''<", +"input":"<!DOCTYPE a PUBLIC''<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''=", +"input":"<!DOCTYPE a PUBLIC''=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''>", +"input":"<!DOCTYPE a PUBLIC''>", +"output":["ParseError", ["DOCTYPE", "a", "", null, true]]}, + +{"description":"<!DOCTYPE a PUBLIC''?", +"input":"<!DOCTYPE a PUBLIC''?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''@", +"input":"<!DOCTYPE a PUBLIC''@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''A", +"input":"<!DOCTYPE a PUBLIC''A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''B", +"input":"<!DOCTYPE a PUBLIC''B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''Y", +"input":"<!DOCTYPE a PUBLIC''Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''Z", +"input":"<!DOCTYPE a PUBLIC''Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''`", +"input":"<!DOCTYPE a PUBLIC''`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''a", +"input":"<!DOCTYPE a PUBLIC''a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''b", +"input":"<!DOCTYPE a PUBLIC''b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''y", +"input":"<!DOCTYPE a PUBLIC''y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''z", +"input":"<!DOCTYPE a PUBLIC''z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''{", +"input":"<!DOCTYPE a PUBLIC''{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC''\\uDBC0\\uDC00", +"input":"<!DOCTYPE a PUBLIC''\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'(", +"input":"<!DOCTYPE a PUBLIC'(", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'-", +"input":"<!DOCTYPE a PUBLIC'-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'/", +"input":"<!DOCTYPE a PUBLIC'/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'0", +"input":"<!DOCTYPE a PUBLIC'0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'1", +"input":"<!DOCTYPE a PUBLIC'1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'9", +"input":"<!DOCTYPE a PUBLIC'9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'<", +"input":"<!DOCTYPE a PUBLIC'<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'=", +"input":"<!DOCTYPE a PUBLIC'=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'>", +"input":"<!DOCTYPE a PUBLIC'>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'?", +"input":"<!DOCTYPE a PUBLIC'?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'@", +"input":"<!DOCTYPE a PUBLIC'@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'A", +"input":"<!DOCTYPE a PUBLIC'A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'B", +"input":"<!DOCTYPE a PUBLIC'B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'Y", +"input":"<!DOCTYPE a PUBLIC'Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'Z", +"input":"<!DOCTYPE a PUBLIC'Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'`", +"input":"<!DOCTYPE a PUBLIC'`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'a", +"input":"<!DOCTYPE a PUBLIC'a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'b", +"input":"<!DOCTYPE a PUBLIC'b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'y", +"input":"<!DOCTYPE a PUBLIC'y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'z", +"input":"<!DOCTYPE a PUBLIC'z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'{", +"input":"<!DOCTYPE a PUBLIC'{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC'\\uDBC0\\uDC00", +"input":"<!DOCTYPE a PUBLIC'\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC(", +"input":"<!DOCTYPE a PUBLIC(", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC-", +"input":"<!DOCTYPE a PUBLIC-", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC/", +"input":"<!DOCTYPE a PUBLIC/", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC0", +"input":"<!DOCTYPE a PUBLIC0", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC1", +"input":"<!DOCTYPE a PUBLIC1", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC9", +"input":"<!DOCTYPE a PUBLIC9", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC<", +"input":"<!DOCTYPE a PUBLIC<", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC=", +"input":"<!DOCTYPE a PUBLIC=", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC>", +"input":"<!DOCTYPE a PUBLIC>", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC?", +"input":"<!DOCTYPE a PUBLIC?", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC@", +"input":"<!DOCTYPE a PUBLIC@", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICA", +"input":"<!DOCTYPE a PUBLICA", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICB", +"input":"<!DOCTYPE a PUBLICB", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICY", +"input":"<!DOCTYPE a PUBLICY", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICZ", +"input":"<!DOCTYPE a PUBLICZ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC`", +"input":"<!DOCTYPE a PUBLIC`", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICa", +"input":"<!DOCTYPE a PUBLICa", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICb", +"input":"<!DOCTYPE a PUBLICb", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICy", +"input":"<!DOCTYPE a PUBLICy", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLICz", +"input":"<!DOCTYPE a PUBLICz", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC{", +"input":"<!DOCTYPE a PUBLIC{", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a PUBLIC\\uDBC0\\uDC00", +"input":"<!DOCTYPE a PUBLIC\uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM", +"input":"<!DOCTYPE a SYSTEM", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u0000", +"input":"<!DOCTYPE a SYSTEM\u0000", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u0008", +"input":"<!DOCTYPE a SYSTEM\u0008", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u0009", +"input":"<!DOCTYPE a SYSTEM\u0009", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u000A", +"input":"<!DOCTYPE a SYSTEM\u000A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u000B", +"input":"<!DOCTYPE a SYSTEM\u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u000C", +"input":"<!DOCTYPE a SYSTEM\u000C", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u000D", +"input":"<!DOCTYPE a SYSTEM\u000D", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\u001F", +"input":"<!DOCTYPE a SYSTEM\u001F", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM ", +"input":"<!DOCTYPE a SYSTEM ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM!", +"input":"<!DOCTYPE a SYSTEM!", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"", +"input":"<!DOCTYPE a SYSTEM\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\u0000", +"input":"<!DOCTYPE a SYSTEM\"\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\u0009", +"input":"<!DOCTYPE a SYSTEM\"\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\u000A", +"input":"<!DOCTYPE a SYSTEM\"\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\u000B", +"input":"<!DOCTYPE a SYSTEM\"\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\u000C", +"input":"<!DOCTYPE a SYSTEM\"\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\" ", +"input":"<!DOCTYPE a SYSTEM\" ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"!", +"input":"<!DOCTYPE a SYSTEM\"!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\"", +"input":"<!DOCTYPE a SYSTEM\"\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"#", +"input":"<!DOCTYPE a SYSTEM\"#", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"&", +"input":"<!DOCTYPE a SYSTEM\"&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"'", +"input":"<!DOCTYPE a SYSTEM\"'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"-", +"input":"<!DOCTYPE a SYSTEM\"-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"/", +"input":"<!DOCTYPE a SYSTEM\"/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"0", +"input":"<!DOCTYPE a SYSTEM\"0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"1", +"input":"<!DOCTYPE a SYSTEM\"1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"9", +"input":"<!DOCTYPE a SYSTEM\"9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"<", +"input":"<!DOCTYPE a SYSTEM\"<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"=", +"input":"<!DOCTYPE a SYSTEM\"=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\">", +"input":"<!DOCTYPE a SYSTEM\">", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"?", +"input":"<!DOCTYPE a SYSTEM\"?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"@", +"input":"<!DOCTYPE a SYSTEM\"@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"A", +"input":"<!DOCTYPE a SYSTEM\"A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"B", +"input":"<!DOCTYPE a SYSTEM\"B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"Y", +"input":"<!DOCTYPE a SYSTEM\"Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"Z", +"input":"<!DOCTYPE a SYSTEM\"Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"`", +"input":"<!DOCTYPE a SYSTEM\"`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"a", +"input":"<!DOCTYPE a SYSTEM\"a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"b", +"input":"<!DOCTYPE a SYSTEM\"b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"y", +"input":"<!DOCTYPE a SYSTEM\"y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"z", +"input":"<!DOCTYPE a SYSTEM\"z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"{", +"input":"<!DOCTYPE a SYSTEM\"{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]}, + +{"description":"<!DOCTYPE a SYSTEM\"\\uDBC0\\uDC00", +"input":"<!DOCTYPE a SYSTEM\"\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]}, + +{"description":"<!DOCTYPE a SYSTEM#", +"input":"<!DOCTYPE a SYSTEM#", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM&", +"input":"<!DOCTYPE a SYSTEM&", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM'", +"input":"<!DOCTYPE a SYSTEM'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\u0000", +"input":"<!DOCTYPE a SYSTEM'\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\u0009", +"input":"<!DOCTYPE a SYSTEM'\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\u000A", +"input":"<!DOCTYPE a SYSTEM'\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\u000B", +"input":"<!DOCTYPE a SYSTEM'\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\u000C", +"input":"<!DOCTYPE a SYSTEM'\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]}, + +{"description":"<!DOCTYPE a SYSTEM' ", +"input":"<!DOCTYPE a SYSTEM' ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'!", +"input":"<!DOCTYPE a SYSTEM'!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\"", +"input":"<!DOCTYPE a SYSTEM'\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'&", +"input":"<!DOCTYPE a SYSTEM'&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''", +"input":"<!DOCTYPE a SYSTEM''", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u0000", +"input":"<!DOCTYPE a SYSTEM''\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u0008", +"input":"<!DOCTYPE a SYSTEM''\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u0009", +"input":"<!DOCTYPE a SYSTEM''\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u000A", +"input":"<!DOCTYPE a SYSTEM''\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u000B", +"input":"<!DOCTYPE a SYSTEM''\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u000C", +"input":"<!DOCTYPE a SYSTEM''\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u000D", +"input":"<!DOCTYPE a SYSTEM''\u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\u001F", +"input":"<!DOCTYPE a SYSTEM''\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM'' ", +"input":"<!DOCTYPE a SYSTEM'' ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM''!", +"input":"<!DOCTYPE a SYSTEM''!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''\"", +"input":"<!DOCTYPE a SYSTEM''\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''&", +"input":"<!DOCTYPE a SYSTEM''&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM'''", +"input":"<!DOCTYPE a SYSTEM'''", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''-", +"input":"<!DOCTYPE a SYSTEM''-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''/", +"input":"<!DOCTYPE a SYSTEM''/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''0", +"input":"<!DOCTYPE a SYSTEM''0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''1", +"input":"<!DOCTYPE a SYSTEM''1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''9", +"input":"<!DOCTYPE a SYSTEM''9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''<", +"input":"<!DOCTYPE a SYSTEM''<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''=", +"input":"<!DOCTYPE a SYSTEM''=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''>", +"input":"<!DOCTYPE a SYSTEM''>", +"output":["ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''?", +"input":"<!DOCTYPE a SYSTEM''?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''@", +"input":"<!DOCTYPE a SYSTEM''@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''A", +"input":"<!DOCTYPE a SYSTEM''A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''B", +"input":"<!DOCTYPE a SYSTEM''B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''Y", +"input":"<!DOCTYPE a SYSTEM''Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''Z", +"input":"<!DOCTYPE a SYSTEM''Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''`", +"input":"<!DOCTYPE a SYSTEM''`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''a", +"input":"<!DOCTYPE a SYSTEM''a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''b", +"input":"<!DOCTYPE a SYSTEM''b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''y", +"input":"<!DOCTYPE a SYSTEM''y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''z", +"input":"<!DOCTYPE a SYSTEM''z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''{", +"input":"<!DOCTYPE a SYSTEM''{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM''\\uDBC0\\uDC00", +"input":"<!DOCTYPE a SYSTEM''\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPE a SYSTEM'(", +"input":"<!DOCTYPE a SYSTEM'(", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'-", +"input":"<!DOCTYPE a SYSTEM'-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'/", +"input":"<!DOCTYPE a SYSTEM'/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'0", +"input":"<!DOCTYPE a SYSTEM'0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'1", +"input":"<!DOCTYPE a SYSTEM'1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'9", +"input":"<!DOCTYPE a SYSTEM'9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'<", +"input":"<!DOCTYPE a SYSTEM'<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'=", +"input":"<!DOCTYPE a SYSTEM'=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'>", +"input":"<!DOCTYPE a SYSTEM'>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'?", +"input":"<!DOCTYPE a SYSTEM'?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'@", +"input":"<!DOCTYPE a SYSTEM'@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'A", +"input":"<!DOCTYPE a SYSTEM'A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'B", +"input":"<!DOCTYPE a SYSTEM'B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'Y", +"input":"<!DOCTYPE a SYSTEM'Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'Z", +"input":"<!DOCTYPE a SYSTEM'Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'`", +"input":"<!DOCTYPE a SYSTEM'`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'a", +"input":"<!DOCTYPE a SYSTEM'a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'b", +"input":"<!DOCTYPE a SYSTEM'b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'y", +"input":"<!DOCTYPE a SYSTEM'y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'z", +"input":"<!DOCTYPE a SYSTEM'z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'{", +"input":"<!DOCTYPE a SYSTEM'{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]}, + +{"description":"<!DOCTYPE a SYSTEM'\\uDBC0\\uDC00", +"input":"<!DOCTYPE a SYSTEM'\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]}, + +{"description":"<!DOCTYPE a SYSTEM(", +"input":"<!DOCTYPE a SYSTEM(", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM-", +"input":"<!DOCTYPE a SYSTEM-", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM/", +"input":"<!DOCTYPE a SYSTEM/", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM0", +"input":"<!DOCTYPE a SYSTEM0", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM1", +"input":"<!DOCTYPE a SYSTEM1", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM9", +"input":"<!DOCTYPE a SYSTEM9", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM<", +"input":"<!DOCTYPE a SYSTEM<", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM=", +"input":"<!DOCTYPE a SYSTEM=", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM>", +"input":"<!DOCTYPE a SYSTEM>", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM?", +"input":"<!DOCTYPE a SYSTEM?", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM@", +"input":"<!DOCTYPE a SYSTEM@", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMA", +"input":"<!DOCTYPE a SYSTEMA", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMB", +"input":"<!DOCTYPE a SYSTEMB", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMY", +"input":"<!DOCTYPE a SYSTEMY", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMZ", +"input":"<!DOCTYPE a SYSTEMZ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM`", +"input":"<!DOCTYPE a SYSTEM`", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMa", +"input":"<!DOCTYPE a SYSTEMa", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMb", +"input":"<!DOCTYPE a SYSTEMb", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMy", +"input":"<!DOCTYPE a SYSTEMy", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEMz", +"input":"<!DOCTYPE a SYSTEMz", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM{", +"input":"<!DOCTYPE a SYSTEM{", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a SYSTEM\\uDBC0\\uDC00", +"input":"<!DOCTYPE a SYSTEM\uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a Y", +"input":"<!DOCTYPE a Y", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a Z", +"input":"<!DOCTYPE a Z", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a `", +"input":"<!DOCTYPE a `", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a", +"input":"<!DOCTYPE a a", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\u0000", +"input":"<!DOCTYPE a a\u0000", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\u0009", +"input":"<!DOCTYPE a a\u0009", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\u000A", +"input":"<!DOCTYPE a a\u000A", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\u000B", +"input":"<!DOCTYPE a a\u000B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\u000C", +"input":"<!DOCTYPE a a\u000C", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a ", +"input":"<!DOCTYPE a a ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a!", +"input":"<!DOCTYPE a a!", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\"", +"input":"<!DOCTYPE a a\"", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a&", +"input":"<!DOCTYPE a a&", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a'", +"input":"<!DOCTYPE a a'", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a-", +"input":"<!DOCTYPE a a-", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a/", +"input":"<!DOCTYPE a a/", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a0", +"input":"<!DOCTYPE a a0", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a1", +"input":"<!DOCTYPE a a1", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a9", +"input":"<!DOCTYPE a a9", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a<", +"input":"<!DOCTYPE a a<", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a=", +"input":"<!DOCTYPE a a=", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a>", +"input":"<!DOCTYPE a a>", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a?", +"input":"<!DOCTYPE a a?", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a@", +"input":"<!DOCTYPE a a@", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a aA", +"input":"<!DOCTYPE a aA", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a aB", +"input":"<!DOCTYPE a aB", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a aY", +"input":"<!DOCTYPE a aY", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a aZ", +"input":"<!DOCTYPE a aZ", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a`", +"input":"<!DOCTYPE a a`", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a aa", +"input":"<!DOCTYPE a aa", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a ab", +"input":"<!DOCTYPE a ab", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a ay", +"input":"<!DOCTYPE a ay", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a az", +"input":"<!DOCTYPE a az", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a{", +"input":"<!DOCTYPE a a{", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a a\\uDBC0\\uDC00", +"input":"<!DOCTYPE a a\uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a b", +"input":"<!DOCTYPE a b", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a y", +"input":"<!DOCTYPE a y", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a z", +"input":"<!DOCTYPE a z", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a {", +"input":"<!DOCTYPE a {", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a \\uDBC0\\uDC00", +"input":"<!DOCTYPE a \uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPE a!", +"input":"<!DOCTYPE a!", +"output":["ParseError", ["DOCTYPE", "a!", null, null, false]]}, + +{"description":"<!DOCTYPE a\"", +"input":"<!DOCTYPE a\"", +"output":["ParseError", ["DOCTYPE", "a\"", null, null, false]]}, + +{"description":"<!DOCTYPE a&", +"input":"<!DOCTYPE a&", +"output":["ParseError", ["DOCTYPE", "a&", null, null, false]]}, + +{"description":"<!DOCTYPE a'", +"input":"<!DOCTYPE a'", +"output":["ParseError", ["DOCTYPE", "a'", null, null, false]]}, + +{"description":"<!DOCTYPE a-", +"input":"<!DOCTYPE a-", +"output":["ParseError", ["DOCTYPE", "a-", null, null, false]]}, + +{"description":"<!DOCTYPE a/", +"input":"<!DOCTYPE a/", +"output":["ParseError", ["DOCTYPE", "a/", null, null, false]]}, + +{"description":"<!DOCTYPE a0", +"input":"<!DOCTYPE a0", +"output":["ParseError", ["DOCTYPE", "a0", null, null, false]]}, + +{"description":"<!DOCTYPE a1", +"input":"<!DOCTYPE a1", +"output":["ParseError", ["DOCTYPE", "a1", null, null, false]]}, + +{"description":"<!DOCTYPE a9", +"input":"<!DOCTYPE a9", +"output":["ParseError", ["DOCTYPE", "a9", null, null, false]]}, + +{"description":"<!DOCTYPE a<", +"input":"<!DOCTYPE a<", +"output":["ParseError", ["DOCTYPE", "a<", null, null, false]]}, + +{"description":"<!DOCTYPE a=", +"input":"<!DOCTYPE a=", +"output":["ParseError", ["DOCTYPE", "a=", null, null, false]]}, + +{"description":"<!DOCTYPE a>", +"input":"<!DOCTYPE a>", +"output":[["DOCTYPE", "a", null, null, true]]}, + +{"description":"<!DOCTYPE a?", +"input":"<!DOCTYPE a?", +"output":["ParseError", ["DOCTYPE", "a?", null, null, false]]}, + +{"description":"<!DOCTYPE a@", +"input":"<!DOCTYPE a@", +"output":["ParseError", ["DOCTYPE", "a@", null, null, false]]}, + +{"description":"<!DOCTYPE aA", +"input":"<!DOCTYPE aA", +"output":["ParseError", ["DOCTYPE", "aa", null, null, false]]}, + +{"description":"<!DOCTYPE aB", +"input":"<!DOCTYPE aB", +"output":["ParseError", ["DOCTYPE", "ab", null, null, false]]}, + +{"description":"<!DOCTYPE aY", +"input":"<!DOCTYPE aY", +"output":["ParseError", ["DOCTYPE", "ay", null, null, false]]}, + +{"description":"<!DOCTYPE aZ", +"input":"<!DOCTYPE aZ", +"output":["ParseError", ["DOCTYPE", "az", null, null, false]]}, + +{"description":"<!DOCTYPE a[", +"input":"<!DOCTYPE a[", +"output":["ParseError", ["DOCTYPE", "a[", null, null, false]]}, + +{"description":"<!DOCTYPE a`", +"input":"<!DOCTYPE a`", +"output":["ParseError", ["DOCTYPE", "a`", null, null, false]]}, + +{"description":"<!DOCTYPE aa", +"input":"<!DOCTYPE aa", +"output":["ParseError", ["DOCTYPE", "aa", null, null, false]]}, + +{"description":"<!DOCTYPE ab", +"input":"<!DOCTYPE ab", +"output":["ParseError", ["DOCTYPE", "ab", null, null, false]]}, + +{"description":"<!DOCTYPE ay", +"input":"<!DOCTYPE ay", +"output":["ParseError", ["DOCTYPE", "ay", null, null, false]]}, + +{"description":"<!DOCTYPE az", +"input":"<!DOCTYPE az", +"output":["ParseError", ["DOCTYPE", "az", null, null, false]]}, + +{"description":"<!DOCTYPE a{", +"input":"<!DOCTYPE a{", +"output":["ParseError", ["DOCTYPE", "a{", null, null, false]]}, + +{"description":"<!DOCTYPE a\\uDBC0\\uDC00", +"input":"<!DOCTYPE a\uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "a\uDBC0\uDC00", null, null, false]]}, + +{"description":"<!DOCTYPE b", +"input":"<!DOCTYPE b", +"output":["ParseError", ["DOCTYPE", "b", null, null, false]]}, + +{"description":"<!DOCTYPE y", +"input":"<!DOCTYPE y", +"output":["ParseError", ["DOCTYPE", "y", null, null, false]]}, + +{"description":"<!DOCTYPE z", +"input":"<!DOCTYPE z", +"output":["ParseError", ["DOCTYPE", "z", null, null, false]]}, + +{"description":"<!DOCTYPE {", +"input":"<!DOCTYPE {", +"output":["ParseError", ["DOCTYPE", "{", null, null, false]]}, + +{"description":"<!DOCTYPE \\uDBC0\\uDC00", +"input":"<!DOCTYPE \uDBC0\uDC00", +"output":["ParseError", ["DOCTYPE", "\uDBC0\uDC00", null, null, false]]}, + +{"description":"<!DOCTYPE!", +"input":"<!DOCTYPE!", +"output":["ParseError", "ParseError", ["DOCTYPE", "!", null, null, false]]}, + +{"description":"<!DOCTYPE\"", +"input":"<!DOCTYPE\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "\"", null, null, false]]}, + +{"description":"<!DOCTYPE&", +"input":"<!DOCTYPE&", +"output":["ParseError", "ParseError", ["DOCTYPE", "&", null, null, false]]}, + +{"description":"<!DOCTYPE'", +"input":"<!DOCTYPE'", +"output":["ParseError", "ParseError", ["DOCTYPE", "'", null, null, false]]}, + +{"description":"<!DOCTYPE-", +"input":"<!DOCTYPE-", +"output":["ParseError", "ParseError", ["DOCTYPE", "-", null, null, false]]}, + +{"description":"<!DOCTYPE/", +"input":"<!DOCTYPE/", +"output":["ParseError", "ParseError", ["DOCTYPE", "/", null, null, false]]}, + +{"description":"<!DOCTYPE0", +"input":"<!DOCTYPE0", +"output":["ParseError", "ParseError", ["DOCTYPE", "0", null, null, false]]}, + +{"description":"<!DOCTYPE1", +"input":"<!DOCTYPE1", +"output":["ParseError", "ParseError", ["DOCTYPE", "1", null, null, false]]}, + +{"description":"<!DOCTYPE9", +"input":"<!DOCTYPE9", +"output":["ParseError", "ParseError", ["DOCTYPE", "9", null, null, false]]}, + +{"description":"<!DOCTYPE<", +"input":"<!DOCTYPE<", +"output":["ParseError", "ParseError", ["DOCTYPE", "<", null, null, false]]}, + +{"description":"<!DOCTYPE=", +"input":"<!DOCTYPE=", +"output":["ParseError", "ParseError", ["DOCTYPE", "=", null, null, false]]}, + +{"description":"<!DOCTYPE>", +"input":"<!DOCTYPE>", +"output":["ParseError", "ParseError", ["DOCTYPE", "", null, null, false]]}, + +{"description":"<!DOCTYPE?", +"input":"<!DOCTYPE?", +"output":["ParseError", "ParseError", ["DOCTYPE", "?", null, null, false]]}, + +{"description":"<!DOCTYPE@", +"input":"<!DOCTYPE@", +"output":["ParseError", "ParseError", ["DOCTYPE", "@", null, null, false]]}, + +{"description":"<!DOCTYPEA", +"input":"<!DOCTYPEA", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEB", +"input":"<!DOCTYPEB", +"output":["ParseError", "ParseError", ["DOCTYPE", "b", null, null, false]]}, + +{"description":"<!DOCTYPEY", +"input":"<!DOCTYPEY", +"output":["ParseError", "ParseError", ["DOCTYPE", "y", null, null, false]]}, + +{"description":"<!DOCTYPEZ", +"input":"<!DOCTYPEZ", +"output":["ParseError", "ParseError", ["DOCTYPE", "z", null, null, false]]}, + +{"description":"<!DOCTYPE`", +"input":"<!DOCTYPE`", +"output":["ParseError", "ParseError", ["DOCTYPE", "`", null, null, false]]}, + +{"description":"<!DOCTYPEa", +"input":"<!DOCTYPEa", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u0000", +"input":"<!DOCTYPEa\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\uFFFD", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u0008", +"input":"<!DOCTYPEa\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u0008", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u0009", +"input":"<!DOCTYPEa\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u000A", +"input":"<!DOCTYPEa\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u000B", +"input":"<!DOCTYPEa\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u000B", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u000C", +"input":"<!DOCTYPEa\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u000D", +"input":"<!DOCTYPEa\u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa\\u001F", +"input":"<!DOCTYPEa\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a\u001F", null, null, false]]}, + +{"description":"<!DOCTYPEa ", +"input":"<!DOCTYPEa ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u0000", +"input":"<!DOCTYPEa \u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u0008", +"input":"<!DOCTYPEa \u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u0009", +"input":"<!DOCTYPEa \u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u000A", +"input":"<!DOCTYPEa \u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u000B", +"input":"<!DOCTYPEa \u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u000C", +"input":"<!DOCTYPEa \u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u000D", +"input":"<!DOCTYPEa \u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\u001F", +"input":"<!DOCTYPEa \u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa ", +"input":"<!DOCTYPEa ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa !", +"input":"<!DOCTYPEa !", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \"", +"input":"<!DOCTYPEa \"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa &", +"input":"<!DOCTYPEa &", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa '", +"input":"<!DOCTYPEa '", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa -", +"input":"<!DOCTYPEa -", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa /", +"input":"<!DOCTYPEa /", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa 0", +"input":"<!DOCTYPEa 0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa 1", +"input":"<!DOCTYPEa 1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa 9", +"input":"<!DOCTYPEa 9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa <", +"input":"<!DOCTYPEa <", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa =", +"input":"<!DOCTYPEa =", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa >", +"input":"<!DOCTYPEa >", +"output":["ParseError", ["DOCTYPE", "a", null, null, true]]}, + +{"description":"<!DOCTYPEa ?", +"input":"<!DOCTYPEa ?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa @", +"input":"<!DOCTYPEa @", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa A", +"input":"<!DOCTYPEa A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa B", +"input":"<!DOCTYPEa B", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC", +"input":"<!DOCTYPEa PUBLIC", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u0000", +"input":"<!DOCTYPEa PUBLIC\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u0008", +"input":"<!DOCTYPEa PUBLIC\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u0009", +"input":"<!DOCTYPEa PUBLIC\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u000A", +"input":"<!DOCTYPEa PUBLIC\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u000B", +"input":"<!DOCTYPEa PUBLIC\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u000C", +"input":"<!DOCTYPEa PUBLIC\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u000D", +"input":"<!DOCTYPEa PUBLIC\u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\u001F", +"input":"<!DOCTYPEa PUBLIC\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC ", +"input":"<!DOCTYPEa PUBLIC ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC!", +"input":"<!DOCTYPEa PUBLIC!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"", +"input":"<!DOCTYPEa PUBLIC\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\u0000", +"input":"<!DOCTYPEa PUBLIC\"\u0000", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\u0009", +"input":"<!DOCTYPEa PUBLIC\"\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\u000A", +"input":"<!DOCTYPEa PUBLIC\"\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\u000B", +"input":"<!DOCTYPEa PUBLIC\"\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\u000C", +"input":"<!DOCTYPEa PUBLIC\"\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\" ", +"input":"<!DOCTYPEa PUBLIC\" ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"!", +"input":"<!DOCTYPEa PUBLIC\"!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\"", +"input":"<!DOCTYPEa PUBLIC\"\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"#", +"input":"<!DOCTYPEa PUBLIC\"#", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "#", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"&", +"input":"<!DOCTYPEa PUBLIC\"&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"'", +"input":"<!DOCTYPEa PUBLIC\"'", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "'", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"-", +"input":"<!DOCTYPEa PUBLIC\"-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"/", +"input":"<!DOCTYPEa PUBLIC\"/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"0", +"input":"<!DOCTYPEa PUBLIC\"0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"1", +"input":"<!DOCTYPEa PUBLIC\"1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"9", +"input":"<!DOCTYPEa PUBLIC\"9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"<", +"input":"<!DOCTYPEa PUBLIC\"<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"=", +"input":"<!DOCTYPEa PUBLIC\"=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\">", +"input":"<!DOCTYPEa PUBLIC\">", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"?", +"input":"<!DOCTYPEa PUBLIC\"?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"@", +"input":"<!DOCTYPEa PUBLIC\"@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"A", +"input":"<!DOCTYPEa PUBLIC\"A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"B", +"input":"<!DOCTYPEa PUBLIC\"B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"Y", +"input":"<!DOCTYPEa PUBLIC\"Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"Z", +"input":"<!DOCTYPEa PUBLIC\"Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"`", +"input":"<!DOCTYPEa PUBLIC\"`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"a", +"input":"<!DOCTYPEa PUBLIC\"a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"b", +"input":"<!DOCTYPEa PUBLIC\"b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"y", +"input":"<!DOCTYPEa PUBLIC\"y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"z", +"input":"<!DOCTYPEa PUBLIC\"z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"{", +"input":"<!DOCTYPEa PUBLIC\"{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\"\\uDBC0\\uDC00", +"input":"<!DOCTYPEa PUBLIC\"\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC#", +"input":"<!DOCTYPEa PUBLIC#", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC&", +"input":"<!DOCTYPEa PUBLIC&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'", +"input":"<!DOCTYPEa PUBLIC'", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\u0000", +"input":"<!DOCTYPEa PUBLIC'\u0000", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uFFFD", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\u0009", +"input":"<!DOCTYPEa PUBLIC'\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u0009", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\u000A", +"input":"<!DOCTYPEa PUBLIC'\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000A", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\u000B", +"input":"<!DOCTYPEa PUBLIC'\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000B", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\u000C", +"input":"<!DOCTYPEa PUBLIC'\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\u000C", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC' ", +"input":"<!DOCTYPEa PUBLIC' ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", " ", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'!", +"input":"<!DOCTYPEa PUBLIC'!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "!", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\"", +"input":"<!DOCTYPEa PUBLIC'\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\"", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'&", +"input":"<!DOCTYPEa PUBLIC'&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "&", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''", +"input":"<!DOCTYPEa PUBLIC''", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u0000", +"input":"<!DOCTYPEa PUBLIC''\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u0008", +"input":"<!DOCTYPEa PUBLIC''\u0008", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u0009", +"input":"<!DOCTYPEa PUBLIC''\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u000A", +"input":"<!DOCTYPEa PUBLIC''\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u000B", +"input":"<!DOCTYPEa PUBLIC''\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u000C", +"input":"<!DOCTYPEa PUBLIC''\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u000D", +"input":"<!DOCTYPEa PUBLIC''\u000D", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\u001F", +"input":"<!DOCTYPEa PUBLIC''\u001F", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'' ", +"input":"<!DOCTYPEa PUBLIC'' ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''!", +"input":"<!DOCTYPEa PUBLIC''!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\"", +"input":"<!DOCTYPEa PUBLIC''\"", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]}, + +{"description":"<!DOCTYPEa PUBLIC''#", +"input":"<!DOCTYPEa PUBLIC''#", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''&", +"input":"<!DOCTYPEa PUBLIC''&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'''", +"input":"<!DOCTYPEa PUBLIC'''", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", "", false]]}, + +{"description":"<!DOCTYPEa PUBLIC''(", +"input":"<!DOCTYPEa PUBLIC''(", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''-", +"input":"<!DOCTYPEa PUBLIC''-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''/", +"input":"<!DOCTYPEa PUBLIC''/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''0", +"input":"<!DOCTYPEa PUBLIC''0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''1", +"input":"<!DOCTYPEa PUBLIC''1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''9", +"input":"<!DOCTYPEa PUBLIC''9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''<", +"input":"<!DOCTYPEa PUBLIC''<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''=", +"input":"<!DOCTYPEa PUBLIC''=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''>", +"input":"<!DOCTYPEa PUBLIC''>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", "", null, true]]}, + +{"description":"<!DOCTYPEa PUBLIC''?", +"input":"<!DOCTYPEa PUBLIC''?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''@", +"input":"<!DOCTYPEa PUBLIC''@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''A", +"input":"<!DOCTYPEa PUBLIC''A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''B", +"input":"<!DOCTYPEa PUBLIC''B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''Y", +"input":"<!DOCTYPEa PUBLIC''Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''Z", +"input":"<!DOCTYPEa PUBLIC''Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''`", +"input":"<!DOCTYPEa PUBLIC''`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''a", +"input":"<!DOCTYPEa PUBLIC''a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''b", +"input":"<!DOCTYPEa PUBLIC''b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''y", +"input":"<!DOCTYPEa PUBLIC''y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''z", +"input":"<!DOCTYPEa PUBLIC''z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''{", +"input":"<!DOCTYPEa PUBLIC''{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC''\\uDBC0\\uDC00", +"input":"<!DOCTYPEa PUBLIC''\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'(", +"input":"<!DOCTYPEa PUBLIC'(", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "(", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'-", +"input":"<!DOCTYPEa PUBLIC'-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "-", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'/", +"input":"<!DOCTYPEa PUBLIC'/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "/", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'0", +"input":"<!DOCTYPEa PUBLIC'0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "0", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'1", +"input":"<!DOCTYPEa PUBLIC'1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "1", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'9", +"input":"<!DOCTYPEa PUBLIC'9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "9", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'<", +"input":"<!DOCTYPEa PUBLIC'<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "<", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'=", +"input":"<!DOCTYPEa PUBLIC'=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "=", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'>", +"input":"<!DOCTYPEa PUBLIC'>", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'?", +"input":"<!DOCTYPEa PUBLIC'?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "?", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'@", +"input":"<!DOCTYPEa PUBLIC'@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "@", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'A", +"input":"<!DOCTYPEa PUBLIC'A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "A", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'B", +"input":"<!DOCTYPEa PUBLIC'B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "B", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'Y", +"input":"<!DOCTYPEa PUBLIC'Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Y", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'Z", +"input":"<!DOCTYPEa PUBLIC'Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "Z", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'`", +"input":"<!DOCTYPEa PUBLIC'`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "`", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'a", +"input":"<!DOCTYPEa PUBLIC'a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "a", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'b", +"input":"<!DOCTYPEa PUBLIC'b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "b", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'y", +"input":"<!DOCTYPEa PUBLIC'y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "y", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'z", +"input":"<!DOCTYPEa PUBLIC'z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "z", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'{", +"input":"<!DOCTYPEa PUBLIC'{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "{", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC'\\uDBC0\\uDC00", +"input":"<!DOCTYPEa PUBLIC'\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", "\uDBC0\uDC00", null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC(", +"input":"<!DOCTYPEa PUBLIC(", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC-", +"input":"<!DOCTYPEa PUBLIC-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC/", +"input":"<!DOCTYPEa PUBLIC/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC0", +"input":"<!DOCTYPEa PUBLIC0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC1", +"input":"<!DOCTYPEa PUBLIC1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC9", +"input":"<!DOCTYPEa PUBLIC9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC<", +"input":"<!DOCTYPEa PUBLIC<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC=", +"input":"<!DOCTYPEa PUBLIC=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC>", +"input":"<!DOCTYPEa PUBLIC>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC?", +"input":"<!DOCTYPEa PUBLIC?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC@", +"input":"<!DOCTYPEa PUBLIC@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICA", +"input":"<!DOCTYPEa PUBLICA", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICB", +"input":"<!DOCTYPEa PUBLICB", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICY", +"input":"<!DOCTYPEa PUBLICY", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICZ", +"input":"<!DOCTYPEa PUBLICZ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC`", +"input":"<!DOCTYPEa PUBLIC`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICa", +"input":"<!DOCTYPEa PUBLICa", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICb", +"input":"<!DOCTYPEa PUBLICb", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICy", +"input":"<!DOCTYPEa PUBLICy", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLICz", +"input":"<!DOCTYPEa PUBLICz", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC{", +"input":"<!DOCTYPEa PUBLIC{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa PUBLIC\\uDBC0\\uDC00", +"input":"<!DOCTYPEa PUBLIC\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM", +"input":"<!DOCTYPEa SYSTEM", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u0000", +"input":"<!DOCTYPEa SYSTEM\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u0008", +"input":"<!DOCTYPEa SYSTEM\u0008", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u0009", +"input":"<!DOCTYPEa SYSTEM\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u000A", +"input":"<!DOCTYPEa SYSTEM\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u000B", +"input":"<!DOCTYPEa SYSTEM\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u000C", +"input":"<!DOCTYPEa SYSTEM\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u000D", +"input":"<!DOCTYPEa SYSTEM\u000D", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\u001F", +"input":"<!DOCTYPEa SYSTEM\u001F", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM ", +"input":"<!DOCTYPEa SYSTEM ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM!", +"input":"<!DOCTYPEa SYSTEM!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"", +"input":"<!DOCTYPEa SYSTEM\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\u0000", +"input":"<!DOCTYPEa SYSTEM\"\u0000", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\u0009", +"input":"<!DOCTYPEa SYSTEM\"\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\u000A", +"input":"<!DOCTYPEa SYSTEM\"\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\u000B", +"input":"<!DOCTYPEa SYSTEM\"\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\u000C", +"input":"<!DOCTYPEa SYSTEM\"\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\" ", +"input":"<!DOCTYPEa SYSTEM\" ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"!", +"input":"<!DOCTYPEa SYSTEM\"!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\"", +"input":"<!DOCTYPEa SYSTEM\"\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"#", +"input":"<!DOCTYPEa SYSTEM\"#", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "#", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"&", +"input":"<!DOCTYPEa SYSTEM\"&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"'", +"input":"<!DOCTYPEa SYSTEM\"'", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "'", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"-", +"input":"<!DOCTYPEa SYSTEM\"-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"/", +"input":"<!DOCTYPEa SYSTEM\"/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"0", +"input":"<!DOCTYPEa SYSTEM\"0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"1", +"input":"<!DOCTYPEa SYSTEM\"1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"9", +"input":"<!DOCTYPEa SYSTEM\"9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"<", +"input":"<!DOCTYPEa SYSTEM\"<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"=", +"input":"<!DOCTYPEa SYSTEM\"=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\">", +"input":"<!DOCTYPEa SYSTEM\">", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"?", +"input":"<!DOCTYPEa SYSTEM\"?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"@", +"input":"<!DOCTYPEa SYSTEM\"@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"A", +"input":"<!DOCTYPEa SYSTEM\"A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"B", +"input":"<!DOCTYPEa SYSTEM\"B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"Y", +"input":"<!DOCTYPEa SYSTEM\"Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"Z", +"input":"<!DOCTYPEa SYSTEM\"Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"`", +"input":"<!DOCTYPEa SYSTEM\"`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"a", +"input":"<!DOCTYPEa SYSTEM\"a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"b", +"input":"<!DOCTYPEa SYSTEM\"b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"y", +"input":"<!DOCTYPEa SYSTEM\"y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"z", +"input":"<!DOCTYPEa SYSTEM\"z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"{", +"input":"<!DOCTYPEa SYSTEM\"{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]}, + +{"description":"<!DOCTYPEa SYSTEM\"\\uDBC0\\uDC00", +"input":"<!DOCTYPEa SYSTEM\"\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]}, + +{"description":"<!DOCTYPEa SYSTEM#", +"input":"<!DOCTYPEa SYSTEM#", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM&", +"input":"<!DOCTYPEa SYSTEM&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM'", +"input":"<!DOCTYPEa SYSTEM'", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\u0000", +"input":"<!DOCTYPEa SYSTEM'\u0000", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uFFFD", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\u0009", +"input":"<!DOCTYPEa SYSTEM'\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u0009", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\u000A", +"input":"<!DOCTYPEa SYSTEM'\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000A", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\u000B", +"input":"<!DOCTYPEa SYSTEM'\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000B", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\u000C", +"input":"<!DOCTYPEa SYSTEM'\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\u000C", false]]}, + +{"description":"<!DOCTYPEa SYSTEM' ", +"input":"<!DOCTYPEa SYSTEM' ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, " ", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'!", +"input":"<!DOCTYPEa SYSTEM'!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "!", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\"", +"input":"<!DOCTYPEa SYSTEM'\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\"", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'&", +"input":"<!DOCTYPEa SYSTEM'&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "&", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''", +"input":"<!DOCTYPEa SYSTEM''", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u0000", +"input":"<!DOCTYPEa SYSTEM''\u0000", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u0008", +"input":"<!DOCTYPEa SYSTEM''\u0008", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u0009", +"input":"<!DOCTYPEa SYSTEM''\u0009", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u000A", +"input":"<!DOCTYPEa SYSTEM''\u000A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u000B", +"input":"<!DOCTYPEa SYSTEM''\u000B", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u000C", +"input":"<!DOCTYPEa SYSTEM''\u000C", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u000D", +"input":"<!DOCTYPEa SYSTEM''\u000D", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\u001F", +"input":"<!DOCTYPEa SYSTEM''\u001F", +"output":["ParseError", "ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM'' ", +"input":"<!DOCTYPEa SYSTEM'' ", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM''!", +"input":"<!DOCTYPEa SYSTEM''!", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''\"", +"input":"<!DOCTYPEa SYSTEM''\"", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''&", +"input":"<!DOCTYPEa SYSTEM''&", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM'''", +"input":"<!DOCTYPEa SYSTEM'''", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''-", +"input":"<!DOCTYPEa SYSTEM''-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''/", +"input":"<!DOCTYPEa SYSTEM''/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''0", +"input":"<!DOCTYPEa SYSTEM''0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''1", +"input":"<!DOCTYPEa SYSTEM''1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''9", +"input":"<!DOCTYPEa SYSTEM''9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''<", +"input":"<!DOCTYPEa SYSTEM''<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''=", +"input":"<!DOCTYPEa SYSTEM''=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''>", +"input":"<!DOCTYPEa SYSTEM''>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''?", +"input":"<!DOCTYPEa SYSTEM''?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''@", +"input":"<!DOCTYPEa SYSTEM''@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''A", +"input":"<!DOCTYPEa SYSTEM''A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''B", +"input":"<!DOCTYPEa SYSTEM''B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''Y", +"input":"<!DOCTYPEa SYSTEM''Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''Z", +"input":"<!DOCTYPEa SYSTEM''Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''`", +"input":"<!DOCTYPEa SYSTEM''`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''a", +"input":"<!DOCTYPEa SYSTEM''a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''b", +"input":"<!DOCTYPEa SYSTEM''b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''y", +"input":"<!DOCTYPEa SYSTEM''y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''z", +"input":"<!DOCTYPEa SYSTEM''z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''{", +"input":"<!DOCTYPEa SYSTEM''{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM''\\uDBC0\\uDC00", +"input":"<!DOCTYPEa SYSTEM''\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", true]]}, + +{"description":"<!DOCTYPEa SYSTEM'(", +"input":"<!DOCTYPEa SYSTEM'(", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "(", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'-", +"input":"<!DOCTYPEa SYSTEM'-", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "-", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'/", +"input":"<!DOCTYPEa SYSTEM'/", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "/", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'0", +"input":"<!DOCTYPEa SYSTEM'0", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "0", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'1", +"input":"<!DOCTYPEa SYSTEM'1", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "1", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'9", +"input":"<!DOCTYPEa SYSTEM'9", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "9", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'<", +"input":"<!DOCTYPEa SYSTEM'<", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "<", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'=", +"input":"<!DOCTYPEa SYSTEM'=", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "=", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'>", +"input":"<!DOCTYPEa SYSTEM'>", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'?", +"input":"<!DOCTYPEa SYSTEM'?", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "?", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'@", +"input":"<!DOCTYPEa SYSTEM'@", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "@", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'A", +"input":"<!DOCTYPEa SYSTEM'A", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "A", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'B", +"input":"<!DOCTYPEa SYSTEM'B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "B", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'Y", +"input":"<!DOCTYPEa SYSTEM'Y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Y", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'Z", +"input":"<!DOCTYPEa SYSTEM'Z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "Z", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'`", +"input":"<!DOCTYPEa SYSTEM'`", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "`", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'a", +"input":"<!DOCTYPEa SYSTEM'a", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "a", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'b", +"input":"<!DOCTYPEa SYSTEM'b", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "b", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'y", +"input":"<!DOCTYPEa SYSTEM'y", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "y", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'z", +"input":"<!DOCTYPEa SYSTEM'z", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "z", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'{", +"input":"<!DOCTYPEa SYSTEM'{", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "{", false]]}, + +{"description":"<!DOCTYPEa SYSTEM'\\uDBC0\\uDC00", +"input":"<!DOCTYPEa SYSTEM'\uDBC0\uDC00", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, "\uDBC0\uDC00", false]]}, + +{"description":"<!DOCTYPEa SYSTEM(", +"input":"<!DOCTYPEa SYSTEM(", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM-", +"input":"<!DOCTYPEa SYSTEM-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM/", +"input":"<!DOCTYPEa SYSTEM/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM0", +"input":"<!DOCTYPEa SYSTEM0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM1", +"input":"<!DOCTYPEa SYSTEM1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM9", +"input":"<!DOCTYPEa SYSTEM9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM<", +"input":"<!DOCTYPEa SYSTEM<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM=", +"input":"<!DOCTYPEa SYSTEM=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM>", +"input":"<!DOCTYPEa SYSTEM>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM?", +"input":"<!DOCTYPEa SYSTEM?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM@", +"input":"<!DOCTYPEa SYSTEM@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMA", +"input":"<!DOCTYPEa SYSTEMA", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMB", +"input":"<!DOCTYPEa SYSTEMB", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMY", +"input":"<!DOCTYPEa SYSTEMY", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMZ", +"input":"<!DOCTYPEa SYSTEMZ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM`", +"input":"<!DOCTYPEa SYSTEM`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMa", +"input":"<!DOCTYPEa SYSTEMa", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMb", +"input":"<!DOCTYPEa SYSTEMb", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMy", +"input":"<!DOCTYPEa SYSTEMy", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEMz", +"input":"<!DOCTYPEa SYSTEMz", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM{", +"input":"<!DOCTYPEa SYSTEM{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa SYSTEM\\uDBC0\\uDC00", +"input":"<!DOCTYPEa SYSTEM\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa Y", +"input":"<!DOCTYPEa Y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa Z", +"input":"<!DOCTYPEa Z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa `", +"input":"<!DOCTYPEa `", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a", +"input":"<!DOCTYPEa a", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\u0000", +"input":"<!DOCTYPEa a\u0000", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\u0009", +"input":"<!DOCTYPEa a\u0009", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\u000A", +"input":"<!DOCTYPEa a\u000A", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\u000B", +"input":"<!DOCTYPEa a\u000B", +"output":["ParseError", "ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\u000C", +"input":"<!DOCTYPEa a\u000C", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a ", +"input":"<!DOCTYPEa a ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a!", +"input":"<!DOCTYPEa a!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\"", +"input":"<!DOCTYPEa a\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a&", +"input":"<!DOCTYPEa a&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a'", +"input":"<!DOCTYPEa a'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a-", +"input":"<!DOCTYPEa a-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a/", +"input":"<!DOCTYPEa a/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a0", +"input":"<!DOCTYPEa a0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a1", +"input":"<!DOCTYPEa a1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a9", +"input":"<!DOCTYPEa a9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a<", +"input":"<!DOCTYPEa a<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a=", +"input":"<!DOCTYPEa a=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a>", +"input":"<!DOCTYPEa a>", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a?", +"input":"<!DOCTYPEa a?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a@", +"input":"<!DOCTYPEa a@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa aA", +"input":"<!DOCTYPEa aA", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa aB", +"input":"<!DOCTYPEa aB", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa aY", +"input":"<!DOCTYPEa aY", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa aZ", +"input":"<!DOCTYPEa aZ", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a`", +"input":"<!DOCTYPEa a`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa aa", +"input":"<!DOCTYPEa aa", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa ab", +"input":"<!DOCTYPEa ab", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa ay", +"input":"<!DOCTYPEa ay", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa az", +"input":"<!DOCTYPEa az", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a{", +"input":"<!DOCTYPEa a{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa a\\uDBC0\\uDC00", +"input":"<!DOCTYPEa a\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa b", +"input":"<!DOCTYPEa b", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa y", +"input":"<!DOCTYPEa y", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa z", +"input":"<!DOCTYPEa z", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa {", +"input":"<!DOCTYPEa {", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa \\uDBC0\\uDC00", +"input":"<!DOCTYPEa \uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a", null, null, false]]}, + +{"description":"<!DOCTYPEa!", +"input":"<!DOCTYPEa!", +"output":["ParseError", "ParseError", ["DOCTYPE", "a!", null, null, false]]}, + +{"description":"<!DOCTYPEa\"", +"input":"<!DOCTYPEa\"", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\"", null, null, false]]}, + +{"description":"<!DOCTYPEa&", +"input":"<!DOCTYPEa&", +"output":["ParseError", "ParseError", ["DOCTYPE", "a&", null, null, false]]}, + +{"description":"<!DOCTYPEa'", +"input":"<!DOCTYPEa'", +"output":["ParseError", "ParseError", ["DOCTYPE", "a'", null, null, false]]}, + +{"description":"<!DOCTYPEa-", +"input":"<!DOCTYPEa-", +"output":["ParseError", "ParseError", ["DOCTYPE", "a-", null, null, false]]}, + +{"description":"<!DOCTYPEa/", +"input":"<!DOCTYPEa/", +"output":["ParseError", "ParseError", ["DOCTYPE", "a/", null, null, false]]}, + +{"description":"<!DOCTYPEa0", +"input":"<!DOCTYPEa0", +"output":["ParseError", "ParseError", ["DOCTYPE", "a0", null, null, false]]}, + +{"description":"<!DOCTYPEa1", +"input":"<!DOCTYPEa1", +"output":["ParseError", "ParseError", ["DOCTYPE", "a1", null, null, false]]}, + +{"description":"<!DOCTYPEa9", +"input":"<!DOCTYPEa9", +"output":["ParseError", "ParseError", ["DOCTYPE", "a9", null, null, false]]}, + +{"description":"<!DOCTYPEa<", +"input":"<!DOCTYPEa<", +"output":["ParseError", "ParseError", ["DOCTYPE", "a<", null, null, false]]}, + +{"description":"<!DOCTYPEa=", +"input":"<!DOCTYPEa=", +"output":["ParseError", "ParseError", ["DOCTYPE", "a=", null, null, false]]}, + +{"description":"<!DOCTYPEa>", +"input":"<!DOCTYPEa>", +"output":["ParseError", ["DOCTYPE", "a", null, null, true]]}, + +{"description":"<!DOCTYPEa?", +"input":"<!DOCTYPEa?", +"output":["ParseError", "ParseError", ["DOCTYPE", "a?", null, null, false]]}, + +{"description":"<!DOCTYPEa@", +"input":"<!DOCTYPEa@", +"output":["ParseError", "ParseError", ["DOCTYPE", "a@", null, null, false]]}, + +{"description":"<!DOCTYPEaA", +"input":"<!DOCTYPEaA", +"output":["ParseError", "ParseError", ["DOCTYPE", "aa", null, null, false]]}, + +{"description":"<!DOCTYPEaB", +"input":"<!DOCTYPEaB", +"output":["ParseError", "ParseError", ["DOCTYPE", "ab", null, null, false]]}, + +{"description":"<!DOCTYPEaY", +"input":"<!DOCTYPEaY", +"output":["ParseError", "ParseError", ["DOCTYPE", "ay", null, null, false]]}, + +{"description":"<!DOCTYPEaZ", +"input":"<!DOCTYPEaZ", +"output":["ParseError", "ParseError", ["DOCTYPE", "az", null, null, false]]}, + +{"description":"<!DOCTYPEa[", +"input":"<!DOCTYPEa[", +"output":["ParseError", "ParseError", ["DOCTYPE", "a[", null, null, false]]}, + +{"description":"<!DOCTYPEa`", +"input":"<!DOCTYPEa`", +"output":["ParseError", "ParseError", ["DOCTYPE", "a`", null, null, false]]}, + +{"description":"<!DOCTYPEaa", +"input":"<!DOCTYPEaa", +"output":["ParseError", "ParseError", ["DOCTYPE", "aa", null, null, false]]}, + +{"description":"<!DOCTYPEab", +"input":"<!DOCTYPEab", +"output":["ParseError", "ParseError", ["DOCTYPE", "ab", null, null, false]]}, + +{"description":"<!DOCTYPEay", +"input":"<!DOCTYPEay", +"output":["ParseError", "ParseError", ["DOCTYPE", "ay", null, null, false]]}, + +{"description":"<!DOCTYPEaz", +"input":"<!DOCTYPEaz", +"output":["ParseError", "ParseError", ["DOCTYPE", "az", null, null, false]]}, + +{"description":"<!DOCTYPEa{", +"input":"<!DOCTYPEa{", +"output":["ParseError", "ParseError", ["DOCTYPE", "a{", null, null, false]]}, + +{"description":"<!DOCTYPEa\\uDBC0\\uDC00", +"input":"<!DOCTYPEa\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "a\uDBC0\uDC00", null, null, false]]}, + +{"description":"<!DOCTYPEb", +"input":"<!DOCTYPEb", +"output":["ParseError", "ParseError", ["DOCTYPE", "b", null, null, false]]}, + +{"description":"<!DOCTYPEy", +"input":"<!DOCTYPEy", +"output":["ParseError", "ParseError", ["DOCTYPE", "y", null, null, false]]}, + +{"description":"<!DOCTYPEz", +"input":"<!DOCTYPEz", +"output":["ParseError", "ParseError", ["DOCTYPE", "z", null, null, false]]}, + +{"description":"<!DOCTYPE{", +"input":"<!DOCTYPE{", +"output":["ParseError", "ParseError", ["DOCTYPE", "{", null, null, false]]}, + +{"description":"<!DOCTYPE\\uDBC0\\uDC00", +"input":"<!DOCTYPE\uDBC0\uDC00", +"output":["ParseError", "ParseError", ["DOCTYPE", "\uDBC0\uDC00", null, null, false]]}, + +{"description":"<!Y", +"input":"<!Y", +"output":["ParseError", ["Comment", "Y"]]}, + +{"description":"<!Z", +"input":"<!Z", +"output":["ParseError", ["Comment", "Z"]]}, + +{"description":"<!`", +"input":"<!`", +"output":["ParseError", ["Comment", "`"]]}, + +{"description":"<!a", +"input":"<!a", +"output":["ParseError", ["Comment", "a"]]}, + +{"description":"<!b", +"input":"<!b", +"output":["ParseError", ["Comment", "b"]]}, + +{"description":"<!y", +"input":"<!y", +"output":["ParseError", ["Comment", "y"]]}, + +{"description":"<!z", +"input":"<!z", +"output":["ParseError", ["Comment", "z"]]}, + +{"description":"<!{", +"input":"<!{", +"output":["ParseError", ["Comment", "{"]]}, + +{"description":"<!\\uDBC0\\uDC00", +"input":"<!\uDBC0\uDC00", +"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]}, + +{"description":"<\"", +"input":"<\"", +"output":["ParseError", ["Character", "<\""]]}, + +{"description":"<&", +"input":"<&", +"output":["ParseError", ["Character", "<&"]]}, + +{"description":"<'", +"input":"<'", +"output":["ParseError", ["Character", "<'"]]}, + +{"description":"<-", +"input":"<-", +"output":["ParseError", ["Character", "<-"]]}, + +{"description":"<.", +"input":"<.", +"output":["ParseError", ["Character", "<."]]}, + +{"description":"</", +"input":"</", +"output":["ParseError", ["Character", "</"]]}, + +{"description":"</\\u0000", +"input":"</\u0000", +"output":["ParseError", ["Comment", "\uFFFD"]]}, + +{"description":"</\\u0009", +"input":"</\u0009", +"output":["ParseError", ["Comment", "\u0009"]]}, + +{"description":"</\\u000A", +"input":"</\u000A", +"output":["ParseError", ["Comment", "\u000A"]]}, + +{"description":"</\\u000B", +"input":"</\u000B", +"output":["ParseError", "ParseError", ["Comment", "\u000B"]]}, + +{"description":"</\\u000C", +"input":"</\u000C", +"output":["ParseError", ["Comment", "\u000C"]]}, + +{"description":"</ ", +"input":"</ ", +"output":["ParseError", ["Comment", " "]]}, + +{"description":"</!", +"input":"</!", +"output":["ParseError", ["Comment", "!"]]}, + +{"description":"</\"", +"input":"</\"", +"output":["ParseError", ["Comment", "\""]]}, + +{"description":"</&", +"input":"</&", +"output":["ParseError", ["Comment", "&"]]}, + +{"description":"</'", +"input":"</'", +"output":["ParseError", ["Comment", "'"]]}, + +{"description":"</-", +"input":"</-", +"output":["ParseError", ["Comment", "-"]]}, + +{"description":"<//", +"input":"<//", +"output":["ParseError", ["Comment", "/"]]}, + +{"description":"</0", +"input":"</0", +"output":["ParseError", ["Comment", "0"]]}, + +{"description":"</1", +"input":"</1", +"output":["ParseError", ["Comment", "1"]]}, + +{"description":"</9", +"input":"</9", +"output":["ParseError", ["Comment", "9"]]}, + +{"description":"</<", +"input":"</<", +"output":["ParseError", ["Comment", "<"]]}, + +{"description":"</=", +"input":"</=", +"output":["ParseError", ["Comment", "="]]}, + +{"description":"</>", +"input":"</>", +"output":["ParseError"]}, + +{"description":"</?", +"input":"</?", +"output":["ParseError", ["Comment", "?"]]}, + +{"description":"</@", +"input":"</@", +"output":["ParseError", ["Comment", "@"]]}, + +{"description":"</A>", +"input":"</A>", +"output":[["EndTag", "a"]]}, + +{"description":"</B>", +"input":"</B>", +"output":[["EndTag", "b"]]}, + +{"description":"</Y>", +"input":"</Y>", +"output":[["EndTag", "y"]]}, + +{"description":"</Z>", +"input":"</Z>", +"output":[["EndTag", "z"]]}, + +{"description":"</[", +"input":"</[", +"output":["ParseError", ["Comment", "["]]}, + +{"description":"</`", +"input":"</`", +"output":["ParseError", ["Comment", "`"]]}, + +{"description":"</a>", +"input":"</a>", +"output":[["EndTag", "a"]]}, + +{"description":"</b>", +"input":"</b>", +"output":[["EndTag", "b"]]}, + +{"description":"</y>", +"input":"</y>", +"output":[["EndTag", "y"]]}, + +{"description":"</z>", +"input":"</z>", +"output":[["EndTag", "z"]]}, + +{"description":"</{", +"input":"</{", +"output":["ParseError", ["Comment", "{"]]}, + +{"description":"</\\uDBC0\\uDC00", +"input":"</\uDBC0\uDC00", +"output":["ParseError", ["Comment", "\uDBC0\uDC00"]]}, + +{"description":"<0", +"input":"<0", +"output":["ParseError", ["Character", "<0"]]}, + +{"description":"<1", +"input":"<1", +"output":["ParseError", ["Character", "<1"]]}, + +{"description":"<9", +"input":"<9", +"output":["ParseError", ["Character", "<9"]]}, + +{"description":"<<", +"input":"<<", +"output":["ParseError", ["Character", "<"], "ParseError", ["Character", "<"]]}, + +{"description":"<=", +"input":"<=", +"output":["ParseError", ["Character", "<="]]}, + +{"description":"<>", +"input":"<>", +"output":["ParseError", ["Character", "<>"]]}, + +{"description":"<?", +"input":"<?", +"output":["ParseError", ["Comment", "?"]]}, + +{"description":"<?\\u0000", +"input":"<?\u0000", +"output":["ParseError", ["Comment", "?\uFFFD"]]}, + +{"description":"<?\\u0009", +"input":"<?\u0009", +"output":["ParseError", ["Comment", "?\u0009"]]}, + +{"description":"<?\\u000A", +"input":"<?\u000A", +"output":["ParseError", ["Comment", "?\u000A"]]}, + +{"description":"<?\\u000B", +"input":"<?\u000B", +"output":["ParseError", "ParseError", ["Comment", "?\u000B"]]}, + +{"description":"<?\\u000C", +"input":"<?\u000C", +"output":["ParseError", ["Comment", "?\u000C"]]}, + +{"description":"<? ", +"input":"<? ", +"output":["ParseError", ["Comment", "? "]]}, + +{"description":"<?!", +"input":"<?!", +"output":["ParseError", ["Comment", "?!"]]}, + +{"description":"<?\"", +"input":"<?\"", +"output":["ParseError", ["Comment", "?\""]]}, + +{"description":"<?&", +"input":"<?&", +"output":["ParseError", ["Comment", "?&"]]}, + +{"description":"<?'", +"input":"<?'", +"output":["ParseError", ["Comment", "?'"]]}, + +{"description":"<?-", +"input":"<?-", +"output":["ParseError", ["Comment", "?-"]]}, + +{"description":"<?/", +"input":"<?/", +"output":["ParseError", ["Comment", "?/"]]}, + +{"description":"<?0", +"input":"<?0", +"output":["ParseError", ["Comment", "?0"]]}, + +{"description":"<?1", +"input":"<?1", +"output":["ParseError", ["Comment", "?1"]]}, + +{"description":"<?9", +"input":"<?9", +"output":["ParseError", ["Comment", "?9"]]}, + +{"description":"<?<", +"input":"<?<", +"output":["ParseError", ["Comment", "?<"]]}, + +{"description":"<?=", +"input":"<?=", +"output":["ParseError", ["Comment", "?="]]}, + +{"description":"<?>", +"input":"<?>", +"output":["ParseError", ["Comment", "?"]]}, + +{"description":"<??", +"input":"<??", +"output":["ParseError", ["Comment", "??"]]}, + +{"description":"<?@", +"input":"<?@", +"output":["ParseError", ["Comment", "?@"]]}, + +{"description":"<?A", +"input":"<?A", +"output":["ParseError", ["Comment", "?A"]]}, + +{"description":"<?B", +"input":"<?B", +"output":["ParseError", ["Comment", "?B"]]}, + +{"description":"<?Y", +"input":"<?Y", +"output":["ParseError", ["Comment", "?Y"]]}, + +{"description":"<?Z", +"input":"<?Z", +"output":["ParseError", ["Comment", "?Z"]]}, + +{"description":"<?`", +"input":"<?`", +"output":["ParseError", ["Comment", "?`"]]}, + +{"description":"<?a", +"input":"<?a", +"output":["ParseError", ["Comment", "?a"]]}, + +{"description":"<?b", +"input":"<?b", +"output":["ParseError", ["Comment", "?b"]]}, + +{"description":"<?y", +"input":"<?y", +"output":["ParseError", ["Comment", "?y"]]}, + +{"description":"<?z", +"input":"<?z", +"output":["ParseError", ["Comment", "?z"]]}, + +{"description":"<?{", +"input":"<?{", +"output":["ParseError", ["Comment", "?{"]]}, + +{"description":"<?\\uDBC0\\uDC00", +"input":"<?\uDBC0\uDC00", +"output":["ParseError", ["Comment", "?\uDBC0\uDC00"]]}, + +{"description":"<@", +"input":"<@", +"output":["ParseError", ["Character", "<@"]]}, + +{"description":"<A>", +"input":"<A>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<B>", +"input":"<B>", +"output":[["StartTag", "b", {}]]}, + +{"description":"<Y>", +"input":"<Y>", +"output":[["StartTag", "y", {}]]}, + +{"description":"<Z>", +"input":"<Z>", +"output":[["StartTag", "z", {}]]}, + +{"description":"<[", +"input":"<[", +"output":["ParseError", ["Character", "<["]]}, + +{"description":"<`", +"input":"<`", +"output":["ParseError", ["Character", "<`"]]}, + +{"description":"<a>", +"input":"<a>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a\\u0000>", +"input":"<a\u0000>", +"output":["ParseError", ["StartTag", "a\uFFFD", {}]]}, + +{"description":"<a\\u0008>", +"input":"<a\u0008>", +"output":["ParseError", ["StartTag", "a\u0008", {}]]}, + +{"description":"<a\\u0009>", +"input":"<a\u0009>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a\\u000A>", +"input":"<a\u000A>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a\\u000B>", +"input":"<a\u000B>", +"output":["ParseError", ["StartTag", "a\u000B", {}]]}, + +{"description":"<a\\u000C>", +"input":"<a\u000C>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a\\u000D>", +"input":"<a\u000D>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a\\u001F>", +"input":"<a\u001F>", +"output":["ParseError", ["StartTag", "a\u001F", {}]]}, + +{"description":"<a >", +"input":"<a >", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a \\u0000>", +"input":"<a \u0000>", +"output":["ParseError", ["StartTag", "a", {"\uFFFD":""}]]}, + +{"description":"<a \\u0008>", +"input":"<a \u0008>", +"output":["ParseError", ["StartTag", "a", {"\u0008":""}]]}, + +{"description":"<a \\u0009>", +"input":"<a \u0009>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a \\u000A>", +"input":"<a \u000A>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a \\u000B>", +"input":"<a \u000B>", +"output":["ParseError", ["StartTag", "a", {"\u000B":""}]]}, + +{"description":"<a \\u000C>", +"input":"<a \u000C>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a \\u000D>", +"input":"<a \u000D>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a \\u001F>", +"input":"<a \u001F>", +"output":["ParseError", ["StartTag", "a", {"\u001F":""}]]}, + +{"description":"<a >", +"input":"<a >", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a !>", +"input":"<a !>", +"output":[["StartTag", "a", {"!":""}]]}, + +{"description":"<a \">", +"input":"<a \">", +"output":["ParseError", ["StartTag", "a", {"\"":""}]]}, + +{"description":"<a #>", +"input":"<a #>", +"output":[["StartTag", "a", {"#":""}]]}, + +{"description":"<a &>", +"input":"<a &>", +"output":[["StartTag", "a", {"&":""}]]}, + +{"description":"<a '>", +"input":"<a '>", +"output":["ParseError", ["StartTag", "a", {"'":""}]]}, + +{"description":"<a (>", +"input":"<a (>", +"output":[["StartTag", "a", {"(":""}]]}, + +{"description":"<a ->", +"input":"<a ->", +"output":[["StartTag", "a", {"-":""}]]}, + +{"description":"<a .>", +"input":"<a .>", +"output":[["StartTag", "a", {".":""}]]}, + +{"description":"<a />", +"input":"<a />", +"output":[["StartTag", "a", {}, true]]}, + +{"description":"<a 0>", +"input":"<a 0>", +"output":[["StartTag", "a", {"0":""}]]}, + +{"description":"<a 1>", +"input":"<a 1>", +"output":[["StartTag", "a", {"1":""}]]}, + +{"description":"<a 9>", +"input":"<a 9>", +"output":[["StartTag", "a", {"9":""}]]}, + +{"description":"<a <>", +"input":"<a <>", +"output":["ParseError", ["StartTag", "a", {"<":""}]]}, + +{"description":"<a =>", +"input":"<a =>", +"output":["ParseError", ["StartTag", "a", {"=":""}]]}, + +{"description":"<a >", +"input":"<a >", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a ?>", +"input":"<a ?>", +"output":[["StartTag", "a", {"?":""}]]}, + +{"description":"<a @>", +"input":"<a @>", +"output":[["StartTag", "a", {"@":""}]]}, + +{"description":"<a A>", +"input":"<a A>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a B>", +"input":"<a B>", +"output":[["StartTag", "a", {"b":""}]]}, + +{"description":"<a Y>", +"input":"<a Y>", +"output":[["StartTag", "a", {"y":""}]]}, + +{"description":"<a Z>", +"input":"<a Z>", +"output":[["StartTag", "a", {"z":""}]]}, + +{"description":"<a [>", +"input":"<a [>", +"output":[["StartTag", "a", {"[":""}]]}, + +{"description":"<a `>", +"input":"<a `>", +"output":[["StartTag", "a", {"`":""}]]}, + +{"description":"<a a>", +"input":"<a a>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a\\u0000>", +"input":"<a a\u0000>", +"output":["ParseError", ["StartTag", "a", {"a\uFFFD":""}]]}, + +{"description":"<a a\\u0008>", +"input":"<a a\u0008>", +"output":["ParseError", ["StartTag", "a", {"a\u0008":""}]]}, + +{"description":"<a a\\u0009>", +"input":"<a a\u0009>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a\\u000A>", +"input":"<a a\u000A>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a\\u000B>", +"input":"<a a\u000B>", +"output":["ParseError", ["StartTag", "a", {"a\u000B":""}]]}, + +{"description":"<a a\\u000C>", +"input":"<a a\u000C>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a\\u000D>", +"input":"<a a\u000D>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a\\u001F>", +"input":"<a a\u001F>", +"output":["ParseError", ["StartTag", "a", {"a\u001F":""}]]}, + +{"description":"<a a >", +"input":"<a a >", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a \\u0000>", +"input":"<a a \u0000>", +"output":["ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]}, + +{"description":"<a a \\u0008>", +"input":"<a a \u0008>", +"output":["ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]}, + +{"description":"<a a \\u0009>", +"input":"<a a \u0009>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a \\u000A>", +"input":"<a a \u000A>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a \\u000B>", +"input":"<a a \u000B>", +"output":["ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]}, + +{"description":"<a a \\u000C>", +"input":"<a a \u000C>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a \\u000D>", +"input":"<a a \u000D>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a \\u001F>", +"input":"<a a \u001F>", +"output":["ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]}, + +{"description":"<a a >", +"input":"<a a >", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a !>", +"input":"<a a !>", +"output":[["StartTag", "a", {"a":"", "!":""}]]}, + +{"description":"<a a \">", +"input":"<a a \">", +"output":["ParseError", ["StartTag", "a", {"a":"", "\"":""}]]}, + +{"description":"<a a #>", +"input":"<a a #>", +"output":[["StartTag", "a", {"a":"", "#":""}]]}, + +{"description":"<a a &>", +"input":"<a a &>", +"output":[["StartTag", "a", {"a":"", "&":""}]]}, + +{"description":"<a a '>", +"input":"<a a '>", +"output":["ParseError", ["StartTag", "a", {"a":"", "'":""}]]}, + +{"description":"<a a (>", +"input":"<a a (>", +"output":[["StartTag", "a", {"a":"", "(":""}]]}, + +{"description":"<a a ->", +"input":"<a a ->", +"output":[["StartTag", "a", {"a":"", "-":""}]]}, + +{"description":"<a a .>", +"input":"<a a .>", +"output":[["StartTag", "a", {"a":"", ".":""}]]}, + +{"description":"<a a />", +"input":"<a a />", +"output":[["StartTag", "a", {"a":""}, true]]}, + +{"description":"<a a 0>", +"input":"<a a 0>", +"output":[["StartTag", "a", {"a":"", "0":""}]]}, + +{"description":"<a a 1>", +"input":"<a a 1>", +"output":[["StartTag", "a", {"a":"", "1":""}]]}, + +{"description":"<a a 9>", +"input":"<a a 9>", +"output":[["StartTag", "a", {"a":"", "9":""}]]}, + +{"description":"<a a <>", +"input":"<a a <>", +"output":["ParseError", ["StartTag", "a", {"a":"", "<":""}]]}, + +{"description":"<a a =>", +"input":"<a a =>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a >", +"input":"<a a >", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a ?>", +"input":"<a a ?>", +"output":[["StartTag", "a", {"a":"", "?":""}]]}, + +{"description":"<a a @>", +"input":"<a a @>", +"output":[["StartTag", "a", {"a":"", "@":""}]]}, + +{"description":"<a a A>", +"input":"<a a A>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a B>", +"input":"<a a B>", +"output":[["StartTag", "a", {"a":"", "b":""}]]}, + +{"description":"<a a Y>", +"input":"<a a Y>", +"output":[["StartTag", "a", {"a":"", "y":""}]]}, + +{"description":"<a a Z>", +"input":"<a a Z>", +"output":[["StartTag", "a", {"a":"", "z":""}]]}, + +{"description":"<a a [>", +"input":"<a a [>", +"output":[["StartTag", "a", {"a":"", "[":""}]]}, + +{"description":"<a a `>", +"input":"<a a `>", +"output":[["StartTag", "a", {"a":"", "`":""}]]}, + +{"description":"<a a a>", +"input":"<a a a>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a b>", +"input":"<a a b>", +"output":[["StartTag", "a", {"a":"", "b":""}]]}, + +{"description":"<a a y>", +"input":"<a a y>", +"output":[["StartTag", "a", {"a":"", "y":""}]]}, + +{"description":"<a a z>", +"input":"<a a z>", +"output":[["StartTag", "a", {"a":"", "z":""}]]}, + +{"description":"<a a {>", +"input":"<a a {>", +"output":[["StartTag", "a", {"a":"", "{":""}]]}, + +{"description":"<a a \\uDBC0\\uDC00>", +"input":"<a a \uDBC0\uDC00>", +"output":[["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]}, + +{"description":"<a a!>", +"input":"<a a!>", +"output":[["StartTag", "a", {"a!":""}]]}, + +{"description":"<a a\">", +"input":"<a a\">", +"output":["ParseError", ["StartTag", "a", {"a\"":""}]]}, + +{"description":"<a a#>", +"input":"<a a#>", +"output":[["StartTag", "a", {"a#":""}]]}, + +{"description":"<a a&>", +"input":"<a a&>", +"output":[["StartTag", "a", {"a&":""}]]}, + +{"description":"<a a'>", +"input":"<a a'>", +"output":["ParseError", ["StartTag", "a", {"a'":""}]]}, + +{"description":"<a a(>", +"input":"<a a(>", +"output":[["StartTag", "a", {"a(":""}]]}, + +{"description":"<a a->", +"input":"<a a->", +"output":[["StartTag", "a", {"a-":""}]]}, + +{"description":"<a a.>", +"input":"<a a.>", +"output":[["StartTag", "a", {"a.":""}]]}, + +{"description":"<a a/>", +"input":"<a a/>", +"output":[["StartTag", "a", {"a":""}, true]]}, + +{"description":"<a a0>", +"input":"<a a0>", +"output":[["StartTag", "a", {"a0":""}]]}, + +{"description":"<a a1>", +"input":"<a a1>", +"output":[["StartTag", "a", {"a1":""}]]}, + +{"description":"<a a9>", +"input":"<a a9>", +"output":[["StartTag", "a", {"a9":""}]]}, + +{"description":"<a a<>", +"input":"<a a<>", +"output":["ParseError", ["StartTag", "a", {"a<":""}]]}, + +{"description":"<a a=>", +"input":"<a a=>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\\u0000>", +"input":"<a a=\u0000>", +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]}, + +{"description":"<a a=\\u0008>", +"input":"<a a=\u0008>", +"output":["ParseError", ["StartTag", "a", {"a":"\u0008"}]]}, + +{"description":"<a a=\\u0009>", +"input":"<a a=\u0009>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\\u000A>", +"input":"<a a=\u000A>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\\u000B>", +"input":"<a a=\u000B>", +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]}, + +{"description":"<a a=\\u000C>", +"input":"<a a=\u000C>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\\u000D>", +"input":"<a a=\u000D>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\\u001F>", +"input":"<a a=\u001F>", +"output":["ParseError", ["StartTag", "a", {"a":"\u001F"}]]}, + +{"description":"<a a= >", +"input":"<a a= >", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=!>", +"input":"<a a=!>", +"output":[["StartTag", "a", {"a":"!"}]]}, + +{"description":"<a a=\"\">", +"input":"<a a=\"\">", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\"\\u0000\">", +"input":"<a a=\"\u0000\">", +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]}, + +{"description":"<a a=\"\\u0009\">", +"input":"<a a=\"\u0009\">", +"output":[["StartTag", "a", {"a":"\u0009"}]]}, + +{"description":"<a a=\"\\u000A\">", +"input":"<a a=\"\u000A\">", +"output":[["StartTag", "a", {"a":"\u000A"}]]}, + +{"description":"<a a=\"\\u000B\">", +"input":"<a a=\"\u000B\">", +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]}, + +{"description":"<a a=\"\\u000C\">", +"input":"<a a=\"\u000C\">", +"output":[["StartTag", "a", {"a":"\u000C"}]]}, + +{"description":"<a a=\" \">", +"input":"<a a=\" \">", +"output":[["StartTag", "a", {"a":" "}]]}, + +{"description":"<a a=\"!\">", +"input":"<a a=\"!\">", +"output":[["StartTag", "a", {"a":"!"}]]}, + +{"description":"<a a=\"\">", +"input":"<a a=\"\">", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=\"#\">", +"input":"<a a=\"#\">", +"output":[["StartTag", "a", {"a":"#"}]]}, + +{"description":"<a a=\"%\">", +"input":"<a a=\"%\">", +"output":[["StartTag", "a", {"a":"%"}]]}, + +{"description":"<a a=\"&\">", +"input":"<a a=\"&\">", +"output":[["StartTag", "a", {"a":"&"}]]}, + +{"description":"<a a=\"'\">", +"input":"<a a=\"'\">", +"output":[["StartTag", "a", {"a":"'"}]]}, + +{"description":"<a a=\"-\">", +"input":"<a a=\"-\">", +"output":[["StartTag", "a", {"a":"-"}]]}, + +{"description":"<a a=\"/\">", +"input":"<a a=\"/\">", +"output":[["StartTag", "a", {"a":"/"}]]}, + +{"description":"<a a=\"0\">", +"input":"<a a=\"0\">", +"output":[["StartTag", "a", {"a":"0"}]]}, + +{"description":"<a a=\"1\">", +"input":"<a a=\"1\">", +"output":[["StartTag", "a", {"a":"1"}]]}, + +{"description":"<a a=\"9\">", +"input":"<a a=\"9\">", +"output":[["StartTag", "a", {"a":"9"}]]}, + +{"description":"<a a=\"<\">", +"input":"<a a=\"<\">", +"output":[["StartTag", "a", {"a":"<"}]]}, + +{"description":"<a a=\"=\">", +"input":"<a a=\"=\">", +"output":[["StartTag", "a", {"a":"="}]]}, + +{"description":"<a a=\">\">", +"input":"<a a=\">\">", +"output":[["StartTag", "a", {"a":">"}]]}, + +{"description":"<a a=\"?\">", +"input":"<a a=\"?\">", +"output":[["StartTag", "a", {"a":"?"}]]}, + +{"description":"<a a=\"@\">", +"input":"<a a=\"@\">", +"output":[["StartTag", "a", {"a":"@"}]]}, + +{"description":"<a a=\"A\">", +"input":"<a a=\"A\">", +"output":[["StartTag", "a", {"a":"A"}]]}, + +{"description":"<a a=\"B\">", +"input":"<a a=\"B\">", +"output":[["StartTag", "a", {"a":"B"}]]}, + +{"description":"<a a=\"Y\">", +"input":"<a a=\"Y\">", +"output":[["StartTag", "a", {"a":"Y"}]]}, + +{"description":"<a a=\"Z\">", +"input":"<a a=\"Z\">", +"output":[["StartTag", "a", {"a":"Z"}]]}, + +{"description":"<a a=\"`\">", +"input":"<a a=\"`\">", +"output":[["StartTag", "a", {"a":"`"}]]}, + +{"description":"<a a=\"a\">", +"input":"<a a=\"a\">", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=\"b\">", +"input":"<a a=\"b\">", +"output":[["StartTag", "a", {"a":"b"}]]}, + +{"description":"<a a=\"y\">", +"input":"<a a=\"y\">", +"output":[["StartTag", "a", {"a":"y"}]]}, + +{"description":"<a a=\"z\">", +"input":"<a a=\"z\">", +"output":[["StartTag", "a", {"a":"z"}]]}, + +{"description":"<a a=\"{\">", +"input":"<a a=\"{\">", +"output":[["StartTag", "a", {"a":"{"}]]}, + +{"description":"<a a=\"\\uDBC0\\uDC00\">", +"input":"<a a=\"\uDBC0\uDC00\">", +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]}, + +{"description":"<a a=#>", +"input":"<a a=#>", +"output":[["StartTag", "a", {"a":"#"}]]}, + +{"description":"<a a=%>", +"input":"<a a=%>", +"output":[["StartTag", "a", {"a":"%"}]]}, + +{"description":"<a a=&>", +"input":"<a a=&>", +"output":[["StartTag", "a", {"a":"&"}]]}, + +{"description":"<a a=''>", +"input":"<a a=''>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a='\\u0000'>", +"input":"<a a='\u0000'>", +"output":["ParseError", ["StartTag", "a", {"a":"\uFFFD"}]]}, + +{"description":"<a a='\\u0009'>", +"input":"<a a='\u0009'>", +"output":[["StartTag", "a", {"a":"\u0009"}]]}, + +{"description":"<a a='\\u000A'>", +"input":"<a a='\u000A'>", +"output":[["StartTag", "a", {"a":"\u000A"}]]}, + +{"description":"<a a='\\u000B'>", +"input":"<a a='\u000B'>", +"output":["ParseError", ["StartTag", "a", {"a":"\u000B"}]]}, + +{"description":"<a a='\\u000C'>", +"input":"<a a='\u000C'>", +"output":[["StartTag", "a", {"a":"\u000C"}]]}, + +{"description":"<a a=' '>", +"input":"<a a=' '>", +"output":[["StartTag", "a", {"a":" "}]]}, + +{"description":"<a a='!'>", +"input":"<a a='!'>", +"output":[["StartTag", "a", {"a":"!"}]]}, + +{"description":"<a a='\"'>", +"input":"<a a='\"'>", +"output":[["StartTag", "a", {"a":"\""}]]}, + +{"description":"<a a='%'>", +"input":"<a a='%'>", +"output":[["StartTag", "a", {"a":"%"}]]}, + +{"description":"<a a='&'>", +"input":"<a a='&'>", +"output":[["StartTag", "a", {"a":"&"}]]}, + +{"description":"<a a=''>", +"input":"<a a=''>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''\\u0000>", +"input":"<a a=''\u0000>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\uFFFD":""}]]}, + +{"description":"<a a=''\\u0008>", +"input":"<a a=''\u0008>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u0008":""}]]}, + +{"description":"<a a=''\\u0009>", +"input":"<a a=''\u0009>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''\\u000A>", +"input":"<a a=''\u000A>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''\\u000B>", +"input":"<a a=''\u000B>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u000B":""}]]}, + +{"description":"<a a=''\\u000C>", +"input":"<a a=''\u000C>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''\\u000D>", +"input":"<a a=''\u000D>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''\\u001F>", +"input":"<a a=''\u001F>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\u001F":""}]]}, + +{"description":"<a a='' >", +"input":"<a a='' >", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''!>", +"input":"<a a=''!>", +"output":["ParseError", ["StartTag", "a", {"a":"", "!":""}]]}, + +{"description":"<a a=''\">", +"input":"<a a=''\">", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "\"":""}]]}, + +{"description":"<a a=''&>", +"input":"<a a=''&>", +"output":["ParseError", ["StartTag", "a", {"a":"", "&":""}]]}, + +{"description":"<a a='''>", +"input":"<a a='''>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "'":""}]]}, + +{"description":"<a a=''->", +"input":"<a a=''->", +"output":["ParseError", ["StartTag", "a", {"a":"", "-":""}]]}, + +{"description":"<a a=''.>", +"input":"<a a=''.>", +"output":["ParseError", ["StartTag", "a", {"a":"", ".":""}]]}, + +{"description":"<a a=''/>", +"input":"<a a=''/>", +"output":[["StartTag", "a", {"a":""}, true]]}, + +{"description":"<a a=''0>", +"input":"<a a=''0>", +"output":["ParseError", ["StartTag", "a", {"a":"", "0":""}]]}, + +{"description":"<a a=''1>", +"input":"<a a=''1>", +"output":["ParseError", ["StartTag", "a", {"a":"", "1":""}]]}, + +{"description":"<a a=''9>", +"input":"<a a=''9>", +"output":["ParseError", ["StartTag", "a", {"a":"", "9":""}]]}, + +{"description":"<a a=''<>", +"input":"<a a=''<>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "<":""}]]}, + +{"description":"<a a=''=>", +"input":"<a a=''=>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":"", "=":""}]]}, + +{"description":"<a a=''>", +"input":"<a a=''>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''?>", +"input":"<a a=''?>", +"output":["ParseError", ["StartTag", "a", {"a":"", "?":""}]]}, + +{"description":"<a a=''@>", +"input":"<a a=''@>", +"output":["ParseError", ["StartTag", "a", {"a":"", "@":""}]]}, + +{"description":"<a a=''A>", +"input":"<a a=''A>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''B>", +"input":"<a a=''B>", +"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]}, + +{"description":"<a a=''Y>", +"input":"<a a=''Y>", +"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]}, + +{"description":"<a a=''Z>", +"input":"<a a=''Z>", +"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]}, + +{"description":"<a a=''`>", +"input":"<a a=''`>", +"output":["ParseError", ["StartTag", "a", {"a":"", "`":""}]]}, + +{"description":"<a a=''a>", +"input":"<a a=''a>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=''b>", +"input":"<a a=''b>", +"output":["ParseError", ["StartTag", "a", {"a":"", "b":""}]]}, + +{"description":"<a a=''y>", +"input":"<a a=''y>", +"output":["ParseError", ["StartTag", "a", {"a":"", "y":""}]]}, + +{"description":"<a a=''z>", +"input":"<a a=''z>", +"output":["ParseError", ["StartTag", "a", {"a":"", "z":""}]]}, + +{"description":"<a a=''{>", +"input":"<a a=''{>", +"output":["ParseError", ["StartTag", "a", {"a":"", "{":""}]]}, + +{"description":"<a a=''\\uDBC0\\uDC00>", +"input":"<a a=''\uDBC0\uDC00>", +"output":["ParseError", ["StartTag", "a", {"a":"", "\uDBC0\uDC00":""}]]}, + +{"description":"<a a='('>", +"input":"<a a='('>", +"output":[["StartTag", "a", {"a":"("}]]}, + +{"description":"<a a='-'>", +"input":"<a a='-'>", +"output":[["StartTag", "a", {"a":"-"}]]}, + +{"description":"<a a='/'>", +"input":"<a a='/'>", +"output":[["StartTag", "a", {"a":"/"}]]}, + +{"description":"<a a='0'>", +"input":"<a a='0'>", +"output":[["StartTag", "a", {"a":"0"}]]}, + +{"description":"<a a='1'>", +"input":"<a a='1'>", +"output":[["StartTag", "a", {"a":"1"}]]}, + +{"description":"<a a='9'>", +"input":"<a a='9'>", +"output":[["StartTag", "a", {"a":"9"}]]}, + +{"description":"<a a='<'>", +"input":"<a a='<'>", +"output":[["StartTag", "a", {"a":"<"}]]}, + +{"description":"<a a='='>", +"input":"<a a='='>", +"output":[["StartTag", "a", {"a":"="}]]}, + +{"description":"<a a='>'>", +"input":"<a a='>'>", +"output":[["StartTag", "a", {"a":">"}]]}, + +{"description":"<a a='?'>", +"input":"<a a='?'>", +"output":[["StartTag", "a", {"a":"?"}]]}, + +{"description":"<a a='@'>", +"input":"<a a='@'>", +"output":[["StartTag", "a", {"a":"@"}]]}, + +{"description":"<a a='A'>", +"input":"<a a='A'>", +"output":[["StartTag", "a", {"a":"A"}]]}, + +{"description":"<a a='B'>", +"input":"<a a='B'>", +"output":[["StartTag", "a", {"a":"B"}]]}, + +{"description":"<a a='Y'>", +"input":"<a a='Y'>", +"output":[["StartTag", "a", {"a":"Y"}]]}, + +{"description":"<a a='Z'>", +"input":"<a a='Z'>", +"output":[["StartTag", "a", {"a":"Z"}]]}, + +{"description":"<a a='`'>", +"input":"<a a='`'>", +"output":[["StartTag", "a", {"a":"`"}]]}, + +{"description":"<a a='a'>", +"input":"<a a='a'>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a='b'>", +"input":"<a a='b'>", +"output":[["StartTag", "a", {"a":"b"}]]}, + +{"description":"<a a='y'>", +"input":"<a a='y'>", +"output":[["StartTag", "a", {"a":"y"}]]}, + +{"description":"<a a='z'>", +"input":"<a a='z'>", +"output":[["StartTag", "a", {"a":"z"}]]}, + +{"description":"<a a='{'>", +"input":"<a a='{'>", +"output":[["StartTag", "a", {"a":"{"}]]}, + +{"description":"<a a='\\uDBC0\\uDC00'>", +"input":"<a a='\uDBC0\uDC00'>", +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]}, + +{"description":"<a a=(>", +"input":"<a a=(>", +"output":[["StartTag", "a", {"a":"("}]]}, + +{"description":"<a a=->", +"input":"<a a=->", +"output":[["StartTag", "a", {"a":"-"}]]}, + +{"description":"<a a=/>", +"input":"<a a=/>", +"output":[["StartTag", "a", {"a":"/"}]]}, + +{"description":"<a a=0>", +"input":"<a a=0>", +"output":[["StartTag", "a", {"a":"0"}]]}, + +{"description":"<a a=1>", +"input":"<a a=1>", +"output":[["StartTag", "a", {"a":"1"}]]}, + +{"description":"<a a=9>", +"input":"<a a=9>", +"output":[["StartTag", "a", {"a":"9"}]]}, + +{"description":"<a a=<>", +"input":"<a a=<>", +"output":["ParseError", ["StartTag", "a", {"a":"<"}]]}, + +{"description":"<a a==>", +"input":"<a a==>", +"output":["ParseError", ["StartTag", "a", {"a":"="}]]}, + +{"description":"<a a=>", +"input":"<a a=>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a a=?>", +"input":"<a a=?>", +"output":[["StartTag", "a", {"a":"?"}]]}, + +{"description":"<a a=@>", +"input":"<a a=@>", +"output":[["StartTag", "a", {"a":"@"}]]}, + +{"description":"<a a=A>", +"input":"<a a=A>", +"output":[["StartTag", "a", {"a":"A"}]]}, + +{"description":"<a a=B>", +"input":"<a a=B>", +"output":[["StartTag", "a", {"a":"B"}]]}, + +{"description":"<a a=Y>", +"input":"<a a=Y>", +"output":[["StartTag", "a", {"a":"Y"}]]}, + +{"description":"<a a=Z>", +"input":"<a a=Z>", +"output":[["StartTag", "a", {"a":"Z"}]]}, + +{"description":"<a a=`>", +"input":"<a a=`>", +"output":["ParseError", ["StartTag", "a", {"a":"`"}]]}, + +{"description":"<a a=a>", +"input":"<a a=a>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a\\u0000>", +"input":"<a a=a\u0000>", +"output":["ParseError", ["StartTag", "a", {"a":"a\uFFFD"}]]}, + +{"description":"<a a=a\\u0008>", +"input":"<a a=a\u0008>", +"output":["ParseError", ["StartTag", "a", {"a":"a\u0008"}]]}, + +{"description":"<a a=a\\u0009>", +"input":"<a a=a\u0009>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a\\u000A>", +"input":"<a a=a\u000A>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a\\u000B>", +"input":"<a a=a\u000B>", +"output":["ParseError", ["StartTag", "a", {"a":"a\u000B"}]]}, + +{"description":"<a a=a\\u000C>", +"input":"<a a=a\u000C>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a\\u000D>", +"input":"<a a=a\u000D>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a\\u001F>", +"input":"<a a=a\u001F>", +"output":["ParseError", ["StartTag", "a", {"a":"a\u001F"}]]}, + +{"description":"<a a=a >", +"input":"<a a=a >", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a!>", +"input":"<a a=a!>", +"output":[["StartTag", "a", {"a":"a!"}]]}, + +{"description":"<a a=a\">", +"input":"<a a=a\">", +"output":["ParseError", ["StartTag", "a", {"a":"a\""}]]}, + +{"description":"<a a=a#>", +"input":"<a a=a#>", +"output":[["StartTag", "a", {"a":"a#"}]]}, + +{"description":"<a a=a%>", +"input":"<a a=a%>", +"output":[["StartTag", "a", {"a":"a%"}]]}, + +{"description":"<a a=a&>", +"input":"<a a=a&>", +"output":[["StartTag", "a", {"a":"a&"}]]}, + +{"description":"<a a=a'>", +"input":"<a a=a'>", +"output":["ParseError", ["StartTag", "a", {"a":"a'"}]]}, + +{"description":"<a a=a(>", +"input":"<a a=a(>", +"output":[["StartTag", "a", {"a":"a("}]]}, + +{"description":"<a a=a->", +"input":"<a a=a->", +"output":[["StartTag", "a", {"a":"a-"}]]}, + +{"description":"<a a=a/>", +"input":"<a a=a/>", +"output":[["StartTag", "a", {"a":"a/"}]]}, + +{"description":"<a a=a0>", +"input":"<a a=a0>", +"output":[["StartTag", "a", {"a":"a0"}]]}, + +{"description":"<a a=a1>", +"input":"<a a=a1>", +"output":[["StartTag", "a", {"a":"a1"}]]}, + +{"description":"<a a=a9>", +"input":"<a a=a9>", +"output":[["StartTag", "a", {"a":"a9"}]]}, + +{"description":"<a a=a<>", +"input":"<a a=a<>", +"output":["ParseError", ["StartTag", "a", {"a":"a<"}]]}, + +{"description":"<a a=a=>", +"input":"<a a=a=>", +"output":["ParseError", ["StartTag", "a", {"a":"a="}]]}, + +{"description":"<a a=a>", +"input":"<a a=a>", +"output":[["StartTag", "a", {"a":"a"}]]}, + +{"description":"<a a=a?>", +"input":"<a a=a?>", +"output":[["StartTag", "a", {"a":"a?"}]]}, + +{"description":"<a a=a@>", +"input":"<a a=a@>", +"output":[["StartTag", "a", {"a":"a@"}]]}, + +{"description":"<a a=aA>", +"input":"<a a=aA>", +"output":[["StartTag", "a", {"a":"aA"}]]}, + +{"description":"<a a=aB>", +"input":"<a a=aB>", +"output":[["StartTag", "a", {"a":"aB"}]]}, + +{"description":"<a a=aY>", +"input":"<a a=aY>", +"output":[["StartTag", "a", {"a":"aY"}]]}, + +{"description":"<a a=aZ>", +"input":"<a a=aZ>", +"output":[["StartTag", "a", {"a":"aZ"}]]}, + +{"description":"<a a=a`>", +"input":"<a a=a`>", +"output":["ParseError", ["StartTag", "a", {"a":"a`"}]]}, + +{"description":"<a a=aa>", +"input":"<a a=aa>", +"output":[["StartTag", "a", {"a":"aa"}]]}, + +{"description":"<a a=ab>", +"input":"<a a=ab>", +"output":[["StartTag", "a", {"a":"ab"}]]}, + +{"description":"<a a=ay>", +"input":"<a a=ay>", +"output":[["StartTag", "a", {"a":"ay"}]]}, + +{"description":"<a a=az>", +"input":"<a a=az>", +"output":[["StartTag", "a", {"a":"az"}]]}, + +{"description":"<a a=a{>", +"input":"<a a=a{>", +"output":[["StartTag", "a", {"a":"a{"}]]}, + +{"description":"<a a=a\\uDBC0\\uDC00>", +"input":"<a a=a\uDBC0\uDC00>", +"output":[["StartTag", "a", {"a":"a\uDBC0\uDC00"}]]}, + +{"description":"<a a=b>", +"input":"<a a=b>", +"output":[["StartTag", "a", {"a":"b"}]]}, + +{"description":"<a a=y>", +"input":"<a a=y>", +"output":[["StartTag", "a", {"a":"y"}]]}, + +{"description":"<a a=z>", +"input":"<a a=z>", +"output":[["StartTag", "a", {"a":"z"}]]}, + +{"description":"<a a={>", +"input":"<a a={>", +"output":[["StartTag", "a", {"a":"{"}]]}, + +{"description":"<a a=\\uDBC0\\uDC00>", +"input":"<a a=\uDBC0\uDC00>", +"output":[["StartTag", "a", {"a":"\uDBC0\uDC00"}]]}, + +{"description":"<a a>", +"input":"<a a>", +"output":[["StartTag", "a", {"a":""}]]}, + +{"description":"<a a?>", +"input":"<a a?>", +"output":[["StartTag", "a", {"a?":""}]]}, + +{"description":"<a a@>", +"input":"<a a@>", +"output":[["StartTag", "a", {"a@":""}]]}, + +{"description":"<a aA>", +"input":"<a aA>", +"output":[["StartTag", "a", {"aa":""}]]}, + +{"description":"<a aB>", +"input":"<a aB>", +"output":[["StartTag", "a", {"ab":""}]]}, + +{"description":"<a aY>", +"input":"<a aY>", +"output":[["StartTag", "a", {"ay":""}]]}, + +{"description":"<a aZ>", +"input":"<a aZ>", +"output":[["StartTag", "a", {"az":""}]]}, + +{"description":"<a a[>", +"input":"<a a[>", +"output":[["StartTag", "a", {"a[":""}]]}, + +{"description":"<a a`>", +"input":"<a a`>", +"output":[["StartTag", "a", {"a`":""}]]}, + +{"description":"<a aa>", +"input":"<a aa>", +"output":[["StartTag", "a", {"aa":""}]]}, + +{"description":"<a ab>", +"input":"<a ab>", +"output":[["StartTag", "a", {"ab":""}]]}, + +{"description":"<a ay>", +"input":"<a ay>", +"output":[["StartTag", "a", {"ay":""}]]}, + +{"description":"<a az>", +"input":"<a az>", +"output":[["StartTag", "a", {"az":""}]]}, + +{"description":"<a a{>", +"input":"<a a{>", +"output":[["StartTag", "a", {"a{":""}]]}, + +{"description":"<a a\\uDBC0\\uDC00>", +"input":"<a a\uDBC0\uDC00>", +"output":[["StartTag", "a", {"a\uDBC0\uDC00":""}]]}, + +{"description":"<a b>", +"input":"<a b>", +"output":[["StartTag", "a", {"b":""}]]}, + +{"description":"<a y>", +"input":"<a y>", +"output":[["StartTag", "a", {"y":""}]]}, + +{"description":"<a z>", +"input":"<a z>", +"output":[["StartTag", "a", {"z":""}]]}, + +{"description":"<a {>", +"input":"<a {>", +"output":[["StartTag", "a", {"{":""}]]}, + +{"description":"<a \\uDBC0\\uDC00>", +"input":"<a \uDBC0\uDC00>", +"output":[["StartTag", "a", {"\uDBC0\uDC00":""}]]}, + +{"description":"<a!>", +"input":"<a!>", +"output":[["StartTag", "a!", {}]]}, + +{"description":"<a\">", +"input":"<a\">", +"output":[["StartTag", "a\"", {}]]}, + +{"description":"<a&>", +"input":"<a&>", +"output":[["StartTag", "a&", {}]]}, + +{"description":"<a'>", +"input":"<a'>", +"output":[["StartTag", "a'", {}]]}, + +{"description":"<a->", +"input":"<a->", +"output":[["StartTag", "a-", {}]]}, + +{"description":"<a.>", +"input":"<a.>", +"output":[["StartTag", "a.", {}]]}, + +{"description":"<a/>", +"input":"<a/>", +"output":[["StartTag", "a", {}, true]]}, + +{"description":"<a/\\u0000>", +"input":"<a/\u0000>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"\uFFFD":""}]]}, + +{"description":"<a/\\u0009>", +"input":"<a/\u0009>", +"output":["ParseError", ["StartTag", "a", {}]]}, + +{"description":"<a/\\u000A>", +"input":"<a/\u000A>", +"output":["ParseError", ["StartTag", "a", {}]]}, + +{"description":"<a/\\u000B>", +"input":"<a/\u000B>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"\u000B":""}]]}, + +{"description":"<a/\\u000C>", +"input":"<a/\u000C>", +"output":["ParseError", ["StartTag", "a", {}]]}, + +{"description":"<a/ >", +"input":"<a/ >", +"output":["ParseError", ["StartTag", "a", {}]]}, + +{"description":"<a/!>", +"input":"<a/!>", +"output":["ParseError", ["StartTag", "a", {"!":""}]]}, + +{"description":"<a/\">", +"input":"<a/\">", +"output":["ParseError", "ParseError", ["StartTag", "a", {"\"":""}]]}, + +{"description":"<a/&>", +"input":"<a/&>", +"output":["ParseError", ["StartTag", "a", {"&":""}]]}, + +{"description":"<a/'>", +"input":"<a/'>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"'":""}]]}, + +{"description":"<a/->", +"input":"<a/->", +"output":["ParseError", ["StartTag", "a", {"-":""}]]}, + +{"description":"<a//>", +"input":"<a//>", +"output":["ParseError", ["StartTag", "a", {}, true]]}, + +{"description":"<a/0>", +"input":"<a/0>", +"output":["ParseError", ["StartTag", "a", {"0":""}]]}, + +{"description":"<a/1>", +"input":"<a/1>", +"output":["ParseError", ["StartTag", "a", {"1":""}]]}, + +{"description":"<a/9>", +"input":"<a/9>", +"output":["ParseError", ["StartTag", "a", {"9":""}]]}, + +{"description":"<a/<>", +"input":"<a/<>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"<":""}]]}, + +{"description":"<a/=>", +"input":"<a/=>", +"output":["ParseError", "ParseError", ["StartTag", "a", {"=":""}]]}, + +{"description":"<a/>", +"input":"<a/>", +"output":[["StartTag", "a", {}, true]]}, + +{"description":"<a/?>", +"input":"<a/?>", +"output":["ParseError", ["StartTag", "a", {"?":""}]]}, + +{"description":"<a/@>", +"input":"<a/@>", +"output":["ParseError", ["StartTag", "a", {"@":""}]]}, + +{"description":"<a/A>", +"input":"<a/A>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a/B>", +"input":"<a/B>", +"output":["ParseError", ["StartTag", "a", {"b":""}]]}, + +{"description":"<a/Y>", +"input":"<a/Y>", +"output":["ParseError", ["StartTag", "a", {"y":""}]]}, + +{"description":"<a/Z>", +"input":"<a/Z>", +"output":["ParseError", ["StartTag", "a", {"z":""}]]}, + +{"description":"<a/`>", +"input":"<a/`>", +"output":["ParseError", ["StartTag", "a", {"`":""}]]}, + +{"description":"<a/a>", +"input":"<a/a>", +"output":["ParseError", ["StartTag", "a", {"a":""}]]}, + +{"description":"<a/b>", +"input":"<a/b>", +"output":["ParseError", ["StartTag", "a", {"b":""}]]}, + +{"description":"<a/y>", +"input":"<a/y>", +"output":["ParseError", ["StartTag", "a", {"y":""}]]}, + +{"description":"<a/z>", +"input":"<a/z>", +"output":["ParseError", ["StartTag", "a", {"z":""}]]}, + +{"description":"<a/{>", +"input":"<a/{>", +"output":["ParseError", ["StartTag", "a", {"{":""}]]}, + +{"description":"<a/\\uDBC0\\uDC00>", +"input":"<a/\uDBC0\uDC00>", +"output":["ParseError", ["StartTag", "a", {"\uDBC0\uDC00":""}]]}, + +{"description":"<a0>", +"input":"<a0>", +"output":[["StartTag", "a0", {}]]}, + +{"description":"<a1>", +"input":"<a1>", +"output":[["StartTag", "a1", {}]]}, + +{"description":"<a9>", +"input":"<a9>", +"output":[["StartTag", "a9", {}]]}, + +{"description":"<a<>", +"input":"<a<>", +"output":[["StartTag", "a<", {}]]}, + +{"description":"<a=>", +"input":"<a=>", +"output":[["StartTag", "a=", {}]]}, + +{"description":"<a>", +"input":"<a>", +"output":[["StartTag", "a", {}]]}, + +{"description":"<a?>", +"input":"<a?>", +"output":[["StartTag", "a?", {}]]}, + +{"description":"<a@>", +"input":"<a@>", +"output":[["StartTag", "a@", {}]]}, + +{"description":"<aA>", +"input":"<aA>", +"output":[["StartTag", "aa", {}]]}, + +{"description":"<aB>", +"input":"<aB>", +"output":[["StartTag", "ab", {}]]}, + +{"description":"<aY>", +"input":"<aY>", +"output":[["StartTag", "ay", {}]]}, + +{"description":"<aZ>", +"input":"<aZ>", +"output":[["StartTag", "az", {}]]}, + +{"description":"<a[>", +"input":"<a[>", +"output":[["StartTag", "a[", {}]]}, + +{"description":"<a`>", +"input":"<a`>", +"output":[["StartTag", "a`", {}]]}, + +{"description":"<aa>", +"input":"<aa>", +"output":[["StartTag", "aa", {}]]}, + +{"description":"<ab>", +"input":"<ab>", +"output":[["StartTag", "ab", {}]]}, + +{"description":"<ay>", +"input":"<ay>", +"output":[["StartTag", "ay", {}]]}, + +{"description":"<az>", +"input":"<az>", +"output":[["StartTag", "az", {}]]}, + +{"description":"<a{>", +"input":"<a{>", +"output":[["StartTag", "a{", {}]]}, + +{"description":"<a\\uDBC0\\uDC00>", +"input":"<a\uDBC0\uDC00>", +"output":[["StartTag", "a\uDBC0\uDC00", {}]]}, + +{"description":"<b>", +"input":"<b>", +"output":[["StartTag", "b", {}]]}, + +{"description":"<y>", +"input":"<y>", +"output":[["StartTag", "y", {}]]}, + +{"description":"<z>", +"input":"<z>", +"output":[["StartTag", "z", {}]]}, + +{"description":"<{", +"input":"<{", +"output":["ParseError", ["Character", "<{"]]}, + +{"description":"<\\uDBC0\\uDC00", +"input":"<\uDBC0\uDC00", +"output":["ParseError", ["Character", "<\uDBC0\uDC00"]]}, + +{"description":"=", +"input":"=", +"output":[["Character", "="]]}, + +{"description":">", +"input":">", +"output":[["Character", ">"]]}, + +{"description":"?", +"input":"?", +"output":[["Character", "?"]]}, + +{"description":"@", +"input":"@", +"output":[["Character", "@"]]}, + +{"description":"A", +"input":"A", +"output":[["Character", "A"]]}, + +{"description":"B", +"input":"B", +"output":[["Character", "B"]]}, + +{"description":"Y", +"input":"Y", +"output":[["Character", "Y"]]}, + +{"description":"Z", +"input":"Z", +"output":[["Character", "Z"]]}, + +{"description":"`", +"input":"`", +"output":[["Character", "`"]]}, + +{"description":"a", +"input":"a", +"output":[["Character", "a"]]}, + +{"description":"b", +"input":"b", +"output":[["Character", "b"]]}, + +{"description":"y", +"input":"y", +"output":[["Character", "y"]]}, + +{"description":"z", +"input":"z", +"output":[["Character", "z"]]}, + +{"description":"{", +"input":"{", +"output":[["Character", "{"]]}, + +{"description":"\\uDBC0\\uDC00", +"input":"\uDBC0\uDC00", +"output":[["Character", "\uDBC0\uDC00"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/test4.test b/pkgs/html/test/data/tokenizer/test4.test new file mode 100644 index 000000000..80f859e21 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/test4.test @@ -0,0 +1,344 @@ +{"tests": [ + +{"description":"< in attribute name", +"input":"<z/0 <>", +"output":["ParseError", "ParseError", ["StartTag", "z", {"0": "", "<": ""}]]}, + +{"description":"< in attribute value", +"input":"<z x=<>", +"output":["ParseError", ["StartTag", "z", {"x": "<"}]]}, + +{"description":"= in unquoted attribute value", +"input":"<z z=z=z>", +"output":["ParseError", ["StartTag", "z", {"z": "z=z"}]]}, + +{"description":"= attribute", +"input":"<z =>", +"output":["ParseError", ["StartTag", "z", {"=": ""}]]}, + +{"description":"== attribute", +"input":"<z ==>", +"output":["ParseError", "ParseError", ["StartTag", "z", {"=": ""}]]}, + +{"description":"=== attribute", +"input":"<z ===>", +"output":["ParseError", "ParseError", ["StartTag", "z", {"=": "="}]]}, + +{"description":"==== attribute", +"input":"<z ====>", +"output":["ParseError", "ParseError", "ParseError", ["StartTag", "z", {"=": "=="}]]}, + +{"description":"Allowed \" after ampersand in attribute value", +"input":"<z z=\"&\">", +"output":[["StartTag", "z", {"z": "&"}]]}, + +{"description":"Non-allowed ' after ampersand in attribute value", +"input":"<z z=\"&'\">", +"output":["ParseError", ["StartTag", "z", {"z": "&'"}]]}, + +{"description":"Allowed ' after ampersand in attribute value", +"input":"<z z='&'>", +"output":[["StartTag", "z", {"z": "&"}]]}, + +{"description":"Non-allowed \" after ampersand in attribute value", +"input":"<z z='&\"'>", +"output":["ParseError", ["StartTag", "z", {"z": "&\""}]]}, + +{"description":"Text after bogus character reference", +"input":"<z z='&xlink_xmlns;'>bar<z>", +"output":["ParseError",["StartTag","z",{"z":"&xlink_xmlns;"}],["Character","bar"],["StartTag","z",{}]]}, + +{"description":"Text after hex character reference", +"input":"<z z='&#x0020; foo'>bar<z>", +"output":[["StartTag","z",{"z":" foo"}],["Character","bar"],["StartTag","z",{}]]}, + +{"description":"Attribute name starting with \"", +"input":"<foo \"='bar'>", +"output":["ParseError", ["StartTag", "foo", {"\"": "bar"}]]}, + +{"description":"Attribute name starting with '", +"input":"<foo '='bar'>", +"output":["ParseError", ["StartTag", "foo", {"'": "bar"}]]}, + +{"description":"Attribute name containing \"", +"input":"<foo a\"b='bar'>", +"output":["ParseError", ["StartTag", "foo", {"a\"b": "bar"}]]}, + +{"description":"Attribute name containing '", +"input":"<foo a'b='bar'>", +"output":["ParseError", ["StartTag", "foo", {"a'b": "bar"}]]}, + +{"description":"Unquoted attribute value containing '", +"input":"<foo a=b'c>", +"output":["ParseError", ["StartTag", "foo", {"a": "b'c"}]]}, + +{"description":"Unquoted attribute value containing \"", +"input":"<foo a=b\"c>", +"output":["ParseError", ["StartTag", "foo", {"a": "b\"c"}]]}, + +{"description":"Double-quoted attribute value not followed by whitespace", +"input":"<foo a=\"b\"c>", +"output":["ParseError", ["StartTag", "foo", {"a": "b", "c": ""}]]}, + +{"description":"Single-quoted attribute value not followed by whitespace", +"input":"<foo a='b'c>", +"output":["ParseError", ["StartTag", "foo", {"a": "b", "c": ""}]]}, + +{"description":"Quoted attribute followed by permitted /", +"input":"<br a='b'/>", +"output":[["StartTag","br",{"a":"b"},true]]}, + +{"description":"Quoted attribute followed by non-permitted /", +"input":"<bar a='b'/>", +"output":[["StartTag","bar",{"a":"b"},true]]}, + +{"description":"CR EOF after doctype name", +"input":"<!doctype html \r", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"CR EOF in tag name", +"input":"<z\r", +"output":["ParseError"]}, + +{"description":"Slash EOF in tag name", +"input":"<z/", +"output":["ParseError"]}, + +{"description":"Zero hex numeric entity", +"input":"&#x0", +"output":["ParseError", "ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Zero decimal numeric entity", +"input":"&#0", +"output":["ParseError", "ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Zero-prefixed hex numeric entity", +"input":"&#x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041;", +"output":[["Character", "A"]]}, + +{"description":"Zero-prefixed decimal numeric entity", +"input":"&#000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000065;", +"output":[["Character", "A"]]}, + +{"description":"Empty hex numeric entities", +"input":"&#x &#X ", +"output":["ParseError", ["Character", "&#x "], "ParseError", ["Character", "&#X "]]}, + +{"description":"Empty decimal numeric entities", +"input":"&# &#; ", +"output":["ParseError", ["Character", "&# "], "ParseError", ["Character", "&#; "]]}, + +{"description":"Non-BMP numeric entity", +"input":"&#x10000;", +"output":[["Character", "\uD800\uDC00"]]}, + +{"description":"Maximum non-BMP numeric entity", +"input":"&#X10FFFF;", +"output":["ParseError", ["Character", "\uDBFF\uDFFF"]]}, + +{"description":"Above maximum numeric entity", +"input":"&#x110000;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"32-bit hex numeric entity", +"input":"&#x80000041;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"33-bit hex numeric entity", +"input":"&#x100000041;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"33-bit decimal numeric entity", +"input":"&#4294967361;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"65-bit hex numeric entity", +"input":"&#x10000000000000041;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"65-bit decimal numeric entity", +"input":"&#18446744073709551681;", +"output":["ParseError", ["Character", "\uFFFD"]]}, + +{"description":"Surrogate code point edge cases", +"input":"&#xD7FF;&#xD800;&#xD801;&#xDFFE;&#xDFFF;&#xE000;", +"output":[["Character", "\uD7FF"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD\uE000"]]}, + +{"description":"Uppercase start tag name", +"input":"<X>", +"output":[["StartTag", "x", {}]]}, + +{"description":"Uppercase end tag name", +"input":"</X>", +"output":[["EndTag", "x"]]}, + +{"description":"Uppercase attribute name", +"input":"<x X>", +"output":[["StartTag", "x", { "x":"" }]]}, + +{"description":"Tag/attribute name case edge values", +"input":"<x@AZ[`az{ @AZ[`az{>", +"output":[["StartTag", "x@az[`az{", { "@az[`az{":"" }]]}, + +{"description":"Duplicate different-case attributes", +"input":"<x x=1 x=2 X=3>", +"output":["ParseError", "ParseError", ["StartTag", "x", { "x":"1" }]]}, + +{"description":"Uppercase close tag attributes", +"input":"</x X>", +"output":["ParseError", ["EndTag", "x"]]}, + +{"description":"Duplicate close tag attributes", +"input":"</x x x>", +"output":["ParseError", "ParseError", ["EndTag", "x"]]}, + +{"description":"Permitted slash", +"input":"<br/>", +"output":[["StartTag","br",{},true]]}, + +{"description":"Non-permitted slash", +"input":"<xr/>", +"output":[["StartTag","xr",{},true]]}, + +{"description":"Permitted slash but in close tag", +"input":"</br/>", +"output":["ParseError", ["EndTag", "br"]]}, + +{"description":"Doctype public case-sensitivity (1)", +"input":"<!DoCtYpE HtMl PuBlIc \"AbC\" \"XyZ\">", +"output":[["DOCTYPE", "html", "AbC", "XyZ", true]]}, + +{"description":"Doctype public case-sensitivity (2)", +"input":"<!dOcTyPe hTmL pUbLiC \"aBc\" \"xYz\">", +"output":[["DOCTYPE", "html", "aBc", "xYz", true]]}, + +{"description":"Doctype system case-sensitivity (1)", +"input":"<!DoCtYpE HtMl SyStEm \"XyZ\">", +"output":[["DOCTYPE", "html", null, "XyZ", true]]}, + +{"description":"Doctype system case-sensitivity (2)", +"input":"<!dOcTyPe hTmL sYsTeM \"xYz\">", +"output":[["DOCTYPE", "html", null, "xYz", true]]}, + +{"description":"U+0000 in lookahead region after non-matching character", +"input":"<!doc>\u0000", +"output":["ParseError", ["Comment", "doc"], "ParseError", ["Character", "\u0000"]], +"ignoreErrorOrder":true}, + +{"description":"U+0000 in lookahead region", +"input":"<!doc\u0000", +"output":["ParseError", ["Comment", "doc\uFFFD"]], +"ignoreErrorOrder":true}, + +{"description":"U+0080 in lookahead region", +"input":"<!doc\u0080", +"output":["ParseError", "ParseError", ["Comment", "doc\u0080"]], +"ignoreErrorOrder":true}, + +{"description":"U+FDD1 in lookahead region", +"input":"<!doc\uFDD1", +"output":["ParseError", "ParseError", ["Comment", "doc\uFDD1"]], +"ignoreErrorOrder":true}, + +{"description":"U+1FFFF in lookahead region", +"input":"<!doc\uD83F\uDFFF", +"output":["ParseError", "ParseError", ["Comment", "doc\uD83F\uDFFF"]], +"ignoreErrorOrder":true}, + +{"description":"CR followed by non-LF", +"input":"\r?", +"output":[["Character", "\n?"]]}, + +{"description":"CR at EOF", +"input":"\r", +"output":[["Character", "\n"]]}, + +{"description":"LF at EOF", +"input":"\n", +"output":[["Character", "\n"]]}, + +{"description":"CR LF", +"input":"\r\n", +"output":[["Character", "\n"]]}, + +{"description":"CR CR", +"input":"\r\r", +"output":[["Character", "\n\n"]]}, + +{"description":"LF LF", +"input":"\n\n", +"output":[["Character", "\n\n"]]}, + +{"description":"LF CR", +"input":"\n\r", +"output":[["Character", "\n\n"]]}, + +{"description":"text CR CR CR text", +"input":"text\r\r\rtext", +"output":[["Character", "text\n\n\ntext"]]}, + +{"description":"Doctype publik", +"input":"<!DOCTYPE html PUBLIK \"AbC\" \"XyZ\">", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"Doctype publi", +"input":"<!DOCTYPE html PUBLI", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"Doctype sistem", +"input":"<!DOCTYPE html SISTEM \"AbC\">", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"Doctype sys", +"input":"<!DOCTYPE html SYS", +"output":["ParseError", ["DOCTYPE", "html", null, null, false]]}, + +{"description":"Doctype html x>text", +"input":"<!DOCTYPE html x>text", +"output":["ParseError", ["DOCTYPE", "html", null, null, false], ["Character", "text"]]}, + +{"description":"Grave accent in unquoted attribute", +"input":"<a a=aa`>", +"output":["ParseError", ["StartTag", "a", {"a":"aa`"}]]}, + +{"description":"EOF in tag name state ", +"input":"<a", +"output":["ParseError"]}, + +{"description":"EOF in tag name state", +"input":"<a", +"output":["ParseError"]}, + +{"description":"EOF in before attribute name state", +"input":"<a ", +"output":["ParseError"]}, + +{"description":"EOF in attribute name state", +"input":"<a a", +"output":["ParseError"]}, + +{"description":"EOF in after attribute name state", +"input":"<a a ", +"output":["ParseError"]}, + +{"description":"EOF in before attribute value state", +"input":"<a a =", +"output":["ParseError"]}, + +{"description":"EOF in attribute value (double quoted) state", +"input":"<a a =\"a", +"output":["ParseError"]}, + +{"description":"EOF in attribute value (single quoted) state", +"input":"<a a ='a", +"output":["ParseError"]}, + +{"description":"EOF in attribute value (unquoted) state", +"input":"<a a =a", +"output":["ParseError"]}, + +{"description":"EOF in after attribute value state", +"input":"<a a ='a'", +"output":["ParseError"]} + +]} diff --git a/pkgs/html/test/data/tokenizer/unicodeChars.test b/pkgs/html/test/data/tokenizer/unicodeChars.test new file mode 100644 index 000000000..c7786682c --- /dev/null +++ b/pkgs/html/test/data/tokenizer/unicodeChars.test @@ -0,0 +1,1295 @@ +{"tests": [ + +{"description": "Invalid Unicode character U+0001", +"input": "\u0001", +"output": ["ParseError", ["Character", "\u0001"]]}, + +{"description": "Invalid Unicode character U+0002", +"input": "\u0002", +"output": ["ParseError", ["Character", "\u0002"]]}, + +{"description": "Invalid Unicode character U+0003", +"input": "\u0003", +"output": ["ParseError", ["Character", "\u0003"]]}, + +{"description": "Invalid Unicode character U+0004", +"input": "\u0004", +"output": ["ParseError", ["Character", "\u0004"]]}, + +{"description": "Invalid Unicode character U+0005", +"input": "\u0005", +"output": ["ParseError", ["Character", "\u0005"]]}, + +{"description": "Invalid Unicode character U+0006", +"input": "\u0006", +"output": ["ParseError", ["Character", "\u0006"]]}, + +{"description": "Invalid Unicode character U+0007", +"input": "\u0007", +"output": ["ParseError", ["Character", "\u0007"]]}, + +{"description": "Invalid Unicode character U+0008", +"input": "\u0008", +"output": ["ParseError", ["Character", "\u0008"]]}, + +{"description": "Invalid Unicode character U+000B", +"input": "\u000B", +"output": ["ParseError", ["Character", "\u000B"]]}, + +{"description": "Invalid Unicode character U+000E", +"input": "\u000E", +"output": ["ParseError", ["Character", "\u000E"]]}, + +{"description": "Invalid Unicode character U+000F", +"input": "\u000F", +"output": ["ParseError", ["Character", "\u000F"]]}, + +{"description": "Invalid Unicode character U+0010", +"input": "\u0010", +"output": ["ParseError", ["Character", "\u0010"]]}, + +{"description": "Invalid Unicode character U+0011", +"input": "\u0011", +"output": ["ParseError", ["Character", "\u0011"]]}, + +{"description": "Invalid Unicode character U+0012", +"input": "\u0012", +"output": ["ParseError", ["Character", "\u0012"]]}, + +{"description": "Invalid Unicode character U+0013", +"input": "\u0013", +"output": ["ParseError", ["Character", "\u0013"]]}, + +{"description": "Invalid Unicode character U+0014", +"input": "\u0014", +"output": ["ParseError", ["Character", "\u0014"]]}, + +{"description": "Invalid Unicode character U+0015", +"input": "\u0015", +"output": ["ParseError", ["Character", "\u0015"]]}, + +{"description": "Invalid Unicode character U+0016", +"input": "\u0016", +"output": ["ParseError", ["Character", "\u0016"]]}, + +{"description": "Invalid Unicode character U+0017", +"input": "\u0017", +"output": ["ParseError", ["Character", "\u0017"]]}, + +{"description": "Invalid Unicode character U+0018", +"input": "\u0018", +"output": ["ParseError", ["Character", "\u0018"]]}, + +{"description": "Invalid Unicode character U+0019", +"input": "\u0019", +"output": ["ParseError", ["Character", "\u0019"]]}, + +{"description": "Invalid Unicode character U+001A", +"input": "\u001A", +"output": ["ParseError", ["Character", "\u001A"]]}, + +{"description": "Invalid Unicode character U+001B", +"input": "\u001B", +"output": ["ParseError", ["Character", "\u001B"]]}, + +{"description": "Invalid Unicode character U+001C", +"input": "\u001C", +"output": ["ParseError", ["Character", "\u001C"]]}, + +{"description": "Invalid Unicode character U+001D", +"input": "\u001D", +"output": ["ParseError", ["Character", "\u001D"]]}, + +{"description": "Invalid Unicode character U+001E", +"input": "\u001E", +"output": ["ParseError", ["Character", "\u001E"]]}, + +{"description": "Invalid Unicode character U+001F", +"input": "\u001F", +"output": ["ParseError", ["Character", "\u001F"]]}, + +{"description": "Invalid Unicode character U+007F", +"input": "\u007F", +"output": ["ParseError", ["Character", "\u007F"]]}, + +{"description": "Invalid Unicode character U+FDD0", +"input": "\uFDD0", +"output": ["ParseError", ["Character", "\uFDD0"]]}, + +{"description": "Invalid Unicode character U+FDD1", +"input": "\uFDD1", +"output": ["ParseError", ["Character", "\uFDD1"]]}, + +{"description": "Invalid Unicode character U+FDD2", +"input": "\uFDD2", +"output": ["ParseError", ["Character", "\uFDD2"]]}, + +{"description": "Invalid Unicode character U+FDD3", +"input": "\uFDD3", +"output": ["ParseError", ["Character", "\uFDD3"]]}, + +{"description": "Invalid Unicode character U+FDD4", +"input": "\uFDD4", +"output": ["ParseError", ["Character", "\uFDD4"]]}, + +{"description": "Invalid Unicode character U+FDD5", +"input": "\uFDD5", +"output": ["ParseError", ["Character", "\uFDD5"]]}, + +{"description": "Invalid Unicode character U+FDD6", +"input": "\uFDD6", +"output": ["ParseError", ["Character", "\uFDD6"]]}, + +{"description": "Invalid Unicode character U+FDD7", +"input": "\uFDD7", +"output": ["ParseError", ["Character", "\uFDD7"]]}, + +{"description": "Invalid Unicode character U+FDD8", +"input": "\uFDD8", +"output": ["ParseError", ["Character", "\uFDD8"]]}, + +{"description": "Invalid Unicode character U+FDD9", +"input": "\uFDD9", +"output": ["ParseError", ["Character", "\uFDD9"]]}, + +{"description": "Invalid Unicode character U+FDDA", +"input": "\uFDDA", +"output": ["ParseError", ["Character", "\uFDDA"]]}, + +{"description": "Invalid Unicode character U+FDDB", +"input": "\uFDDB", +"output": ["ParseError", ["Character", "\uFDDB"]]}, + +{"description": "Invalid Unicode character U+FDDC", +"input": "\uFDDC", +"output": ["ParseError", ["Character", "\uFDDC"]]}, + +{"description": "Invalid Unicode character U+FDDD", +"input": "\uFDDD", +"output": ["ParseError", ["Character", "\uFDDD"]]}, + +{"description": "Invalid Unicode character U+FDDE", +"input": "\uFDDE", +"output": ["ParseError", ["Character", "\uFDDE"]]}, + +{"description": "Invalid Unicode character U+FDDF", +"input": "\uFDDF", +"output": ["ParseError", ["Character", "\uFDDF"]]}, + +{"description": "Invalid Unicode character U+FDE0", +"input": "\uFDE0", +"output": ["ParseError", ["Character", "\uFDE0"]]}, + +{"description": "Invalid Unicode character U+FDE1", +"input": "\uFDE1", +"output": ["ParseError", ["Character", "\uFDE1"]]}, + +{"description": "Invalid Unicode character U+FDE2", +"input": "\uFDE2", +"output": ["ParseError", ["Character", "\uFDE2"]]}, + +{"description": "Invalid Unicode character U+FDE3", +"input": "\uFDE3", +"output": ["ParseError", ["Character", "\uFDE3"]]}, + +{"description": "Invalid Unicode character U+FDE4", +"input": "\uFDE4", +"output": ["ParseError", ["Character", "\uFDE4"]]}, + +{"description": "Invalid Unicode character U+FDE5", +"input": "\uFDE5", +"output": ["ParseError", ["Character", "\uFDE5"]]}, + +{"description": "Invalid Unicode character U+FDE6", +"input": "\uFDE6", +"output": ["ParseError", ["Character", "\uFDE6"]]}, + +{"description": "Invalid Unicode character U+FDE7", +"input": "\uFDE7", +"output": ["ParseError", ["Character", "\uFDE7"]]}, + +{"description": "Invalid Unicode character U+FDE8", +"input": "\uFDE8", +"output": ["ParseError", ["Character", "\uFDE8"]]}, + +{"description": "Invalid Unicode character U+FDE9", +"input": "\uFDE9", +"output": ["ParseError", ["Character", "\uFDE9"]]}, + +{"description": "Invalid Unicode character U+FDEA", +"input": "\uFDEA", +"output": ["ParseError", ["Character", "\uFDEA"]]}, + +{"description": "Invalid Unicode character U+FDEB", +"input": "\uFDEB", +"output": ["ParseError", ["Character", "\uFDEB"]]}, + +{"description": "Invalid Unicode character U+FDEC", +"input": "\uFDEC", +"output": ["ParseError", ["Character", "\uFDEC"]]}, + +{"description": "Invalid Unicode character U+FDED", +"input": "\uFDED", +"output": ["ParseError", ["Character", "\uFDED"]]}, + +{"description": "Invalid Unicode character U+FDEE", +"input": "\uFDEE", +"output": ["ParseError", ["Character", "\uFDEE"]]}, + +{"description": "Invalid Unicode character U+FDEF", +"input": "\uFDEF", +"output": ["ParseError", ["Character", "\uFDEF"]]}, + +{"description": "Invalid Unicode character U+FFFE", +"input": "\uFFFE", +"output": ["ParseError", ["Character", "\uFFFE"]]}, + +{"description": "Invalid Unicode character U+FFFF", +"input": "\uFFFF", +"output": ["ParseError", ["Character", "\uFFFF"]]}, + +{"description": "Invalid Unicode character U+1FFFE", +"input": "\uD83F\uDFFE", +"output": ["ParseError", ["Character", "\uD83F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+1FFFF", +"input": "\uD83F\uDFFF", +"output": ["ParseError", ["Character", "\uD83F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+2FFFE", +"input": "\uD87F\uDFFE", +"output": ["ParseError", ["Character", "\uD87F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+2FFFF", +"input": "\uD87F\uDFFF", +"output": ["ParseError", ["Character", "\uD87F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+3FFFE", +"input": "\uD8BF\uDFFE", +"output": ["ParseError", ["Character", "\uD8BF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+3FFFF", +"input": "\uD8BF\uDFFF", +"output": ["ParseError", ["Character", "\uD8BF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+4FFFE", +"input": "\uD8FF\uDFFE", +"output": ["ParseError", ["Character", "\uD8FF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+4FFFF", +"input": "\uD8FF\uDFFF", +"output": ["ParseError", ["Character", "\uD8FF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+5FFFE", +"input": "\uD93F\uDFFE", +"output": ["ParseError", ["Character", "\uD93F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+5FFFF", +"input": "\uD93F\uDFFF", +"output": ["ParseError", ["Character", "\uD93F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+6FFFE", +"input": "\uD97F\uDFFE", +"output": ["ParseError", ["Character", "\uD97F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+6FFFF", +"input": "\uD97F\uDFFF", +"output": ["ParseError", ["Character", "\uD97F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+7FFFE", +"input": "\uD9BF\uDFFE", +"output": ["ParseError", ["Character", "\uD9BF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+7FFFF", +"input": "\uD9BF\uDFFF", +"output": ["ParseError", ["Character", "\uD9BF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+8FFFE", +"input": "\uD9FF\uDFFE", +"output": ["ParseError", ["Character", "\uD9FF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+8FFFF", +"input": "\uD9FF\uDFFF", +"output": ["ParseError", ["Character", "\uD9FF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+9FFFE", +"input": "\uDA3F\uDFFE", +"output": ["ParseError", ["Character", "\uDA3F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+9FFFF", +"input": "\uDA3F\uDFFF", +"output": ["ParseError", ["Character", "\uDA3F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+AFFFE", +"input": "\uDA7F\uDFFE", +"output": ["ParseError", ["Character", "\uDA7F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+AFFFF", +"input": "\uDA7F\uDFFF", +"output": ["ParseError", ["Character", "\uDA7F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+BFFFE", +"input": "\uDABF\uDFFE", +"output": ["ParseError", ["Character", "\uDABF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+BFFFF", +"input": "\uDABF\uDFFF", +"output": ["ParseError", ["Character", "\uDABF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+CFFFE", +"input": "\uDAFF\uDFFE", +"output": ["ParseError", ["Character", "\uDAFF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+CFFFF", +"input": "\uDAFF\uDFFF", +"output": ["ParseError", ["Character", "\uDAFF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+DFFFE", +"input": "\uDB3F\uDFFE", +"output": ["ParseError", ["Character", "\uDB3F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+DFFFF", +"input": "\uDB3F\uDFFF", +"output": ["ParseError", ["Character", "\uDB3F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+EFFFE", +"input": "\uDB7F\uDFFE", +"output": ["ParseError", ["Character", "\uDB7F\uDFFE"]]}, + +{"description": "Invalid Unicode character U+EFFFF", +"input": "\uDB7F\uDFFF", +"output": ["ParseError", ["Character", "\uDB7F\uDFFF"]]}, + +{"description": "Invalid Unicode character U+FFFFE", +"input": "\uDBBF\uDFFE", +"output": ["ParseError", ["Character", "\uDBBF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+FFFFF", +"input": "\uDBBF\uDFFF", +"output": ["ParseError", ["Character", "\uDBBF\uDFFF"]]}, + +{"description": "Invalid Unicode character U+10FFFE", +"input": "\uDBFF\uDFFE", +"output": ["ParseError", ["Character", "\uDBFF\uDFFE"]]}, + +{"description": "Invalid Unicode character U+10FFFF", +"input": "\uDBFF\uDFFF", +"output": ["ParseError", ["Character", "\uDBFF\uDFFF"]]}, + +{"description": "Valid Unicode character U+0009", +"input": "\u0009", +"output": [["Character", "\u0009"]]}, + +{"description": "Valid Unicode character U+000A", +"input": "\u000A", +"output": [["Character", "\u000A"]]}, + +{"description": "Valid Unicode character U+0020", +"input": "\u0020", +"output": [["Character", "\u0020"]]}, + +{"description": "Valid Unicode character U+0021", +"input": "\u0021", +"output": [["Character", "\u0021"]]}, + +{"description": "Valid Unicode character U+0022", +"input": "\u0022", +"output": [["Character", "\u0022"]]}, + +{"description": "Valid Unicode character U+0023", +"input": "\u0023", +"output": [["Character", "\u0023"]]}, + +{"description": "Valid Unicode character U+0024", +"input": "\u0024", +"output": [["Character", "\u0024"]]}, + +{"description": "Valid Unicode character U+0025", +"input": "\u0025", +"output": [["Character", "\u0025"]]}, + +{"description": "Valid Unicode character U+0026", +"input": "\u0026", +"output": [["Character", "\u0026"]]}, + +{"description": "Valid Unicode character U+0027", +"input": "\u0027", +"output": [["Character", "\u0027"]]}, + +{"description": "Valid Unicode character U+0028", +"input": "\u0028", +"output": [["Character", "\u0028"]]}, + +{"description": "Valid Unicode character U+0029", +"input": "\u0029", +"output": [["Character", "\u0029"]]}, + +{"description": "Valid Unicode character U+002A", +"input": "\u002A", +"output": [["Character", "\u002A"]]}, + +{"description": "Valid Unicode character U+002B", +"input": "\u002B", +"output": [["Character", "\u002B"]]}, + +{"description": "Valid Unicode character U+002C", +"input": "\u002C", +"output": [["Character", "\u002C"]]}, + +{"description": "Valid Unicode character U+002D", +"input": "\u002D", +"output": [["Character", "\u002D"]]}, + +{"description": "Valid Unicode character U+002E", +"input": "\u002E", +"output": [["Character", "\u002E"]]}, + +{"description": "Valid Unicode character U+002F", +"input": "\u002F", +"output": [["Character", "\u002F"]]}, + +{"description": "Valid Unicode character U+0030", +"input": "\u0030", +"output": [["Character", "\u0030"]]}, + +{"description": "Valid Unicode character U+0031", +"input": "\u0031", +"output": [["Character", "\u0031"]]}, + +{"description": "Valid Unicode character U+0032", +"input": "\u0032", +"output": [["Character", "\u0032"]]}, + +{"description": "Valid Unicode character U+0033", +"input": "\u0033", +"output": [["Character", "\u0033"]]}, + +{"description": "Valid Unicode character U+0034", +"input": "\u0034", +"output": [["Character", "\u0034"]]}, + +{"description": "Valid Unicode character U+0035", +"input": "\u0035", +"output": [["Character", "\u0035"]]}, + +{"description": "Valid Unicode character U+0036", +"input": "\u0036", +"output": [["Character", "\u0036"]]}, + +{"description": "Valid Unicode character U+0037", +"input": "\u0037", +"output": [["Character", "\u0037"]]}, + +{"description": "Valid Unicode character U+0038", +"input": "\u0038", +"output": [["Character", "\u0038"]]}, + +{"description": "Valid Unicode character U+0039", +"input": "\u0039", +"output": [["Character", "\u0039"]]}, + +{"description": "Valid Unicode character U+003A", +"input": "\u003A", +"output": [["Character", "\u003A"]]}, + +{"description": "Valid Unicode character U+003B", +"input": "\u003B", +"output": [["Character", "\u003B"]]}, + +{"description": "Valid Unicode character U+003D", +"input": "\u003D", +"output": [["Character", "\u003D"]]}, + +{"description": "Valid Unicode character U+003E", +"input": "\u003E", +"output": [["Character", "\u003E"]]}, + +{"description": "Valid Unicode character U+003F", +"input": "\u003F", +"output": [["Character", "\u003F"]]}, + +{"description": "Valid Unicode character U+0040", +"input": "\u0040", +"output": [["Character", "\u0040"]]}, + +{"description": "Valid Unicode character U+0041", +"input": "\u0041", +"output": [["Character", "\u0041"]]}, + +{"description": "Valid Unicode character U+0042", +"input": "\u0042", +"output": [["Character", "\u0042"]]}, + +{"description": "Valid Unicode character U+0043", +"input": "\u0043", +"output": [["Character", "\u0043"]]}, + +{"description": "Valid Unicode character U+0044", +"input": "\u0044", +"output": [["Character", "\u0044"]]}, + +{"description": "Valid Unicode character U+0045", +"input": "\u0045", +"output": [["Character", "\u0045"]]}, + +{"description": "Valid Unicode character U+0046", +"input": "\u0046", +"output": [["Character", "\u0046"]]}, + +{"description": "Valid Unicode character U+0047", +"input": "\u0047", +"output": [["Character", "\u0047"]]}, + +{"description": "Valid Unicode character U+0048", +"input": "\u0048", +"output": [["Character", "\u0048"]]}, + +{"description": "Valid Unicode character U+0049", +"input": "\u0049", +"output": [["Character", "\u0049"]]}, + +{"description": "Valid Unicode character U+004A", +"input": "\u004A", +"output": [["Character", "\u004A"]]}, + +{"description": "Valid Unicode character U+004B", +"input": "\u004B", +"output": [["Character", "\u004B"]]}, + +{"description": "Valid Unicode character U+004C", +"input": "\u004C", +"output": [["Character", "\u004C"]]}, + +{"description": "Valid Unicode character U+004D", +"input": "\u004D", +"output": [["Character", "\u004D"]]}, + +{"description": "Valid Unicode character U+004E", +"input": "\u004E", +"output": [["Character", "\u004E"]]}, + +{"description": "Valid Unicode character U+004F", +"input": "\u004F", +"output": [["Character", "\u004F"]]}, + +{"description": "Valid Unicode character U+0050", +"input": "\u0050", +"output": [["Character", "\u0050"]]}, + +{"description": "Valid Unicode character U+0051", +"input": "\u0051", +"output": [["Character", "\u0051"]]}, + +{"description": "Valid Unicode character U+0052", +"input": "\u0052", +"output": [["Character", "\u0052"]]}, + +{"description": "Valid Unicode character U+0053", +"input": "\u0053", +"output": [["Character", "\u0053"]]}, + +{"description": "Valid Unicode character U+0054", +"input": "\u0054", +"output": [["Character", "\u0054"]]}, + +{"description": "Valid Unicode character U+0055", +"input": "\u0055", +"output": [["Character", "\u0055"]]}, + +{"description": "Valid Unicode character U+0056", +"input": "\u0056", +"output": [["Character", "\u0056"]]}, + +{"description": "Valid Unicode character U+0057", +"input": "\u0057", +"output": [["Character", "\u0057"]]}, + +{"description": "Valid Unicode character U+0058", +"input": "\u0058", +"output": [["Character", "\u0058"]]}, + +{"description": "Valid Unicode character U+0059", +"input": "\u0059", +"output": [["Character", "\u0059"]]}, + +{"description": "Valid Unicode character U+005A", +"input": "\u005A", +"output": [["Character", "\u005A"]]}, + +{"description": "Valid Unicode character U+005B", +"input": "\u005B", +"output": [["Character", "\u005B"]]}, + +{"description": "Valid Unicode character U+005C", +"input": "\u005C", +"output": [["Character", "\u005C"]]}, + +{"description": "Valid Unicode character U+005D", +"input": "\u005D", +"output": [["Character", "\u005D"]]}, + +{"description": "Valid Unicode character U+005E", +"input": "\u005E", +"output": [["Character", "\u005E"]]}, + +{"description": "Valid Unicode character U+005F", +"input": "\u005F", +"output": [["Character", "\u005F"]]}, + +{"description": "Valid Unicode character U+0060", +"input": "\u0060", +"output": [["Character", "\u0060"]]}, + +{"description": "Valid Unicode character U+0061", +"input": "\u0061", +"output": [["Character", "\u0061"]]}, + +{"description": "Valid Unicode character U+0062", +"input": "\u0062", +"output": [["Character", "\u0062"]]}, + +{"description": "Valid Unicode character U+0063", +"input": "\u0063", +"output": [["Character", "\u0063"]]}, + +{"description": "Valid Unicode character U+0064", +"input": "\u0064", +"output": [["Character", "\u0064"]]}, + +{"description": "Valid Unicode character U+0065", +"input": "\u0065", +"output": [["Character", "\u0065"]]}, + +{"description": "Valid Unicode character U+0066", +"input": "\u0066", +"output": [["Character", "\u0066"]]}, + +{"description": "Valid Unicode character U+0067", +"input": "\u0067", +"output": [["Character", "\u0067"]]}, + +{"description": "Valid Unicode character U+0068", +"input": "\u0068", +"output": [["Character", "\u0068"]]}, + +{"description": "Valid Unicode character U+0069", +"input": "\u0069", +"output": [["Character", "\u0069"]]}, + +{"description": "Valid Unicode character U+006A", +"input": "\u006A", +"output": [["Character", "\u006A"]]}, + +{"description": "Valid Unicode character U+006B", +"input": "\u006B", +"output": [["Character", "\u006B"]]}, + +{"description": "Valid Unicode character U+006C", +"input": "\u006C", +"output": [["Character", "\u006C"]]}, + +{"description": "Valid Unicode character U+006D", +"input": "\u006D", +"output": [["Character", "\u006D"]]}, + +{"description": "Valid Unicode character U+006E", +"input": "\u006E", +"output": [["Character", "\u006E"]]}, + +{"description": "Valid Unicode character U+006F", +"input": "\u006F", +"output": [["Character", "\u006F"]]}, + +{"description": "Valid Unicode character U+0070", +"input": "\u0070", +"output": [["Character", "\u0070"]]}, + +{"description": "Valid Unicode character U+0071", +"input": "\u0071", +"output": [["Character", "\u0071"]]}, + +{"description": "Valid Unicode character U+0072", +"input": "\u0072", +"output": [["Character", "\u0072"]]}, + +{"description": "Valid Unicode character U+0073", +"input": "\u0073", +"output": [["Character", "\u0073"]]}, + +{"description": "Valid Unicode character U+0074", +"input": "\u0074", +"output": [["Character", "\u0074"]]}, + +{"description": "Valid Unicode character U+0075", +"input": "\u0075", +"output": [["Character", "\u0075"]]}, + +{"description": "Valid Unicode character U+0076", +"input": "\u0076", +"output": [["Character", "\u0076"]]}, + +{"description": "Valid Unicode character U+0077", +"input": "\u0077", +"output": [["Character", "\u0077"]]}, + +{"description": "Valid Unicode character U+0078", +"input": "\u0078", +"output": [["Character", "\u0078"]]}, + +{"description": "Valid Unicode character U+0079", +"input": "\u0079", +"output": [["Character", "\u0079"]]}, + +{"description": "Valid Unicode character U+007A", +"input": "\u007A", +"output": [["Character", "\u007A"]]}, + +{"description": "Valid Unicode character U+007B", +"input": "\u007B", +"output": [["Character", "\u007B"]]}, + +{"description": "Valid Unicode character U+007C", +"input": "\u007C", +"output": [["Character", "\u007C"]]}, + +{"description": "Valid Unicode character U+007D", +"input": "\u007D", +"output": [["Character", "\u007D"]]}, + +{"description": "Valid Unicode character U+007E", +"input": "\u007E", +"output": [["Character", "\u007E"]]}, + +{"description": "Valid Unicode character U+00A0", +"input": "\u00A0", +"output": [["Character", "\u00A0"]]}, + +{"description": "Valid Unicode character U+00A1", +"input": "\u00A1", +"output": [["Character", "\u00A1"]]}, + +{"description": "Valid Unicode character U+00A2", +"input": "\u00A2", +"output": [["Character", "\u00A2"]]}, + +{"description": "Valid Unicode character U+00A3", +"input": "\u00A3", +"output": [["Character", "\u00A3"]]}, + +{"description": "Valid Unicode character U+00A4", +"input": "\u00A4", +"output": [["Character", "\u00A4"]]}, + +{"description": "Valid Unicode character U+00A5", +"input": "\u00A5", +"output": [["Character", "\u00A5"]]}, + +{"description": "Valid Unicode character U+00A6", +"input": "\u00A6", +"output": [["Character", "\u00A6"]]}, + +{"description": "Valid Unicode character U+00A7", +"input": "\u00A7", +"output": [["Character", "\u00A7"]]}, + +{"description": "Valid Unicode character U+00A8", +"input": "\u00A8", +"output": [["Character", "\u00A8"]]}, + +{"description": "Valid Unicode character U+00A9", +"input": "\u00A9", +"output": [["Character", "\u00A9"]]}, + +{"description": "Valid Unicode character U+00AA", +"input": "\u00AA", +"output": [["Character", "\u00AA"]]}, + +{"description": "Valid Unicode character U+00AB", +"input": "\u00AB", +"output": [["Character", "\u00AB"]]}, + +{"description": "Valid Unicode character U+00AC", +"input": "\u00AC", +"output": [["Character", "\u00AC"]]}, + +{"description": "Valid Unicode character U+00AD", +"input": "\u00AD", +"output": [["Character", "\u00AD"]]}, + +{"description": "Valid Unicode character U+00AE", +"input": "\u00AE", +"output": [["Character", "\u00AE"]]}, + +{"description": "Valid Unicode character U+00AF", +"input": "\u00AF", +"output": [["Character", "\u00AF"]]}, + +{"description": "Valid Unicode character U+00B0", +"input": "\u00B0", +"output": [["Character", "\u00B0"]]}, + +{"description": "Valid Unicode character U+00B1", +"input": "\u00B1", +"output": [["Character", "\u00B1"]]}, + +{"description": "Valid Unicode character U+00B2", +"input": "\u00B2", +"output": [["Character", "\u00B2"]]}, + +{"description": "Valid Unicode character U+00B3", +"input": "\u00B3", +"output": [["Character", "\u00B3"]]}, + +{"description": "Valid Unicode character U+00B4", +"input": "\u00B4", +"output": [["Character", "\u00B4"]]}, + +{"description": "Valid Unicode character U+00B5", +"input": "\u00B5", +"output": [["Character", "\u00B5"]]}, + +{"description": "Valid Unicode character U+00B6", +"input": "\u00B6", +"output": [["Character", "\u00B6"]]}, + +{"description": "Valid Unicode character U+00B7", +"input": "\u00B7", +"output": [["Character", "\u00B7"]]}, + +{"description": "Valid Unicode character U+00B8", +"input": "\u00B8", +"output": [["Character", "\u00B8"]]}, + +{"description": "Valid Unicode character U+00B9", +"input": "\u00B9", +"output": [["Character", "\u00B9"]]}, + +{"description": "Valid Unicode character U+00BA", +"input": "\u00BA", +"output": [["Character", "\u00BA"]]}, + +{"description": "Valid Unicode character U+00BB", +"input": "\u00BB", +"output": [["Character", "\u00BB"]]}, + +{"description": "Valid Unicode character U+00BC", +"input": "\u00BC", +"output": [["Character", "\u00BC"]]}, + +{"description": "Valid Unicode character U+00BD", +"input": "\u00BD", +"output": [["Character", "\u00BD"]]}, + +{"description": "Valid Unicode character U+00BE", +"input": "\u00BE", +"output": [["Character", "\u00BE"]]}, + +{"description": "Valid Unicode character U+00BF", +"input": "\u00BF", +"output": [["Character", "\u00BF"]]}, + +{"description": "Valid Unicode character U+00C0", +"input": "\u00C0", +"output": [["Character", "\u00C0"]]}, + +{"description": "Valid Unicode character U+00C1", +"input": "\u00C1", +"output": [["Character", "\u00C1"]]}, + +{"description": "Valid Unicode character U+00C2", +"input": "\u00C2", +"output": [["Character", "\u00C2"]]}, + +{"description": "Valid Unicode character U+00C3", +"input": "\u00C3", +"output": [["Character", "\u00C3"]]}, + +{"description": "Valid Unicode character U+00C4", +"input": "\u00C4", +"output": [["Character", "\u00C4"]]}, + +{"description": "Valid Unicode character U+00C5", +"input": "\u00C5", +"output": [["Character", "\u00C5"]]}, + +{"description": "Valid Unicode character U+00C6", +"input": "\u00C6", +"output": [["Character", "\u00C6"]]}, + +{"description": "Valid Unicode character U+00C7", +"input": "\u00C7", +"output": [["Character", "\u00C7"]]}, + +{"description": "Valid Unicode character U+00C8", +"input": "\u00C8", +"output": [["Character", "\u00C8"]]}, + +{"description": "Valid Unicode character U+00C9", +"input": "\u00C9", +"output": [["Character", "\u00C9"]]}, + +{"description": "Valid Unicode character U+00CA", +"input": "\u00CA", +"output": [["Character", "\u00CA"]]}, + +{"description": "Valid Unicode character U+00CB", +"input": "\u00CB", +"output": [["Character", "\u00CB"]]}, + +{"description": "Valid Unicode character U+00CC", +"input": "\u00CC", +"output": [["Character", "\u00CC"]]}, + +{"description": "Valid Unicode character U+00CD", +"input": "\u00CD", +"output": [["Character", "\u00CD"]]}, + +{"description": "Valid Unicode character U+00CE", +"input": "\u00CE", +"output": [["Character", "\u00CE"]]}, + +{"description": "Valid Unicode character U+00CF", +"input": "\u00CF", +"output": [["Character", "\u00CF"]]}, + +{"description": "Valid Unicode character U+00D0", +"input": "\u00D0", +"output": [["Character", "\u00D0"]]}, + +{"description": "Valid Unicode character U+00D1", +"input": "\u00D1", +"output": [["Character", "\u00D1"]]}, + +{"description": "Valid Unicode character U+00D2", +"input": "\u00D2", +"output": [["Character", "\u00D2"]]}, + +{"description": "Valid Unicode character U+00D3", +"input": "\u00D3", +"output": [["Character", "\u00D3"]]}, + +{"description": "Valid Unicode character U+00D4", +"input": "\u00D4", +"output": [["Character", "\u00D4"]]}, + +{"description": "Valid Unicode character U+00D5", +"input": "\u00D5", +"output": [["Character", "\u00D5"]]}, + +{"description": "Valid Unicode character U+00D6", +"input": "\u00D6", +"output": [["Character", "\u00D6"]]}, + +{"description": "Valid Unicode character U+00D7", +"input": "\u00D7", +"output": [["Character", "\u00D7"]]}, + +{"description": "Valid Unicode character U+00D8", +"input": "\u00D8", +"output": [["Character", "\u00D8"]]}, + +{"description": "Valid Unicode character U+00D9", +"input": "\u00D9", +"output": [["Character", "\u00D9"]]}, + +{"description": "Valid Unicode character U+00DA", +"input": "\u00DA", +"output": [["Character", "\u00DA"]]}, + +{"description": "Valid Unicode character U+00DB", +"input": "\u00DB", +"output": [["Character", "\u00DB"]]}, + +{"description": "Valid Unicode character U+00DC", +"input": "\u00DC", +"output": [["Character", "\u00DC"]]}, + +{"description": "Valid Unicode character U+00DD", +"input": "\u00DD", +"output": [["Character", "\u00DD"]]}, + +{"description": "Valid Unicode character U+00DE", +"input": "\u00DE", +"output": [["Character", "\u00DE"]]}, + +{"description": "Valid Unicode character U+00DF", +"input": "\u00DF", +"output": [["Character", "\u00DF"]]}, + +{"description": "Valid Unicode character U+00E0", +"input": "\u00E0", +"output": [["Character", "\u00E0"]]}, + +{"description": "Valid Unicode character U+00E1", +"input": "\u00E1", +"output": [["Character", "\u00E1"]]}, + +{"description": "Valid Unicode character U+00E2", +"input": "\u00E2", +"output": [["Character", "\u00E2"]]}, + +{"description": "Valid Unicode character U+00E3", +"input": "\u00E3", +"output": [["Character", "\u00E3"]]}, + +{"description": "Valid Unicode character U+00E4", +"input": "\u00E4", +"output": [["Character", "\u00E4"]]}, + +{"description": "Valid Unicode character U+00E5", +"input": "\u00E5", +"output": [["Character", "\u00E5"]]}, + +{"description": "Valid Unicode character U+00E6", +"input": "\u00E6", +"output": [["Character", "\u00E6"]]}, + +{"description": "Valid Unicode character U+00E7", +"input": "\u00E7", +"output": [["Character", "\u00E7"]]}, + +{"description": "Valid Unicode character U+00E8", +"input": "\u00E8", +"output": [["Character", "\u00E8"]]}, + +{"description": "Valid Unicode character U+00E9", +"input": "\u00E9", +"output": [["Character", "\u00E9"]]}, + +{"description": "Valid Unicode character U+00EA", +"input": "\u00EA", +"output": [["Character", "\u00EA"]]}, + +{"description": "Valid Unicode character U+00EB", +"input": "\u00EB", +"output": [["Character", "\u00EB"]]}, + +{"description": "Valid Unicode character U+00EC", +"input": "\u00EC", +"output": [["Character", "\u00EC"]]}, + +{"description": "Valid Unicode character U+00ED", +"input": "\u00ED", +"output": [["Character", "\u00ED"]]}, + +{"description": "Valid Unicode character U+00EE", +"input": "\u00EE", +"output": [["Character", "\u00EE"]]}, + +{"description": "Valid Unicode character U+00EF", +"input": "\u00EF", +"output": [["Character", "\u00EF"]]}, + +{"description": "Valid Unicode character U+00F0", +"input": "\u00F0", +"output": [["Character", "\u00F0"]]}, + +{"description": "Valid Unicode character U+00F1", +"input": "\u00F1", +"output": [["Character", "\u00F1"]]}, + +{"description": "Valid Unicode character U+00F2", +"input": "\u00F2", +"output": [["Character", "\u00F2"]]}, + +{"description": "Valid Unicode character U+00F3", +"input": "\u00F3", +"output": [["Character", "\u00F3"]]}, + +{"description": "Valid Unicode character U+00F4", +"input": "\u00F4", +"output": [["Character", "\u00F4"]]}, + +{"description": "Valid Unicode character U+00F5", +"input": "\u00F5", +"output": [["Character", "\u00F5"]]}, + +{"description": "Valid Unicode character U+00F6", +"input": "\u00F6", +"output": [["Character", "\u00F6"]]}, + +{"description": "Valid Unicode character U+00F7", +"input": "\u00F7", +"output": [["Character", "\u00F7"]]}, + +{"description": "Valid Unicode character U+00F8", +"input": "\u00F8", +"output": [["Character", "\u00F8"]]}, + +{"description": "Valid Unicode character U+00F9", +"input": "\u00F9", +"output": [["Character", "\u00F9"]]}, + +{"description": "Valid Unicode character U+00FA", +"input": "\u00FA", +"output": [["Character", "\u00FA"]]}, + +{"description": "Valid Unicode character U+00FB", +"input": "\u00FB", +"output": [["Character", "\u00FB"]]}, + +{"description": "Valid Unicode character U+00FC", +"input": "\u00FC", +"output": [["Character", "\u00FC"]]}, + +{"description": "Valid Unicode character U+00FD", +"input": "\u00FD", +"output": [["Character", "\u00FD"]]}, + +{"description": "Valid Unicode character U+00FE", +"input": "\u00FE", +"output": [["Character", "\u00FE"]]}, + +{"description": "Valid Unicode character U+00FF", +"input": "\u00FF", +"output": [["Character", "\u00FF"]]}, + +{"description": "Valid Unicode character U+D7FF", +"input": "\uD7FF", +"output": [["Character", "\uD7FF"]]}, + +{"description": "Valid Unicode character U+E000", +"input": "\uE000", +"output": [["Character", "\uE000"]]}, + +{"description": "Valid Unicode character U+FDCF", +"input": "\uFDCF", +"output": [["Character", "\uFDCF"]]}, + +{"description": "Valid Unicode character U+FDF0", +"input": "\uFDF0", +"output": [["Character", "\uFDF0"]]}, + +{"description": "Valid Unicode character U+FFFD", +"input": "\uFFFD", +"output": [["Character", "\uFFFD"]]}, + +{"description": "Valid Unicode character U+10000", +"input": "\uD800\uDC00", +"output": [["Character", "\uD800\uDC00"]]}, + +{"description": "Valid Unicode character U+1FFFD", +"input": "\uD83F\uDFFD", +"output": [["Character", "\uD83F\uDFFD"]]}, + +{"description": "Valid Unicode character U+20000", +"input": "\uD840\uDC00", +"output": [["Character", "\uD840\uDC00"]]}, + +{"description": "Valid Unicode character U+2FFFD", +"input": "\uD87F\uDFFD", +"output": [["Character", "\uD87F\uDFFD"]]}, + +{"description": "Valid Unicode character U+30000", +"input": "\uD880\uDC00", +"output": [["Character", "\uD880\uDC00"]]}, + +{"description": "Valid Unicode character U+3FFFD", +"input": "\uD8BF\uDFFD", +"output": [["Character", "\uD8BF\uDFFD"]]}, + +{"description": "Valid Unicode character U+40000", +"input": "\uD8C0\uDC00", +"output": [["Character", "\uD8C0\uDC00"]]}, + +{"description": "Valid Unicode character U+4FFFD", +"input": "\uD8FF\uDFFD", +"output": [["Character", "\uD8FF\uDFFD"]]}, + +{"description": "Valid Unicode character U+50000", +"input": "\uD900\uDC00", +"output": [["Character", "\uD900\uDC00"]]}, + +{"description": "Valid Unicode character U+5FFFD", +"input": "\uD93F\uDFFD", +"output": [["Character", "\uD93F\uDFFD"]]}, + +{"description": "Valid Unicode character U+60000", +"input": "\uD940\uDC00", +"output": [["Character", "\uD940\uDC00"]]}, + +{"description": "Valid Unicode character U+6FFFD", +"input": "\uD97F\uDFFD", +"output": [["Character", "\uD97F\uDFFD"]]}, + +{"description": "Valid Unicode character U+70000", +"input": "\uD980\uDC00", +"output": [["Character", "\uD980\uDC00"]]}, + +{"description": "Valid Unicode character U+7FFFD", +"input": "\uD9BF\uDFFD", +"output": [["Character", "\uD9BF\uDFFD"]]}, + +{"description": "Valid Unicode character U+80000", +"input": "\uD9C0\uDC00", +"output": [["Character", "\uD9C0\uDC00"]]}, + +{"description": "Valid Unicode character U+8FFFD", +"input": "\uD9FF\uDFFD", +"output": [["Character", "\uD9FF\uDFFD"]]}, + +{"description": "Valid Unicode character U+90000", +"input": "\uDA00\uDC00", +"output": [["Character", "\uDA00\uDC00"]]}, + +{"description": "Valid Unicode character U+9FFFD", +"input": "\uDA3F\uDFFD", +"output": [["Character", "\uDA3F\uDFFD"]]}, + +{"description": "Valid Unicode character U+A0000", +"input": "\uDA40\uDC00", +"output": [["Character", "\uDA40\uDC00"]]}, + +{"description": "Valid Unicode character U+AFFFD", +"input": "\uDA7F\uDFFD", +"output": [["Character", "\uDA7F\uDFFD"]]}, + +{"description": "Valid Unicode character U+B0000", +"input": "\uDA80\uDC00", +"output": [["Character", "\uDA80\uDC00"]]}, + +{"description": "Valid Unicode character U+BFFFD", +"input": "\uDABF\uDFFD", +"output": [["Character", "\uDABF\uDFFD"]]}, + +{"description": "Valid Unicode character U+C0000", +"input": "\uDAC0\uDC00", +"output": [["Character", "\uDAC0\uDC00"]]}, + +{"description": "Valid Unicode character U+CFFFD", +"input": "\uDAFF\uDFFD", +"output": [["Character", "\uDAFF\uDFFD"]]}, + +{"description": "Valid Unicode character U+D0000", +"input": "\uDB00\uDC00", +"output": [["Character", "\uDB00\uDC00"]]}, + +{"description": "Valid Unicode character U+DFFFD", +"input": "\uDB3F\uDFFD", +"output": [["Character", "\uDB3F\uDFFD"]]}, + +{"description": "Valid Unicode character U+E0000", +"input": "\uDB40\uDC00", +"output": [["Character", "\uDB40\uDC00"]]}, + +{"description": "Valid Unicode character U+EFFFD", +"input": "\uDB7F\uDFFD", +"output": [["Character", "\uDB7F\uDFFD"]]}, + +{"description": "Valid Unicode character U+F0000", +"input": "\uDB80\uDC00", +"output": [["Character", "\uDB80\uDC00"]]}, + +{"description": "Valid Unicode character U+FFFFD", +"input": "\uDBBF\uDFFD", +"output": [["Character", "\uDBBF\uDFFD"]]}, + +{"description": "Valid Unicode character U+100000", +"input": "\uDBC0\uDC00", +"output": [["Character", "\uDBC0\uDC00"]]}, + +{"description": "Valid Unicode character U+10FFFD", +"input": "\uDBFF\uDFFD", +"output": [["Character", "\uDBFF\uDFFD"]]} + +]} diff --git a/pkgs/html/test/data/tokenizer/unicodeCharsProblematic.test b/pkgs/html/test/data/tokenizer/unicodeCharsProblematic.test new file mode 100644 index 000000000..cf2fbe61a --- /dev/null +++ b/pkgs/html/test/data/tokenizer/unicodeCharsProblematic.test @@ -0,0 +1,27 @@ +{"tests" : [ +{"description": "Invalid Unicode character U+DFFF", +"doubleEscaped":true, +"input": "\\uDFFF", +"output":["ParseError", ["Character", "\\uFFFD"]]}, + +{"description": "Invalid Unicode character U+D800", +"doubleEscaped":true, +"input": "\\uD800", +"output":["ParseError", ["Character", "\\uFFFD"]]}, + +{"description": "Invalid Unicode character U+DFFF with valid preceding character", +"doubleEscaped":true, +"input": "a\\uDFFF", +"output":["ParseError", ["Character", "a\\uFFFD"]]}, + +{"description": "Invalid Unicode character U+D800 with valid following character", +"doubleEscaped":true, +"input": "\\uD800a", +"output":["ParseError", ["Character", "\\uFFFDa"]]}, + +{"description":"CR followed by U+0000", +"input":"\r\u0000", +"output":[["Character", "\n"], "ParseError", ["Character", "\u0000"]], +"ignoreErrorOrder":true} +] +} \ No newline at end of file diff --git a/pkgs/html/test/data/tokenizer/xmlViolation.test b/pkgs/html/test/data/tokenizer/xmlViolation.test new file mode 100644 index 000000000..137d96429 --- /dev/null +++ b/pkgs/html/test/data/tokenizer/xmlViolation.test @@ -0,0 +1,22 @@ +{"xmlViolationTests": [ + +{"description":"Non-XML character", +"input":"a\uFFFFb", +"ignoreErrorOrder":true, +"output":["ParseError",["Character","a\uFFFDb"]]}, + +{"description":"Non-XML space", +"input":"a\u000Cb", +"ignoreErrorOrder":true, +"output":[["Character","a b"]]}, + +{"description":"Double hyphen in comment", +"input":"<!-- foo -- bar -->", +"output":["ParseError",["Comment"," foo - - bar "]]}, + +{"description":"FF between attributes", +"input":"<a b=''\u000Cc=''>", +"output":[["StartTag","a",{"b":"","c":""}]]} +]} + + diff --git a/pkgs/html/test/data/tree-construction/adoption01.dat b/pkgs/html/test/data/tree-construction/adoption01.dat new file mode 100644 index 000000000..787e1b01e --- /dev/null +++ b/pkgs/html/test/data/tree-construction/adoption01.dat @@ -0,0 +1,194 @@ +#data +<a><p></a></p> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <p> +| <a> + +#data +<a>1<p>2</a>3</p> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <p> +| <a> +| "2" +| "3" + +#data +<a>1<button>2</a>3</button> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <button> +| <a> +| "2" +| "3" + +#data +<a>1<b>2</a>3</b> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <b> +| "2" +| <b> +| "3" + +#data +<a>1<div>2<div>3</a>4</div>5</div> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <div> +| <a> +| "2" +| <div> +| <a> +| "3" +| "4" +| "5" + +#data +<table><a>1<p>2</a>3</p> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <p> +| <a> +| "2" +| "3" +| <table> + +#data +<b><b><a><p></a> +#errors +#document +| <html> +| <head> +| <body> +| <b> +| <b> +| <a> +| <p> +| <a> + +#data +<b><a><b><p></a> +#errors +#document +| <html> +| <head> +| <body> +| <b> +| <a> +| <b> +| <b> +| <p> +| <a> + +#data +<a><b><b><p></a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <b> +| <b> +| <b> +| <b> +| <p> +| <a> + +#data +<p>1<s id="A">2<b id="B">3</p>4</s>5</b> +#errors +#document +| <html> +| <head> +| <body> +| <p> +| "1" +| <s> +| id="A" +| "2" +| <b> +| id="B" +| "3" +| <s> +| id="A" +| <b> +| id="B" +| "4" +| <b> +| id="B" +| "5" + +#data +<table><a>1<td>2</td>3</table> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "1" +| <a> +| "3" +| <table> +| <tbody> +| <tr> +| <td> +| "2" + +#data +<table>A<td>B</td>C</table> +#errors +#document +| <html> +| <head> +| <body> +| "AC" +| <table> +| <tbody> +| <tr> +| <td> +| "B" + +#data +<a><svg><tr><input></a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <svg svg> +| <svg tr> +| <svg input> diff --git a/pkgs/html/test/data/tree-construction/adoption02.dat b/pkgs/html/test/data/tree-construction/adoption02.dat new file mode 100644 index 000000000..d18151b44 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/adoption02.dat @@ -0,0 +1,31 @@ +#data +<b>1<i>2<p>3</b>4 +#errors +#document +| <html> +| <head> +| <body> +| <b> +| "1" +| <i> +| "2" +| <i> +| <p> +| <b> +| "3" +| "4" + +#data +<a><div><style></style><address><a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <div> +| <a> +| <style> +| <address> +| <a> +| <a> diff --git a/pkgs/html/test/data/tree-construction/comments01.dat b/pkgs/html/test/data/tree-construction/comments01.dat new file mode 100644 index 000000000..44f187683 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/comments01.dat @@ -0,0 +1,135 @@ +#data +FOO<!-- BAR -->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR --> +| "BAZ" + +#data +FOO<!-- BAR --!>BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR --> +| "BAZ" + +#data +FOO<!-- BAR -- >BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR -- >BAZ --> + +#data +FOO<!-- BAR -- <QUX> -- MUX -->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR -- <QUX> -- MUX --> +| "BAZ" + +#data +FOO<!-- BAR -- <QUX> -- MUX --!>BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR -- <QUX> -- MUX --> +| "BAZ" + +#data +FOO<!-- BAR -- <QUX> -- MUX -- >BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- BAR -- <QUX> -- MUX -- >BAZ --> + +#data +FOO<!---->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- --> +| "BAZ" + +#data +FOO<!--->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- --> +| "BAZ" + +#data +FOO<!-->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- --> +| "BAZ" + +#data +<?xml version="1.0">Hi +#errors +#document +| <!-- ?xml version="1.0" --> +| <html> +| <head> +| <body> +| "Hi" + +#data +<?xml version="1.0"> +#errors +#document +| <!-- ?xml version="1.0" --> +| <html> +| <head> +| <body> + +#data +<?xml version +#errors +#document +| <!-- ?xml version --> +| <html> +| <head> +| <body> + +#data +FOO<!----->BAZ +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <!-- - --> +| "BAZ" diff --git a/pkgs/html/test/data/tree-construction/doctype01.dat b/pkgs/html/test/data/tree-construction/doctype01.dat new file mode 100644 index 000000000..ae457328a --- /dev/null +++ b/pkgs/html/test/data/tree-construction/doctype01.dat @@ -0,0 +1,370 @@ +#data +<!DOCTYPE html>Hello +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!dOctYpE HtMl>Hello +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPEhtml>Hello +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE>Hello +#errors +#document +| <!DOCTYPE > +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE >Hello +#errors +#document +| <!DOCTYPE > +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato >Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato taco>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato taco "ddd>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato sYstEM>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato sYstEM >Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato sYstEM ggg>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato SYSTEM taco >Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato SYSTEM 'taco"'>Hello +#errors +#document +| <!DOCTYPE potato "" "taco""> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato SYSTEM "taco">Hello +#errors +#document +| <!DOCTYPE potato "" "taco"> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato SYSTEM "tai'co">Hello +#errors +#document +| <!DOCTYPE potato "" "tai'co"> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato SYSTEMtaco "ddd">Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato grass SYSTEM taco>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato pUbLIc>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato pUbLIc >Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato pUbLIcgoof>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato PUBLIC goof>Hello +#errors +#document +| <!DOCTYPE potato> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato PUBLIC "go'of">Hello +#errors +#document +| <!DOCTYPE potato "go'of" ""> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato PUBLIC 'go'of'>Hello +#errors +#document +| <!DOCTYPE potato "go" ""> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato PUBLIC 'go:hh of' >Hello +#errors +#document +| <!DOCTYPE potato "go:hh of" ""> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE potato PUBLIC "W3C-//dfdf" SYSTEM ggg>Hello +#errors +#document +| <!DOCTYPE potato "W3C-//dfdf" ""> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd">Hello +#errors +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE ...>Hello +#errors +#document +| <!DOCTYPE ...> +| <html> +| <head> +| <body> +| "Hello" + +#data +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [ +<!-- internal declarations --> +]> +#errors +#document +| <!DOCTYPE root-element> +| <html> +| <head> +| <body> +| "]>" + +#data +<!DOCTYPE html PUBLIC + "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" + "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"> +#errors +#document +| <!DOCTYPE html "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE HTML SYSTEM "http://www.w3.org/DTD/HTML4-strict.dtd"><body><b>Mine!</b></body> +#errors +#document +| <!DOCTYPE html "" "http://www.w3.org/DTD/HTML4-strict.dtd"> +| <html> +| <head> +| <body> +| <b> +| "Mine!" + +#data +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd"> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'> +#errors +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> +| <html> +| <head> +| <body> diff --git a/pkgs/html/test/data/tree-construction/domjs-unsafe.dat b/pkgs/html/test/data/tree-construction/domjs-unsafe.dat new file mode 100644 index 0000000000000000000000000000000000000000..905b94e43ad1b316eaa9246e7cb2c247d44c0181 GIT binary patch literal 6639 zcmc(ky>8nu5XUnM=sPgV;7QPukunfC9Xd6ry%a$P*`iYewq;04ffRkUqL0*9=#j^x zKHZA4C}%NEllTAe?syWJyCg1RkLTZC=lu40@%XTMc;2R|w~n)ym$`Q*vMkMV?=DF< zZwGNKyq}DJD-QcPG#E5Roap8{P2RBy{a}wtn`#scWWF})dtj?m^1~G*r&#7D+ntJe z9L;WKJk0T%g<qvJ^(5(W`R9YNKfiy?e2f7)-ndl_X2ttSM85R24}lGWn~}6DcFWjG z0RXb$fpl<=1R9o945qkul~Nf(HW8X_EY*50OX;&|rEJ?ImYTp_XFICcb1hxEi7)Me z!sX)2r>B)orSGUn<Asl(=B{H05;lIK@@ue6!%-|-f<tJ_;yM*B6f`3>gt$`Nj2*`w zmW9q}4Pw3q^a#{}S+!}nc6Cr{4)L_+gyNtJ)>Pmv;S1>5wdhOX3+TgZ(U-!#>G4H7 zbo(qJ5lbpI1r@V<#^F-jg25qyHdAkpm2)74=^WJmP-^q4qV2N*Y>=Rnu!Ws$w~wC} ztFKQVnL3yA`q%EV-Wc<rGd&$G``iE54ME+Sx<F_!^AN8U`p22q&%g+ZrqNbIq1!8c zsFe^8@uT6!!MsJh-U~RU*8>@1w>>M~6L3A9{GE%v*c5FQ-9K1{=97+I%qHExX6YNe z&Nr7;{xZ@E>0X2z%jS})4HE=~$crF=T4#oHcOb+Dl?ZAXliCc#&jVuaPQrFBV)Af1 zqIcxg9~Lfff=)_uOC@B~1@~J}gNe;#Z6$7$an}0{B{<C|#qP+EvJMDMx>S@Fw$0*$ z$OUXjEnqrqc49fHZ8tPO>Kj`NbTici!u0Tp-TKzP3>@81tFIyU4Ogi@7Vwh0QDoIE zwS{NUBxMp^bCdU##5O%bSVR3Wj)2KkFbDe+1WaU%Cfg+u?6nD`iH1o@+}|w^uzdGJ zME7oJIJ$s1l$3v8DI4<t8FCDRBA;eaCXz`&P|XLqE*1$C<?%6h!y?~yO?HrLn97#O Im$JV17pVBTQUCw| literal 0 HcmV?d00001 diff --git a/pkgs/html/test/data/tree-construction/entities01.dat b/pkgs/html/test/data/tree-construction/entities01.dat new file mode 100644 index 000000000..c8073b781 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/entities01.dat @@ -0,0 +1,603 @@ +#data +FOO&gt;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO>BAR" + +#data +FOO&gtBAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO>BAR" + +#data +FOO&gt BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO> BAR" + +#data +FOO&gt;;;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO>;;BAR" + +#data +I'm &notit; I tell you +#errors +#document +| <html> +| <head> +| <body> +| "I'm ¬it; I tell you" + +#data +I'm &notin; I tell you +#errors +#document +| <html> +| <head> +| <body> +| "I'm ∉ I tell you" + +#data +FOO& BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO& BAR" + +#data +FOO&<BAR> +#errors +#document +| <html> +| <head> +| <body> +| "FOO&" +| <bar> + +#data +FOO&&&&gt;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO&&&>BAR" + +#data +FOO&#41;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO)BAR" + +#data +FOO&#x41;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOOABAR" + +#data +FOO&#X41;BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOOABAR" + +#data +FOO&#BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO&#BAR" + +#data +FOO&#ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO&#ZOO" + +#data +FOO&#xBAR +#errors +#document +| <html> +| <head> +| <body> +| "FOOºR" + +#data +FOO&#xZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO&#xZOO" + +#data +FOO&#XZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO&#XZOO" + +#data +FOO&#41BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO)BAR" + +#data +FOO&#x41BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO䆺R" + +#data +FOO&#x41ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOAZOO" + +#data +FOO&#x0000;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#x0078;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOxZOO" + +#data +FOO&#x0079;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOyZOO" + +#data +FOO&#x0080;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO€ZOO" + +#data +FOO&#x0081;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x0082;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO‚ZOO" + +#data +FOO&#x0083;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOƒZOO" + +#data +FOO&#x0084;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO„ZOO" + +#data +FOO&#x0085;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO…ZOO" + +#data +FOO&#x0086;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO†ZOO" + +#data +FOO&#x0087;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO‡ZOO" + +#data +FOO&#x0088;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOˆZOO" + +#data +FOO&#x0089;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO‰ZOO" + +#data +FOO&#x008A;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOŠZOO" + +#data +FOO&#x008B;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO‹ZOO" + +#data +FOO&#x008C;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOŒZOO" + +#data +FOO&#x008D;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x008E;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOŽZOO" + +#data +FOO&#x008F;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x0090;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x0091;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO‘ZOO" + +#data +FOO&#x0092;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO’ZOO" + +#data +FOO&#x0093;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO“ZOO" + +#data +FOO&#x0094;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO”ZOO" + +#data +FOO&#x0095;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO•ZOO" + +#data +FOO&#x0096;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO–ZOO" + +#data +FOO&#x0097;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO—ZOO" + +#data +FOO&#x0098;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO˜ZOO" + +#data +FOO&#x0099;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO™ZOO" + +#data +FOO&#x009A;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOšZOO" + +#data +FOO&#x009B;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO›ZOO" + +#data +FOO&#x009C;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOœZOO" + +#data +FOO&#x009D;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x009E;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOžZOO" + +#data +FOO&#x009F;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOŸZOO" + +#data +FOO&#x00A0;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO ZOO" + +#data +FOO&#xD7FF;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO퟿ZOO" + +#data +FOO&#xD800;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#xD801;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#xDFFE;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#xDFFF;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#xE000;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOOZOO" + +#data +FOO&#x10FFFE;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO􏿾ZOO" + +#data +FOO&#x1087D4;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO􈟔ZOO" + +#data +FOO&#x10FFFF;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO􏿿ZOO" + +#data +FOO&#x110000;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" + +#data +FOO&#xFFFFFF;ZOO +#errors +#document +| <html> +| <head> +| <body> +| "FOO�ZOO" diff --git a/pkgs/html/test/data/tree-construction/entities02.dat b/pkgs/html/test/data/tree-construction/entities02.dat new file mode 100644 index 000000000..e2fb42a07 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/entities02.dat @@ -0,0 +1,249 @@ +#data +<div bar="ZZ&gt;YY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ>YY" + +#data +<div bar="ZZ&"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&" + +#data +<div bar='ZZ&'></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&" + +#data +<div bar=ZZ&></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&" + +#data +<div bar="ZZ&gt=YY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&gt=YY" + +#data +<div bar="ZZ&gt0YY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&gt0YY" + +#data +<div bar="ZZ&gt9YY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&gt9YY" + +#data +<div bar="ZZ&gtaYY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&gtaYY" + +#data +<div bar="ZZ&gtZYY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&gtZYY" + +#data +<div bar="ZZ&gt YY"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ> YY" + +#data +<div bar="ZZ&gt"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ>" + +#data +<div bar='ZZ&gt'></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ>" + +#data +<div bar=ZZ&gt></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ>" + +#data +<div bar="ZZ&pound_id=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ£_id=23" + +#data +<div bar="ZZ&prod_id=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&prod_id=23" + +#data +<div bar="ZZ&pound;_id=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ£_id=23" + +#data +<div bar="ZZ&prod;_id=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ∏_id=23" + +#data +<div bar="ZZ&pound=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&pound=23" + +#data +<div bar="ZZ&prod=23"></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| bar="ZZ&prod=23" + +#data +<div>ZZ&pound_id=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ£_id=23" + +#data +<div>ZZ&prod_id=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ&prod_id=23" + +#data +<div>ZZ&pound;_id=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ£_id=23" + +#data +<div>ZZ&prod;_id=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ∏_id=23" + +#data +<div>ZZ&pound=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ£=23" + +#data +<div>ZZ&prod=23</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "ZZ&prod=23" diff --git a/pkgs/html/test/data/tree-construction/html5test-com.dat b/pkgs/html/test/data/tree-construction/html5test-com.dat new file mode 100644 index 000000000..d7cb71db0 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/html5test-com.dat @@ -0,0 +1,246 @@ +#data +<div<div> +#errors +#document +| <html> +| <head> +| <body> +| <div<div> + +#data +<div foo<bar=''> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| foo<bar="" + +#data +<div foo=`bar`> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| foo="`bar`" + +#data +<div \"foo=''> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| \"foo="" + +#data +<a href='\nbar'></a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| href="\nbar" + +#data +<!DOCTYPE html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +&lang;&rang; +#errors +#document +| <html> +| <head> +| <body> +| "⟨⟩" + +#data +&apos; +#errors +#document +| <html> +| <head> +| <body> +| "'" + +#data +&ImaginaryI; +#errors +#document +| <html> +| <head> +| <body> +| "ⅈ" + +#data +&Kopf; +#errors +#document +| <html> +| <head> +| <body> +| "𝕂" + +#data +&notinva; +#errors +#document +| <html> +| <head> +| <body> +| "∉" + +#data +<?import namespace="foo" implementation="#bar"> +#errors +#document +| <!-- ?import namespace="foo" implementation="#bar" --> +| <html> +| <head> +| <body> + +#data +<!--foo--bar--> +#errors +#document +| <!-- foo--bar --> +| <html> +| <head> +| <body> + +#data +<![CDATA[x]]> +#errors +#document +| <!-- [CDATA[x]] --> +| <html> +| <head> +| <body> + +#data +<textarea><!--</textarea>--></textarea> +#errors +#document +| <html> +| <head> +| <body> +| <textarea> +| "<!--" +| "-->" + +#data +<textarea><!--</textarea>--> +#errors +#document +| <html> +| <head> +| <body> +| <textarea> +| "<!--" +| "-->" + +#data +<style><!--</style>--></style> +#errors +#document +| <html> +| <head> +| <style> +| "<!--" +| <body> +| "-->" + +#data +<style><!--</style>--> +#errors +#document +| <html> +| <head> +| <style> +| "<!--" +| <body> +| "-->" + +#data +<ul><li>A </li> <li>B</li></ul> +#errors +#document +| <html> +| <head> +| <body> +| <ul> +| <li> +| "A " +| " " +| <li> +| "B" + +#data +<table><form><input type=hidden><input></form><div></div></table> +#errors +#document +| <html> +| <head> +| <body> +| <input> +| <div> +| <table> +| <form> +| <input> +| type="hidden" + +#data +<i>A<b>B<p></i>C</b>D +#errors +#document +| <html> +| <head> +| <body> +| <i> +| "A" +| <b> +| "B" +| <b> +| <p> +| <b> +| <i> +| "C" +| "D" + +#data +<div></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> + +#data +<svg></svg> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> + +#data +<math></math> +#errors +#document +| <html> +| <head> +| <body> +| <math math> diff --git a/pkgs/html/test/data/tree-construction/inbody01.dat b/pkgs/html/test/data/tree-construction/inbody01.dat new file mode 100644 index 000000000..3f2bd374c --- /dev/null +++ b/pkgs/html/test/data/tree-construction/inbody01.dat @@ -0,0 +1,43 @@ +#data +<button>1</foo> +#errors +#document +| <html> +| <head> +| <body> +| <button> +| "1" + +#data +<foo>1<p>2</foo> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| "1" +| <p> +| "2" + +#data +<dd>1</foo> +#errors +#document +| <html> +| <head> +| <body> +| <dd> +| "1" + +#data +<foo>1<dd>2</foo> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| "1" +| <dd> +| "2" diff --git a/pkgs/html/test/data/tree-construction/isindex.dat b/pkgs/html/test/data/tree-construction/isindex.dat new file mode 100644 index 000000000..88325ffe6 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/isindex.dat @@ -0,0 +1,40 @@ +#data +<isindex> +#errors +#document +| <html> +| <head> +| <body> +| <form> +| <hr> +| <label> +| "This is a searchable index. Enter search keywords: " +| <input> +| name="isindex" +| <hr> + +#data +<isindex name="A" action="B" prompt="C" foo="D"> +#errors +#document +| <html> +| <head> +| <body> +| <form> +| action="B" +| <hr> +| <label> +| "C" +| <input> +| foo="D" +| name="isindex" +| <hr> + +#data +<form><isindex> +#errors +#document +| <html> +| <head> +| <body> +| <form> diff --git a/pkgs/html/test/data/tree-construction/pending-spec-changes-plain-text-unsafe.dat b/pkgs/html/test/data/tree-construction/pending-spec-changes-plain-text-unsafe.dat new file mode 100644 index 0000000000000000000000000000000000000000..a5ebb1eb285116af391137bc94beac0c8a6834b4 GIT binary patch literal 115 zcmXZUQ3`+{41i&ucZ#9c5brYEqF^T2f`Sg8m2W@)!xxy0Am++fibh!_xp`HU=1fj= l5Tv!*b_iUjqsV4(V_d9g>VZ9lc;ttC7t#O7YxuDS4-Zl&BR>ED literal 0 HcmV?d00001 diff --git a/pkgs/html/test/data/tree-construction/pending-spec-changes.dat b/pkgs/html/test/data/tree-construction/pending-spec-changes.dat new file mode 100644 index 000000000..5a9208465 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/pending-spec-changes.dat @@ -0,0 +1,52 @@ +#data +<input type="hidden"><frameset> +#errors +21: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +31: “frameset” start tag seen. +31: End of file seen and there were open elements. +#document +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><table><caption><svg>foo</table>bar +#errors +47: End tag “table” did not match the name of the current open element (“svg”). +47: “table” closed but “caption” was still open. +47: End tag “table” seen, but there were open elements. +36: Unclosed element “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <svg svg> +| "foo" +| "bar" + +#data +<table><tr><td><svg><desc><td></desc><circle> +#errors +7: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +30: A table cell was implicitly closed, but there were open elements. +26: Unclosed element “desc”. +20: Unclosed element “svg”. +37: Stray end tag “desc”. +45: End of file seen and there were open elements. +45: Unclosed element “circle”. +7: Unclosed element “table”. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| <svg desc> +| <td> +| <circle> diff --git a/pkgs/html/test/data/tree-construction/plain-text-unsafe.dat b/pkgs/html/test/data/tree-construction/plain-text-unsafe.dat new file mode 100644 index 0000000000000000000000000000000000000000..04cc11fb9d458ea32dca02e2f3bf39221196ab8e GIT binary patch literal 4166 zcmds4&1%~~5Y}1XcNojiOL5|Zdr6iB6Q@@dnjYGa!^&DaD*8j(rYZE*N*}4O(Ai!6 zt?Ym#%MQd~yz+X#nfd0M+40P0g4rKk_ucGyu~@9HzqzhG<5`wuxjplf&5wx3!u}29 zQA8od1>ll1zgT*S|4T0c9E6$RdB?_+5>}tF$TnjU&$*!FvRd{rQXeva!GcpkGm9M! zZBWBlo0XH%V%aC7h2%Ws8$qo;*=zDp0+b3F08~mq!5(ow4OtKi{*2LVgD~WoB_9R= z%96mMsPR;h$nTtgfB$G~Tu5~MsAZ5p?I@Yv->g@6t9!$ThX*>G;HMo(<c>}#7Rl5a zZg4uE1I7jOIW4nFO4J6iM;kDRJYY@HxlJ-2>|)pZu4LM<KOUh3ErDsMA{%qAZOUw$ zscvR?JZJVK)-qamv2krWRmhr-vcp#rkm+dl=W)$LH~WnyKCXT2=DO^$@Rb}6$4@S` zDy!WdH|zeTS5P`WCOgJYv%MecK8>qS(UCIoh@(L9F*ZXarNczOPxy50-rRltbPH<s zA!)|x#GcqI^c|On6=j}5m2?=K6mlgf$6nP%Y{F?5Ca>+lsqMcUzhGX-DG?dIeM%yw zq)6Z5tV+moc?F-@Px$g4N7@AhG2|lSEV{6lAFkjw_958<_GvD+SlP=VmQ!lVHXJsI znhY+?3E0d<$JA<%tK<^VtQR#nU@+CT{-PMJ<%52yKtV-o{8a81dy0d-O}vj9)n^7k zT4d@%G%wJ%%qhlePD%yYMMpP?=tpcJ%YZV=t3+x1nKCnh=v}&mgl&nSNPf^%ki)ze l`$yqfayHMBo}R^L^DOS^S$;Op@}8cl(m$8f+I>c;?LSw^)ujLc literal 0 HcmV?d00001 diff --git a/pkgs/html/test/data/tree-construction/scriptdata01.dat b/pkgs/html/test/data/tree-construction/scriptdata01.dat new file mode 100644 index 000000000..76b67f4ba --- /dev/null +++ b/pkgs/html/test/data/tree-construction/scriptdata01.dat @@ -0,0 +1,308 @@ +#data +FOO<script>'Hello'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'Hello'" +| "BAR" + +#data +FOO<script></script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "BAR" + +#data +FOO<script></script >BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "BAR" + +#data +FOO<script></script/>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "BAR" + +#data +FOO<script></script/ >BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "BAR" + +#data +FOO<script type="text/plain"></scriptx>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "</scriptx>BAR" + +#data +FOO<script></script foo=">" dd>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "BAR" + +#data +FOO<script>'<'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<'" +| "BAR" + +#data +FOO<script>'<!'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!'" +| "BAR" + +#data +FOO<script>'<!-'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-'" +| "BAR" + +#data +FOO<script>'<!--'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!--'" +| "BAR" + +#data +FOO<script>'<!---'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!---'" +| "BAR" + +#data +FOO<script>'<!-->'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-->'" +| "BAR" + +#data +FOO<script>'<!-->'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-->'" +| "BAR" + +#data +FOO<script>'<!-- potato'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-- potato'" +| "BAR" + +#data +FOO<script>'<!-- <sCrIpt'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-- <sCrIpt'" +| "BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt>'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt>'</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt> -'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt> -'</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt> --'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt> --'</script>BAR" + +#data +FOO<script>'<!-- <sCrIpt> -->'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| "'<!-- <sCrIpt> -->'" +| "BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt> --!>'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt> --!>'</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt> -- >'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt> -- >'</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt '</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt '</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt/'</script>BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt\'</script>BAR +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt\'" +| "BAR" + +#data +FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR</script>QUX +#errors +#document +| <html> +| <head> +| <body> +| "FOO" +| <script> +| type="text/plain" +| "'<!-- <sCrIpt/'</script>BAR" +| "QUX" diff --git a/pkgs/html/test/data/tree-construction/scripted/adoption01.dat b/pkgs/html/test/data/tree-construction/scripted/adoption01.dat new file mode 100644 index 000000000..4e08d0e84 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/scripted/adoption01.dat @@ -0,0 +1,15 @@ +#data +<p><b id="A"><script>document.getElementById("A").id = "B"</script></p>TEXT</b> +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <b> +| id="B" +| <script> +| "document.getElementById("A").id = "B"" +| <b> +| id="A" +| "TEXT" diff --git a/pkgs/html/test/data/tree-construction/scripted/ark.dat b/pkgs/html/test/data/tree-construction/scripted/ark.dat new file mode 100644 index 000000000..acbac41df --- /dev/null +++ b/pkgs/html/test/data/tree-construction/scripted/ark.dat @@ -0,0 +1,26 @@ +#data +<p><font size=4><font size=4><font size=4><script>document.getElementsByTagName("font")[2].setAttribute("size", "5");</script><font size=4><p>X +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="5" +| <script> +| "document.getElementsByTagName("font")[2].setAttribute("size", "5");" +| <font> +| size="4" +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| "X" diff --git a/pkgs/html/test/data/tree-construction/scripted/webkit01.dat b/pkgs/html/test/data/tree-construction/scripted/webkit01.dat new file mode 100644 index 000000000..ef4a41ca0 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/scripted/webkit01.dat @@ -0,0 +1,28 @@ +#data +1<script>document.write("2")</script>3 +#errors +#document +| <html> +| <head> +| <body> +| "1" +| <script> +| "document.write("2")" +| "23" + +#data +1<script>document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")</script>4 +#errors +#document +| <html> +| <head> +| <body> +| "1" +| <script> +| "document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")" +| <script> +| "document.write('2')" +| "2" +| <script> +| "document.write('3')" +| "34" diff --git a/pkgs/html/test/data/tree-construction/tables01.dat b/pkgs/html/test/data/tree-construction/tables01.dat new file mode 100644 index 000000000..c4b47e48a --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tables01.dat @@ -0,0 +1,212 @@ +#data +<table><th> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <th> + +#data +<table><td> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<table><col foo='bar'> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <colgroup> +| <col> +| foo="bar" + +#data +<table><colgroup></html>foo +#errors +#document +| <html> +| <head> +| <body> +| "foo" +| <table> +| <colgroup> + +#data +<table></table><p>foo +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <p> +| "foo" + +#data +<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<table><select><option>3</select></table> +#errors +#document +| <html> +| <head> +| <body> +| <select> +| <option> +| "3" +| <table> + +#data +<table><select><table></table></select></table> +#errors +#document +| <html> +| <head> +| <body> +| <select> +| <table> +| <table> + +#data +<table><select></table> +#errors +#document +| <html> +| <head> +| <body> +| <select> +| <table> + +#data +<table><select><option>A<tr><td>B</td></tr></table> +#errors +#document +| <html> +| <head> +| <body> +| <select> +| <option> +| "A" +| <table> +| <tbody> +| <tr> +| <td> +| "B" + +#data +<table><td></body></caption></col></colgroup></html>foo +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "foo" + +#data +<table><td>A</table>B +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "A" +| "B" + +#data +<table><tr><caption> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <caption> + +#data +<table><tr></body></caption></col></colgroup></html></td></th><td>foo +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "foo" + +#data +<table><td><tr> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <tr> + +#data +<table><td><button><td> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <button> +| <td> + +#data +<table><tr><td><svg><desc><td> +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| <svg desc> +| <td> diff --git a/pkgs/html/test/data/tree-construction/tests1.dat b/pkgs/html/test/data/tree-construction/tests1.dat new file mode 100644 index 000000000..cbf8bdda6 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests1.dat @@ -0,0 +1,1952 @@ +#data +Test +#errors +Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "Test" + +#data +<p>One<p>Two +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <p> +| "One" +| <p> +| "Two" + +#data +Line1<br>Line2<br>Line3<br>Line4 +#errors +Line: 1 Col: 5 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "Line1" +| <br> +| "Line2" +| <br> +| "Line3" +| <br> +| "Line4" + +#data +<html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<head> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<body> +#errors +Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head></head> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head></head><body> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head></head><body></body> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head><body></body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><head></body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +Line: 1 Col: 19 Unexpected end tag (body). +Line: 1 Col: 26 Unexpected end tag (html). +#document +| <html> +| <head> +| <body> + +#data +<html><head><body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<html><body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<head></html> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end tag (html). Ignored. +#document +| <html> +| <head> +| <body> + +#data +</head> +#errors +Line: 1 Col: 7 Unexpected end tag (head). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +</body> +#errors +Line: 1 Col: 7 Unexpected end tag (body). Expected DOCTYPE. +Line: 1 Col: 7 Unexpected end tag (body) after the (implied) root element. +#document +| <html> +| <head> +| <body> + +#data +</html> +#errors +Line: 1 Col: 7 Unexpected end tag (html). Expected DOCTYPE. +Line: 1 Col: 7 Unexpected end tag (html) after the (implied) root element. +#document +| <html> +| <head> +| <body> + +#data +<b><table><td><i></table> +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 25 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 25 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| <table> +| <tbody> +| <tr> +| <td> +| <i> + +#data +<b><table><td></b><i></table>X +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 18 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 29 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 30 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| <table> +| <tbody> +| <tr> +| <td> +| <i> +| "X" + +#data +<h1>Hello<h2>World +#errors +4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +13: Heading cannot be a child of another heading. +18: End of file seen and there were open elements. +#document +| <html> +| <head> +| <body> +| <h1> +| "Hello" +| <h2> +| "World" + +#data +<a><p>X<a>Y</a>Z</p></a> +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 10 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 10 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 24 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <a> +| <p> +| <a> +| "X" +| <a> +| "Y" +| "Z" + +#data +<b><button>foo</b>bar +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 15 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <b> +| <button> +| <b> +| "foo" +| "bar" + +#data +<!DOCTYPE html><span><button>foo</span>bar +#errors +39: End tag “span” seen but there were unclosed elements. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <span> +| <button> +| "foobar" + +#data +<p><b><div><marquee></p></b></div>X +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end tag (p). Ignored. +Line: 1 Col: 24 Unexpected end tag (p). Ignored. +Line: 1 Col: 28 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 34 End tag (div) seen too early. Expected other end tag. +Line: 1 Col: 35 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <p> +| <b> +| <div> +| <b> +| <marquee> +| <p> +| "X" + +#data +<script><div></script></div><title><p></title><p><p> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 28 Unexpected end tag (div). Ignored. +#document +| <html> +| <head> +| <script> +| "<div>" +| <title> +| "<p>" +| <body> +| <p> +| <p> + +#data +<!--><div>--<!--> +#errors +Line: 1 Col: 5 Incorrect comment. +Line: 1 Col: 10 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 17 Incorrect comment. +Line: 1 Col: 17 Expected closing tag. Unexpected end of file. +#document +| <!-- --> +| <html> +| <head> +| <body> +| <div> +| "--" +| <!-- --> + +#data +<p><hr></p> +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end tag (p). Ignored. +#document +| <html> +| <head> +| <body> +| <p> +| <hr> +| <p> + +#data +<select><b><option><select><option></b></select>X +#errors +Line: 1 Col: 8 Unexpected start tag (select). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected start tag token (b) in the select phase. Ignored. +Line: 1 Col: 27 Unexpected select start tag in the select phase treated as select end tag. +Line: 1 Col: 39 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 48 Unexpected end tag (select). Ignored. +Line: 1 Col: 49 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <select> +| <option> +| <option> +| "X" + +#data +<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 40 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 43 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 43 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 43 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 51 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 63 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 64 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| <a> +| <table> +| <tbody> +| <tr> +| <td> +| <a> +| <table> +| <a> +| <a> +| <b> +| "X" +| "C" +| <a> +| "Y" + +#data +<a X>0<b>1<a Y>2 +#errors +Line: 1 Col: 5 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 15 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 16 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| x="" +| "0" +| <b> +| "1" +| <b> +| <a> +| y="" +| "2" + +#data +<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X--> +#errors +Line: 1 Col: 7 Unexpected '-' after '--' found in comment. +Line: 1 Col: 14 Unexpected start tag (font). Expected DOCTYPE. +Line: 1 Col: 38 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 41 Unexpected start tag (b) in table context caused voodoo mode. +Line: 1 Col: 48 Unexpected implied end tag (b) in the table phase. +Line: 1 Col: 48 Unexpected table cell start tag (th) in the table body phase. +Line: 1 Col: 63 Got table cell end tag (th) while required end tags are missing. +Line: 1 Col: 71 Unexpected end of file. Expected table content. +#document +| <!-- - --> +| <html> +| <head> +| <body> +| <font> +| <div> +| "helloexcite!" +| <b> +| "me!" +| <table> +| <tbody> +| <tr> +| <th> +| <i> +| "please!" +| <!-- X --> + +#data +<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do--> +#errors +Line: 1 Col: 61 Unexpected end tag (li). Missing end tag (body). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <li> +| "hello" +| <li> +| "world" +| <ul> +| "how" +| <li> +| "do" +| "you" +| <!-- do --> + +#data +<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E +#errors +Line: 1 Col: 54 Unexpected end tag (option) in the select phase. Ignored. +Line: 1 Col: 55 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "A" +| <option> +| "B" +| <optgroup> +| "C" +| <select> +| "DE" + +#data +< +#errors +Line: 1 Col: 1 Expected tag name. Got something else instead +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "<" + +#data +<# +#errors +Line: 1 Col: 1 Expected tag name. Got something else instead +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "<#" + +#data +</ +#errors +Line: 1 Col: 2 Expected closing tag. Unexpected end of file. +Line: 1 Col: 2 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "</" + +#data +</# +#errors +Line: 1 Col: 2 Expected closing tag. Unexpected character '#' found. +Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- # --> +| <html> +| <head> +| <body> + +#data +<? +#errors +Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.) +Line: 1 Col: 2 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- ? --> +| <html> +| <head> +| <body> + +#data +<?# +#errors +Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.) +Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- ?# --> +| <html> +| <head> +| <body> + +#data +<! +#errors +Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found. +Line: 1 Col: 2 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- --> +| <html> +| <head> +| <body> + +#data +<!# +#errors +Line: 1 Col: 3 Expected '--' or 'DOCTYPE'. Not found. +Line: 1 Col: 3 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- # --> +| <html> +| <head> +| <body> + +#data +<?COMMENT?> +#errors +Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.) +Line: 1 Col: 11 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- ?COMMENT? --> +| <html> +| <head> +| <body> + +#data +<!COMMENT> +#errors +Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found. +Line: 1 Col: 10 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- COMMENT --> +| <html> +| <head> +| <body> + +#data +</ COMMENT > +#errors +Line: 1 Col: 2 Expected closing tag. Unexpected character ' ' found. +Line: 1 Col: 12 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- COMMENT --> +| <html> +| <head> +| <body> + +#data +<?COM--MENT?> +#errors +Line: 1 Col: 1 Expected tag name. Got '?' instead. (HTML doesn't support processing instructions.) +Line: 1 Col: 13 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- ?COM--MENT? --> +| <html> +| <head> +| <body> + +#data +<!COM--MENT> +#errors +Line: 1 Col: 2 Expected '--' or 'DOCTYPE'. Not found. +Line: 1 Col: 12 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- COM--MENT --> +| <html> +| <head> +| <body> + +#data +</ COM--MENT > +#errors +Line: 1 Col: 2 Expected closing tag. Unexpected character ' ' found. +Line: 1 Col: 14 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- COM--MENT --> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><style> EOF +#errors +Line: 1 Col: 26 Unexpected end of file. Expected end tag (style). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| " EOF" +| <body> + +#data +<!DOCTYPE html><script> <!-- </script> --> </script> EOF +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| " <!-- " +| " " +| <body> +| "--> EOF" + +#data +<b><p></b>TEST +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 10 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <b> +| <p> +| <b> +| "TEST" + +#data +<p id=a><b><p id=b></b>TEST +#errors +Line: 1 Col: 8 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 19 Unexpected end tag (p). Ignored. +Line: 1 Col: 23 End tag (b) violates step 1, paragraph 2 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <p> +| id="a" +| <b> +| <p> +| id="b" +| "TEST" + +#data +<b id=a><p><b id=b></p></b>TEST +#errors +Line: 1 Col: 8 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end tag (p). Ignored. +Line: 1 Col: 27 End tag (b) violates step 1, paragraph 2 of the adoption agency algorithm. +Line: 1 Col: 31 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| id="a" +| <p> +| <b> +| id="b" +| "TEST" + +#data +<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body> +#errors +Line: 1 Col: 61 Unexpected end tag (p). Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "U-test" +| <body> +| <div> +| <p> +| "Test" +| <u> + +#data +<!DOCTYPE html><font><table></font></table></font> +#errors +Line: 1 Col: 35 Unexpected end tag (font) in table context caused voodoo mode. +Line: 1 Col: 35 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <font> +| <table> + +#data +<font><p>hello<b>cruel</font>world +#errors +Line: 1 Col: 6 Unexpected start tag (font). Expected DOCTYPE. +Line: 1 Col: 29 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 29 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 34 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <font> +| <p> +| <font> +| "hello" +| <b> +| "cruel" +| <b> +| "world" + +#data +<b>Test</i>Test +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 11 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 15 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| "TestTest" + +#data +<b>A<cite>B<div>C +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 17 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| "A" +| <cite> +| "B" +| <div> +| "C" + +#data +<b>A<cite>B<div>C</cite>D +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 24 Unexpected end tag (cite). Ignored. +Line: 1 Col: 25 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| "A" +| <cite> +| "B" +| <div> +| "CD" + +#data +<b>A<cite>B<div>C</b>D +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 21 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 22 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| "A" +| <cite> +| "B" +| <div> +| <b> +| "C" +| "D" + +#data + +#errors +Line: 1 Col: 0 Unexpected End of file. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<DIV> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 5 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> + +#data +<DIV> abc +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 9 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc" + +#data +<DIV> abc <B> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 13 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> + +#data +<DIV> abc <B> def +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 17 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def" + +#data +<DIV> abc <B> def <I> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 21 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> + +#data +<DIV> abc <B> def <I> ghi +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 25 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi" + +#data +<DIV> abc <B> def <I> ghi <P> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 29 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <p> + +#data +<DIV> abc <B> def <I> ghi <P> jkl +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 33 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <p> +| " jkl" + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 38 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <b> +| " jkl " + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> mno +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 42 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <b> +| " jkl " +| " mno" + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 47 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <i> +| <b> +| " jkl " +| " mno " + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 51 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <i> +| <b> +| " jkl " +| " mno " +| " pqr" + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 56 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <i> +| <b> +| " jkl " +| " mno " +| " pqr " + +#data +<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 38 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 47 End tag (i) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 60 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " abc " +| <b> +| " def " +| <i> +| " ghi " +| <i> +| <p> +| <i> +| <b> +| " jkl " +| " mno " +| " pqr " +| " stu" + +#data +<test attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------> +#errors +Line: 1 Col: 1040 Unexpected start tag (test). Expected DOCTYPE. +Line: 1 Col: 1040 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <test> +| attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------="" + +#data +<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe +#errors +Line: 1 Col: 15 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 39 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 39 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 39 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 45 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 68 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 71 Expected closing tag. Unexpected end of file. + +#document +| <html> +| <head> +| <body> +| <a> +| href="blah" +| "aba" +| <a> +| href="foo" +| "br" +| <a> +| href="foo" +| "x" +| <table> +| <tbody> +| <tr> +| <td> +| <a> +| href="foo" +| "aoe" + +#data +<a href="blah">aba<table><tr><td><a href="foo">br</td></tr>x</table>aoe +#errors +Line: 1 Col: 15 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 54 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 60 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 71 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| href="blah" +| "abax" +| <table> +| <tbody> +| <tr> +| <td> +| <a> +| href="foo" +| "br" +| "aoe" + +#data +<table><a href="blah">aba<tr><td><a href="foo">br</td></tr>x</table>aoe +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 29 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 54 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 68 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 71 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| href="blah" +| "aba" +| <a> +| href="blah" +| "x" +| <table> +| <tbody> +| <tr> +| <td> +| <a> +| href="foo" +| "br" +| <a> +| href="blah" +| "aoe" + +#data +<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa +#errors +Line: 1 Col: 10 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 45 End tag (marquee) seen too early. Expected other end tag. +Line: 1 Col: 47 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| href="a" +| "aa" +| <marquee> +| "aa" +| <a> +| href="b" +| "bb" +| "aa" + +#data +<wbr><strike><code></strike><code><strike></code> +#errors +Line: 1 Col: 5 Unexpected start tag (wbr). Expected DOCTYPE. +Line: 1 Col: 28 End tag (strike) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 49 Unexpected end tag (code). Ignored. +#document +| <html> +| <head> +| <body> +| <wbr> +| <strike> +| <code> +| <code> +| <code> +| <strike> + +#data +<!DOCTYPE html><spacer>foo +#errors +26: End of file seen and there were open elements. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <spacer> +| "foo" + +#data +<title><meta></title><link><title><meta></title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| "<meta>" +| <link> +| <title> +| "<meta>" +| <body> + +#data +<style><!--</style><meta><script>--><link></script> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 51 Unexpected end of file. Expected end tag (style). +#document +| <html> +| <head> +| <style> +| "<!--" +| <meta> +| <script> +| "--><link>" +| <body> + +#data +<head><meta></head><link> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 25 Unexpected start tag (link) that can be in head. Moved. +#document +| <html> +| <head> +| <meta> +| <link> +| <body> + +#data +<table><tr><tr><td><td><span><th><span>X</table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 33 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 48 Got table cell end tag (th) while required end tags are missing. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <tr> +| <td> +| <td> +| <span> +| <th> +| <span> +| "X" + +#data +<body><body><base><link><meta><title><p></title><body><p></body> +#errors +Line: 1 Col: 6 Unexpected start tag (body). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected start tag (body). +Line: 1 Col: 54 Unexpected start tag (body). +Line: 1 Col: 64 Unexpected end tag (p). Missing end tag (body). +#document +| <html> +| <head> +| <body> +| <base> +| <link> +| <meta> +| <title> +| "<p>" +| <p> + +#data +<textarea><p></textarea> +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <textarea> +| "<p>" + +#data +<p><image></p> +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 10 Unexpected start tag (image). Treated as img. +#document +| <html> +| <head> +| <body> +| <p> +| <img> + +#data +<a><table><a></table><p><a><div><a> +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 13 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 13 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 21 Unexpected end tag (table). Expected end tag (a). +Line: 1 Col: 27 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 27 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm. +Line: 1 Col: 32 Unexpected end tag (p). Ignored. +Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 35 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm. +Line: 1 Col: 35 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| <a> +| <table> +| <p> +| <a> +| <div> +| <a> + +#data +<head></p><meta><p> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 10 Unexpected end tag (p). Ignored. +#document +| <html> +| <head> +| <meta> +| <body> +| <p> + +#data +<head></html><meta><p> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 19 Unexpected start tag (meta). +#document +| <html> +| <head> +| <body> +| <meta> +| <p> + +#data +<b><table><td><i></table> +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 25 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 25 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| <table> +| <tbody> +| <tr> +| <td> +| <i> + +#data +<b><table><td></b><i></table> +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 18 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 29 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 29 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| <table> +| <tbody> +| <tr> +| <td> +| <i> + +#data +<h1><h2> +#errors +4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +8: Heading cannot be a child of another heading. +8: End of file seen and there were open elements. +#document +| <html> +| <head> +| <body> +| <h1> +| <h2> + +#data +<a><p><a></a></p></a> +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 9 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 9 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 21 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <a> +| <p> +| <a> +| <a> + +#data +<b><button></b></button></b> +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 15 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <b> +| <button> +| <b> + +#data +<p><b><div><marquee></p></b></div> +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end tag (p). Ignored. +Line: 1 Col: 24 Unexpected end tag (p). Ignored. +Line: 1 Col: 28 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 34 End tag (div) seen too early. Expected other end tag. +Line: 1 Col: 34 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <p> +| <b> +| <div> +| <b> +| <marquee> +| <p> + +#data +<script></script></div><title></title><p><p> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end tag (div). Ignored. +#document +| <html> +| <head> +| <script> +| <title> +| <body> +| <p> +| <p> + +#data +<p><hr></p> +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end tag (p). Ignored. +#document +| <html> +| <head> +| <body> +| <p> +| <hr> +| <p> + +#data +<select><b><option><select><option></b></select> +#errors +Line: 1 Col: 8 Unexpected start tag (select). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected start tag token (b) in the select phase. Ignored. +Line: 1 Col: 27 Unexpected select start tag in the select phase treated as select end tag. +Line: 1 Col: 39 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 48 Unexpected end tag (select). Ignored. +Line: 1 Col: 48 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <select> +| <option> +| <option> + +#data +<html><head><title></title><body></body></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| <body> + +#data +<a><table><td><a><table></table><a></tr><a></table><a> +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 35 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 40 Got table cell end tag (td) while required end tags are missing. +Line: 1 Col: 43 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 43 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 43 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 51 Unexpected implied end tag (a) in the table phase. +Line: 1 Col: 54 Unexpected start tag (a) implies end tag (a). +Line: 1 Col: 54 End tag (a) violates step 1, paragraph 2 of the adoption agency algorithm. +Line: 1 Col: 54 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| <a> +| <table> +| <tbody> +| <tr> +| <td> +| <a> +| <table> +| <a> +| <a> + +#data +<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul> +#errors +Line: 1 Col: 4 Unexpected start tag (ul). Expected DOCTYPE. +Line: 1 Col: 45 Missing end tag (div, li). +Line: 1 Col: 58 Missing end tag (address, li). +Line: 1 Col: 69 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +#document +| <html> +| <head> +| <body> +| <ul> +| <li> +| <div> +| <li> +| <li> +| <li> +| <div> +| <li> +| <address> +| <li> +| <b> +| <em> +| <li> + +#data +<ul><li><ul></li><li>a</li></ul></li></ul> +#errors +XXX: fix me +#document +| <html> +| <head> +| <body> +| <ul> +| <li> +| <ul> +| <li> +| "a" + +#data +<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +#document +| <html> +| <head> +| <frameset> +| <frame> +| <frameset> +| <frame> +| <noframes> + +#data +<h1><table><td><h3></table><h3></h1> +#errors +4: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +15: “td” start tag in table body. +27: Unclosed elements. +31: Heading cannot be a child of another heading. +36: End tag “h1” seen but there were unclosed elements. +#document +| <html> +| <head> +| <body> +| <h1> +| <table> +| <tbody> +| <tr> +| <td> +| <h3> +| <h3> + +#data +<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <table> +| <colgroup> +| <col> +| <colgroup> +| <col> +| <col> +| <col> +| <colgroup> +| <col> +| <col> +| <thead> +| <tr> +| <td> + +#data +<table><col><tbody><col><tr><col><td><col></table><col> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 37 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 55 Unexpected start tag col. Ignored. +#document +| <html> +| <head> +| <body> +| <table> +| <colgroup> +| <col> +| <tbody> +| <colgroup> +| <col> +| <tbody> +| <tr> +| <colgroup> +| <col> +| <tbody> +| <tr> +| <td> +| <colgroup> +| <col> + +#data +<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 52 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 80 Unexpected start tag colgroup. Ignored. +#document +| <html> +| <head> +| <body> +| <table> +| <colgroup> +| <tbody> +| <colgroup> +| <tbody> +| <tr> +| <colgroup> +| <tbody> +| <tr> +| <td> +| <colgroup> + +#data +</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea> +#errors +Line: 1 Col: 9 Unexpected end tag (strong). Expected DOCTYPE. +Line: 1 Col: 9 Unexpected end tag (strong) after the (implied) root element. +Line: 1 Col: 13 Unexpected end tag (b) after the (implied) root element. +Line: 1 Col: 18 Unexpected end tag (em) after the (implied) root element. +Line: 1 Col: 22 Unexpected end tag (i) after the (implied) root element. +Line: 1 Col: 26 Unexpected end tag (u) after the (implied) root element. +Line: 1 Col: 35 Unexpected end tag (strike) after the (implied) root element. +Line: 1 Col: 39 Unexpected end tag (s) after the (implied) root element. +Line: 1 Col: 47 Unexpected end tag (blink) after the (implied) root element. +Line: 1 Col: 52 Unexpected end tag (tt) after the (implied) root element. +Line: 1 Col: 58 Unexpected end tag (pre) after the (implied) root element. +Line: 1 Col: 64 Unexpected end tag (big) after the (implied) root element. +Line: 1 Col: 72 Unexpected end tag (small) after the (implied) root element. +Line: 1 Col: 79 Unexpected end tag (font) after the (implied) root element. +Line: 1 Col: 88 Unexpected end tag (select) after the (implied) root element. +Line: 1 Col: 93 Unexpected end tag (h1) after the (implied) root element. +Line: 1 Col: 98 Unexpected end tag (h2) after the (implied) root element. +Line: 1 Col: 103 Unexpected end tag (h3) after the (implied) root element. +Line: 1 Col: 108 Unexpected end tag (h4) after the (implied) root element. +Line: 1 Col: 113 Unexpected end tag (h5) after the (implied) root element. +Line: 1 Col: 118 Unexpected end tag (h6) after the (implied) root element. +Line: 1 Col: 125 Unexpected end tag (body) after the (implied) root element. +Line: 1 Col: 130 Unexpected end tag (br). Treated as br element. +Line: 1 Col: 134 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 140 This element (img) has no end tag. +Line: 1 Col: 148 Unexpected end tag (title). Ignored. +Line: 1 Col: 155 Unexpected end tag (span). Ignored. +Line: 1 Col: 163 Unexpected end tag (style). Ignored. +Line: 1 Col: 172 Unexpected end tag (script). Ignored. +Line: 1 Col: 180 Unexpected end tag (table). Ignored. +Line: 1 Col: 185 Unexpected end tag (th). Ignored. +Line: 1 Col: 190 Unexpected end tag (td). Ignored. +Line: 1 Col: 195 Unexpected end tag (tr). Ignored. +Line: 1 Col: 203 This element (frame) has no end tag. +Line: 1 Col: 210 This element (area) has no end tag. +Line: 1 Col: 217 Unexpected end tag (link). Ignored. +Line: 1 Col: 225 This element (param) has no end tag. +Line: 1 Col: 230 This element (hr) has no end tag. +Line: 1 Col: 238 This element (input) has no end tag. +Line: 1 Col: 244 Unexpected end tag (col). Ignored. +Line: 1 Col: 251 Unexpected end tag (base). Ignored. +Line: 1 Col: 258 Unexpected end tag (meta). Ignored. +Line: 1 Col: 269 This element (basefont) has no end tag. +Line: 1 Col: 279 This element (bgsound) has no end tag. +Line: 1 Col: 287 This element (embed) has no end tag. +Line: 1 Col: 296 This element (spacer) has no end tag. +Line: 1 Col: 300 Unexpected end tag (p). Ignored. +Line: 1 Col: 305 End tag (dd) seen too early. Expected other end tag. +Line: 1 Col: 310 End tag (dt) seen too early. Expected other end tag. +Line: 1 Col: 320 Unexpected end tag (caption). Ignored. +Line: 1 Col: 331 Unexpected end tag (colgroup). Ignored. +Line: 1 Col: 339 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 347 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 355 Unexpected end tag (thead). Ignored. +Line: 1 Col: 365 End tag (address) seen too early. Expected other end tag. +Line: 1 Col: 378 End tag (blockquote) seen too early. Expected other end tag. +Line: 1 Col: 387 End tag (center) seen too early. Expected other end tag. +Line: 1 Col: 393 Unexpected end tag (dir). Ignored. +Line: 1 Col: 399 End tag (div) seen too early. Expected other end tag. +Line: 1 Col: 404 End tag (dl) seen too early. Expected other end tag. +Line: 1 Col: 415 End tag (fieldset) seen too early. Expected other end tag. +Line: 1 Col: 425 End tag (listing) seen too early. Expected other end tag. +Line: 1 Col: 432 End tag (menu) seen too early. Expected other end tag. +Line: 1 Col: 437 End tag (ol) seen too early. Expected other end tag. +Line: 1 Col: 442 End tag (ul) seen too early. Expected other end tag. +Line: 1 Col: 447 End tag (li) seen too early. Expected other end tag. +Line: 1 Col: 454 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 460 This element (wbr) has no end tag. +Line: 1 Col: 476 End tag (button) seen too early. Expected other end tag. +Line: 1 Col: 486 End tag (marquee) seen too early. Expected other end tag. +Line: 1 Col: 495 End tag (object) seen too early. Expected other end tag. +Line: 1 Col: 513 Unexpected end tag (html). Ignored. +Line: 1 Col: 513 Unexpected end tag (frameset). Ignored. +Line: 1 Col: 520 Unexpected end tag (head). Ignored. +Line: 1 Col: 529 Unexpected end tag (iframe). Ignored. +Line: 1 Col: 537 This element (image) has no end tag. +Line: 1 Col: 547 This element (isindex) has no end tag. +Line: 1 Col: 557 Unexpected end tag (noembed). Ignored. +Line: 1 Col: 568 Unexpected end tag (noframes). Ignored. +Line: 1 Col: 579 Unexpected end tag (noscript). Ignored. +Line: 1 Col: 590 Unexpected end tag (optgroup). Ignored. +Line: 1 Col: 599 Unexpected end tag (option). Ignored. +Line: 1 Col: 611 Unexpected end tag (plaintext). Ignored. +Line: 1 Col: 622 Unexpected end tag (textarea). Ignored. +#document +| <html> +| <head> +| <body> +| <br> +| <p> + +#data +<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end tag (strong) in table context caused voodoo mode. +Line: 1 Col: 20 End tag (strong) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 24 Unexpected end tag (b) in table context caused voodoo mode. +Line: 1 Col: 24 End tag (b) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 29 Unexpected end tag (em) in table context caused voodoo mode. +Line: 1 Col: 29 End tag (em) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 33 Unexpected end tag (i) in table context caused voodoo mode. +Line: 1 Col: 33 End tag (i) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 37 Unexpected end tag (u) in table context caused voodoo mode. +Line: 1 Col: 37 End tag (u) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 46 Unexpected end tag (strike) in table context caused voodoo mode. +Line: 1 Col: 46 End tag (strike) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 50 Unexpected end tag (s) in table context caused voodoo mode. +Line: 1 Col: 50 End tag (s) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 58 Unexpected end tag (blink) in table context caused voodoo mode. +Line: 1 Col: 58 Unexpected end tag (blink). Ignored. +Line: 1 Col: 63 Unexpected end tag (tt) in table context caused voodoo mode. +Line: 1 Col: 63 End tag (tt) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 69 Unexpected end tag (pre) in table context caused voodoo mode. +Line: 1 Col: 69 End tag (pre) seen too early. Expected other end tag. +Line: 1 Col: 75 Unexpected end tag (big) in table context caused voodoo mode. +Line: 1 Col: 75 End tag (big) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 83 Unexpected end tag (small) in table context caused voodoo mode. +Line: 1 Col: 83 End tag (small) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 90 Unexpected end tag (font) in table context caused voodoo mode. +Line: 1 Col: 90 End tag (font) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 99 Unexpected end tag (select) in table context caused voodoo mode. +Line: 1 Col: 99 Unexpected end tag (select). Ignored. +Line: 1 Col: 104 Unexpected end tag (h1) in table context caused voodoo mode. +Line: 1 Col: 104 End tag (h1) seen too early. Expected other end tag. +Line: 1 Col: 109 Unexpected end tag (h2) in table context caused voodoo mode. +Line: 1 Col: 109 End tag (h2) seen too early. Expected other end tag. +Line: 1 Col: 114 Unexpected end tag (h3) in table context caused voodoo mode. +Line: 1 Col: 114 End tag (h3) seen too early. Expected other end tag. +Line: 1 Col: 119 Unexpected end tag (h4) in table context caused voodoo mode. +Line: 1 Col: 119 End tag (h4) seen too early. Expected other end tag. +Line: 1 Col: 124 Unexpected end tag (h5) in table context caused voodoo mode. +Line: 1 Col: 124 End tag (h5) seen too early. Expected other end tag. +Line: 1 Col: 129 Unexpected end tag (h6) in table context caused voodoo mode. +Line: 1 Col: 129 End tag (h6) seen too early. Expected other end tag. +Line: 1 Col: 136 Unexpected end tag (body) in the table row phase. Ignored. +Line: 1 Col: 141 Unexpected end tag (br) in table context caused voodoo mode. +Line: 1 Col: 141 Unexpected end tag (br). Treated as br element. +Line: 1 Col: 145 Unexpected end tag (a) in table context caused voodoo mode. +Line: 1 Col: 145 End tag (a) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 151 Unexpected end tag (img) in table context caused voodoo mode. +Line: 1 Col: 151 This element (img) has no end tag. +Line: 1 Col: 159 Unexpected end tag (title) in table context caused voodoo mode. +Line: 1 Col: 159 Unexpected end tag (title). Ignored. +Line: 1 Col: 166 Unexpected end tag (span) in table context caused voodoo mode. +Line: 1 Col: 166 Unexpected end tag (span). Ignored. +Line: 1 Col: 174 Unexpected end tag (style) in table context caused voodoo mode. +Line: 1 Col: 174 Unexpected end tag (style). Ignored. +Line: 1 Col: 183 Unexpected end tag (script) in table context caused voodoo mode. +Line: 1 Col: 183 Unexpected end tag (script). Ignored. +Line: 1 Col: 196 Unexpected end tag (th). Ignored. +Line: 1 Col: 201 Unexpected end tag (td). Ignored. +Line: 1 Col: 206 Unexpected end tag (tr). Ignored. +Line: 1 Col: 214 This element (frame) has no end tag. +Line: 1 Col: 221 This element (area) has no end tag. +Line: 1 Col: 228 Unexpected end tag (link). Ignored. +Line: 1 Col: 236 This element (param) has no end tag. +Line: 1 Col: 241 This element (hr) has no end tag. +Line: 1 Col: 249 This element (input) has no end tag. +Line: 1 Col: 255 Unexpected end tag (col). Ignored. +Line: 1 Col: 262 Unexpected end tag (base). Ignored. +Line: 1 Col: 269 Unexpected end tag (meta). Ignored. +Line: 1 Col: 280 This element (basefont) has no end tag. +Line: 1 Col: 290 This element (bgsound) has no end tag. +Line: 1 Col: 298 This element (embed) has no end tag. +Line: 1 Col: 307 This element (spacer) has no end tag. +Line: 1 Col: 311 Unexpected end tag (p). Ignored. +Line: 1 Col: 316 End tag (dd) seen too early. Expected other end tag. +Line: 1 Col: 321 End tag (dt) seen too early. Expected other end tag. +Line: 1 Col: 331 Unexpected end tag (caption). Ignored. +Line: 1 Col: 342 Unexpected end tag (colgroup). Ignored. +Line: 1 Col: 350 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 358 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 366 Unexpected end tag (thead). Ignored. +Line: 1 Col: 376 End tag (address) seen too early. Expected other end tag. +Line: 1 Col: 389 End tag (blockquote) seen too early. Expected other end tag. +Line: 1 Col: 398 End tag (center) seen too early. Expected other end tag. +Line: 1 Col: 404 Unexpected end tag (dir). Ignored. +Line: 1 Col: 410 End tag (div) seen too early. Expected other end tag. +Line: 1 Col: 415 End tag (dl) seen too early. Expected other end tag. +Line: 1 Col: 426 End tag (fieldset) seen too early. Expected other end tag. +Line: 1 Col: 436 End tag (listing) seen too early. Expected other end tag. +Line: 1 Col: 443 End tag (menu) seen too early. Expected other end tag. +Line: 1 Col: 448 End tag (ol) seen too early. Expected other end tag. +Line: 1 Col: 453 End tag (ul) seen too early. Expected other end tag. +Line: 1 Col: 458 End tag (li) seen too early. Expected other end tag. +Line: 1 Col: 465 End tag (nobr) violates step 1, paragraph 1 of the adoption agency algorithm. +Line: 1 Col: 471 This element (wbr) has no end tag. +Line: 1 Col: 487 End tag (button) seen too early. Expected other end tag. +Line: 1 Col: 497 End tag (marquee) seen too early. Expected other end tag. +Line: 1 Col: 506 End tag (object) seen too early. Expected other end tag. +Line: 1 Col: 524 Unexpected end tag (html). Ignored. +Line: 1 Col: 524 Unexpected end tag (frameset). Ignored. +Line: 1 Col: 531 Unexpected end tag (head). Ignored. +Line: 1 Col: 540 Unexpected end tag (iframe). Ignored. +Line: 1 Col: 548 This element (image) has no end tag. +Line: 1 Col: 558 This element (isindex) has no end tag. +Line: 1 Col: 568 Unexpected end tag (noembed). Ignored. +Line: 1 Col: 579 Unexpected end tag (noframes). Ignored. +Line: 1 Col: 590 Unexpected end tag (noscript). Ignored. +Line: 1 Col: 601 Unexpected end tag (optgroup). Ignored. +Line: 1 Col: 610 Unexpected end tag (option). Ignored. +Line: 1 Col: 622 Unexpected end tag (plaintext). Ignored. +Line: 1 Col: 633 Unexpected end tag (textarea). Ignored. +#document +| <html> +| <head> +| <body> +| <br> +| <table> +| <tbody> +| <tr> +| <p> + +#data +<frameset> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 1 Col: 10 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <frameset> diff --git a/pkgs/html/test/data/tree-construction/tests10.dat b/pkgs/html/test/data/tree-construction/tests10.dat new file mode 100644 index 000000000..4f8df86f2 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests10.dat @@ -0,0 +1,799 @@ +#data +<!DOCTYPE html><svg></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> + +#data +<!DOCTYPE html><svg></svg><![CDATA[a]]> +#errors +29: Bogus comment +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <!-- [CDATA[a]] --> + +#data +<!DOCTYPE html><body><svg></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> + +#data +<!DOCTYPE html><body><select><svg></svg></select> +#errors +35: Stray “svg” start tag. +42: Stray end tag “svg” +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!DOCTYPE html><body><select><option><svg></svg></option></select> +#errors +43: Stray “svg” start tag. +50: Stray end tag “svg” +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> + +#data +<!DOCTYPE html><body><table><svg></svg></table> +#errors +34: Start tag “svg” seen in “table”. +41: Stray end tag “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <table> + +#data +<!DOCTYPE html><body><table><svg><g>foo</g></svg></table> +#errors +34: Start tag “svg” seen in “table”. +46: Stray end tag “g”. +53: Stray end tag “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <table> + +#data +<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table> +#errors +34: Start tag “svg” seen in “table”. +46: Stray end tag “g”. +58: Stray end tag “g”. +65: Stray end tag “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <table> + +#data +<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table> +#errors +41: Start tag “svg” seen in “table”. +53: Stray end tag “g”. +65: Stray end tag “g”. +72: Stray end tag “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <table> +| <tbody> + +#data +<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table> +#errors +45: Start tag “svg” seen in “table”. +57: Stray end tag “g”. +69: Stray end tag “g”. +76: Stray end tag “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <table> +| <tbody> +| <tr> + +#data +<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" + +#data +<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux +#errors +70: HTML start tag “p” in a foreign namespace context. +81: “table” closed but “caption” was still open. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux +#errors +78: “table” closed but “caption” was still open. +78: Unclosed elements on stack. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| "baz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux +#errors +44: Start tag “svg” seen in “table”. +56: Stray end tag “g”. +68: Stray end tag “g”. +71: HTML start tag “p” in a foreign namespace context. +71: Start tag “p” seen in “table”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" +| <table> +| <colgroup> +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux +#errors +50: Stray “svg” start tag. +54: Stray “g” start tag. +62: Stray end tag “g” +66: Stray “g” start tag. +74: Stray end tag “g” +77: Stray “p” start tag. +88: “table” end tag with “select” open. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <select> +| "foobarbaz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux +#errors +36: Start tag “select” seen in “table”. +42: Stray “svg” start tag. +46: Stray “g” start tag. +54: Stray end tag “g” +58: Stray “g” start tag. +66: Stray end tag “g” +69: Stray “p” start tag. +80: “table” end tag with “select” open. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| "foobarbaz" +| <table> +| <p> +| "quux" + +#data +<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz +#errors +41: Stray “svg” start tag. +68: HTML start tag “p” in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz +#errors +34: Stray “svg” start tag. +61: HTML start tag “p” in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg g> +| "foo" +| <svg g> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><frameset><svg><g></g><g></g><p><span> +#errors +31: Stray “svg” start tag. +35: Stray “g” start tag. +40: Stray end tag “g” +44: Stray “g” start tag. +49: Stray end tag “g” +52: Stray “p” start tag. +58: Stray “span” start tag. +58: End of file seen and there were open elements. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span> +#errors +42: Stray “svg” start tag. +46: Stray “g” start tag. +51: Stray end tag “g” +55: Stray “g” start tag. +60: Stray end tag “g” +63: Stray “p” start tag. +69: Stray “span” start tag. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| <svg svg> +| xlink href="foo" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <svg svg> +| <svg g> +| xlink href="foo" +| xml lang="en" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <svg svg> +| <svg g> +| xlink href="foo" +| xml lang="en" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <svg svg> +| <svg g> +| xlink href="foo" +| xml lang="en" +| "bar" + +#data +<svg></path> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> + +#data +<div><svg></div>a +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| "a" + +#data +<div><svg><path></div>a +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| <svg path> +| "a" + +#data +<div><svg><path></svg><path> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| <svg path> +| <path> + +#data +<div><svg><path><foreignObject><math></div>a +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| <svg path> +| <svg foreignObject> +| <math math> +| "a" + +#data +<div><svg><path><foreignObject><p></div>a +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| <svg path> +| <svg foreignObject> +| <p> +| "a" + +#data +<!DOCTYPE html><svg><desc><div><svg><ul>a +#errors +40: HTML start tag “ul” in a foreign namespace context. +41: End of file in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg desc> +| <div> +| <svg svg> +| <ul> +| "a" + +#data +<!DOCTYPE html><svg><desc><svg><ul>a +#errors +35: HTML start tag “ul” in a foreign namespace context. +36: End of file in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg desc> +| <svg svg> +| <ul> +| "a" + +#data +<!DOCTYPE html><p><svg><desc><p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <svg svg> +| <svg desc> +| <p> + +#data +<!DOCTYPE html><p><svg><title><p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <svg svg> +| <svg title> +| <p> + +#data +<div><svg><path><foreignObject><p></foreignObject><p> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <svg svg> +| <svg path> +| <svg foreignObject> +| <p> +| <p> + +#data +<math><mi><div><object><div><span></span></div></object></div></mi><mi> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| <div> +| <object> +| <div> +| <span> +| <math mi> + +#data +<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| <svg svg> +| <svg foreignObject> +| <div> +| <div> +| <math mi> + +#data +<svg><script></script><path> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg script> +| <svg path> + +#data +<table><svg></svg><tr> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <table> +| <tbody> +| <tr> + +#data +<math><mi><mglyph> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| <math mglyph> + +#data +<math><mi><malignmark> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| <math malignmark> + +#data +<math><mo><mglyph> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mo> +| <math mglyph> + +#data +<math><mo><malignmark> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mo> +| <math malignmark> + +#data +<math><mn><mglyph> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mn> +| <math mglyph> + +#data +<math><mn><malignmark> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mn> +| <math malignmark> + +#data +<math><ms><mglyph> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math ms> +| <math mglyph> + +#data +<math><ms><malignmark> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math ms> +| <math malignmark> + +#data +<math><mtext><mglyph> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mtext> +| <math mglyph> + +#data +<math><mtext><malignmark> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mtext> +| <math malignmark> + +#data +<math><annotation-xml><svg></svg></annotation-xml><mi> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| <svg svg> +| <math mi> + +#data +<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| <svg svg> +| <svg foreignObject> +| <div> +| <math math> +| <math mi> +| <span> +| <svg path> +| <math mi> + +#data +<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| <svg svg> +| <svg foreignObject> +| <math math> +| <math mi> +| <svg svg> +| <math mo> +| <span> +| <svg path> +| <math mi> diff --git a/pkgs/html/test/data/tree-construction/tests11.dat b/pkgs/html/test/data/tree-construction/tests11.dat new file mode 100644 index 000000000..638cde479 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests11.dat @@ -0,0 +1,482 @@ +#data +<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| attributeName="" +| attributeType="" +| baseFrequency="" +| baseProfile="" +| calcMode="" +| clipPathUnits="" +| contentScriptType="" +| contentStyleType="" +| diffuseConstant="" +| edgeMode="" +| externalResourcesRequired="" +| filterRes="" +| filterUnits="" +| glyphRef="" +| gradientTransform="" +| gradientUnits="" +| kernelMatrix="" +| kernelUnitLength="" +| keyPoints="" +| keySplines="" +| keyTimes="" +| lengthAdjust="" +| limitingConeAngle="" +| markerHeight="" +| markerUnits="" +| markerWidth="" +| maskContentUnits="" +| maskUnits="" +| numOctaves="" +| pathLength="" +| patternContentUnits="" +| patternTransform="" +| patternUnits="" +| pointsAtX="" +| pointsAtY="" +| pointsAtZ="" +| preserveAlpha="" +| preserveAspectRatio="" +| primitiveUnits="" +| refX="" +| refY="" +| repeatCount="" +| repeatDur="" +| requiredExtensions="" +| requiredFeatures="" +| specularConstant="" +| specularExponent="" +| spreadMethod="" +| startOffset="" +| stdDeviation="" +| stitchTiles="" +| surfaceScale="" +| systemLanguage="" +| tableValues="" +| targetX="" +| targetY="" +| textLength="" +| viewBox="" +| viewTarget="" +| xChannelSelector="" +| yChannelSelector="" +| zoomAndPan="" + +#data +<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' DIFFUSECONSTANT='' EDGEMODE='' EXTERNALRESOURCESREQUIRED='' FILTERRES='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| attributeName="" +| attributeType="" +| baseFrequency="" +| baseProfile="" +| calcMode="" +| clipPathUnits="" +| contentScriptType="" +| contentStyleType="" +| diffuseConstant="" +| edgeMode="" +| externalResourcesRequired="" +| filterRes="" +| filterUnits="" +| glyphRef="" +| gradientTransform="" +| gradientUnits="" +| kernelMatrix="" +| kernelUnitLength="" +| keyPoints="" +| keySplines="" +| keyTimes="" +| lengthAdjust="" +| limitingConeAngle="" +| markerHeight="" +| markerUnits="" +| markerWidth="" +| maskContentUnits="" +| maskUnits="" +| numOctaves="" +| pathLength="" +| patternContentUnits="" +| patternTransform="" +| patternUnits="" +| pointsAtX="" +| pointsAtY="" +| pointsAtZ="" +| preserveAlpha="" +| preserveAspectRatio="" +| primitiveUnits="" +| refX="" +| refY="" +| repeatCount="" +| repeatDur="" +| requiredExtensions="" +| requiredFeatures="" +| specularConstant="" +| specularExponent="" +| spreadMethod="" +| startOffset="" +| stdDeviation="" +| stitchTiles="" +| surfaceScale="" +| systemLanguage="" +| tableValues="" +| targetX="" +| targetY="" +| textLength="" +| viewBox="" +| viewTarget="" +| xChannelSelector="" +| yChannelSelector="" +| zoomAndPan="" + +#data +<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' contentscripttype='' contentstyletype='' diffuseconstant='' edgemode='' externalresourcesrequired='' filterres='' filterunits='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| attributeName="" +| attributeType="" +| baseFrequency="" +| baseProfile="" +| calcMode="" +| clipPathUnits="" +| contentScriptType="" +| contentStyleType="" +| diffuseConstant="" +| edgeMode="" +| externalResourcesRequired="" +| filterRes="" +| filterUnits="" +| glyphRef="" +| gradientTransform="" +| gradientUnits="" +| kernelMatrix="" +| kernelUnitLength="" +| keyPoints="" +| keySplines="" +| keyTimes="" +| lengthAdjust="" +| limitingConeAngle="" +| markerHeight="" +| markerUnits="" +| markerWidth="" +| maskContentUnits="" +| maskUnits="" +| numOctaves="" +| pathLength="" +| patternContentUnits="" +| patternTransform="" +| patternUnits="" +| pointsAtX="" +| pointsAtY="" +| pointsAtZ="" +| preserveAlpha="" +| preserveAspectRatio="" +| primitiveUnits="" +| refX="" +| refY="" +| repeatCount="" +| repeatDur="" +| requiredExtensions="" +| requiredFeatures="" +| specularConstant="" +| specularExponent="" +| spreadMethod="" +| startOffset="" +| stdDeviation="" +| stitchTiles="" +| surfaceScale="" +| systemLanguage="" +| tableValues="" +| targetX="" +| targetY="" +| textLength="" +| viewBox="" +| viewTarget="" +| xChannelSelector="" +| yChannelSelector="" +| zoomAndPan="" + +#data +<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' contentScriptType='' contentStyleType='' diffuseConstant='' edgeMode='' externalResourcesRequired='' filterRes='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| attributename="" +| attributetype="" +| basefrequency="" +| baseprofile="" +| calcmode="" +| clippathunits="" +| contentscripttype="" +| contentstyletype="" +| diffuseconstant="" +| edgemode="" +| externalresourcesrequired="" +| filterres="" +| filterunits="" +| glyphref="" +| gradienttransform="" +| gradientunits="" +| kernelmatrix="" +| kernelunitlength="" +| keypoints="" +| keysplines="" +| keytimes="" +| lengthadjust="" +| limitingconeangle="" +| markerheight="" +| markerunits="" +| markerwidth="" +| maskcontentunits="" +| maskunits="" +| numoctaves="" +| pathlength="" +| patterncontentunits="" +| patterntransform="" +| patternunits="" +| pointsatx="" +| pointsaty="" +| pointsatz="" +| preservealpha="" +| preserveaspectratio="" +| primitiveunits="" +| refx="" +| refy="" +| repeatcount="" +| repeatdur="" +| requiredextensions="" +| requiredfeatures="" +| specularconstant="" +| specularexponent="" +| spreadmethod="" +| startoffset="" +| stddeviation="" +| stitchtiles="" +| surfacescale="" +| systemlanguage="" +| tablevalues="" +| targetx="" +| targety="" +| textlength="" +| viewbox="" +| viewtarget="" +| xchannelselector="" +| ychannelselector="" +| zoomandpan="" + +#data +<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg altGlyph> +| <svg altGlyphDef> +| <svg altGlyphItem> +| <svg animateColor> +| <svg animateMotion> +| <svg animateTransform> +| <svg clipPath> +| <svg feBlend> +| <svg feColorMatrix> +| <svg feComponentTransfer> +| <svg feComposite> +| <svg feConvolveMatrix> +| <svg feDiffuseLighting> +| <svg feDisplacementMap> +| <svg feDistantLight> +| <svg feFlood> +| <svg feFuncA> +| <svg feFuncB> +| <svg feFuncG> +| <svg feFuncR> +| <svg feGaussianBlur> +| <svg feImage> +| <svg feMerge> +| <svg feMergeNode> +| <svg feMorphology> +| <svg feOffset> +| <svg fePointLight> +| <svg feSpecularLighting> +| <svg feSpotLight> +| <svg feTile> +| <svg feTurbulence> +| <svg foreignObject> +| <svg glyphRef> +| <svg linearGradient> +| <svg radialGradient> +| <svg textPath> + +#data +<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg altGlyph> +| <svg altGlyphDef> +| <svg altGlyphItem> +| <svg animateColor> +| <svg animateMotion> +| <svg animateTransform> +| <svg clipPath> +| <svg feBlend> +| <svg feColorMatrix> +| <svg feComponentTransfer> +| <svg feComposite> +| <svg feConvolveMatrix> +| <svg feDiffuseLighting> +| <svg feDisplacementMap> +| <svg feDistantLight> +| <svg feFlood> +| <svg feFuncA> +| <svg feFuncB> +| <svg feFuncG> +| <svg feFuncR> +| <svg feGaussianBlur> +| <svg feImage> +| <svg feMerge> +| <svg feMergeNode> +| <svg feMorphology> +| <svg feOffset> +| <svg fePointLight> +| <svg feSpecularLighting> +| <svg feSpotLight> +| <svg feTile> +| <svg feTurbulence> +| <svg foreignObject> +| <svg glyphRef> +| <svg linearGradient> +| <svg radialGradient> +| <svg textPath> + +#data +<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg altGlyph> +| <svg altGlyphDef> +| <svg altGlyphItem> +| <svg animateColor> +| <svg animateMotion> +| <svg animateTransform> +| <svg clipPath> +| <svg feBlend> +| <svg feColorMatrix> +| <svg feComponentTransfer> +| <svg feComposite> +| <svg feConvolveMatrix> +| <svg feDiffuseLighting> +| <svg feDisplacementMap> +| <svg feDistantLight> +| <svg feFlood> +| <svg feFuncA> +| <svg feFuncB> +| <svg feFuncG> +| <svg feFuncR> +| <svg feGaussianBlur> +| <svg feImage> +| <svg feMerge> +| <svg feMergeNode> +| <svg feMorphology> +| <svg feOffset> +| <svg fePointLight> +| <svg feSpecularLighting> +| <svg feSpotLight> +| <svg feTile> +| <svg feTurbulence> +| <svg foreignObject> +| <svg glyphRef> +| <svg linearGradient> +| <svg radialGradient> +| <svg textPath> + +#data +<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math altglyph> +| <math altglyphdef> +| <math altglyphitem> +| <math animatecolor> +| <math animatemotion> +| <math animatetransform> +| <math clippath> +| <math feblend> +| <math fecolormatrix> +| <math fecomponenttransfer> +| <math fecomposite> +| <math feconvolvematrix> +| <math fediffuselighting> +| <math fedisplacementmap> +| <math fedistantlight> +| <math feflood> +| <math fefunca> +| <math fefuncb> +| <math fefuncg> +| <math fefuncr> +| <math fegaussianblur> +| <math feimage> +| <math femerge> +| <math femergenode> +| <math femorphology> +| <math feoffset> +| <math fepointlight> +| <math fespecularlighting> +| <math fespotlight> +| <math fetile> +| <math feturbulence> +| <math foreignobject> +| <math glyphref> +| <math lineargradient> +| <math radialgradient> +| <math textpath> + +#data +<!DOCTYPE html><body><svg><solidColor /></svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg solidcolor> diff --git a/pkgs/html/test/data/tree-construction/tests12.dat b/pkgs/html/test/data/tree-construction/tests12.dat new file mode 100644 index 000000000..63107d277 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests12.dat @@ -0,0 +1,62 @@ +#data +<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| "foo" +| <math math> +| <math mtext> +| <i> +| "baz" +| <math annotation-xml> +| <svg svg> +| <svg desc> +| <b> +| "eggs" +| <svg g> +| <svg foreignObject> +| <p> +| "spam" +| <table> +| <tbody> +| <tr> +| <td> +| <img> +| <svg g> +| "quux" +| "bar" + +#data +<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "foo" +| <math math> +| <math mtext> +| <i> +| "baz" +| <math annotation-xml> +| <svg svg> +| <svg desc> +| <b> +| "eggs" +| <svg g> +| <svg foreignObject> +| <p> +| "spam" +| <table> +| <tbody> +| <tr> +| <td> +| <img> +| <svg g> +| "quux" +| "bar" diff --git a/pkgs/html/test/data/tree-construction/tests14.dat b/pkgs/html/test/data/tree-construction/tests14.dat new file mode 100644 index 000000000..b8713f885 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests14.dat @@ -0,0 +1,74 @@ +#data +<!DOCTYPE html><html><body><xyz:abc></xyz:abc> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <xyz:abc> + +#data +<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <xyz:abc> +| <span> + +#data +<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc> +#errors +15: Unexpected start tag html +#document +| <!DOCTYPE html> +| <html> +| abc:def="gh" +| <head> +| <body> +| <xyz:abc> + +#data +<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo> +#errors +15: Unexpected start tag html +#document +| <!DOCTYPE html> +| <html> +| xml:lang="bar" +| <head> +| <body> + +#data +<!DOCTYPE html><html 123=456> +#errors +#document +| <!DOCTYPE html> +| <html> +| 123="456" +| <head> +| <body> + +#data +<!DOCTYPE html><html 123=456><html 789=012> +#errors +#document +| <!DOCTYPE html> +| <html> +| 123="456" +| 789="012" +| <head> +| <body> + +#data +<!DOCTYPE html><html><body 789=012> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| 789="012" diff --git a/pkgs/html/test/data/tree-construction/tests15.dat b/pkgs/html/test/data/tree-construction/tests15.dat new file mode 100644 index 000000000..6ce1c0d16 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests15.dat @@ -0,0 +1,208 @@ +#data +<!DOCTYPE html><p><b><i><u></p> <p>X +#errors +Line: 1 Col: 31 Unexpected end tag (p). Ignored. +Line: 1 Col: 36 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <b> +| <i> +| <u> +| <b> +| <i> +| <u> +| " " +| <p> +| "X" + +#data +<p><b><i><u></p> +<p>X +#errors +Line: 1 Col: 3 Unexpected start tag (p). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected end tag (p). Ignored. +Line: 2 Col: 4 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <p> +| <b> +| <i> +| <u> +| <b> +| <i> +| <u> +| " +" +| <p> +| "X" + +#data +<!doctype html></html> <head> +#errors +Line: 1 Col: 22 Unexpected end tag (html) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " " + +#data +<!doctype html></body><meta> +#errors +Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <meta> + +#data +<html></html><!-- foo --> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end tag (html) after the (implied) root element. +#document +| <html> +| <head> +| <body> +| <!-- foo --> + +#data +<!doctype html></body><title>X</title> +#errors +Line: 1 Col: 22 Unexpected end tag (body) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <title> +| "X" + +#data +<!doctype html><table> X<meta></table> +#errors +Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 30 Unexpected start tag (meta) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " X" +| <meta> +| <table> + +#data +<!doctype html><table> x</table> +#errors +Line: 1 Col: 24 Unexpected non-space characters in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " x" +| <table> + +#data +<!doctype html><table> x </table> +#errors +Line: 1 Col: 25 Unexpected non-space characters in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " x " +| <table> + +#data +<!doctype html><table><tr> x</table> +#errors +Line: 1 Col: 28 Unexpected non-space characters in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " x" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><table>X<style> <tr>x </style> </table> +#errors +Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" +| <table> +| <style> +| " <tr>x " +| " " + +#data +<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div> +#errors +Line: 1 Col: 30 Unexpected start tag (a) in table context caused voodoo mode. +Line: 1 Col: 37 Unexpected end tag (a) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> +| <a> +| "foo" +| <table> +| " " +| <tbody> +| <tr> +| <td> +| "bar" +| " " + +#data +<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes> +#errors +6: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +13: Stray start tag “frame”. +21: Stray end tag “frame”. +29: Stray end tag “frame”. +39: “frameset” start tag after “body” already open. +105: End of file seen inside an [R]CDATA element. +105: End of file seen and there were open elements. +XXX: These errors are wrong, please fix me! +#document +| <html> +| <head> +| <frameset> +| <frame> +| <frameset> +| <frame> +| <noframes> +| "</frameset><noframes>" + +#data +<!DOCTYPE html><object></html> +#errors +1: Expected closing tag. Unexpected end of file +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <object> diff --git a/pkgs/html/test/data/tree-construction/tests16.dat b/pkgs/html/test/data/tree-construction/tests16.dat new file mode 100644 index 000000000..c8ef66f0e --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests16.dat @@ -0,0 +1,2299 @@ +#data +<!doctype html><script> +#errors +Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| <body> + +#data +<!doctype html><script>a +#errors +Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "a" +| <body> + +#data +<!doctype html><script>< +#errors +Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<" +| <body> + +#data +<!doctype html><script></ +#errors +Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</" +| <body> + +#data +<!doctype html><script></S +#errors +Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</S" +| <body> + +#data +<!doctype html><script></SC +#errors +Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</SC" +| <body> + +#data +<!doctype html><script></SCR +#errors +Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</SCR" +| <body> + +#data +<!doctype html><script></SCRI +#errors +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</SCRI" +| <body> + +#data +<!doctype html><script></SCRIP +#errors +Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</SCRIP" +| <body> + +#data +<!doctype html><script></SCRIPT +#errors +Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</SCRIPT" +| <body> + +#data +<!doctype html><script></SCRIPT +#errors +Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| <body> + +#data +<!doctype html><script></s +#errors +Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</s" +| <body> + +#data +<!doctype html><script></sc +#errors +Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</sc" +| <body> + +#data +<!doctype html><script></scr +#errors +Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</scr" +| <body> + +#data +<!doctype html><script></scri +#errors +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</scri" +| <body> + +#data +<!doctype html><script></scrip +#errors +Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</scrip" +| <body> + +#data +<!doctype html><script></script +#errors +Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "</script" +| <body> + +#data +<!doctype html><script></script +#errors +Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| <body> + +#data +<!doctype html><script><! +#errors +Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!" +| <body> + +#data +<!doctype html><script><!a +#errors +Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!a" +| <body> + +#data +<!doctype html><script><!- +#errors +Line: 1 Col: 26 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!-" +| <body> + +#data +<!doctype html><script><!-a +#errors +Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!-a" +| <body> + +#data +<!doctype html><script><!-- +#errors +Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--" +| <body> + +#data +<!doctype html><script><!--a +#errors +Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--a" +| <body> + +#data +<!doctype html><script><!--< +#errors +Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<" +| <body> + +#data +<!doctype html><script><!--<a +#errors +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<a" +| <body> + +#data +<!doctype html><script><!--</ +#errors +Line: 1 Col: 27 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--</" +| <body> + +#data +<!doctype html><script><!--</script +#errors +Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--</script" +| <body> + +#data +<!doctype html><script><!--</script +#errors +Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--" +| <body> + +#data +<!doctype html><script><!--<s +#errors +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<s" +| <body> + +#data +<!doctype html><script><!--<script +#errors +Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script" +| <body> + +#data +<!doctype html><script><!--<script +#errors +Line: 1 Col: 35 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script " +| <body> + +#data +<!doctype html><script><!--<script < +#errors +Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script <" +| <body> + +#data +<!doctype html><script><!--<script <a +#errors +Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script <a" +| <body> + +#data +<!doctype html><script><!--<script </ +#errors +Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </" +| <body> + +#data +<!doctype html><script><!--<script </s +#errors +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </s" +| <body> + +#data +<!doctype html><script><!--<script </script +#errors +Line: 1 Col: 43 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script" +| <body> + +#data +<!doctype html><script><!--<script </scripta +#errors +Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </scripta" +| <body> + +#data +<!doctype html><script><!--<script </script +#errors +Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<!doctype html><script><!--<script </script> +#errors +Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script>" +| <body> + +#data +<!doctype html><script><!--<script </script/ +#errors +Line: 1 Col: 44 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script/" +| <body> + +#data +<!doctype html><script><!--<script </script < +#errors +Line: 1 Col: 45 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script <" +| <body> + +#data +<!doctype html><script><!--<script </script <a +#errors +Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script <a" +| <body> + +#data +<!doctype html><script><!--<script </script </ +#errors +Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script </" +| <body> + +#data +<!doctype html><script><!--<script </script </script +#errors +Line: 1 Col: 52 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script </script" +| <body> + +#data +<!doctype html><script><!--<script </script </script +#errors +Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<!doctype html><script><!--<script </script </script/ +#errors +Line: 1 Col: 53 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<!doctype html><script><!--<script </script </script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<!doctype html><script><!--<script - +#errors +Line: 1 Col: 36 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -" +| <body> + +#data +<!doctype html><script><!--<script -a +#errors +Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -a" +| <body> + +#data +<!doctype html><script><!--<script -< +#errors +Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -<" +| <body> + +#data +<!doctype html><script><!--<script -- +#errors +Line: 1 Col: 37 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --" +| <body> + +#data +<!doctype html><script><!--<script --a +#errors +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --a" +| <body> + +#data +<!doctype html><script><!--<script --< +#errors +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --<" +| <body> + +#data +<!doctype html><script><!--<script --> +#errors +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<!doctype html><script><!--<script -->< +#errors +Line: 1 Col: 39 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --><" +| <body> + +#data +<!doctype html><script><!--<script --></ +#errors +Line: 1 Col: 40 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --></" +| <body> + +#data +<!doctype html><script><!--<script --></script +#errors +Line: 1 Col: 46 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script --></script" +| <body> + +#data +<!doctype html><script><!--<script --></script +#errors +Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<!doctype html><script><!--<script --></script/ +#errors +Line: 1 Col: 47 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<!doctype html><script><!--<script --></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<!doctype html><script><!--<script><\/script>--></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script><\/script>-->" +| <body> + +#data +<!doctype html><script><!--<script></scr'+'ipt>--></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></scr'+'ipt>-->" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script>--><!--</script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>--><!--" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script>-- ></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>-- >" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script>- -></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>- ->" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script>- - ></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>- - >" +| <body> + +#data +<!doctype html><script><!--<script></script><script></script>-></script> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>->" +| <body> + +#data +<!doctype html><script><!--<script>--!></script>X +#errors +Line: 1 Col: 49 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script>--!></script>X" +| <body> + +#data +<!doctype html><script><!--<scr'+'ipt></script>--></script> +#errors +Line: 1 Col: 59 Unexpected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<scr'+'ipt>" +| <body> +| "-->" + +#data +<!doctype html><script><!--<script></scr'+'ipt></script>X +#errors +Line: 1 Col: 57 Unexpected end of file. Expected end tag (script). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| "<!--<script></scr'+'ipt></script>X" +| <body> + +#data +<!doctype html><style><!--<style></style>--></style> +#errors +Line: 1 Col: 52 Unexpected end tag (style). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--<style>" +| <body> +| "-->" + +#data +<!doctype html><style><!--</style>X +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--" +| <body> +| "X" + +#data +<!doctype html><style><!--...</style>...--></style> +#errors +Line: 1 Col: 51 Unexpected end tag (style). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--..." +| <body> +| "...-->" + +#data +<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" +| <body> +| "X" + +#data +<!doctype html><style><!--...<style><!--...--!></style>--></style> +#errors +Line: 1 Col: 66 Unexpected end tag (style). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--...<style><!--...--!>" +| <body> +| "-->" + +#data +<!doctype html><style><!--...</style><!-- --><style>@import ...</style> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "<!--..." +| <!-- --> +| <style> +| "@import ..." +| <body> + +#data +<!doctype html><style>...<style><!--...</style><!-- --></style> +#errors +Line: 1 Col: 63 Unexpected end tag (style). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "...<style><!--..." +| <!-- --> +| <body> + +#data +<!doctype html><style>...<!--[if IE]><style>...</style>X +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <style> +| "...<!--[if IE]><style>..." +| <body> +| "X" + +#data +<!doctype html><title><!--<title></title>--></title> +#errors +Line: 1 Col: 52 Unexpected end tag (title). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "<!--<title>" +| <body> +| "-->" + +#data +<!doctype html><title>&lt;/title></title> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "</title>" +| <body> + +#data +<!doctype html><title>foo/title><link></head><body>X +#errors +Line: 1 Col: 52 Unexpected end of file. Expected end tag (title). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "foo/title><link></head><body>X" +| <body> + +#data +<!doctype html><noscript><!--<noscript></noscript>--></noscript> +#errors +Line: 1 Col: 64 Unexpected end tag (noscript). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <noscript> +| "<!--<noscript>" +| <body> +| "-->" + +#data +<!doctype html><noscript><!--</noscript>X<noscript>--></noscript> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <noscript> +| "<!--" +| <body> +| "X" +| <noscript> +| "-->" + +#data +<!doctype html><noscript><iframe></noscript>X +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <noscript> +| "<iframe>" +| <body> +| "X" + +#data +<!doctype html><noframes><!--<noframes></noframes>--></noframes> +#errors +Line: 1 Col: 64 Unexpected end tag (noframes). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <noframes> +| "<!--<noframes>" +| <body> +| "-->" + +#data +<!doctype html><noframes><body><script><!--...</script></body></noframes></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <noframes> +| "<body><script><!--...</script></body>" +| <body> + +#data +<!doctype html><textarea><!--<textarea></textarea>--></textarea> +#errors +Line: 1 Col: 64 Unexpected end tag (textarea). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| "<!--<textarea>" +| "-->" + +#data +<!doctype html><textarea>&lt;/textarea></textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| "</textarea>" + +#data +<!doctype html><textarea>&lt;</textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| "<" + +#data +<!doctype html><textarea>a&lt;b</textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| "a<b" + +#data +<!doctype html><iframe><!--<iframe></iframe>--></iframe> +#errors +Line: 1 Col: 56 Unexpected end tag (iframe). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <iframe> +| "<!--<iframe>" +| "-->" + +#data +<!doctype html><iframe>...<!--X->...<!--/X->...</iframe> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <iframe> +| "...<!--X->...<!--/X->..." + +#data +<!doctype html><xmp><!--<xmp></xmp>--></xmp> +#errors +Line: 1 Col: 44 Unexpected end tag (xmp). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <xmp> +| "<!--<xmp>" +| "-->" + +#data +<!doctype html><noembed><!--<noembed></noembed>--></noembed> +#errors +Line: 1 Col: 60 Unexpected end tag (noembed). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <noembed> +| "<!--<noembed>" +| "-->" + +#data +<script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 8 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| <body> + +#data +<script>a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "a" +| <body> + +#data +<script>< +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 9 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<" +| <body> + +#data +<script></ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</" +| <body> + +#data +<script></S +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</S" +| <body> + +#data +<script></SC +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</SC" +| <body> + +#data +<script></SCR +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</SCR" +| <body> + +#data +<script></SCRI +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</SCRI" +| <body> + +#data +<script></SCRIP +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</SCRIP" +| <body> + +#data +<script></SCRIPT +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</SCRIPT" +| <body> + +#data +<script></SCRIPT +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| <body> + +#data +<script></s +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</s" +| <body> + +#data +<script></sc +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</sc" +| <body> + +#data +<script></scr +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</scr" +| <body> + +#data +<script></scri +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</scri" +| <body> + +#data +<script></scrip +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 15 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</scrip" +| <body> + +#data +<script></script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</script" +| <body> + +#data +<script></script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 17 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| <body> + +#data +<script><! +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 10 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!" +| <body> + +#data +<script><!a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!a" +| <body> + +#data +<script><!- +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!-" +| <body> + +#data +<script><!-a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!-a" +| <body> + +#data +<script><!-- +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--" +| <body> + +#data +<script><!--a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--a" +| <body> + +#data +<script><!--< +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<" +| <body> + +#data +<script><!--<a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<a" +| <body> + +#data +<script><!--</ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--</" +| <body> + +#data +<script><!--</script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--</script" +| <body> + +#data +<script><!--</script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--" +| <body> + +#data +<script><!--<s +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<s" +| <body> + +#data +<script><!--<script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 19 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script" +| <body> + +#data +<script><!--<script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script " +| <body> + +#data +<script><!--<script < +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script <" +| <body> + +#data +<script><!--<script <a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script <a" +| <body> + +#data +<script><!--<script </ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </" +| <body> + +#data +<script><!--<script </s +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </s" +| <body> + +#data +<script><!--<script </script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 28 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script" +| <body> + +#data +<script><!--<script </scripta +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </scripta" +| <body> + +#data +<script><!--<script </script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<script><!--<script </script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script>" +| <body> + +#data +<script><!--<script </script/ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 29 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script/" +| <body> + +#data +<script><!--<script </script < +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 30 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script <" +| <body> + +#data +<script><!--<script </script <a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script <a" +| <body> + +#data +<script><!--<script </script </ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script </" +| <body> + +#data +<script><!--<script </script </script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script </script" +| <body> + +#data +<script><!--<script </script </script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<script><!--<script </script </script/ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 38 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<script><!--<script </script </script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script </script " +| <body> + +#data +<script><!--<script - +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 21 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script -" +| <body> + +#data +<script><!--<script -a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script -a" +| <body> + +#data +<script><!--<script -- +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script --" +| <body> + +#data +<script><!--<script --a +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script --a" +| <body> + +#data +<script><!--<script --> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<script><!--<script -->< +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 24 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script --><" +| <body> + +#data +<script><!--<script --></ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 25 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script --></" +| <body> + +#data +<script><!--<script --></script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 31 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script --></script" +| <body> + +#data +<script><!--<script --></script +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<script><!--<script --></script/ +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 32 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<script><!--<script --></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script -->" +| <body> + +#data +<script><!--<script><\/script>--></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script><\/script>-->" +| <body> + +#data +<script><!--<script></scr'+'ipt>--></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></scr'+'ipt>-->" +| <body> + +#data +<script><!--<script></script><script></script></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>" +| <body> + +#data +<script><!--<script></script><script></script>--><!--</script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>--><!--" +| <body> + +#data +<script><!--<script></script><script></script>-- ></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>-- >" +| <body> + +#data +<script><!--<script></script><script></script>- -></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>- ->" +| <body> + +#data +<script><!--<script></script><script></script>- - ></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>- - >" +| <body> + +#data +<script><!--<script></script><script></script>-></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| "<!--<script></script><script></script>->" +| <body> + +#data +<script><!--<script>--!></script>X +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 34 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script>--!></script>X" +| <body> + +#data +<script><!--<scr'+'ipt></script>--></script> +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 44 Unexpected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<scr'+'ipt>" +| <body> +| "-->" + +#data +<script><!--<script></scr'+'ipt></script>X +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 42 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "<!--<script></scr'+'ipt></script>X" +| <body> + +#data +<style><!--<style></style>--></style> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 37 Unexpected end tag (style). +#document +| <html> +| <head> +| <style> +| "<!--<style>" +| <body> +| "-->" + +#data +<style><!--</style>X +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| "<!--" +| <body> +| "X" + +#data +<style><!--...</style>...--></style> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 36 Unexpected end tag (style). +#document +| <html> +| <head> +| <style> +| "<!--..." +| <body> +| "...-->" + +#data +<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>" +| <body> +| "X" + +#data +<style><!--...<style><!--...--!></style>--></style> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 51 Unexpected end tag (style). +#document +| <html> +| <head> +| <style> +| "<!--...<style><!--...--!>" +| <body> +| "-->" + +#data +<style><!--...</style><!-- --><style>@import ...</style> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| "<!--..." +| <!-- --> +| <style> +| "@import ..." +| <body> + +#data +<style>...<style><!--...</style><!-- --></style> +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 48 Unexpected end tag (style). +#document +| <html> +| <head> +| <style> +| "...<style><!--..." +| <!-- --> +| <body> + +#data +<style>...<!--[if IE]><style>...</style>X +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| "...<!--[if IE]><style>..." +| <body> +| "X" + +#data +<title><!--<title></title>--></title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +Line: 1 Col: 37 Unexpected end tag (title). +#document +| <html> +| <head> +| <title> +| "<!--<title>" +| <body> +| "-->" + +#data +<title>&lt;/title></title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| "</title>" +| <body> + +#data +<title>foo/title><link></head><body>X +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +Line: 1 Col: 37 Unexpected end of file. Expected end tag (title). +#document +| <html> +| <head> +| <title> +| "foo/title><link></head><body>X" +| <body> + +#data +<noscript><!--<noscript></noscript>--></noscript> +#errors +Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. +Line: 1 Col: 49 Unexpected end tag (noscript). +#document +| <html> +| <head> +| <noscript> +| "<!--<noscript>" +| <body> +| "-->" + +#data +<noscript><!--</noscript>X<noscript>--></noscript> +#errors +Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. +#document +| <html> +| <head> +| <noscript> +| "<!--" +| <body> +| "X" +| <noscript> +| "-->" + +#data +<noscript><iframe></noscript>X +#errors +Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. +#document +| <html> +| <head> +| <noscript> +| "<iframe>" +| <body> +| "X" + +#data +<noframes><!--<noframes></noframes>--></noframes> +#errors +Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. +Line: 1 Col: 49 Unexpected end tag (noframes). +#document +| <html> +| <head> +| <noframes> +| "<!--<noframes>" +| <body> +| "-->" + +#data +<noframes><body><script><!--...</script></body></noframes></html> +#errors +Line: 1 Col: 10 Unexpected start tag (noframes). Expected DOCTYPE. +#document +| <html> +| <head> +| <noframes> +| "<body><script><!--...</script></body>" +| <body> + +#data +<textarea><!--<textarea></textarea>--></textarea> +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +Line: 1 Col: 49 Unexpected end tag (textarea). +#document +| <html> +| <head> +| <body> +| <textarea> +| "<!--<textarea>" +| "-->" + +#data +<textarea>&lt;/textarea></textarea> +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <textarea> +| "</textarea>" + +#data +<iframe><!--<iframe></iframe>--></iframe> +#errors +Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. +Line: 1 Col: 41 Unexpected end tag (iframe). +#document +| <html> +| <head> +| <body> +| <iframe> +| "<!--<iframe>" +| "-->" + +#data +<iframe>...<!--X->...<!--/X->...</iframe> +#errors +Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <iframe> +| "...<!--X->...<!--/X->..." + +#data +<xmp><!--<xmp></xmp>--></xmp> +#errors +Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE. +Line: 1 Col: 29 Unexpected end tag (xmp). +#document +| <html> +| <head> +| <body> +| <xmp> +| "<!--<xmp>" +| "-->" + +#data +<noembed><!--<noembed></noembed>--></noembed> +#errors +Line: 1 Col: 9 Unexpected start tag (noembed). Expected DOCTYPE. +Line: 1 Col: 45 Unexpected end tag (noembed). +#document +| <html> +| <head> +| <body> +| <noembed> +| "<!--<noembed>" +| "-->" + +#data +<!doctype html><table> + +#errors +Line 2 Col 0 Unexpected end of file. Expected table content. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| " +" + +#data +<!doctype html><table><td><span><font></span><span> +#errors +Line 1 Col 26 Unexpected table cell start tag (td) in the table body phase. +Line 1 Col 45 Unexpected end tag (span). +Line 1 Col 51 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <span> +| <font> +| <font> +| <span> + +#data +<!doctype html><form><table></form><form></table></form> +#errors +35: Stray end tag “form”. +41: Start tag “form” seen in “table”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <table> +| <form> diff --git a/pkgs/html/test/data/tree-construction/tests17.dat b/pkgs/html/test/data/tree-construction/tests17.dat new file mode 100644 index 000000000..7b555f888 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests17.dat @@ -0,0 +1,153 @@ +#data +<!doctype html><table><tbody><select><tr> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><table><tr><select><td> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<!doctype html><table><tr><td><select><td> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <select> +| <td> + +#data +<!doctype html><table><tr><th><select><td> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <th> +| <select> +| <td> + +#data +<!doctype html><table><caption><select><tr> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <select> +| <tbody> +| <tr> + +#data +<!doctype html><select><tr> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><td> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><th> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><tbody> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><thead> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><tfoot> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><select><caption> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><table><tr></table>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| "a" diff --git a/pkgs/html/test/data/tree-construction/tests18.dat b/pkgs/html/test/data/tree-construction/tests18.dat new file mode 100644 index 000000000..680e1f068 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests18.dat @@ -0,0 +1,269 @@ +#data +<!doctype html><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" + +#data +<!doctype html><table><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" +| <table> + +#data +<!doctype html><table><tbody><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" +| <table> +| <tbody> + +#data +<!doctype html><table><tbody><tr><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><table><tbody><tr><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><table><td><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <plaintext> +| "</plaintext>" + +#data +<!doctype html><table><caption><plaintext></plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <plaintext> +| "</plaintext>" + +#data +<!doctype html><table><tr><style></script></style>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "abc" +| <table> +| <tbody> +| <tr> +| <style> +| "</script>" + +#data +<!doctype html><table><tr><script></style></script>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "abc" +| <table> +| <tbody> +| <tr> +| <script> +| "</style>" + +#data +<!doctype html><table><caption><style></script></style>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <style> +| "</script>" +| "abc" + +#data +<!doctype html><table><td><style></script></style>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <style> +| "</script>" +| "abc" + +#data +<!doctype html><select><script></style></script>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <script> +| "</style>" +| "abc" + +#data +<!doctype html><table><select><script></style></script>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <script> +| "</style>" +| "abc" +| <table> + +#data +<!doctype html><table><tr><select><script></style></script>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <script> +| "</style>" +| "abc" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><frameset></frameset><noframes>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <noframes> +| "abc" + +#data +<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <noframes> +| "abc" +| <!-- abc --> + +#data +<!doctype html><frameset></frameset></html><noframes>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <noframes> +| "abc" + +#data +<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <noframes> +| "abc" +| <!-- abc --> + +#data +<!doctype html><table><tr></tbody><tfoot> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <tfoot> + +#data +<!doctype html><table><td><svg></svg>abc<td> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| "abc" +| <td> diff --git a/pkgs/html/test/data/tree-construction/tests19.dat b/pkgs/html/test/data/tree-construction/tests19.dat new file mode 100644 index 000000000..0d62f5a5b --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests19.dat @@ -0,0 +1,1237 @@ +#data +<!doctype html><math><mn DefinitionUrl="foo"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mn> +| definitionURL="foo" + +#data +<!doctype html><html></p><!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <!-- foo --> +| <head> +| <body> + +#data +<!doctype html><head></head></p><!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <!-- foo --> +| <body> + +#data +<!doctype html><body><p><pre> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <pre> + +#data +<!doctype html><body><p><listing> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <listing> + +#data +<!doctype html><p><plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <plaintext> + +#data +<!doctype html><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <h1> + +#data +<!doctype html><form><isindex> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> + +#data +<!doctype html><isindex action="POST"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| action="POST" +| <hr> +| <label> +| "This is a searchable index. Enter search keywords: " +| <input> +| name="isindex" +| <hr> + +#data +<!doctype html><isindex prompt="this is isindex"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <hr> +| <label> +| "this is isindex" +| <input> +| name="isindex" +| <hr> + +#data +<!doctype html><isindex type="hidden"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <hr> +| <label> +| "This is a searchable index. Enter search keywords: " +| <input> +| name="isindex" +| type="hidden" +| <hr> + +#data +<!doctype html><isindex name="foo"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <hr> +| <label> +| "This is a searchable index. Enter search keywords: " +| <input> +| name="isindex" +| <hr> + +#data +<!doctype html><ruby><p><rp> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <p> +| <rp> + +#data +<!doctype html><ruby><div><span><rp> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <span> +| <rp> + +#data +<!doctype html><ruby><div><p><rp> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <p> +| <rp> + +#data +<!doctype html><ruby><p><rt> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <p> +| <rt> + +#data +<!doctype html><ruby><div><span><rt> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <span> +| <rt> + +#data +<!doctype html><ruby><div><p><rt> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <p> +| <rt> + +#data +<!doctype html><math/><foo> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <foo> + +#data +<!doctype html><svg/><foo> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <foo> + +#data +<!doctype html><div></body><!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> +| <!-- foo --> + +#data +<!doctype html><h1><div><h3><span></h1>foo +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <h1> +| <div> +| <h3> +| <span> +| "foo" + +#data +<!doctype html><p></h3>foo +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| "foo" + +#data +<!doctype html><h3><li>abc</h2>foo +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <h3> +| <li> +| "abc" +| "foo" + +#data +<!doctype html><table>abc<!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "abc" +| <table> +| <!-- foo --> + +#data +<!doctype html><table> <!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| " " +| <!-- foo --> + +#data +<!doctype html><table> b <!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| " b " +| <table> +| <!-- foo --> + +#data +<!doctype html><select><option><option> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> +| <option> + +#data +<!doctype html><select><option></optgroup> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> + +#data +<!doctype html><select><option></optgroup> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> + +#data +<!doctype html><p><math><mi><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math mi> +| <p> +| <h1> + +#data +<!doctype html><p><math><mo><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math mo> +| <p> +| <h1> + +#data +<!doctype html><p><math><mn><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math mn> +| <p> +| <h1> + +#data +<!doctype html><p><math><ms><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math ms> +| <p> +| <h1> + +#data +<!doctype html><p><math><mtext><p><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math mtext> +| <p> +| <h1> + +#data +<!doctype html><frameset></noframes> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!doctype html><html c=d><body></html><html a=b> +#errors +#document +| <!DOCTYPE html> +| <html> +| a="b" +| c="d" +| <head> +| <body> + +#data +<!doctype html><html c=d><frameset></frameset></html><html a=b> +#errors +#document +| <!DOCTYPE html> +| <html> +| a="b" +| c="d" +| <head> +| <frameset> + +#data +<!doctype html><html><frameset></frameset></html><!--foo--> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <!-- foo --> + +#data +<!doctype html><html><frameset></frameset></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| " " + +#data +<!doctype html><html><frameset></frameset></html>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!doctype html><html><frameset></frameset></html><p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!doctype html><html><frameset></frameset></html></p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<html><frameset></frameset></html><!doctype html> +#errors +#document +| <html> +| <head> +| <frameset> + +#data +<!doctype html><body><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<!doctype html><p><frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<!doctype html><p>a<frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| "a" + +#data +<!doctype html><p> <frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<!doctype html><pre><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> + +#data +<!doctype html><listing><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <listing> + +#data +<!doctype html><li><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <li> + +#data +<!doctype html><dd><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <dd> + +#data +<!doctype html><dt><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <dt> + +#data +<!doctype html><button><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <button> + +#data +<!doctype html><applet><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <applet> + +#data +<!doctype html><marquee><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <marquee> + +#data +<!doctype html><object><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <object> + +#data +<!doctype html><table><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> + +#data +<!doctype html><area><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <area> + +#data +<!doctype html><basefont><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <basefont> +| <frameset> + +#data +<!doctype html><bgsound><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <bgsound> +| <frameset> + +#data +<!doctype html><br><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <br> + +#data +<!doctype html><embed><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <embed> + +#data +<!doctype html><img><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <img> + +#data +<!doctype html><input><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <input> + +#data +<!doctype html><keygen><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <keygen> + +#data +<!doctype html><wbr><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <wbr> + +#data +<!doctype html><hr><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <hr> + +#data +<!doctype html><textarea></textarea><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> + +#data +<!doctype html><xmp></xmp><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <xmp> + +#data +<!doctype html><iframe></iframe><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <iframe> + +#data +<!doctype html><select></select><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!doctype html><svg></svg><frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<!doctype html><math></math><frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<!doctype html><svg><foreignObject><div> <frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<!doctype html><svg>a</svg><frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| "a" + +#data +<!doctype html><svg> </svg><frameset><frame> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> +| <frame> + +#data +<html>aaa<frameset></frameset> +#errors +#document +| <html> +| <head> +| <body> +| "aaa" + +#data +<html> a <frameset></frameset> +#errors +#document +| <html> +| <head> +| <body> +| "a " + +#data +<!doctype html><div><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!doctype html><div><body><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> + +#data +<!doctype html><p><math></p>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| "a" + +#data +<!doctype html><p><math><mn><span></p>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <math math> +| <math mn> +| <span> +| <p> +| "a" + +#data +<!doctype html><math></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> + +#data +<!doctype html><meta charset="ascii"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <meta> +| charset="ascii" +| <body> + +#data +<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <meta> +| content="text/html;charset=ascii" +| http-equiv="content-type" +| <body> + +#data +<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8"> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --> +| <meta> +| charset="utf8" +| <body> + +#data +<!doctype html><html a=b><head></head><html c=d> +#errors +#document +| <!DOCTYPE html> +| <html> +| a="b" +| c="d" +| <head> +| <body> + +#data +<!doctype html><image/> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <img> + +#data +<!doctype html>a<i>b<table>c<b>d</i>e</b>f +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "a" +| <i> +| "bc" +| <b> +| "de" +| "f" +| <table> + +#data +<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <i> +| "a" +| <b> +| "b" +| <b> +| <div> +| <b> +| <i> +| "c" +| <a> +| "d" +| <a> +| "e" +| <a> +| "f" +| <table> + +#data +<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <i> +| "a" +| <b> +| "b" +| <b> +| <div> +| <b> +| <i> +| "c" +| <a> +| "d" +| <a> +| "e" +| <a> +| "f" + +#data +<!doctype html><table><i>a<b>b<div>c</i> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <i> +| "a" +| <b> +| "b" +| <b> +| <div> +| <i> +| "c" +| <table> + +#data +<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <i> +| "a" +| <b> +| "b" +| <b> +| <div> +| <b> +| <i> +| "c" +| <a> +| "d" +| <a> +| "e" +| <a> +| "f" +| <table> + +#data +<!doctype html><table><i>a<div>b<tr>c<b>d</i>e +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <i> +| "a" +| <div> +| "b" +| <i> +| "c" +| <b> +| "d" +| <b> +| "e" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><table><td><table><i>a<div>b<b>c</i>d +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <i> +| "a" +| <div> +| <i> +| "b" +| <b> +| "c" +| <b> +| "d" +| <table> + +#data +<!doctype html><body><bgsound> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <bgsound> + +#data +<!doctype html><body><basefont> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <basefont> + +#data +<!doctype html><a><b></a><basefont> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <a> +| <b> +| <basefont> + +#data +<!doctype html><a><b></a><bgsound> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <a> +| <b> +| <bgsound> + +#data +<!doctype html><figcaption><article></figcaption>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <figcaption> +| <article> +| "a" + +#data +<!doctype html><summary><article></summary>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <summary> +| <article> +| "a" + +#data +<!doctype html><p><a><plaintext>b +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <a> +| <plaintext> +| <a> +| "b" + +#data +<!DOCTYPE html><div>a<a></div>b<p>c</p>d +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> +| "a" +| <a> +| <a> +| "b" +| <p> +| "c" +| "d" diff --git a/pkgs/html/test/data/tree-construction/tests2.dat b/pkgs/html/test/data/tree-construction/tests2.dat new file mode 100644 index 000000000..60d859221 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests2.dat @@ -0,0 +1,763 @@ +#data +<!DOCTYPE html>Test +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "Test" + +#data +<textarea>test</div>test +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +Line: 1 Col: 24 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <textarea> +| "test</div>test" + +#data +<table><td> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 11 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<table><td>test</tbody></table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected table cell start tag (td) in the table body phase. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "test" + +#data +<frame>test +#errors +Line: 1 Col: 7 Unexpected start tag (frame). Expected DOCTYPE. +Line: 1 Col: 7 Unexpected start tag frame. Ignored. +#document +| <html> +| <head> +| <body> +| "test" + +#data +<!DOCTYPE html><frameset>test +#errors +Line: 1 Col: 29 Unepxected characters in the frameset phase. Characters ignored. +Line: 1 Col: 29 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><frameset><!DOCTYPE html> +#errors +Line: 1 Col: 40 Unexpected DOCTYPE. Ignored. +Line: 1 Col: 40 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><font><p><b>test</font> +#errors +Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 38 End tag (font) violates step 1, paragraph 3 of the adoption agency algorithm. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <font> +| <p> +| <font> +| <b> +| "test" + +#data +<!DOCTYPE html><dt><div><dd> +#errors +Line: 1 Col: 28 Missing end tag (div, dt). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <dt> +| <div> +| <dd> + +#data +<script></x +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +Line: 1 Col: 11 Unexpected end of file. Expected end tag (script). +#document +| <html> +| <head> +| <script> +| "</x" +| <body> + +#data +<table><plaintext><td> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 18 Unexpected start tag (plaintext) in table context caused voodoo mode. +Line: 1 Col: 22 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <plaintext> +| "<td>" +| <table> + +#data +<plaintext></plaintext> +#errors +Line: 1 Col: 11 Unexpected start tag (plaintext). Expected DOCTYPE. +Line: 1 Col: 23 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <plaintext> +| "</plaintext>" + +#data +<!DOCTYPE html><table><tr>TEST +#errors +Line: 1 Col: 30 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 30 Unexpected end of file. Expected table content. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "TEST" +| <table> +| <tbody> +| <tr> + +#data +<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4> +#errors +Line: 1 Col: 37 Unexpected start tag (body). +Line: 1 Col: 53 Unexpected start tag (body). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| t1="1" +| t2="2" +| t3="3" +| t4="4" + +#data +</b test +#errors +Line: 1 Col: 8 Unexpected end of file in attribute name. +Line: 1 Col: 8 End tag contains unexpected attributes. +Line: 1 Col: 8 Unexpected end tag (b). Expected DOCTYPE. +Line: 1 Col: 8 Unexpected end tag (b) after the (implied) root element. +#document +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html></b test<b &=&amp>X +#errors +Line: 1 Col: 32 Named entity didn't end with ';'. +Line: 1 Col: 33 End tag contains unexpected attributes. +Line: 1 Col: 33 Unexpected end tag (b) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" + +#data +<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +Line: 1 Col: 54 Unexpected end of file in the tag name. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| type="text/x-foobar;baz" +| "X</SCRipt" +| <body> + +#data +& +#errors +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&" + +#data +&# +#errors +Line: 1 Col: 1 Numeric entity expected. Got end of file instead. +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&#" + +#data +&#X +#errors +Line: 1 Col: 3 Numeric entity expected but none found. +Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&#X" + +#data +&#x +#errors +Line: 1 Col: 3 Numeric entity expected but none found. +Line: 1 Col: 3 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&#x" + +#data +&#45 +#errors +Line: 1 Col: 4 Numeric entity didn't end with ';'. +Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "-" + +#data +&x-test +#errors +Line: 1 Col: 1 Named entity expected. Got none. +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&x-test" + +#data +<!doctypehtml><p><li> +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <li> + +#data +<!doctypehtml><p><dt> +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <dt> + +#data +<!doctypehtml><p><dd> +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <dd> + +#data +<!doctypehtml><p><form> +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +Line: 1 Col: 23 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <form> + +#data +<!DOCTYPE html><p></P>X +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| "X" + +#data +&AMP +#errors +Line: 1 Col: 4 Named entity didn't end with ';'. +Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&" + +#data +&AMp; +#errors +Line: 1 Col: 1 Named entity expected. Got none. +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "&AMp;" + +#data +<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY> +#errors +Line: 1 Col: 110 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly> + +#data +<!DOCTYPE html>X</body>X +#errors +Line: 1 Col: 24 Unexpected non-space characters in the after body phase. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "XX" + +#data +<!DOCTYPE html><!-- X +#errors +Line: 1 Col: 21 Unexpected end of file in comment. +#document +| <!DOCTYPE html> +| <!-- X --> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><table><caption>test TEST</caption><td>test +#errors +Line: 1 Col: 54 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 58 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| "test TEST" +| <tbody> +| <tr> +| <td> +| "test" + +#data +<!DOCTYPE html><select><option><optgroup> +#errors +Line: 1 Col: 41 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> +| <optgroup> + +#data +<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option> +#errors +Line: 1 Col: 68 Unexpected select start tag in the select phase treated as select end tag. +Line: 1 Col: 76 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <optgroup> +| <option> +| <option> +| <option> + +#data +<!DOCTYPE html><select><optgroup><option><optgroup> +#errors +Line: 1 Col: 51 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <optgroup> +| <option> +| <optgroup> + +#data +<!DOCTYPE html><datalist><option>foo</datalist>bar +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <datalist> +| <option> +| "foo" +| "bar" + +#data +<!DOCTYPE html><font><input><input></font> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <font> +| <input> +| <input> + +#data +<!DOCTYPE html><!-- XXX - XXX --> +#errors +#document +| <!DOCTYPE html> +| <!-- XXX - XXX --> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><!-- XXX - XXX +#errors +Line: 1 Col: 29 Unexpected end of file in comment (-) +#document +| <!DOCTYPE html> +| <!-- XXX - XXX --> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><!-- XXX - XXX - XXX --> +#errors +#document +| <!DOCTYPE html> +| <!-- XXX - XXX - XXX --> +| <html> +| <head> +| <body> + +#data +<isindex test=x name=x> +#errors +Line: 1 Col: 23 Unexpected start tag (isindex). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected start tag isindex. Don't use it! +#document +| <html> +| <head> +| <body> +| <form> +| <hr> +| <label> +| "This is a searchable index. Enter search keywords: " +| <input> +| name="isindex" +| test="x" +| <hr> + +#data +test +test +#errors +Line: 2 Col: 4 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "test +test" + +#data +<!DOCTYPE html><body><title>test</body></title> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <title> +| "test</body>" + +#data +<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style> +x { content:"</style" } </style> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <title> +| "X" +| <meta> +| name="z" +| <link> +| rel="foo" +| <style> +| " +x { content:"</style" } " + +#data +<!DOCTYPE html><select><optgroup></optgroup></select> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <optgroup> + +#data + + +#errors +Line: 2 Col: 1 Unexpected End of file. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html> <html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><script> +</script> <title>x</title> </head> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <script> +| " +" +| " " +| <title> +| "x" +| " " +| <body> + +#data +<!DOCTYPE html><html><body><html id=x> +#errors +Line: 1 Col: 38 html needs to be the first start tag. +#document +| <!DOCTYPE html> +| <html> +| id="x" +| <head> +| <body> + +#data +<!DOCTYPE html>X</body><html id="x"> +#errors +Line: 1 Col: 36 Unexpected start tag token (html) in the after body phase. +Line: 1 Col: 36 html needs to be the first start tag. +#document +| <!DOCTYPE html> +| <html> +| id="x" +| <head> +| <body> +| "X" + +#data +<!DOCTYPE html><head><html id=x> +#errors +Line: 1 Col: 32 html needs to be the first start tag. +#document +| <!DOCTYPE html> +| <html> +| id="x" +| <head> +| <body> + +#data +<!DOCTYPE html>X</html>X +#errors +Line: 1 Col: 24 Unexpected non-space characters in the after body phase. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "XX" + +#data +<!DOCTYPE html>X</html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X " + +#data +<!DOCTYPE html>X</html><p>X +#errors +Line: 1 Col: 26 Unexpected start tag (p). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" +| <p> +| "X" + +#data +<!DOCTYPE html>X<p/x/y/z> +#errors +Line: 1 Col: 19 Expected a > after the /. +Line: 1 Col: 21 Solidus (/) incorrectly placed in tag. +Line: 1 Col: 23 Solidus (/) incorrectly placed in tag. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" +| <p> +| x="" +| y="" +| z="" + +#data +<!DOCTYPE html><!--x-- +#errors +Line: 1 Col: 22 Unexpected end of file in comment (--). +#document +| <!DOCTYPE html> +| <!-- x --> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE html><table><tr><td></p></table> +#errors +Line: 1 Col: 34 Unexpected end tag (p). Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <p> + +#data +<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->--> +#errors +Line: 1 Col: 20 Expected space or '>'. Got '' +Line: 1 Col: 25 Erroneous DOCTYPE. +Line: 1 Col: 35 Unexpected character in comment found. +#document +| <!DOCTYPE <!doctype> +| <html> +| <head> +| <body> +| ">" +| <!-- <!--x --> +| "-->" + +#data +<!doctype html><div><form></form><div></div></div> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> +| <form> +| <div> diff --git a/pkgs/html/test/data/tree-construction/tests20.dat b/pkgs/html/test/data/tree-construction/tests20.dat new file mode 100644 index 000000000..6bd825608 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests20.dat @@ -0,0 +1,455 @@ +#data +<!doctype html><p><button><button> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <button> + +#data +<!doctype html><p><button><address> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <address> + +#data +<!doctype html><p><button><blockquote> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <blockquote> + +#data +<!doctype html><p><button><menu> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <menu> + +#data +<!doctype html><p><button><p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <p> + +#data +<!doctype html><p><button><ul> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <ul> + +#data +<!doctype html><p><button><h1> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <h1> + +#data +<!doctype html><p><button><h6> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <h6> + +#data +<!doctype html><p><button><listing> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <listing> + +#data +<!doctype html><p><button><pre> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <pre> + +#data +<!doctype html><p><button><form> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <form> + +#data +<!doctype html><p><button><li> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <li> + +#data +<!doctype html><p><button><dd> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <dd> + +#data +<!doctype html><p><button><dt> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <dt> + +#data +<!doctype html><p><button><plaintext> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <plaintext> + +#data +<!doctype html><p><button><table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <table> + +#data +<!doctype html><p><button><hr> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <hr> + +#data +<!doctype html><p><button><xmp> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <xmp> + +#data +<!doctype html><p><button></p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <button> +| <p> + +#data +<!doctype html><address><button></address>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <address> +| <button> +| "a" + +#data +<!doctype html><address><button></address>a +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <address> +| <button> +| "a" + +#data +<p><table></p> +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <p> +| <table> + +#data +<!doctype html><svg> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> + +#data +<!doctype html><p><figcaption> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <figcaption> + +#data +<!doctype html><p><summary> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <summary> + +#data +<!doctype html><form><table><form> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <table> + +#data +<!doctype html><table><form><form> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <form> + +#data +<!doctype html><table><form></table><form> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <form> + +#data +<!doctype html><svg><foreignObject><p> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg foreignObject> +| <p> + +#data +<!doctype html><svg><title>abc +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg title> +| "abc" + +#data +<option><span><option> +#errors +#document +| <html> +| <head> +| <body> +| <option> +| <span> +| <option> + +#data +<option><option> +#errors +#document +| <html> +| <head> +| <body> +| <option> +| <option> + +#data +<math><annotation-xml><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| <div> + +#data +<math><annotation-xml encoding="application/svg+xml"><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding="application/svg+xml" +| <div> + +#data +<math><annotation-xml encoding="application/xhtml+xml"><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding="application/xhtml+xml" +| <div> + +#data +<math><annotation-xml encoding="aPPlication/xhtmL+xMl"><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding="aPPlication/xhtmL+xMl" +| <div> + +#data +<math><annotation-xml encoding="text/html"><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding="text/html" +| <div> + +#data +<math><annotation-xml encoding="Text/htmL"><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding="Text/htmL" +| <div> + +#data +<math><annotation-xml encoding=" text/html "><div> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| encoding=" text/html " +| <div> diff --git a/pkgs/html/test/data/tree-construction/tests21.dat b/pkgs/html/test/data/tree-construction/tests21.dat new file mode 100644 index 000000000..1260ec03e --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests21.dat @@ -0,0 +1,221 @@ +#data +<svg><![CDATA[foo]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "foo" + +#data +<math><![CDATA[foo]]> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| "foo" + +#data +<div><![CDATA[foo]]> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <!-- [CDATA[foo]] --> + +#data +<svg><![CDATA[foo +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "foo" + +#data +<svg><![CDATA[foo +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "foo" + +#data +<svg><![CDATA[ +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> + +#data +<svg><![CDATA[]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> + +#data +<svg><![CDATA[]] >]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "]] >" + +#data +<svg><![CDATA[]] >]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "]] >" + +#data +<svg><![CDATA[]] +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "]]" + +#data +<svg><![CDATA[] +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "]" + +#data +<svg><![CDATA[]>a +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "]>a" + +#data +<svg><foreignObject><div><![CDATA[foo]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg foreignObject> +| <div> +| <!-- [CDATA[foo]] --> + +#data +<svg><![CDATA[<svg>]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>" + +#data +<svg><![CDATA[</svg>a]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "</svg>a" + +#data +<svg><![CDATA[<svg>a +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>a" + +#data +<svg><![CDATA[</svg>a +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "</svg>a" + +#data +<svg><![CDATA[<svg>]]><path> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>" +| <svg path> + +#data +<svg><![CDATA[<svg>]]></path> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>" + +#data +<svg><![CDATA[<svg>]]><!--path--> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>" +| <!-- path --> + +#data +<svg><![CDATA[<svg>]]>path +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<svg>path" + +#data +<svg><![CDATA[<!--svg-->]]> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| "<!--svg-->" diff --git a/pkgs/html/test/data/tree-construction/tests22.dat b/pkgs/html/test/data/tree-construction/tests22.dat new file mode 100644 index 000000000..aab27b2e9 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests22.dat @@ -0,0 +1,157 @@ +#data +<a><b><big><em><strong><div>X</a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <b> +| <big> +| <em> +| <strong> +| <big> +| <em> +| <strong> +| <div> +| <a> +| "X" + +#data +<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <b> +| <b> +| <div> +| id="1" +| <a> +| <div> +| id="2" +| <a> +| <div> +| id="3" +| <a> +| <div> +| id="4" +| <a> +| <div> +| id="5" +| <a> +| <div> +| id="6" +| <a> +| <div> +| id="7" +| <a> +| <div> +| id="8" +| <a> +| "A" + +#data +<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <b> +| <b> +| <div> +| id="1" +| <a> +| <div> +| id="2" +| <a> +| <div> +| id="3" +| <a> +| <div> +| id="4" +| <a> +| <div> +| id="5" +| <a> +| <div> +| id="6" +| <a> +| <div> +| id="7" +| <a> +| <div> +| id="8" +| <a> +| <div> +| id="9" +| "A" + +#data +<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <b> +| <b> +| <div> +| id="1" +| <a> +| <div> +| id="2" +| <a> +| <div> +| id="3" +| <a> +| <div> +| id="4" +| <a> +| <div> +| id="5" +| <a> +| <div> +| id="6" +| <a> +| <div> +| id="7" +| <a> +| <div> +| id="8" +| <a> +| <div> +| id="9" +| <div> +| id="10" +| "A" + +#data +<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST +#errors +Line: 1 Col: 6 Unexpected start tag (cite). Expected DOCTYPE. +Line: 1 Col: 46 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 50 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <cite> +| <b> +| <cite> +| <i> +| <cite> +| <i> +| <cite> +| <i> +| <i> +| <i> +| <div> +| <b> +| "X" +| "TEST" diff --git a/pkgs/html/test/data/tree-construction/tests23.dat b/pkgs/html/test/data/tree-construction/tests23.dat new file mode 100644 index 000000000..34d2a73f1 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests23.dat @@ -0,0 +1,155 @@ +#data +<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X +#errors +3: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +116: Unclosed elements. +117: End of file seen and there were open elements. +#document +| <html> +| <head> +| <body> +| <p> +| <font> +| size="4" +| <font> +| color="red" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| color="red" +| <p> +| <font> +| color="red" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| color="red" +| "X" + +#data +<p><font size=4><font size=4><font size=4><font size=4><p>X +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| "X" + +#data +<p><font size=4><font size=4><font size=4><font size="5"><font size=4><p>X +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="5" +| <font> +| size="4" +| <p> +| <font> +| size="4" +| <font> +| size="4" +| <font> +| size="5" +| <font> +| size="4" +| "X" + +#data +<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <font> +| id="a" +| size="4" +| <font> +| id="b" +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| <p> +| <font> +| id="a" +| size="4" +| <font> +| id="b" +| size="4" +| <font> +| size="4" +| <font> +| size="4" +| "X" + +#data +<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <b> +| id="a" +| <b> +| id="a" +| <b> +| id="a" +| <b> +| <object> +| <b> +| id="a" +| <b> +| id="a" +| "X" +| <p> +| <b> +| id="a" +| <b> +| id="a" +| <b> +| id="a" +| <b> +| "Y" diff --git a/pkgs/html/test/data/tree-construction/tests24.dat b/pkgs/html/test/data/tree-construction/tests24.dat new file mode 100644 index 000000000..f6dc7eb48 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests24.dat @@ -0,0 +1,79 @@ +#data +<!DOCTYPE html>&NotEqualTilde; +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "≂̸" + +#data +<!DOCTYPE html>&NotEqualTilde;A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "≂̸A" + +#data +<!DOCTYPE html>&ThickSpace; +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "  " + +#data +<!DOCTYPE html>&ThickSpace;A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "  A" + +#data +<!DOCTYPE html>&NotSubset; +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "⊂⃒" + +#data +<!DOCTYPE html>&NotSubset;A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "⊂⃒A" + +#data +<!DOCTYPE html>&Gopf; +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "𝔾" + +#data +<!DOCTYPE html>&Gopf;A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "𝔾A" diff --git a/pkgs/html/test/data/tree-construction/tests25.dat b/pkgs/html/test/data/tree-construction/tests25.dat new file mode 100644 index 000000000..00de7295b --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests25.dat @@ -0,0 +1,219 @@ +#data +<!DOCTYPE html><body><foo>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <foo> +| "A" + +#data +<!DOCTYPE html><body><area>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <area> +| "A" + +#data +<!DOCTYPE html><body><base>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <base> +| "A" + +#data +<!DOCTYPE html><body><basefont>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <basefont> +| "A" + +#data +<!DOCTYPE html><body><bgsound>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <bgsound> +| "A" + +#data +<!DOCTYPE html><body><br>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <br> +| "A" + +#data +<!DOCTYPE html><body><col>A +#errors +26: Stray start tag “col”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "A" + +#data +<!DOCTYPE html><body><command>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <command> +| "A" + +#data +<!DOCTYPE html><body><embed>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <embed> +| "A" + +#data +<!DOCTYPE html><body><frame>A +#errors +26: Stray start tag “frame”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "A" + +#data +<!DOCTYPE html><body><hr>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <hr> +| "A" + +#data +<!DOCTYPE html><body><img>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <img> +| "A" + +#data +<!DOCTYPE html><body><input>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <input> +| "A" + +#data +<!DOCTYPE html><body><keygen>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <keygen> +| "A" + +#data +<!DOCTYPE html><body><link>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <link> +| "A" + +#data +<!DOCTYPE html><body><meta>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <meta> +| "A" + +#data +<!DOCTYPE html><body><param>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <param> +| "A" + +#data +<!DOCTYPE html><body><source>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <source> +| "A" + +#data +<!DOCTYPE html><body><track>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <track> +| "A" + +#data +<!DOCTYPE html><body><wbr>A +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <wbr> +| "A" diff --git a/pkgs/html/test/data/tree-construction/tests26.dat b/pkgs/html/test/data/tree-construction/tests26.dat new file mode 100644 index 000000000..fae11ffdf --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests26.dat @@ -0,0 +1,313 @@ +#data +<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <a> +| href="#1" +| <nobr> +| "1" +| <nobr> +| <nobr> +| <br> +| <a> +| href="#2" +| <a> +| href="#2" +| <nobr> +| "2" +| <nobr> +| <nobr> +| <br> +| <a> +| href="#3" +| <a> +| href="#3" +| <nobr> +| "3" +| <nobr> + +#data +<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <nobr> +| <nobr> +| <i> +| <i> +| <nobr> +| "2" +| <nobr> +| <nobr> +| "3" + +#data +<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <nobr> +| <i> +| <i> +| <nobr> +| "2" +| <nobr> +| <nobr> +| "3" +| <table> + +#data +<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <table> +| <tbody> +| <tr> +| <td> +| <nobr> +| <i> +| <i> +| <nobr> +| "2" +| <nobr> +| <nobr> +| "3" + +#data +<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <div> +| <b> +| <nobr> +| <nobr> +| <nobr> +| <i> +| <i> +| <nobr> +| "2" +| <nobr> +| <nobr> +| "3" + +#data +<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <nobr> +| <div> +| <nobr> +| <i> +| <i> +| <nobr> +| "2" +| <nobr> +| <nobr> +| "3" + +#data +<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <nobr> +| <ins> +| <nobr> +| <i> +| <i> +| <nobr> + +#data +<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2 +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| <nobr> +| "1" +| <ins> +| <nobr> +| <nobr> +| <i> +| "2" + +#data +<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <b> +| "1" +| <nobr> +| <nobr> +| <i> +| <i> +| <nobr> +| "2" + +#data +<p><code x</code></p> + +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <code> +| code="" +| x<="" +| <code> +| code="" +| x<="" +| " +" + +#data +<!DOCTYPE html><svg><foreignObject><p><i></p>a +#errors +45: End tag “p” seen, but there were open elements. +41: Unclosed element “i”. +46: End of file seen and there were open elements. +35: Unclosed element “foreignObject”. +20: Unclosed element “svg”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <svg svg> +| <svg foreignObject> +| <p> +| <i> +| <i> +| "a" + +#data +<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a +#errors +56: End tag “p” seen, but there were open elements. +52: Unclosed element “i”. +57: End of file seen and there were open elements. +46: Unclosed element “foreignObject”. +31: Unclosed element “svg”. +22: Unclosed element “table”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <svg svg> +| <svg foreignObject> +| <p> +| <i> +| <i> +| "a" + +#data +<!DOCTYPE html><math><mtext><p><i></p>a +#errors +38: End tag “p” seen, but there were open elements. +34: Unclosed element “i”. +39: End of file in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mtext> +| <p> +| <i> +| <i> +| "a" + +#data +<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a +#errors +53: End tag “p” seen, but there were open elements. +49: Unclosed element “i”. +54: End of file in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <math math> +| <math mtext> +| <p> +| <i> +| <i> +| "a" + +#data +<!DOCTYPE html><body><div><!/div>a +#errors +29: Bogus comment. +34: End of file seen and there were open elements. +26: Unclosed element “div”. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <div> +| <!-- /div --> +| "a" diff --git a/pkgs/html/test/data/tree-construction/tests3.dat b/pkgs/html/test/data/tree-construction/tests3.dat new file mode 100644 index 000000000..38dc501be --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests3.dat @@ -0,0 +1,305 @@ +#data +<head></head><style></style> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected start tag (style) that can be in head. Moved. +#document +| <html> +| <head> +| <style> +| <body> + +#data +<head></head><script></script> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 21 Unexpected start tag (script) that can be in head. Moved. +#document +| <html> +| <head> +| <script> +| <body> + +#data +<head></head><!-- --><style></style><!-- --><script></script> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +Line: 1 Col: 28 Unexpected start tag (style) that can be in head. Moved. +#document +| <html> +| <head> +| <style> +| <script> +| <!-- --> +| <!-- --> +| <body> + +#data +<head></head><!-- -->x<style></style><!-- --><script></script> +#errors +Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE. +#document +| <html> +| <head> +| <!-- --> +| <body> +| "x" +| <style> +| <!-- --> +| <script> + +#data +<!DOCTYPE html><html><head></head><body><pre> +</pre></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> + +#data +<!DOCTYPE html><html><head></head><body><pre> +foo</pre></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| "foo" + +#data +<!DOCTYPE html><html><head></head><body><pre> + +foo</pre></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| " +foo" + +#data +<!DOCTYPE html><html><head></head><body><pre> +foo +</pre></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| "foo +" + +#data +<!DOCTYPE html><html><head></head><body><pre>x</pre><span> +</span></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| "x" +| <span> +| " +" + +#data +<!DOCTYPE html><html><head></head><body><pre>x +y</pre></body></html> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| "x +y" + +#data +<!DOCTYPE html><html><head></head><body><pre>x<div> +y</pre></body></html> +#errors +Line: 2 Col: 7 End tag (pre) seen too early. Expected other end tag. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| "x" +| <div> +| " +y" + +#data +<!DOCTYPE html><pre>&#x0a;&#x0a;A</pre> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <pre> +| " +A" + +#data +<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML> +#errors +Line: 1 Col: 33 Unexpected start tag head in existing head. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <meta> +| <body> + +#data +<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML> +#errors +Line: 1 Col: 33 Unexpected start tag head in existing head. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<textarea>foo<span>bar</span><i>baz +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +Line: 1 Col: 35 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <textarea> +| "foo<span>bar</span><i>baz" + +#data +<title>foo<span>bar</em><i>baz +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +Line: 1 Col: 30 Unexpected end of file. Expected end tag (title). +#document +| <html> +| <head> +| <title> +| "foo<span>bar</em><i>baz" +| <body> + +#data +<!DOCTYPE html><textarea> +</textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> + +#data +<!DOCTYPE html><textarea> +foo</textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| "foo" + +#data +<!DOCTYPE html><textarea> + +foo</textarea> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <textarea> +| " +foo" + +#data +<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html> +#errors +Line: 1 Col: 60 Missing end tag (div, li). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <ul> +| <li> +| <div> +| <p> +| <li> + +#data +<!doctype html><nobr><nobr><nobr> +#errors +Line: 1 Col: 27 Unexpected start tag (nobr) implies end tag (nobr). +Line: 1 Col: 33 Unexpected start tag (nobr) implies end tag (nobr). +Line: 1 Col: 33 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <nobr> +| <nobr> +| <nobr> + +#data +<!doctype html><nobr><nobr></nobr><nobr> +#errors +Line: 1 Col: 27 Unexpected start tag (nobr) implies end tag (nobr). +Line: 1 Col: 40 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <nobr> +| <nobr> +| <nobr> + +#data +<!doctype html><html><body><p><table></table></body></html> +#errors +Not known +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <table> + +#data +<p><table></table> +#errors +Not known +#document +| <html> +| <head> +| <body> +| <p> +| <table> diff --git a/pkgs/html/test/data/tree-construction/tests4.dat b/pkgs/html/test/data/tree-construction/tests4.dat new file mode 100644 index 000000000..3c506326d --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests4.dat @@ -0,0 +1,59 @@ +#data +direct div content +#errors +#document-fragment +div +#document +| "direct div content" + +#data +direct textarea content +#errors +#document-fragment +textarea +#document +| "direct textarea content" + +#data +textarea content with <em>pseudo</em> <foo>markup +#errors +#document-fragment +textarea +#document +| "textarea content with <em>pseudo</em> <foo>markup" + +#data +this is &#x0043;DATA inside a <style> element +#errors +#document-fragment +style +#document +| "this is &#x0043;DATA inside a <style> element" + +#data +</plaintext> +#errors +#document-fragment +plaintext +#document +| "</plaintext>" + +#data +setting html's innerHTML +#errors +Line: 1 Col: 24 Unexpected EOF in inner html mode. +#document-fragment +html +#document +| <head> +| <body> +| "setting html's innerHTML" + +#data +<title>setting head's innerHTML</title> +#errors +#document-fragment +head +#document +| <title> +| "setting head's innerHTML" diff --git a/pkgs/html/test/data/tree-construction/tests5.dat b/pkgs/html/test/data/tree-construction/tests5.dat new file mode 100644 index 000000000..d7b5128a4 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests5.dat @@ -0,0 +1,191 @@ +#data +<style> <!-- </style>x +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end of file. Expected end tag (style). +#document +| <html> +| <head> +| <style> +| " <!-- " +| <body> +| "x" + +#data +<style> <!-- </style> --> </style>x +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| " <!-- " +| " " +| <body> +| "--> x" + +#data +<style> <!--> </style>x +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| " <!--> " +| <body> +| "x" + +#data +<style> <!---> </style>x +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| " <!---> " +| <body> +| "x" + +#data +<iframe> <!---> </iframe>x +#errors +Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <iframe> +| " <!---> " +| "x" + +#data +<iframe> <!--- </iframe>->x</iframe> --> </iframe>x +#errors +Line: 1 Col: 8 Unexpected start tag (iframe). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <iframe> +| " <!--- " +| "->x --> x" + +#data +<script> <!-- </script> --> </script>x +#errors +Line: 1 Col: 8 Unexpected start tag (script). Expected DOCTYPE. +#document +| <html> +| <head> +| <script> +| " <!-- " +| " " +| <body> +| "--> x" + +#data +<title> <!-- </title> --> </title>x +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| " <!-- " +| " " +| <body> +| "--> x" + +#data +<textarea> <!--- </textarea>->x</textarea> --> </textarea>x +#errors +Line: 1 Col: 10 Unexpected start tag (textarea). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <textarea> +| " <!--- " +| "->x --> x" + +#data +<style> <!</-- </style>x +#errors +Line: 1 Col: 7 Unexpected start tag (style). Expected DOCTYPE. +#document +| <html> +| <head> +| <style> +| " <!</-- " +| <body> +| "x" + +#data +<p><xmp></xmp> +#errors +XXX: Unknown +#document +| <html> +| <head> +| <body> +| <p> +| <xmp> + +#data +<xmp> <!-- > --> </xmp> +#errors +Line: 1 Col: 5 Unexpected start tag (xmp). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <xmp> +| " <!-- > --> " + +#data +<title>&amp;</title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| "&" +| <body> + +#data +<title><!--&amp;--></title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +#document +| <html> +| <head> +| <title> +| "<!--&-->" +| <body> + +#data +<title><!--</title> +#errors +Line: 1 Col: 7 Unexpected start tag (title). Expected DOCTYPE. +Line: 1 Col: 19 Unexpected end of file. Expected end tag (title). +#document +| <html> +| <head> +| <title> +| "<!--" +| <body> + +#data +<noscript><!--</noscript>--></noscript> +#errors +Line: 1 Col: 10 Unexpected start tag (noscript). Expected DOCTYPE. +#document +| <html> +| <head> +| <noscript> +| "<!--" +| <body> +| "-->" diff --git a/pkgs/html/test/data/tree-construction/tests6.dat b/pkgs/html/test/data/tree-construction/tests6.dat new file mode 100644 index 000000000..f28ece4fb --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests6.dat @@ -0,0 +1,663 @@ +#data +<!doctype html></head> <head> +#errors +Line: 1 Col: 29 Unexpected start tag head. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| " " +| <body> + +#data +<!doctype html><form><div></form><div> +#errors +33: End tag "form" seen but there were unclosed elements. +38: End of file seen and there were open elements. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <form> +| <div> +| <div> + +#data +<!doctype html><title>&amp;</title> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "&" +| <body> + +#data +<!doctype html><title><!--&amp;--></title> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "<!--&-->" +| <body> + +#data +<!doctype> +#errors +Line: 1 Col: 9 No space after literal string 'DOCTYPE'. +Line: 1 Col: 10 Unexpected > character. Expected DOCTYPE name. +Line: 1 Col: 10 Erroneous DOCTYPE. +#document +| <!DOCTYPE > +| <html> +| <head> +| <body> + +#data +<!---x +#errors +Line: 1 Col: 6 Unexpected end of file in comment. +Line: 1 Col: 6 Unexpected End of file. Expected DOCTYPE. +#document +| <!-- -x --> +| <html> +| <head> +| <body> + +#data +<body> +<div> +#errors +Line: 1 Col: 6 Unexpected start tag (body). +Line: 2 Col: 5 Expected closing tag. Unexpected end of file. +#document-fragment +div +#document +| " +" +| <div> + +#data +<frameset></frameset> +foo +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 2 Col: 3 Unexpected non-space characters in the after frameset phase. Ignored. +#document +| <html> +| <head> +| <frameset> +| " +" + +#data +<frameset></frameset> +<noframes> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 2 Col: 10 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <frameset> +| " +" +| <noframes> + +#data +<frameset></frameset> +<div> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 2 Col: 5 Unexpected start tag (div) in the after frameset phase. Ignored. +#document +| <html> +| <head> +| <frameset> +| " +" + +#data +<frameset></frameset> +</html> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +#document +| <html> +| <head> +| <frameset> +| " +" + +#data +<frameset></frameset> +</div> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 2 Col: 6 Unexpected end tag (div) in the after frameset phase. Ignored. +#document +| <html> +| <head> +| <frameset> +| " +" + +#data +<form><form> +#errors +Line: 1 Col: 6 Unexpected start tag (form). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected start tag (form). +Line: 1 Col: 12 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <form> + +#data +<button><button> +#errors +Line: 1 Col: 8 Unexpected start tag (button). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected start tag (button) implies end tag (button). +Line: 1 Col: 16 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <button> +| <button> + +#data +<table><tr><td></th> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end tag (th). Ignored. +Line: 1 Col: 20 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<table><caption><td> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end tag (td). Ignored. +Line: 1 Col: 20 Unexpected table cell start tag (td) in the table body phase. +Line: 1 Col: 20 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> +| <tbody> +| <tr> +| <td> + +#data +<table><caption><div> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 21 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> +| <div> + +#data +</caption><div> +#errors +Line: 1 Col: 10 Unexpected end tag (caption). Ignored. +Line: 1 Col: 15 Expected closing tag. Unexpected end of file. +#document-fragment +caption +#document +| <div> + +#data +<table><caption><div></caption> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 31 Unexpected end tag (caption). Missing end tag (div). +Line: 1 Col: 31 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> +| <div> + +#data +<table><caption></table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 24 Unexpected end table tag in caption. Generates implied end caption. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> + +#data +</table><div> +#errors +Line: 1 Col: 8 Unexpected end table tag in caption. Generates implied end caption. +Line: 1 Col: 8 Unexpected end tag (caption). Ignored. +Line: 1 Col: 13 Expected closing tag. Unexpected end of file. +#document-fragment +caption +#document +| <div> + +#data +<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 23 Unexpected end tag (body). Ignored. +Line: 1 Col: 29 Unexpected end tag (col). Ignored. +Line: 1 Col: 40 Unexpected end tag (colgroup). Ignored. +Line: 1 Col: 47 Unexpected end tag (html). Ignored. +Line: 1 Col: 55 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 60 Unexpected end tag (td). Ignored. +Line: 1 Col: 68 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 73 Unexpected end tag (th). Ignored. +Line: 1 Col: 81 Unexpected end tag (thead). Ignored. +Line: 1 Col: 86 Unexpected end tag (tr). Ignored. +Line: 1 Col: 86 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> + +#data +<table><caption><div></div> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 27 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <caption> +| <div> + +#data +<table><tr><td></body></caption></col></colgroup></html> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end tag (body). Ignored. +Line: 1 Col: 32 Unexpected end tag (caption). Ignored. +Line: 1 Col: 38 Unexpected end tag (col). Ignored. +Line: 1 Col: 49 Unexpected end tag (colgroup). Ignored. +Line: 1 Col: 56 Unexpected end tag (html). Ignored. +Line: 1 Col: 56 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> + +#data +</table></tbody></tfoot></thead></tr><div> +#errors +Line: 1 Col: 8 Unexpected end tag (table). Ignored. +Line: 1 Col: 16 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 24 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 32 Unexpected end tag (thead). Ignored. +Line: 1 Col: 37 Unexpected end tag (tr). Ignored. +Line: 1 Col: 42 Expected closing tag. Unexpected end of file. +#document-fragment +td +#document +| <div> + +#data +<table><colgroup>foo +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 20 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| "foo" +| <table> +| <colgroup> + +#data +foo<col> +#errors +Line: 1 Col: 3 Unexpected end tag (colgroup). Ignored. +#document-fragment +colgroup +#document +| <col> + +#data +<table><colgroup></col> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 23 This element (col) has no end tag. +Line: 1 Col: 23 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <table> +| <colgroup> + +#data +<frameset><div> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 1 Col: 15 Unexpected start tag token (div) in the frameset phase. Ignored. +Line: 1 Col: 15 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <frameset> + +#data +</frameset><frame> +#errors +Line: 1 Col: 11 Unexpected end tag token (frameset) in the frameset phase (innerHTML). +#document-fragment +frameset +#document +| <frame> + +#data +<frameset></div> +#errors +Line: 1 Col: 10 Unexpected start tag (frameset). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected end tag token (div) in the frameset phase. Ignored. +Line: 1 Col: 16 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <frameset> + +#data +</body><div> +#errors +Line: 1 Col: 7 Unexpected end tag (body). Ignored. +Line: 1 Col: 12 Expected closing tag. Unexpected end of file. +#document-fragment +body +#document +| <div> + +#data +<table><tr><div> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected start tag (div) in table context caused voodoo mode. +Line: 1 Col: 16 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <div> +| <table> +| <tbody> +| <tr> + +#data +</tr><td> +#errors +Line: 1 Col: 5 Unexpected end tag (tr). Ignored. +#document-fragment +tr +#document +| <td> + +#data +</tbody></tfoot></thead><td> +#errors +Line: 1 Col: 8 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 16 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 24 Unexpected end tag (thead). Ignored. +#document-fragment +tr +#document +| <td> + +#data +<table><tr><div><td> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 16 Unexpected start tag (div) in table context caused voodoo mode. +Line: 1 Col: 20 Unexpected implied end tag (div) in the table row phase. +Line: 1 Col: 20 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| <table> +| <tbody> +| <tr> +| <td> + +#data +<caption><col><colgroup><tbody><tfoot><thead><tr> +#errors +Line: 1 Col: 9 Unexpected start tag (caption). +Line: 1 Col: 14 Unexpected start tag (col). +Line: 1 Col: 24 Unexpected start tag (colgroup). +Line: 1 Col: 31 Unexpected start tag (tbody). +Line: 1 Col: 38 Unexpected start tag (tfoot). +Line: 1 Col: 45 Unexpected start tag (thead). +Line: 1 Col: 49 Unexpected end of file. Expected table content. +#document-fragment +tbody +#document +| <tr> + +#data +<table><tbody></thead> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 22 Unexpected end tag (thead) in the table body phase. Ignored. +Line: 1 Col: 22 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> + +#data +</table><tr> +#errors +Line: 1 Col: 8 Unexpected end tag (table). Ignored. +Line: 1 Col: 12 Unexpected end of file. Expected table content. +#document-fragment +tbody +#document +| <tr> + +#data +<table><tbody></body></caption></col></colgroup></html></td></th></tr> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 21 Unexpected end tag (body) in the table body phase. Ignored. +Line: 1 Col: 31 Unexpected end tag (caption) in the table body phase. Ignored. +Line: 1 Col: 37 Unexpected end tag (col) in the table body phase. Ignored. +Line: 1 Col: 48 Unexpected end tag (colgroup) in the table body phase. Ignored. +Line: 1 Col: 55 Unexpected end tag (html) in the table body phase. Ignored. +Line: 1 Col: 60 Unexpected end tag (td) in the table body phase. Ignored. +Line: 1 Col: 65 Unexpected end tag (th) in the table body phase. Ignored. +Line: 1 Col: 70 Unexpected end tag (tr) in the table body phase. Ignored. +Line: 1 Col: 70 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> + +#data +<table><tbody></div> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 20 Unexpected end tag (div) in table context caused voodoo mode. +Line: 1 Col: 20 End tag (div) seen too early. Expected other end tag. +Line: 1 Col: 20 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> + +#data +<table><table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected start tag (table) implies end tag (table). +Line: 1 Col: 14 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> +| <table> + +#data +<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 14 Unexpected end tag (body). Ignored. +Line: 1 Col: 24 Unexpected end tag (caption). Ignored. +Line: 1 Col: 30 Unexpected end tag (col). Ignored. +Line: 1 Col: 41 Unexpected end tag (colgroup). Ignored. +Line: 1 Col: 48 Unexpected end tag (html). Ignored. +Line: 1 Col: 56 Unexpected end tag (tbody). Ignored. +Line: 1 Col: 61 Unexpected end tag (td). Ignored. +Line: 1 Col: 69 Unexpected end tag (tfoot). Ignored. +Line: 1 Col: 74 Unexpected end tag (th). Ignored. +Line: 1 Col: 82 Unexpected end tag (thead). Ignored. +Line: 1 Col: 87 Unexpected end tag (tr). Ignored. +Line: 1 Col: 87 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <table> + +#data +</table><tr> +#errors +Line: 1 Col: 8 Unexpected end tag (table). Ignored. +Line: 1 Col: 12 Unexpected end of file. Expected table content. +#document-fragment +table +#document +| <tbody> +| <tr> + +#data +<body></body></html> +#errors +Line: 1 Col: 20 Unexpected html end tag in inner html mode. +Line: 1 Col: 20 Unexpected EOF in inner html mode. +#document-fragment +html +#document +| <head> +| <body> + +#data +<html><frameset></frameset></html> +#errors +Line: 1 Col: 6 Unexpected start tag (html). Expected DOCTYPE. +#document +| <html> +| <head> +| <frameset> +| " " + +#data +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html></html> +#errors +Line: 1 Col: 50 Erroneous DOCTYPE. +Line: 1 Col: 63 Unexpected end tag (html) after the (implied) root element. +#document +| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" ""> +| <html> +| <head> +| <body> + +#data +<param><frameset></frameset> +#errors +Line: 1 Col: 7 Unexpected start tag (param). Expected DOCTYPE. +Line: 1 Col: 17 Unexpected start tag (frameset). +#document +| <html> +| <head> +| <frameset> + +#data +<source><frameset></frameset> +#errors +Line: 1 Col: 7 Unexpected start tag (source). Expected DOCTYPE. +Line: 1 Col: 17 Unexpected start tag (frameset). +#document +| <html> +| <head> +| <frameset> + +#data +<track><frameset></frameset> +#errors +Line: 1 Col: 7 Unexpected start tag (track). Expected DOCTYPE. +Line: 1 Col: 17 Unexpected start tag (frameset). +#document +| <html> +| <head> +| <frameset> + +#data +</html><frameset></frameset> +#errors +7: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +17: Stray “frameset” start tag. +17: “frameset” start tag seen. +#document +| <html> +| <head> +| <frameset> + +#data +</body><frameset></frameset> +#errors +7: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”. +17: Stray “frameset” start tag. +17: “frameset” start tag seen. +#document +| <html> +| <head> +| <frameset> diff --git a/pkgs/html/test/data/tree-construction/tests7.dat b/pkgs/html/test/data/tree-construction/tests7.dat new file mode 100644 index 000000000..f5193c660 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests7.dat @@ -0,0 +1,390 @@ +#data +<!doctype html><body><title>X</title> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <title> +| "X" + +#data +<!doctype html><table><title>X</title></table> +#errors +Line: 1 Col: 29 Unexpected start tag (title) in table context caused voodoo mode. +Line: 1 Col: 38 Unexpected end tag (title) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <title> +| "X" +| <table> + +#data +<!doctype html><head></head><title>X</title> +#errors +Line: 1 Col: 35 Unexpected start tag (title) that can be in head. Moved. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "X" +| <body> + +#data +<!doctype html></head><title>X</title> +#errors +Line: 1 Col: 29 Unexpected start tag (title) that can be in head. Moved. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <title> +| "X" +| <body> + +#data +<!doctype html><table><meta></table> +#errors +Line: 1 Col: 28 Unexpected start tag (meta) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <meta> +| <table> + +#data +<!doctype html><table>X<tr><td><table> <meta></table></table> +#errors +Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 45 Unexpected start tag (meta) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" +| <table> +| <tbody> +| <tr> +| <td> +| <meta> +| <table> +| " " + +#data +<!doctype html><html> <head> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<!doctype html> <head> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<!doctype html><table><style> <tr>x </style> </table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <style> +| " <tr>x " +| " " + +#data +<!doctype html><table><TBODY><script> <tr>x </script> </table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <script> +| " <tr>x " +| " " + +#data +<!doctype html><p><applet><p>X</p></applet> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <p> +| <applet> +| <p> +| "X" + +#data +<!doctype html><listing> +X</listing> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <listing> +| "X" + +#data +<!doctype html><select><input>X +#errors +Line: 1 Col: 30 Unexpected input start tag in the select phase. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <input> +| "X" + +#data +<!doctype html><select><select>X +#errors +Line: 1 Col: 31 Unexpected select start tag in the select phase treated as select end tag. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| "X" + +#data +<!doctype html><table><input type=hidDEN></table> +#errors +Line: 1 Col: 41 Unexpected input with type hidden in table context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <input> +| type="hidDEN" + +#data +<!doctype html><table>X<input type=hidDEN></table> +#errors +Line: 1 Col: 23 Unexpected non-space characters in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| "X" +| <table> +| <input> +| type="hidDEN" + +#data +<!doctype html><table> <input type=hidDEN></table> +#errors +Line: 1 Col: 43 Unexpected input with type hidden in table context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| " " +| <input> +| type="hidDEN" + +#data +<!doctype html><table> <input type='hidDEN'></table> +#errors +Line: 1 Col: 45 Unexpected input with type hidden in table context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| " " +| <input> +| type="hidDEN" + +#data +<!doctype html><table><input type=" hidden"><input type=hidDEN></table> +#errors +Line: 1 Col: 44 Unexpected start tag (input) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <input> +| type=" hidden" +| <table> +| <input> +| type="hidDEN" + +#data +<!doctype html><table><select>X<tr> +#errors +Line: 1 Col: 30 Unexpected start tag (select) in table context caused voodoo mode. +Line: 1 Col: 35 Unexpected table element start tag (trs) in the select in table phase. +Line: 1 Col: 35 Unexpected end of file. Expected table content. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| "X" +| <table> +| <tbody> +| <tr> + +#data +<!doctype html><select>X</select> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| "X" + +#data +<!DOCTYPE hTmL><html></html> +#errors +Line: 1 Col: 28 Unexpected end tag (html) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<!DOCTYPE HTML><html></html> +#errors +Line: 1 Col: 28 Unexpected end tag (html) after the (implied) root element. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> + +#data +<body>X</body></body> +#errors +Line: 1 Col: 21 Unexpected end tag token (body) in the after body phase. +Line: 1 Col: 21 Unexpected EOF in inner html mode. +#document-fragment +html +#document +| <head> +| <body> +| "X" + +#data +<div><p>a</x> b +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 13 Unexpected end tag (x). Ignored. +Line: 1 Col: 15 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| <p> +| "a b" + +#data +<table><tr><td><code></code> </table> +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <code> +| " " + +#data +<table><b><tr><td>aaa</td></tr>bbb</table>ccc +#errors +XXX: Fix me +#document +| <html> +| <head> +| <body> +| <b> +| <b> +| "bbb" +| <table> +| <tbody> +| <tr> +| <td> +| "aaa" +| <b> +| "ccc" + +#data +A<table><tr> B</tr> B</table> +#errors +XXX: Fix me +#document +| <html> +| <head> +| <body> +| "A B B" +| <table> +| <tbody> +| <tr> + +#data +A<table><tr> B</tr> </em>C</table> +#errors +XXX: Fix me +#document +| <html> +| <head> +| <body> +| "A BC" +| <table> +| <tbody> +| <tr> +| " " + +#data +<select><keygen> +#errors +Not known +#document +| <html> +| <head> +| <body> +| <select> +| <keygen> diff --git a/pkgs/html/test/data/tree-construction/tests8.dat b/pkgs/html/test/data/tree-construction/tests8.dat new file mode 100644 index 000000000..90e6c919e --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests8.dat @@ -0,0 +1,148 @@ +#data +<div> +<div></div> +</span>x +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 3 Col: 7 Unexpected end tag (span). Ignored. +Line: 3 Col: 8 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| " +" +| <div> +| " +x" + +#data +<div>x<div></div> +</span>x +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 2 Col: 7 Unexpected end tag (span). Ignored. +Line: 2 Col: 8 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| "x" +| <div> +| " +x" + +#data +<div>x<div></div>x</span>x +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 25 Unexpected end tag (span). Ignored. +Line: 1 Col: 26 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| "x" +| <div> +| "xx" + +#data +<div>x<div></div>y</span>z +#errors +Line: 1 Col: 5 Unexpected start tag (div). Expected DOCTYPE. +Line: 1 Col: 25 Unexpected end tag (span). Ignored. +Line: 1 Col: 26 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <div> +| "x" +| <div> +| "yz" + +#data +<table><div>x<div></div>x</span>x +#errors +Line: 1 Col: 7 Unexpected start tag (table). Expected DOCTYPE. +Line: 1 Col: 12 Unexpected start tag (div) in table context caused voodoo mode. +Line: 1 Col: 18 Unexpected start tag (div) in table context caused voodoo mode. +Line: 1 Col: 24 Unexpected end tag (div) in table context caused voodoo mode. +Line: 1 Col: 32 Unexpected end tag (span) in table context caused voodoo mode. +Line: 1 Col: 32 Unexpected end tag (span). Ignored. +Line: 1 Col: 33 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| <div> +| "x" +| <div> +| "xx" +| <table> + +#data +x<table>x +#errors +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +Line: 1 Col: 9 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 9 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| "xx" +| <table> + +#data +x<table><table>x +#errors +Line: 1 Col: 1 Unexpected non-space characters. Expected DOCTYPE. +Line: 1 Col: 15 Unexpected start tag (table) implies end tag (table). +Line: 1 Col: 16 Unexpected non-space characters in table context caused voodoo mode. +Line: 1 Col: 16 Unexpected end of file. Expected table content. +#document +| <html> +| <head> +| <body> +| "x" +| <table> +| "x" +| <table> + +#data +<b>a<div></div><div></b>y +#errors +Line: 1 Col: 3 Unexpected start tag (b). Expected DOCTYPE. +Line: 1 Col: 24 End tag (b) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 25 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <b> +| "a" +| <div> +| <div> +| <b> +| "y" + +#data +<a><div><p></a> +#errors +Line: 1 Col: 3 Unexpected start tag (a). Expected DOCTYPE. +Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 15 End tag (a) violates step 1, paragraph 3 of the adoption agency algorithm. +Line: 1 Col: 15 Expected closing tag. Unexpected end of file. +#document +| <html> +| <head> +| <body> +| <a> +| <div> +| <a> +| <p> +| <a> diff --git a/pkgs/html/test/data/tree-construction/tests9.dat b/pkgs/html/test/data/tree-construction/tests9.dat new file mode 100644 index 000000000..554e27aec --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests9.dat @@ -0,0 +1,457 @@ +#data +<!DOCTYPE html><math></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> + +#data +<!DOCTYPE html><body><math></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> + +#data +<!DOCTYPE html><math><mi> +#errors +25: End of file in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> + +#data +<!DOCTYPE html><math><annotation-xml><svg><u> +#errors +45: HTML start tag “u” in a foreign namespace context. +45: End of file seen and there were open elements. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math annotation-xml> +| <svg svg> +| <u> + +#data +<!DOCTYPE html><body><select><math></math></select> +#errors +Line: 1 Col: 35 Unexpected start tag token (math) in the select phase. Ignored. +Line: 1 Col: 42 Unexpected end tag (math) in the select phase. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> + +#data +<!DOCTYPE html><body><select><option><math></math></option></select> +#errors +Line: 1 Col: 43 Unexpected start tag token (math) in the select phase. Ignored. +Line: 1 Col: 50 Unexpected end tag (math) in the select phase. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| <option> + +#data +<!DOCTYPE html><body><table><math></math></table> +#errors +Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 41 Unexpected end tag (math) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <table> + +#data +<!DOCTYPE html><body><table><math><mi>foo</mi></math></table> +#errors +Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 46 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 53 Unexpected end tag (math) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <table> + +#data +<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table> +#errors +Line: 1 Col: 34 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 46 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 58 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 65 Unexpected end tag (math) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <table> + +#data +<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table> +#errors +Line: 1 Col: 41 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 53 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 65 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 72 Unexpected end tag (math) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <table> +| <tbody> + +#data +<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table> +#errors +Line: 1 Col: 45 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 57 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 69 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 76 Unexpected end tag (math) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <table> +| <tbody> +| <tr> + +#data +<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" + +#data +<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux +#errors +Line: 1 Col: 70 HTML start tag "p" in a foreign namespace context. +Line: 1 Col: 81 Unexpected end table tag in caption. Generates implied end caption. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux +#errors +Line: 1 Col: 78 Unexpected end table tag in caption. Generates implied end caption. +Line: 1 Col: 78 Unexpected end tag (caption). Missing end tag (math). +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <caption> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| "baz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux +#errors +Line: 1 Col: 44 Unexpected start tag (math) in table context caused voodoo mode. +Line: 1 Col: 56 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 68 Unexpected end tag (mi) in table context caused voodoo mode. +Line: 1 Col: 71 HTML start tag "p" in a foreign namespace context. +Line: 1 Col: 71 Unexpected start tag (p) in table context caused voodoo mode. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" +| <table> +| <colgroup> +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux +#errors +Line: 1 Col: 50 Unexpected start tag token (math) in the select phase. Ignored. +Line: 1 Col: 54 Unexpected start tag token (mi) in the select phase. Ignored. +Line: 1 Col: 62 Unexpected end tag (mi) in the select phase. Ignored. +Line: 1 Col: 66 Unexpected start tag token (mi) in the select phase. Ignored. +Line: 1 Col: 74 Unexpected end tag (mi) in the select phase. Ignored. +Line: 1 Col: 77 Unexpected start tag token (p) in the select phase. Ignored. +Line: 1 Col: 88 Unexpected table element end tag (tables) in the select in table phase. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| <select> +| "foobarbaz" +| <p> +| "quux" + +#data +<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux +#errors +Line: 1 Col: 36 Unexpected start tag (select) in table context caused voodoo mode. +Line: 1 Col: 42 Unexpected start tag token (math) in the select phase. Ignored. +Line: 1 Col: 46 Unexpected start tag token (mi) in the select phase. Ignored. +Line: 1 Col: 54 Unexpected end tag (mi) in the select phase. Ignored. +Line: 1 Col: 58 Unexpected start tag token (mi) in the select phase. Ignored. +Line: 1 Col: 66 Unexpected end tag (mi) in the select phase. Ignored. +Line: 1 Col: 69 Unexpected start tag token (p) in the select phase. Ignored. +Line: 1 Col: 80 Unexpected table element end tag (tables) in the select in table phase. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <select> +| "foobarbaz" +| <table> +| <p> +| "quux" + +#data +<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz +#errors +Line: 1 Col: 41 Unexpected start tag (math). +Line: 1 Col: 68 HTML start tag "p" in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz +#errors +Line: 1 Col: 34 Unexpected start tag token (math) in the after body phase. +Line: 1 Col: 61 HTML start tag "p" in a foreign namespace context. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <math math> +| <math mi> +| "foo" +| <math mi> +| "bar" +| <p> +| "baz" + +#data +<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span> +#errors +Line: 1 Col: 31 Unexpected start tag token (math) in the frameset phase. Ignored. +Line: 1 Col: 35 Unexpected start tag token (mi) in the frameset phase. Ignored. +Line: 1 Col: 40 Unexpected end tag token (mi) in the frameset phase. Ignored. +Line: 1 Col: 44 Unexpected start tag token (mi) in the frameset phase. Ignored. +Line: 1 Col: 49 Unexpected end tag token (mi) in the frameset phase. Ignored. +Line: 1 Col: 52 Unexpected start tag token (p) in the frameset phase. Ignored. +Line: 1 Col: 58 Unexpected start tag token (span) in the frameset phase. Ignored. +Line: 1 Col: 58 Expected closing tag. Unexpected end of file. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span> +#errors +Line: 1 Col: 42 Unexpected start tag (math) in the after frameset phase. Ignored. +Line: 1 Col: 46 Unexpected start tag (mi) in the after frameset phase. Ignored. +Line: 1 Col: 51 Unexpected end tag (mi) in the after frameset phase. Ignored. +Line: 1 Col: 55 Unexpected start tag (mi) in the after frameset phase. Ignored. +Line: 1 Col: 60 Unexpected end tag (mi) in the after frameset phase. Ignored. +Line: 1 Col: 63 Unexpected start tag (p) in the after frameset phase. Ignored. +Line: 1 Col: 69 Unexpected start tag (span) in the after frameset phase. Ignored. +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| <math math> +| xlink href="foo" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <math math> +| <math mi> +| xlink href="foo" +| xml lang="en" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <math math> +| <math mi> +| xlink href="foo" +| xml lang="en" + +#data +<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| xlink:href="foo" +| xml:lang="en" +| <math math> +| <math mi> +| xlink href="foo" +| xml lang="en" +| "bar" diff --git a/pkgs/html/test/data/tree-construction/tests_innerHTML_1.dat b/pkgs/html/test/data/tree-construction/tests_innerHTML_1.dat new file mode 100644 index 000000000..6c78661e0 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tests_innerHTML_1.dat @@ -0,0 +1,741 @@ +#data +<body><span> +#errors +#document-fragment +body +#document +| <span> + +#data +<span><body> +#errors +#document-fragment +body +#document +| <span> + +#data +<span><body> +#errors +#document-fragment +div +#document +| <span> + +#data +<body><span> +#errors +#document-fragment +html +#document +| <head> +| <body> +| <span> + +#data +<frameset><span> +#errors +#document-fragment +body +#document +| <span> + +#data +<span><frameset> +#errors +#document-fragment +body +#document +| <span> + +#data +<span><frameset> +#errors +#document-fragment +div +#document +| <span> + +#data +<frameset><span> +#errors +#document-fragment +html +#document +| <head> +| <frameset> + +#data +<table><tr> +#errors +#document-fragment +table +#document +| <tbody> +| <tr> + +#data +</table><tr> +#errors +#document-fragment +table +#document +| <tbody> +| <tr> + +#data +<a> +#errors +#document-fragment +table +#document +| <a> + +#data +<a> +#errors +#document-fragment +table +#document +| <a> + +#data +<a><caption>a +#errors +#document-fragment +table +#document +| <a> +| <caption> +| "a" + +#data +<a><colgroup><col> +#errors +#document-fragment +table +#document +| <a> +| <colgroup> +| <col> + +#data +<a><tbody><tr> +#errors +#document-fragment +table +#document +| <a> +| <tbody> +| <tr> + +#data +<a><tfoot><tr> +#errors +#document-fragment +table +#document +| <a> +| <tfoot> +| <tr> + +#data +<a><thead><tr> +#errors +#document-fragment +table +#document +| <a> +| <thead> +| <tr> + +#data +<a><tr> +#errors +#document-fragment +table +#document +| <a> +| <tbody> +| <tr> + +#data +<a><th> +#errors +#document-fragment +table +#document +| <a> +| <tbody> +| <tr> +| <th> + +#data +<a><td> +#errors +#document-fragment +table +#document +| <a> +| <tbody> +| <tr> +| <td> + +#data +<table></table><tbody> +#errors +#document-fragment +caption +#document +| <table> + +#data +</table><span> +#errors +#document-fragment +caption +#document +| <span> + +#data +<span></table> +#errors +#document-fragment +caption +#document +| <span> + +#data +</caption><span> +#errors +#document-fragment +caption +#document +| <span> + +#data +<span></caption><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><caption><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><col><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><colgroup><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><html><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><tbody><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><td><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><tfoot><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><thead><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><th><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span><tr><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +<span></table><span> +#errors +#document-fragment +caption +#document +| <span> +| <span> + +#data +</colgroup><col> +#errors +#document-fragment +colgroup +#document +| <col> + +#data +<a><col> +#errors +#document-fragment +colgroup +#document +| <col> + +#data +<caption><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<col><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<colgroup><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<tbody><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<tfoot><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<thead><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +</table><a> +#errors +#document-fragment +tbody +#document +| <a> + +#data +<a><tr> +#errors +#document-fragment +tbody +#document +| <a> +| <tr> + +#data +<a><td> +#errors +#document-fragment +tbody +#document +| <a> +| <tr> +| <td> + +#data +<a><td> +#errors +#document-fragment +tbody +#document +| <a> +| <tr> +| <td> + +#data +<a><td> +#errors +#document-fragment +tbody +#document +| <a> +| <tr> +| <td> + +#data +<td><table><tbody><a><tr> +#errors +#document-fragment +tbody +#document +| <tr> +| <td> +| <a> +| <table> +| <tbody> +| <tr> + +#data +</tr><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<td><table><a><tr></tr><tr> +#errors +#document-fragment +tr +#document +| <td> +| <a> +| <table> +| <tbody> +| <tr> +| <tr> + +#data +<caption><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<col><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<colgroup><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<tbody><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<tfoot><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<thead><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<tr><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +</table><td> +#errors +#document-fragment +tr +#document +| <td> + +#data +<td><table></table><td> +#errors +#document-fragment +tr +#document +| <td> +| <table> +| <td> + +#data +<td><table></table><td> +#errors +#document-fragment +tr +#document +| <td> +| <table> +| <td> + +#data +<caption><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<col><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<colgroup><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<tbody><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<tfoot><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<th><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<thead><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<tr><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</table><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</tbody><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</td><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</tfoot><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</thead><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</th><a> +#errors +#document-fragment +td +#document +| <a> + +#data +</tr><a> +#errors +#document-fragment +td +#document +| <a> + +#data +<table><td><td> +#errors +#document-fragment +td +#document +| <table> +| <tbody> +| <tr> +| <td> +| <td> + +#data +</select><option> +#errors +#document-fragment +select +#document +| <option> + +#data +<input><option> +#errors +#document-fragment +select +#document +| <option> + +#data +<keygen><option> +#errors +#document-fragment +select +#document +| <option> + +#data +<textarea><option> +#errors +#document-fragment +select +#document +| <option> + +#data +</html><!--abc--> +#errors +#document-fragment +html +#document +| <head> +| <body> +| <!-- abc --> + +#data +</frameset><frame> +#errors +#document-fragment +frameset +#document +| <frame> + +#data +#errors +#document-fragment +html +#document +| <head> +| <body> diff --git a/pkgs/html/test/data/tree-construction/tricky01.dat b/pkgs/html/test/data/tree-construction/tricky01.dat new file mode 100644 index 000000000..084199244 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/tricky01.dat @@ -0,0 +1,261 @@ +#data +<b><p>Bold </b> Not bold</p> +Also not bold. +#errors +#document +| <html> +| <head> +| <body> +| <b> +| <p> +| <b> +| "Bold " +| " Not bold" +| " +Also not bold." + +#data +<html> +<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain +<p>I should not be red. <font color=red>Red. <i>Italic and red.</p> +<p>Italic and red. </i> Red.</font> I should not be red.</p> +<b>Bold <i>Bold and italic</b> Only Italic </i> Plain +#errors +#document +| <html> +| <head> +| <body> +| <font> +| color="red" +| <i> +| "Italic and Red" +| <i> +| <p> +| <font> +| color="red" +| "Italic and Red " +| " Just italic." +| " Italic only." +| " Plain +" +| <p> +| "I should not be red. " +| <font> +| color="red" +| "Red. " +| <i> +| "Italic and red." +| <font> +| color="red" +| <i> +| " +" +| <p> +| <font> +| color="red" +| <i> +| "Italic and red. " +| " Red." +| " I should not be red." +| " +" +| <b> +| "Bold " +| <i> +| "Bold and italic" +| <i> +| " Only Italic " +| " Plain" + +#data +<html><body> +<p><font size="7">First paragraph.</p> +<p>Second paragraph.</p></font> +<b><p><i>Bold and Italic</b> Italic</p> +#errors +#document +| <html> +| <head> +| <body> +| " +" +| <p> +| <font> +| size="7" +| "First paragraph." +| <font> +| size="7" +| " +" +| <p> +| "Second paragraph." +| " +" +| <b> +| <p> +| <b> +| <i> +| "Bold and Italic" +| <i> +| " Italic" + +#data +<html> +<dl> +<dt><b>Boo +<dd>Goo? +</dl> +</html> +#errors +#document +| <html> +| <head> +| <body> +| <dl> +| " +" +| <dt> +| <b> +| "Boo +" +| <dd> +| <b> +| "Goo? +" +| <b> +| " +" + +#data +<html><body> +<label><a><div>Hello<div>World</div></a></label> +</body></html> +#errors +#document +| <html> +| <head> +| <body> +| " +" +| <label> +| <a> +| <div> +| <a> +| "Hello" +| <div> +| "World" +| " +" + +#data +<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table> +#errors +#document +| <html> +| <head> +| <body> +| <center> +| " " +| <font> +| "a" +| <font> +| <img> +| " " +| <table> +| " " +| <tbody> +| <tr> +| <td> +| " " +| " " +| " " + +#data +<table><tr><p><a><p>You should see this text. +#errors +#document +| <html> +| <head> +| <body> +| <p> +| <a> +| <p> +| <a> +| "You should see this text." +| <table> +| <tbody> +| <tr> + +#data +<TABLE> +<TR> +<CENTER><CENTER><TD></TD></TR><TR> +<FONT> +<TABLE><tr></tr></TABLE> +</P> +<a></font><font></a> +This page contains an insanely badly-nested tag sequence. +#errors +#document +| <html> +| <head> +| <body> +| <center> +| <center> +| <font> +| " +" +| <table> +| " +" +| <tbody> +| <tr> +| " +" +| <td> +| <tr> +| " +" +| <table> +| <tbody> +| <tr> +| <font> +| " +" +| <p> +| " +" +| <a> +| <a> +| <font> +| <font> +| " +This page contains an insanely badly-nested tag sequence." + +#data +<html> +<body> +<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the +nobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre> +</body> +</html> +#errors +#document +| <html> +| <head> +| <body> +| " +" +| <b> +| <nobr> +| <div> +| <b> +| <nobr> +| "This text is in a div inside a nobr" +| "More text that should not be in the nobr, i.e., the +nobr should have closed the div inside it implicitly. " +| <pre> +| "A pre tag outside everything else." +| " + +" diff --git a/pkgs/html/test/data/tree-construction/webkit01.dat b/pkgs/html/test/data/tree-construction/webkit01.dat new file mode 100644 index 000000000..06bc436b6 --- /dev/null +++ b/pkgs/html/test/data/tree-construction/webkit01.dat @@ -0,0 +1,594 @@ +#data +Test +#errors +Line: 1 Col: 4 Unexpected non-space characters. Expected DOCTYPE. +#document +| <html> +| <head> +| <body> +| "Test" + +#data +<div></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> + +#data +<div>Test</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "Test" + +#data +<di +#errors +#document +| <html> +| <head> +| <body> + +#data +<div>Hello</div> +<script> +console.log("PASS"); +</script> +<div>Bye</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "Hello" +| " +" +| <script> +| " +console.log("PASS"); +" +| " +" +| <div> +| "Bye" + +#data +<div foo="bar">Hello</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| foo="bar" +| "Hello" + +#data +<div>Hello</div> +<script> +console.log("FOO<span>BAR</span>BAZ"); +</script> +<div>Bye</div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| "Hello" +| " +" +| <script> +| " +console.log("FOO<span>BAR</span>BAZ"); +" +| " +" +| <div> +| "Bye" + +#data +<foo bar="baz"></foo><potato quack="duck"></potato> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| bar="baz" +| <potato> +| quack="duck" + +#data +<foo bar="baz"><potato quack="duck"></potato></foo> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| bar="baz" +| <potato> +| quack="duck" + +#data +<foo></foo bar="baz"><potato></potato quack="duck"> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| <potato> + +#data +</ tttt> +#errors +#document +| <!-- tttt --> +| <html> +| <head> +| <body> + +#data +<div FOO ><img><img></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| foo="" +| <img> +| <img> + +#data +<p>Test</p<p>Test2</p> +#errors +#document +| <html> +| <head> +| <body> +| <p> +| "TestTest2" + +#data +<rdar://problem/6869687> +#errors +#document +| <html> +| <head> +| <body> +| <rdar:> +| 6869687="" +| problem="" + +#data +<A>test< /A> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| "test< /A>" + +#data +&lt; +#errors +#document +| <html> +| <head> +| <body> +| "<" + +#data +<body foo='bar'><body foo='baz' yo='mama'> +#errors +#document +| <html> +| <head> +| <body> +| foo="bar" +| yo="mama" + +#data +<body></br foo="bar"></body> +#errors +#document +| <html> +| <head> +| <body> +| <br> + +#data +<bdy><br foo="bar"></body> +#errors +#document +| <html> +| <head> +| <body> +| <bdy> +| <br> +| foo="bar" + +#data +<body></body></br foo="bar"> +#errors +#document +| <html> +| <head> +| <body> +| <br> + +#data +<bdy></body><br foo="bar"> +#errors +#document +| <html> +| <head> +| <body> +| <bdy> +| <br> +| foo="bar" + +#data +<html><body></body></html><!-- Hi there --> +#errors +#document +| <html> +| <head> +| <body> +| <!-- Hi there --> + +#data +<html><body></body></html>x<!-- Hi there --> +#errors +#document +| <html> +| <head> +| <body> +| "x" +| <!-- Hi there --> + +#data +<html><body></body></html>x<!-- Hi there --></html><!-- Again --> +#errors +#document +| <html> +| <head> +| <body> +| "x" +| <!-- Hi there --> +| <!-- Again --> + +#data +<html><body></body></html>x<!-- Hi there --></body></html><!-- Again --> +#errors +#document +| <html> +| <head> +| <body> +| "x" +| <!-- Hi there --> +| <!-- Again --> + +#data +<html><body><ruby><div><rp>xx</rp></div></ruby></body></html> +#errors +#document +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <rp> +| "xx" + +#data +<html><body><ruby><div><rt>xx</rt></div></ruby></body></html> +#errors +#document +| <html> +| <head> +| <body> +| <ruby> +| <div> +| <rt> +| "xx" + +#data +<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6--> +#errors +#document +| <html> +| <head> +| <frameset> +| <!-- 1 --> +| <noframes> +| "A" +| <!-- 2 --> +| <!-- 3 --> +| <noframes> +| "B" +| <!-- 4 --> +| <noframes> +| "C" +| <!-- 5 --> +| <!-- 6 --> + +#data +<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select> +#errors +#document +| <html> +| <head> +| <body> +| <select> +| <option> +| "A" +| <option> +| "B" +| <select> +| <option> +| "C" +| <option> +| "D" +| <select> +| <option> +| "E" +| <option> +| "F" +| <select> +| <option> +| "G" + +#data +<dd><dd><dt><dt><dd><li><li> +#errors +#document +| <html> +| <head> +| <body> +| <dd> +| <dd> +| <dt> +| <dt> +| <dd> +| <li> +| <li> + +#data +<div><b></div><div><nobr>a<nobr> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <b> +| <div> +| <b> +| <nobr> +| "a" +| <nobr> + +#data +<head></head> +<body></body> +#errors +#document +| <html> +| <head> +| " +" +| <body> + +#data +<head></head> <style></style>ddd +#errors +#document +| <html> +| <head> +| <style> +| " " +| <body> +| "ddd" + +#data +<kbd><table></kbd><col><select><tr> +#errors +#document +| <html> +| <head> +| <body> +| <kbd> +| <select> +| <table> +| <colgroup> +| <col> +| <tbody> +| <tr> + +#data +<kbd><table></kbd><col><select><tr></table><div> +#errors +#document +| <html> +| <head> +| <body> +| <kbd> +| <select> +| <table> +| <colgroup> +| <col> +| <tbody> +| <tr> +| <div> + +#data +<a><li><style></style><title></title></a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <li> +| <a> +| <style> +| <title> + +#data +<font></p><p><meta><title></title></font> +#errors +#document +| <html> +| <head> +| <body> +| <font> +| <p> +| <p> +| <font> +| <meta> +| <title> + +#data +<a><center><title></title><a> +#errors +#document +| <html> +| <head> +| <body> +| <a> +| <center> +| <a> +| <title> +| <a> + +#data +<svg><title><div> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg title> +| <div> + +#data +<svg><title><rect><div> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg title> +| <rect> +| <div> + +#data +<svg><title><svg><div> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg title> +| <svg svg> +| <div> + +#data +<img <="" FAIL> +#errors +#document +| <html> +| <head> +| <body> +| <img> +| <="" +| fail="" + +#data +<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul> +#errors +#document +| <html> +| <head> +| <body> +| <ul> +| <li> +| <div> +| id="foo" +| "A" +| <li> +| "B" +| <div> +| "C" + +#data +<svg><em><desc></em> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <em> +| <desc> + +#data +<svg><tfoot></mi><td> +#errors +#document +| <html> +| <head> +| <body> +| <svg svg> +| <svg tfoot> +| <svg td> + +#data +<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math> +#errors +#document +| <html> +| <head> +| <body> +| <math math> +| <math mrow> +| <math mrow> +| <math mn> +| "1" +| <math mi> +| "a" + +#data +<!doctype html><input type="hidden"><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <frameset> + +#data +<!doctype html><input type="button"><frameset> +#errors +#document +| <!DOCTYPE html> +| <html> +| <head> +| <body> +| <input> +| type="button" diff --git a/pkgs/html/test/data/tree-construction/webkit02.dat b/pkgs/html/test/data/tree-construction/webkit02.dat new file mode 100644 index 000000000..468879b3c --- /dev/null +++ b/pkgs/html/test/data/tree-construction/webkit02.dat @@ -0,0 +1,94 @@ +#data +<foo bar=qux/> +#errors +#document +| <html> +| <head> +| <body> +| <foo> +| bar="qux/" + +#data +<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p> +#errors +#document +| <html> +| <head> +| <body> +| <p> +| id="status" +| <noscript> +| "<strong>A</strong>" +| <span> +| "B" + +#data +<div><sarcasm><div></div></sarcasm></div> +#errors +#document +| <html> +| <head> +| <body> +| <div> +| <sarcasm> +| <div> + +#data +<html><body><img src="" border="0" alt="><div>A</div></body></html> +#errors +#document +| <html> +| <head> +| <body> + +#data +<table><td></tbody>A +#errors +#document +| <html> +| <head> +| <body> +| "A" +| <table> +| <tbody> +| <tr> +| <td> + +#data +<table><td></thead>A +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "A" + +#data +<table><td></tfoot>A +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <tbody> +| <tr> +| <td> +| "A" + +#data +<table><thead><td></tbody>A +#errors +#document +| <html> +| <head> +| <body> +| <table> +| <thead> +| <tr> +| <td> +| "A" diff --git a/pkgs/html/test/dom_compat_test.dart b/pkgs/html/test/dom_compat_test.dart new file mode 100644 index 000000000..f95659bc0 --- /dev/null +++ b/pkgs/html/test/dom_compat_test.dart @@ -0,0 +1,31 @@ +library dom_compat_test; + +import 'dart:async'; +import 'dart:io'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/compact_vm_config.dart'; +import 'package:html5lib/dom.dart'; + +part 'dom_compat_test_definitions.dart'; + +main() { + useCompactVMConfiguration(); + + registerDomCompatTests(); + + test('content_shell', () { + _runDrt('test/browser/browser_test.html'); + }); +} + +void _runDrt(String htmlFile) { + final allPassedRegExp = new RegExp('All \\d+ tests passed'); + + final future = Process.run('content_shell', ['--dump-render-tree', htmlFile]) + .then((ProcessResult pr) { + expect(pr.exitCode, 0); + expect(pr.stdout, matches(allPassedRegExp), reason: pr.stdout); + }); + + expect(future, completion(isNull)); +} diff --git a/pkgs/html/test/dom_compat_test_definitions.dart b/pkgs/html/test/dom_compat_test_definitions.dart new file mode 100644 index 000000000..f1d83e7a9 --- /dev/null +++ b/pkgs/html/test/dom_compat_test_definitions.dart @@ -0,0 +1,10 @@ +part of dom_compat_test; + +void registerDomCompatTests() { + group('Element', () { + test('outerHtml', () { + final element = new Element.tag('div'); + expect(element.outerHtml, '<div></div>'); + }); + }); +} diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart new file mode 100644 index 000000000..8b339f0da --- /dev/null +++ b/pkgs/html/test/dom_test.dart @@ -0,0 +1,34 @@ +/** Additional feature tests that aren't based on test data. */ +library dom_test; + +import 'package:unittest/unittest.dart'; +import 'package:html5lib/parser.dart'; +import 'package:html5lib/dom.dart'; + +main() { + group('Node.query type selectors', () { + test('x-foo', () { + expect(parse('<x-foo>').body.query('x-foo'), isNotNull); + }); + + test('-x-foo', () { + var doc = parse('<body><-x-foo>'); + expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>')); + expect(doc.body.query('-x-foo'), isNull); + }); + + test('foo123', () { + expect(parse('<foo123>').body.query('foo123'), isNotNull); + }); + + test('123 - invalid', () { + var doc = parse('<123>'); + expect(() => doc.body.query('123'), throwsUnimplementedError); + }); + + test('x\\ny - not implemented', () { + var doc = parse('<x\\ny>'); + expect(() => doc.body.query('x\\ny'), throwsUnimplementedError); + }); + }); +} diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart new file mode 100644 index 000000000..32269c324 --- /dev/null +++ b/pkgs/html/test/parser_feature_test.dart @@ -0,0 +1,251 @@ +/** Additional feature tests that aren't based on test data. */ +library parser_feature_test; + +import 'package:unittest/unittest.dart'; +import 'package:html5lib/dom.dart'; +import 'package:html5lib/dom_parsing.dart'; +import 'package:html5lib/parser.dart'; +import 'package:html5lib/src/constants.dart'; +import 'package:html5lib/src/tokenizer.dart'; +import 'package:html5lib/src/treebuilder.dart'; + +main() { + test('doctype is cloneable', () { + var doc = parse('<!DOCTYPE HTML>'); + DocumentType doctype = doc.nodes[0]; + expect(doctype.clone().outerHtml, '<!DOCTYPE html>'); + }); + + test('line counter', () { + // http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 + var doc = parse("<pre>\nx\n&gt;\n</pre>"); + expect(doc.body.innerHtml, "<pre>x\n&gt;\n</pre>"); + }); + + test('namespace html elements on', () { + var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse(); + expect(doc.nodes[0].namespace, Namespaces.html); + }); + + test('namespace html elements off', () { + var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse(); + expect(doc.nodes[0].namespace, null); + }); + + test('parse error spans - full', () { + var parser = new HtmlParser(''' +<!DOCTYPE html> +<html> + <body> + <!DOCTYPE html> + </body> +</html> +''', generateSpans: true, sourceUrl: 'ParseError'); + var doc = parser.parse(); + expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); + expect(parser.errors.length, 1); + ParseError error = parser.errors[0]; + expect(error.errorCode, 'unexpected-doctype'); + + // Note: these values are 0-based, but the printed format is 1-based. + expect(error.span.start.line, 3); + expect(error.span.end.line, 3); + expect(error.span.start.column, 2); + expect(error.span.end.column, 17); + expect(error.span.text, '<!DOCTYPE html>'); + + expect(error.toString(), ''' +ParseError:4:3: Unexpected DOCTYPE. Ignored. + <!DOCTYPE html> + ^^^^^^^^^^^^^^^'''); + }); + + test('parse error spans - minimal', () { + var parser = new HtmlParser(''' +<!DOCTYPE html> +<html> + <body> + <!DOCTYPE html> + </body> +</html> +'''); + var doc = parser.parse(); + expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); + expect(parser.errors.length, 1); + ParseError error = parser.errors[0]; + expect(error.errorCode, 'unexpected-doctype'); + expect(error.span.start.line, 3); + // Note: error position is at the end, not the beginning + expect(error.span.start.column, 17); + }); + + test('text spans should have the correct length', () { + var textContent = '\n hello {{name}}'; + var html = '<body><div>$textContent</div>'; + var doc = parse(html, generateSpans: true); + var text = doc.body.nodes[0].nodes[0]; + expect(text, new isInstanceOf<Text>()); + expect(text.value, textContent); + expect(text.sourceSpan.start.offset, html.indexOf(textContent)); + expect(text.sourceSpan.length, textContent.length); + }); + + test('attribute spans', () { + var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + var doc = parse(text, generateSpans: true); + var elem = doc.query('element'); + expect(elem.sourceSpan.start.offset, 0); + expect(elem.sourceSpan.end.offset, text.length); + expect(elem.sourceSpan.text, text); + + expect(elem.attributeSpans['quux'], null); + + var span = elem.attributeSpans['extends']; + expect(span.start.offset, text.indexOf('extends')); + expect(span.text, 'extends="x-bar"'); + }); + + test('attribute value spans', () { + var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + var doc = parse(text, generateSpans: true); + var elem = doc.query('element'); + + expect(elem.attributeValueSpans['quux'], null); + + var span = elem.attributeValueSpans['extends']; + expect(span.start.offset, text.indexOf('x-bar')); + expect(span.text, 'x-bar'); + }); + + test('attribute spans if no attributes', () { + var text = '<element>'; + var doc = parse(text, generateSpans: true); + var elem = doc.query('element'); + + expect(elem.attributeSpans['quux'], null); + expect(elem.attributeValueSpans['quux'], null); + }); + + test('attribute spans if no attribute value', () { + var text = '<foo template>'; + var doc = parse(text, generateSpans: true); + var elem = doc.query('foo'); + + expect(elem.attributeSpans['template'].start.offset, + text.indexOf('template')); + expect(elem.attributeValueSpans.containsKey('template'), false); + }); + + test('attribute spans null if code parsed without spans', () { + var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + var doc = parse(text); + var elem = doc.query('element'); + expect(elem.sourceSpan, null); + expect(elem.attributeSpans['quux'], null); + expect(elem.attributeSpans['extends'], null); + }); + + test('void element innerHTML', () { + var doc = parse('<div></div>'); + expect(doc.body.innerHtml, '<div></div>'); + doc = parse('<body><script></script></body>'); + expect(doc.body.innerHtml, '<script></script>'); + doc = parse('<br>'); + expect(doc.body.innerHtml, '<br>'); + doc = parse('<br><foo><bar>'); + expect(doc.body.innerHtml, '<br><foo><bar></bar></foo>'); + }); + + test('empty document has html, body, and head', () { + var doc = parse(''); + expect(doc.outerHtml, '<html><head></head><body></body></html>'); + expect(doc.head.outerHtml, '<head></head>'); + expect(doc.body.outerHtml, '<body></body>'); + }); + + test('strange table case', () { + var doc = parseFragment('<table><tbody><foo>'); + expect(doc.outerHtml, '<foo></foo><table><tbody></tbody></table>'); + }); + + group('html serialization', () { + test('attribute order', () { + // Note: the spec only requires a stable order. + // However, we preserve the input order via LinkedHashMap + var doc = parseFragment('<foo d=1 a=2 c=3 b=4>'); + expect(doc.outerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); + expect(doc.query('foo').attributes.remove('a'), '2'); + expect(doc.outerHtml, '<foo d="1" c="3" b="4"></foo>'); + doc.query('foo').attributes['a'] = '0'; + expect(doc.outerHtml, '<foo d="1" c="3" b="4" a="0"></foo>'); + }); + + test('escaping Text node in <script>', () { + var doc = parseFragment('<script>a && b</script>'); + expect(doc.outerHtml, '<script>a && b</script>'); + }); + + test('escaping Text node in <span>', () { + var doc = parseFragment('<span>a && b</span>'); + expect(doc.outerHtml, '<span>a &amp;&amp; b</span>'); + }); + + test('Escaping attributes', () { + var doc = parseFragment('<div class="a<b>">'); + expect(doc.outerHtml, '<div class="a<b>"></div>'); + doc = parseFragment('<div class=\'a"b\'>'); + expect(doc.outerHtml, '<div class="a&quot;b"></div>'); + }); + + test('Escaping non-breaking space', () { + var text = '<span>foO\u00A0bar</span>'; + expect(text.codeUnitAt(text.indexOf('O') + 1), 0xA0); + var doc = parseFragment(text); + expect(doc.outerHtml, '<span>foO&nbsp;bar</span>'); + }); + + test('Newline after <pre>', () { + var doc = parseFragment('<pre>\n\nsome text</span>'); + expect(doc.query('pre').nodes[0].value, '\nsome text'); + expect(doc.outerHtml, '<pre>\n\nsome text</pre>'); + + doc = parseFragment('<pre>\nsome text</span>'); + expect(doc.query('pre').nodes[0].value, 'some text'); + expect(doc.outerHtml, '<pre>some text</pre>'); + }); + + test('xml namespaces', () { + // Note: this is a nonsensical example, but it triggers the behavior + // we're looking for with attribute names in foreign content. + var doc = parse(''' + <body> + <svg> + <desc xlink:type="simple" + xlink:href="http://example.com/logo.png" + xlink:show="new"></desc> + '''); + var n = doc.query('desc'); + var keys = n.attributes.keys.toList(); + expect(keys[0], new isInstanceOf<AttributeName>()); + expect(keys[0].prefix, 'xlink'); + expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); + expect(keys[0].name, 'type'); + + expect(n.outerHtml, '<desc xlink:type="simple" ' + 'xlink:href="http://example.com/logo.png" xlink:show="new"></desc>'); + }); + }); + + test('error printing without spans', () { + var parser = new HtmlParser('foo'); + var doc = parser.parse(); + expect(doc.body.innerHtml, 'foo'); + expect(parser.errors.length, 1); + expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars'); + expect(parser.errors[0].message, + 'Unexpected non-space characters. Expected DOCTYPE.'); + expect(parser.errors[0].toString(), + 'ParserError:1:4: Unexpected non-space characters. ' + 'Expected DOCTYPE.'); + }); +} diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart new file mode 100644 index 000000000..01256347d --- /dev/null +++ b/pkgs/html/test/parser_test.dart @@ -0,0 +1,124 @@ +library parser_test; + +import 'dart:io'; +import 'dart:json' as json; +import 'package:path/path.dart' as pathos; +import 'package:unittest/unittest.dart'; +import 'package:html5lib/dom.dart'; +import 'package:html5lib/parser.dart'; +import 'package:html5lib/parser_console.dart' as parser_console; +import 'package:html5lib/src/constants.dart'; +import 'package:html5lib/src/inputstream.dart' as inputstream; +import 'package:html5lib/src/tokenizer.dart'; +import 'package:html5lib/src/utils.dart'; +import 'support.dart'; + +// Run the parse error checks +// TODO(jmesserly): presumably we want this on by default? +final checkParseErrors = false; + +String namespaceHtml(String expected) { + // TODO(jmesserly): this is a workaround for http://dartbug.com/2979 + // We can't do regex replace directly =\ + // final namespaceExpected = new RegExp(@"^(\s*)<(\S+)>", multiLine: true); + // return expected.replaceAll(namespaceExpected, @"$1<html $2>"); + final namespaceExpected = new RegExp(r"^(\|\s*)<(\S+)>"); + var lines = expected.split("\n"); + for (int i = 0; i < lines.length; i++) { + var match = namespaceExpected.firstMatch(lines[i]); + if (match != null) { + lines[i] = "${match[1]}<html ${match[2]}>"; + } + } + return lines.join("\n"); +} + +void runParserTest(String groupName, String innerHTML, String input, + String expected, List errors, TreeBuilderFactory treeCtor, + bool namespaceHTMLElements) { + + // XXX - move this out into the setup function + // concatenate all consecutive character tokens into a single token + var builder = treeCtor(namespaceHTMLElements); + var parser = new HtmlParser(input, tree: builder); + + Node document; + if (innerHTML != null) { + document = parser.parseFragment(innerHTML); + } else { + document = parser.parse(); + } + + var output = testSerializer(document); + + if (namespaceHTMLElements) { + expected = namespaceHtml(expected); + } + + expect(output, equals(expected), reason: + "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); + + if (checkParseErrors) { + expect(parser.errors.length, equals(errors.length), reason: + "\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n" + "${errors.join('\n')}\n\n" + "Actual errors (${parser.errors.length}):\n" + "${parser.errors.map((e) => '$e').join('\n')}"); + } +} + + +void main() { + + test('dart:io', () { + // ensure IO support is unregistered + expect(inputstream.consoleSupport, + new isInstanceOf<inputstream.ConsoleSupport>()); + var file = new File('$testDataDir/parser_feature/raw_file.html').openSync(); + expect(() => parse(file), throwsA(new isInstanceOf<ArgumentError>())); + parser_console.useConsole(); + expect(parse(file).body.innerHtml.trim(), 'Hello world!'); + }); + + for (var path in getDataFiles('tree-construction')) { + if (!path.endsWith('.dat')) continue; + + var tests = new TestData(path, "data"); + var testName = pathos.basenameWithoutExtension(path); + + group(testName, () { + int index = 0; + for (var testData in tests) { + var input = testData['data']; + var errors = testData['errors']; + var innerHTML = testData['document-fragment']; + var expected = testData['document']; + if (errors != null) { + errors = errors.split("\n"); + } + + for (var treeCtor in treeTypes.values) { + for (var namespaceHTMLElements in const [false, true]) { + test(_nameFor(input), () { + runParserTest(testName, innerHTML, input, expected, errors, + treeCtor, namespaceHTMLElements); + }); + } + } + + index++; + } + }); + } +} + +/** Extract the name for the test based on the test input data. */ +_nameFor(String input) { + // Using json.parse to unescape other unicode characters + var escapeQuote = input + .replaceAll(new RegExp('\\\\.'), '_') + .replaceAll(new RegExp('\u0000'), '_') + .replaceAll('"', '\\"') + .replaceAll(new RegExp('[\n\r\t]'),'_'); + return json.parse('"$escapeQuote"'); +} diff --git a/pkgs/html/test/run.sh b/pkgs/html/test/run.sh new file mode 100755 index 000000000..f269bdaa0 --- /dev/null +++ b/pkgs/html/test/run.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright (c) 2012, the Dart project authors. Please see the LICENSE file +# for details. All rights reserved. Use of this source code is governed by a +# MIT-style license that can be found in the LICENSE file. + +# bail on error +set -e + +# TODO(sigmund): replace with a real test runner +DIR=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd ) + +# Note: dart_analyzer needs to be run from the root directory for proper path +# canonicalization. +pushd $DIR/.. +# TODO(jmesserly): switch to new analyzer. Note: it's missing a lot of the +# tests for implemented members; we should get that fixed before switching. +echo Analyzing library for warnings or type errors +dartanalyzer --fatal-warnings --fatal-type-errors lib/*.dart || \ + echo "ignore analyzer errors" +popd + +dart --enable-type-checks --enable-asserts test/run_all.dart $@ diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart new file mode 100644 index 000000000..dcff52417 --- /dev/null +++ b/pkgs/html/test/run_all.dart @@ -0,0 +1,34 @@ +#!/usr/bin/env dart +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library test.run_all; + +import 'dart:io' show Options; +import 'package:unittest/compact_vm_config.dart'; +import 'package:unittest/unittest.dart'; + +import 'dom_test.dart' as dom_test; +import 'parser_feature_test.dart' as parser_feature_test; +import 'parser_test.dart' as parser_test; +import 'tokenizer_test.dart' as tokenizer_test; +import 'dom_compat_test.dart' as dom_compat_test; + +main() { + var args = new Options().arguments; + var pattern = new RegExp(args.length > 0 ? args[0] : '.'); + useCompactVMConfiguration(); + + void addGroup(testFile, testMain) { + if (pattern.hasMatch(testFile)) { + group(testFile.replaceAll('_test.dart', ':'), testMain); + } + } + + addGroup('dom_test.dart', dom_test.main); + addGroup('dom_compat_test.dart', dom_compat_test.main); + addGroup('parser_feature_test.dart', parser_feature_test.main); + addGroup('parser_test.dart', parser_test.main); + addGroup('tokenizer_test.dart', tokenizer_test.main); +} diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart new file mode 100644 index 000000000..c879bf806 --- /dev/null +++ b/pkgs/html/test/support.dart @@ -0,0 +1,168 @@ +/** Support code for the tests in this directory. */ +library support; + +import 'dart:async'; +import 'dart:io'; +import 'dart:collection'; +import 'package:path/path.dart' as path; +import 'package:html5lib/src/treebuilder.dart'; +import 'package:html5lib/dom.dart'; +import 'package:html5lib/dom_parsing.dart'; + +typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements); + +Map _treeTypes; +Map<String, TreeBuilderFactory> get treeTypes { + if (_treeTypes == null) { + // TODO(jmesserly): add DOM here once it's implemented + _treeTypes = { "simpletree": (useNs) => new TreeBuilder(useNs) }; + } + return _treeTypes; +} + +final testDataDir = path.join(path.dirname(new Options().script), 'data'); + +Iterable<String> getDataFiles(String subdirectory) { + var dir = new Directory(path.join(testDataDir, subdirectory)); + return dir.listSync().where((f) => f is File).map((f) => f.path); +} + +// TODO(jmesserly): make this class simpler. We could probably split on +// "\n#" instead of newline and remove a lot of code. +class TestData extends IterableBase<Map> { + final String _text; + final String newTestHeading; + + TestData(String filename, [this.newTestHeading = "data"]) + // Note: can't use readAsLinesSync here because it splits on \r + : _text = new File(filename).readAsStringSync(); + + // Note: in Python this was a generator, but since we can't do that in Dart, + // it's easier to convert it into an upfront computation. + Iterator<Map> get iterator => _getData().iterator; + + List<Map> _getData() { + var data = <String, String>{}; + var key = null; + var result = <Map>[]; + var lines = _text.split('\n'); + int numLines = lines.length; + // Remove trailing newline to match Python + if (lines.last == '') { + lines.removeLast(); + } + for (var line in lines) { + var heading = sectionHeading(line); + if (heading != null) { + if (data.length > 0 && heading == newTestHeading) { + // Remove trailing newline + data[key] = data[key].substring(0, data[key].length - 1); + result.add(normaliseOutput(data)); + data = <String, String>{}; + } + key = heading; + data[key] = ""; + } else if (key != null) { + data[key] = '${data[key]}$line\n'; + } + } + + if (data.length > 0) { + result.add(normaliseOutput(data)); + } + return result; + } + + /** + * If the current heading is a test section heading return the heading, + * otherwise return null. + */ + static String sectionHeading(String line) { + return line.startsWith("#") ? line.substring(1).trim() : null; + } + + static Map normaliseOutput(Map data) { + // Remove trailing newlines + data.forEach((key, value) { + if (value.endsWith("\n")) { + data[key] = value.substring(0, value.length - 1); + } + }); + return data; + } +} + +/** + * Serialize the [document] into the html5 test data format. + */ +testSerializer(Document document) { + return (new TestSerializer()..visit(document)).toString(); +} + +/** Serializes the DOM into test format. See [testSerializer]. */ +class TestSerializer extends TreeVisitor { + final StringBuffer _str; + int _indent = 0; + String _spaces = ''; + + TestSerializer() : _str = new StringBuffer(); + + String toString() => _str.toString(); + + int get indent => _indent; + + set indent(int value) { + if (_indent == value) return; + + var arr = new List<int>(value); + for (int i = 0; i < value; i++) { + arr[i] = 32; + } + _spaces = new String.fromCharCodes(arr); + _indent = value; + } + + void _newline() { + if (_str.length > 0) _str.write('\n'); + _str.write('|$_spaces'); + } + + visitNodeFallback(Node node) { + _newline(); + _str.write(node); + visitChildren(node); + } + + visitChildren(Node node) { + indent += 2; + for (var child in node.nodes) visit(child); + indent -= 2; + } + + visitDocument(Document node) { + indent += 1; + for (var child in node.nodes) visit(child); + indent -= 1; + } + + visitElement(Element node) { + _newline(); + _str.write(node); + if (node.attributes.length > 0) { + indent += 2; + var keys = new List.from(node.attributes.keys); + keys.sort((x, y) => x.compareTo(y)); + for (var key in keys) { + var v = node.attributes[key]; + if (key is AttributeName) { + AttributeName attr = key; + key = "${attr.prefix} ${attr.name}"; + } + _newline(); + _str.write('$key="$v"'); + } + indent -= 2; + } + visitChildren(node); + } +} diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart new file mode 100644 index 000000000..fc98012ef --- /dev/null +++ b/pkgs/html/test/tokenizer_test.dart @@ -0,0 +1,270 @@ +library tokenizer_test; + +// Note: mirrors used to match the getattr usage in the original test +import 'dart:async'; +import 'dart:io'; +import 'dart:json' as json; +import 'dart:mirrors'; +import 'dart:utf'; +import 'package:path/path.dart' as pathos; +import 'package:unittest/unittest.dart'; +import 'package:html5lib/src/char_encodings.dart'; +import 'package:html5lib/src/constants.dart' as constants; +import 'package:html5lib/src/token.dart'; +import 'package:html5lib/src/tokenizer.dart'; +import 'package:html5lib/src/utils.dart'; +import 'support.dart'; + +class TokenizerTestParser { + String _state; + var _lastStartTag; + List outputTokens; + + TokenizerTestParser(String initialState, [lastStartTag]) + : _state = initialState, + _lastStartTag = lastStartTag; + + List parse(String str) { + // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. + var bytes = codepointsToUtf8(toCodepoints(str)); + var tokenizer = new HtmlTokenizer(bytes, encoding: 'utf-8'); + outputTokens = []; + + // Note: we can't get a closure of the state method. However, we can + // create a new closure to invoke it via mirrors. + var mtok = reflect(tokenizer); + tokenizer.state = () => deprecatedFutureValue( + mtok.invokeAsync(new Symbol(_state), const [])).reflectee; + + if (_lastStartTag != null) { + tokenizer.currentToken = new StartTagToken(_lastStartTag); + } + + while (tokenizer.moveNext()) { + var token = tokenizer.current; + switch (token.kind) { + case TokenKind.characters: + processCharacters(token); + break; + case TokenKind.spaceCharacters: + processSpaceCharacters(token); + break; + case TokenKind.startTag: + processStartTag(token); + break; + case TokenKind.endTag: + processEndTag(token); + break; + case TokenKind.comment: + processComment(token); + break; + case TokenKind.doctype: + processDoctype(token); + break; + case TokenKind.parseError: + processParseError(token); + break; + } + } + + return outputTokens; + } + + void processDoctype(DoctypeToken token) { + outputTokens.add(["DOCTYPE", token.name, token.publicId, + token.systemId, token.correct]); + } + + void processStartTag(StartTagToken token) { + outputTokens.add(["StartTag", token.name, token.data, token.selfClosing]); + } + + void processEndTag(EndTagToken token) { + outputTokens.add(["EndTag", token.name, token.selfClosing]); + } + + void processComment(StringToken token) { + outputTokens.add(["Comment", token.data]); + } + + void processSpaceCharacters(StringToken token) { + processCharacters(token); + } + + void processCharacters(StringToken token) { + outputTokens.add(["Character", token.data]); + } + + void processEOF(token) { + } + + void processParseError(StringToken token) { + // TODO(jmesserly): when debugging test failures it can be useful to add + // logging here like `print('ParseError $token');`. It would be nice to + // use the actual logging library. + outputTokens.add(["ParseError", token.data]); + } +} + +List concatenateCharacterTokens(List tokens) { + var outputTokens = []; + for (var token in tokens) { + if (token.indexOf("ParseError") == -1 && token[0] == "Character") { + if (outputTokens.length > 0 && + outputTokens.last.indexOf("ParseError") == -1 && + outputTokens.last[0] == "Character") { + + outputTokens.last[1] = '${outputTokens.last[1]}${token[1]}'; + } else { + outputTokens.add(token); + } + } else { + outputTokens.add(token); + } + } + return outputTokens; +} + +List normalizeTokens(List tokens) { + // TODO: convert tests to reflect arrays + for (int i = 0; i < tokens.length; i++) { + var token = tokens[i]; + if (token[0] == 'ParseError') { + tokens[i] = token[0]; + } + } + return tokens; +} + + +/** + * Test whether the test has passed or failed + * + * If the ignoreErrorOrder flag is set to true we don't test the relative + * positions of parse errors and non parse errors. + */ +void expectTokensMatch(List expectedTokens, List receivedTokens, + bool ignoreErrorOrder, [bool ignoreErrors = false, String message]) { + + var checkSelfClosing = false; + for (var token in expectedTokens) { + if (token[0] == "StartTag" && token.length == 4 + || token[0] == "EndTag" && token.length == 3) { + checkSelfClosing = true; + break; + } + } + + if (!checkSelfClosing) { + for (var token in receivedTokens) { + if (token[0] == "StartTag" || token[0] == "EndTag") { + token.removeLast(); + } + } + } + + if (!ignoreErrorOrder && !ignoreErrors) { + expect(receivedTokens, equals(expectedTokens), reason: message); + } else { + // Sort the tokens into two groups; non-parse errors and parse errors + var expectedNonErrors = expectedTokens.where((t) => t != "ParseError"); + var receivedNonErrors = receivedTokens.where((t) => t != "ParseError"); + + expect(receivedNonErrors, equals(expectedNonErrors), reason: message); + if (!ignoreErrors) { + var expectedParseErrors = expectedTokens.where((t) => t == "ParseError"); + var receivedParseErrors = receivedTokens.where((t) => t == "ParseError"); + expect(receivedParseErrors, equals(expectedParseErrors), reason: message); + } + } +} + +void runTokenizerTest(Map testInfo) { + // XXX - move this out into the setup function + // concatenate all consecutive character tokens into a single token + if (testInfo.containsKey('doubleEscaped')) { + testInfo = unescape(testInfo); + } + + var expected = concatenateCharacterTokens(testInfo['output']); + if (!testInfo.containsKey('lastStartTag')) { + testInfo['lastStartTag'] = null; + } + var parser = new TokenizerTestParser(testInfo['initialState'], + testInfo['lastStartTag']); + var tokens = parser.parse(testInfo['input']); + tokens = concatenateCharacterTokens(tokens); + var received = normalizeTokens(tokens); + var errorMsg = ["\n\nInitial state:", + testInfo['initialState'], + "\nInput:", testInfo['input'], + "\nExpected:", expected, + "\nreceived:", tokens].map((s) => '$s').join('\n'); + var ignoreErrorOrder = testInfo['ignoreErrorOrder']; + if (ignoreErrorOrder == null) ignoreErrorOrder = false; + + expectTokensMatch(expected, received, ignoreErrorOrder, true, errorMsg); +} + +Map unescape(Map testInfo) { + // TODO(sigmundch,jmesserly): we currently use json.parse to unescape the + // unicode characters in the string, we should use a decoding that works with + // any control characters. + decode(inp) => inp == '\u0000' ? inp : json.parse('"$inp"'); + + testInfo["input"] = decode(testInfo["input"]); + for (var token in testInfo["output"]) { + if (token == "ParseError") { + continue; + } else { + token[1] = decode(token[1]); + if (token.length > 2) { + for (var pair in token[2]) { + var key = pair[0]; + var value = pair[1]; + token[2].remove(key); + token[2][decode(key)] = decode(value); + } + } + } + } + return testInfo; +} + + +String camelCase(String s) { + s = s.toLowerCase(); + var result = new StringBuffer(); + for (var match in new RegExp(r"\W+(\w)(\w+)").allMatches(s)) { + if (result.length == 0) result.write(s.substring(0, match.start)); + result.write(match.group(1).toUpperCase()); + result.write(match.group(2)); + } + return result.toString(); +} + +void main() { + for (var path in getDataFiles('tokenizer')) { + if (!path.endsWith('.test')) continue; + + var text = new File(path).readAsStringSync(); + var tests = json.parse(text); + var testName = pathos.basenameWithoutExtension(path); + var testList = tests['tests']; + if (testList == null) continue; + + group(testName, () { + for (int index = 0; index < testList.length; index++) { + final testInfo = testList[index]; + + testInfo.putIfAbsent("initialStates", () => ["Data state"]); + for (var initialState in testInfo["initialStates"]) { + test(testInfo["description"], () { + testInfo["initialState"] = camelCase(initialState); + runTokenizerTest(testInfo); + }); + } + } + }); + } +} From cf0eba1b367d12c5bcb53ae229c23b90918f4865 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Wed, 14 Aug 2013 22:09:44 +0000 Subject: [PATCH 002/212] html5lib -- workaround dart2js checked issues Review URL: https://codereview.chromium.org//23221002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@26161 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/src/tokenizer.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index ee867b7cc..2c2ada79d 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -59,7 +59,9 @@ class HtmlTokenizer implements Iterator<Token> { /** * Holds a reference to the method to be invoked for the next parser state. */ - Predicate state; + // TODO(jmesserly): the type should be "Predicate" but a dart2js checked mode + // bug prevents us from doing that. See http://dartbug.com/12465 + Function state; String temporaryBuffer; From 72c0bd6bdf0f323c08ffcbdf6adc1a2a32132c8f Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" <floitsch@google.com> Date: Wed, 28 Aug 2013 15:39:35 +0000 Subject: [PATCH 003/212] Remove use of dart:json from third_party. R=jmesserly@google.com Review URL: https://codereview.chromium.org//23540004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@26795 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/parser_test.dart | 6 +++--- pkgs/html/test/tokenizer_test.dart | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 01256347d..ba1ea3ef7 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -1,7 +1,7 @@ library parser_test; +import 'dart:convert; import 'dart:io'; -import 'dart:json' as json; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; import 'package:html5lib/dom.dart'; @@ -114,11 +114,11 @@ void main() { /** Extract the name for the test based on the test input data. */ _nameFor(String input) { - // Using json.parse to unescape other unicode characters + // Using JSON.decode to unescape other unicode characters var escapeQuote = input .replaceAll(new RegExp('\\\\.'), '_') .replaceAll(new RegExp('\u0000'), '_') .replaceAll('"', '\\"') .replaceAll(new RegExp('[\n\r\t]'),'_'); - return json.parse('"$escapeQuote"'); + return JSON.decode('"$escapeQuote"'); } diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index fc98012ef..e3d08e6d3 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -2,8 +2,8 @@ library tokenizer_test; // Note: mirrors used to match the getattr usage in the original test import 'dart:async'; +import 'dart:convert'; import 'dart:io'; -import 'dart:json' as json; import 'dart:mirrors'; import 'dart:utf'; import 'package:path/path.dart' as pathos; @@ -207,10 +207,10 @@ void runTokenizerTest(Map testInfo) { } Map unescape(Map testInfo) { - // TODO(sigmundch,jmesserly): we currently use json.parse to unescape the + // TODO(sigmundch,jmesserly): we currently use JSON.decode to unescape the // unicode characters in the string, we should use a decoding that works with // any control characters. - decode(inp) => inp == '\u0000' ? inp : json.parse('"$inp"'); + decode(inp) => inp == '\u0000' ? inp : JSON.decode('"$inp"'); testInfo["input"] = decode(testInfo["input"]); for (var token in testInfo["output"]) { @@ -248,7 +248,7 @@ void main() { if (!path.endsWith('.test')) continue; var text = new File(path).readAsStringSync(); - var tests = json.parse(text); + var tests = JSON.decode(text); var testName = pathos.basenameWithoutExtension(path); var testList = tests['tests']; if (testList == null) continue; From 6a20b1f4f7d80a6d6607eecc2074145e94344562 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" <floitsch@google.com> Date: Wed, 28 Aug 2013 15:40:46 +0000 Subject: [PATCH 004/212] Remove dart:utf in third_party. R=jmesserly@google.com Review URL: https://codereview.chromium.org//23493006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@26796 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom_parsing.dart | 2 +- pkgs/html/lib/src/char_encodings.dart | 2 +- pkgs/html/lib/src/inputstream.dart | 2 +- pkgs/html/pubspec.yaml | 1 + pkgs/html/test/tokenizer_test.dart | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 91b37ece7..363db7dfc 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -5,7 +5,7 @@ library dom_parsing; import 'dart:math'; -import 'dart:utf' show codepointsToString; +import 'package:utf/utf.dart' show codepointsToString; import 'dom.dart'; /** A simple tree visitor for the DOM nodes. */ diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 610a8da9c..7fce8fdc3 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -2,7 +2,7 @@ library char_encodings; import 'dart:collection'; -import 'dart:utf'; +import 'package:utf/utf.dart'; // TODO(jmesserly): this function is conspicuously absent from dart:utf. /** diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index 29ee1dcbc..a3d604674 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -1,7 +1,7 @@ library inputstream; import 'dart:collection'; -import 'dart:utf'; +import 'package:utf/utf.dart'; import 'package:source_maps/span.dart' show SourceFile; import 'char_encodings.dart'; import 'constants.dart'; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 79a09be83..cd968ae38 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -4,6 +4,7 @@ description: A library for working with HTML documents. homepage: https://github.com/dart-lang/html5lib dependencies: source_maps: any + utf: any dev_dependencies: browser: any path: any diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index e3d08e6d3..637cc9a68 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -5,7 +5,6 @@ import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:mirrors'; -import 'dart:utf'; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; import 'package:html5lib/src/char_encodings.dart'; @@ -13,6 +12,7 @@ import 'package:html5lib/src/constants.dart' as constants; import 'package:html5lib/src/token.dart'; import 'package:html5lib/src/tokenizer.dart'; import 'package:html5lib/src/utils.dart'; +import 'package:utf/utf.dart'; import 'support.dart'; class TokenizerTestParser { From d1c7b67ce5de0637ff755360b435316dc9370f08 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" <floitsch@google.com> Date: Wed, 28 Aug 2013 15:57:30 +0000 Subject: [PATCH 005/212] Fix missing quote. Review URL: https://codereview.chromium.org//23532008 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@26797 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/parser_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index ba1ea3ef7..060359c37 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -1,6 +1,6 @@ library parser_test; -import 'dart:convert; +import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; From 2f4e900089b141d72d99457c16860aea2d256254 Mon Sep 17 00:00:00 2001 From: "floitsch@google.com" <floitsch@google.com> Date: Wed, 4 Sep 2013 13:15:59 +0000 Subject: [PATCH 006/212] remove use of deprecatedFutureValue from html5lib R=floitsch@google.com Review URL: https://codereview.chromium.org//23480032 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@27122 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/tokenizer_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 637cc9a68..b9e43fedb 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -33,8 +33,8 @@ class TokenizerTestParser { // Note: we can't get a closure of the state method. However, we can // create a new closure to invoke it via mirrors. var mtok = reflect(tokenizer); - tokenizer.state = () => deprecatedFutureValue( - mtok.invokeAsync(new Symbol(_state), const [])).reflectee; + tokenizer.state = () => + mtok.invoke(new Symbol(_state), const []).reflectee; if (_lastStartTag != null) { tokenizer.currentToken = new StartTagToken(_lastStartTag); From 2c5c298193d67d41b29d0f4a300342d5d3804390 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" <lrn@google.com> Date: Thu, 3 Oct 2013 11:09:01 +0000 Subject: [PATCH 007/212] Add List.shuffle(). Will add tests too. R=floitsch@google.com Review URL: https://codereview.chromium.org//24740003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@28206 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/src/list_proxy.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 99adb3fdb..786e39373 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -51,6 +51,7 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void addLast(E value) { add(value); } void addAll(Iterable<E> collection) { _list.addAll(collection); } void sort([int compare(E a, E b)]) { _list.sort(compare); } + void shuffle() { _list.shuffle(); } int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); From b297907cf431486062585a65fbe9e77fed7d9785 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" <lrn@google.com> Date: Mon, 7 Oct 2013 12:07:30 +0000 Subject: [PATCH 008/212] Make List.shuffle take an optional Random object to use. R=floitsch@google.com Review URL: https://codereview.chromium.org//25931003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@28305 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/src/list_proxy.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 786e39373..d779043cd 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -5,6 +5,7 @@ library list_proxy; import 'dart:collection'; +import 'dart:math' show Random; // TOOD(jmesserly): this needs to be removed, but fixing NodeList is tricky. class ListProxy<E> extends IterableBase<E> implements List<E> { @@ -51,7 +52,7 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void addLast(E value) { add(value); } void addAll(Iterable<E> collection) { _list.addAll(collection); } void sort([int compare(E a, E b)]) { _list.sort(compare); } - void shuffle() { _list.shuffle(); } + void shuffle([Random random]) { _list.shuffle(random); } int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); From 5626969f1eeaf5f5e0e30da8251bac7333b3342e Mon Sep 17 00:00:00 2001 From: "whesse@google.com" <whesse@google.com> Date: Wed, 30 Oct 2013 15:17:01 +0000 Subject: [PATCH 009/212] Remove uses of Options from pkg, samples, tests, and third_party directories. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//52573002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29552 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/run_all.dart | 3 +-- pkgs/html/test/support.dart | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart index dcff52417..b1490983c 100644 --- a/pkgs/html/test/run_all.dart +++ b/pkgs/html/test/run_all.dart @@ -15,8 +15,7 @@ import 'parser_test.dart' as parser_test; import 'tokenizer_test.dart' as tokenizer_test; import 'dom_compat_test.dart' as dom_compat_test; -main() { - var args = new Options().arguments; +main(List<String> args) { var pattern = new RegExp(args.length > 0 ? args[0] : '.'); useCompactVMConfiguration(); diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index c879bf806..22b0f4808 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -20,7 +20,7 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDataDir = path.join(path.dirname(new Options().script), 'data'); +final testDataDir = path.join(path.dirname(Platform.script), 'data'); Iterable<String> getDataFiles(String subdirectory) { var dir = new Directory(path.join(testDataDir, subdirectory)); From d4437a96e5da25cef2859cc3758468cf71d2b7c3 Mon Sep 17 00:00:00 2001 From: "sethladd@google.com" <sethladd@google.com> Date: Wed, 30 Oct 2013 22:36:58 +0000 Subject: [PATCH 010/212] change homepage for html5lib BUG= R=jmesserly@google.com Review URL: https://codereview.chromium.org//53173003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29602 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index cd968ae38..6a2a57f28 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,7 +1,7 @@ name: html5lib author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. -homepage: https://github.com/dart-lang/html5lib +homepage: http://pub.dartlang.org/packages/html5lib dependencies: source_maps: any utf: any From 3a00df81b5bfe0850a9a11909a7b5044ea3e5901 Mon Sep 17 00:00:00 2001 From: "whesse@google.com" <whesse@google.com> Date: Thu, 31 Oct 2013 01:08:11 +0000 Subject: [PATCH 011/212] Change dart:io Platform.script to return a URI. Change all uses of Platform.script to work with the new value. R=floitsch@google.com Review URL: https://codereview.chromium.org//53313007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29619 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/support.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 22b0f4808..f894aa4a4 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -20,7 +20,7 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDataDir = path.join(path.dirname(Platform.script), 'data'); +final testDataDir = Platform.script.resolve('data').toFilePath(); Iterable<String> getDataFiles(String subdirectory) { var dir = new Directory(path.join(testDataDir, subdirectory)); From e838f04a37d4717e500078c5dfeef206f7d63639 Mon Sep 17 00:00:00 2001 From: "whesse@google.com" <whesse@google.com> Date: Thu, 31 Oct 2013 02:17:37 +0000 Subject: [PATCH 012/212] Revert "Change dart:io Platform.script to return a Uri." This reverts r29619 and r29624. The changes look fine on the buildbot, but need review before adding to the repository. BUG= TBR=sgjesse@google.com Review URL: https://codereview.chromium.org//52723007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29627 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/support.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index f894aa4a4..22b0f4808 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -20,7 +20,7 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDataDir = Platform.script.resolve('data').toFilePath(); +final testDataDir = path.join(path.dirname(Platform.script), 'data'); Iterable<String> getDataFiles(String subdirectory) { var dir = new Directory(path.join(testDataDir, subdirectory)); From 3cb0a0e80977d86bdd2ca72bcad775bf3425cd44 Mon Sep 17 00:00:00 2001 From: "sgjesse@google.com" <sgjesse@google.com> Date: Thu, 31 Oct 2013 07:29:01 +0000 Subject: [PATCH 013/212] Change dart:io Platform.script to return a Uri. BUG= R=sgjesse@google.com Review URL: https://codereview.chromium.org//46063010 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29651 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/support.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 22b0f4808..f894aa4a4 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -20,7 +20,7 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDataDir = path.join(path.dirname(Platform.script), 'data'); +final testDataDir = Platform.script.resolve('data').toFilePath(); Iterable<String> getDataFiles(String subdirectory) { var dir = new Directory(path.join(testDataDir, subdirectory)); From 33f4422c3bc5e194689a785d6ae67adbe9a01c9a Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Wed, 6 Nov 2013 03:27:58 +0000 Subject: [PATCH 014/212] add versions and constraints for packages and samples - all packages at 0.9.0, except "analyzer" which had a version already - dependencies at ">=0.9.0 <0.10.0" except analyzer is ">=0.10.0 <0.11.0" - sdk constraint ">=1.0.0 <2.0.0" R=sigmund@google.com Review URL: https://codereview.chromium.org//59763006 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29957 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 6a2a57f28..333133332 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,11 +1,14 @@ name: html5lib +version: 0.9.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib dependencies: - source_maps: any - utf: any + source_maps: ">=0.9.0 <0.10.0" + utf: ">=0.9.0 <0.10.0" dev_dependencies: - browser: any - path: any - unittest: any + browser: ">=0.9.0 <0.10.0" + path: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=1.0.0 <2.0.0" From 655df968ec7f9a41622783467f6775fdd97bc3a5 Mon Sep 17 00:00:00 2001 From: "ajohnsen@google.com" <ajohnsen@google.com> Date: Wed, 6 Nov 2013 09:09:18 +0000 Subject: [PATCH 015/212] Revert "add versions and constraints for packages and samples" This is currently blocking us from testing samples. BUG= R=kasperl@google.com Review URL: https://codereview.chromium.org//59513007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29960 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 333133332..6a2a57f28 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,14 +1,11 @@ name: html5lib -version: 0.9.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib dependencies: - source_maps: ">=0.9.0 <0.10.0" - utf: ">=0.9.0 <0.10.0" + source_maps: any + utf: any dev_dependencies: - browser: ">=0.9.0 <0.10.0" - path: ">=0.9.0 <0.10.0" - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + browser: any + path: any + unittest: any From 1e1f98e5b740fa665ae290df19ec8186d53e119d Mon Sep 17 00:00:00 2001 From: "dgrove@google.com" <dgrove@google.com> Date: Wed, 6 Nov 2013 18:28:22 +0000 Subject: [PATCH 016/212] Re-land r29957 (add versions and constraints for packages and samples), with SDK constraints bumped from 1.0.0 to 0.8.10+6 . R=ricow@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//62473002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@29986 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 6a2a57f28..728b00886 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,11 +1,14 @@ name: html5lib +version: 0.9.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib dependencies: - source_maps: any - utf: any + source_maps: ">=0.9.0 <0.10.0" + utf: ">=0.9.0 <0.10.0" dev_dependencies: - browser: any - path: any - unittest: any + browser: ">=0.9.0 <0.10.0" + path: ">=0.9.0 <0.10.0" + unittest: ">=0.9.0 <0.10.0" +environment: + sdk: ">=0.8.10+6 <2.0.0" From 4bdd3864610f890bc9544366493772180ced0708 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Wed, 20 Nov 2013 22:13:52 +0000 Subject: [PATCH 017/212] fix script tags -- remove special case handling for polymer-element also enforce one-dart-script-per-document rule also fixes bug about inlining all content, not just polymer-element R=sigmund@google.com Review URL: https://codereview.chromium.org//78663004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@30486 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 2 ++ pkgs/html/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index d73edaac3..1c0b6de94 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -181,6 +181,8 @@ abstract class Node { nodes.addAll(parseFragment(value, container: tagName).nodes); } + Node get firstChild => nodes.isNotEmpty ? nodes[0] : null; + void _addOuterHtml(StringBuffer str); void _addInnerHtml(StringBuffer str) { diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 728b00886..0e543661e 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.9.0 +version: 0.9.1-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib From e8e4c3a7e3b2d9d3b5592001deca9cc8f6668f49 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Fri, 22 Nov 2013 23:25:39 +0000 Subject: [PATCH 018/212] bump pubspecs for package release R=sigmund@google.com Review URL: https://codereview.chromium.org//83403004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@30597 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 0e543661e..955132dfd 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.9.1-dev +version: 0.9.1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib @@ -11,4 +11,4 @@ dev_dependencies: path: ">=0.9.0 <0.10.0" unittest: ">=0.9.0 <0.10.0" environment: - sdk: ">=0.8.10+6 <2.0.0" + sdk: ">=1.0.0 <2.0.0" From 871c4aa8442b551fa33e62658e30337de5bd88fb Mon Sep 17 00:00:00 2001 From: "kevmoo@google.com" <kevmoo@google.com> Date: Mon, 10 Feb 2014 23:52:45 +0000 Subject: [PATCH 019/212] pkg/third_party/html5lib: lots of cleanup make a lot of things constants updated pub dependencies unused imports R=jmesserly@google.com Review URL: https://codereview.chromium.org//157983005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32528 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 1 - pkgs/html/lib/dom_parsing.dart | 2 - pkgs/html/lib/parser.dart | 1 - pkgs/html/lib/src/constants.dart | 121 ++++++++++++------------ pkgs/html/lib/src/encoding_parser.dart | 1 - pkgs/html/lib/src/tokenizer.dart | 1 - pkgs/html/lib/src/treebuilder.dart | 7 +- pkgs/html/lib/src/utils.dart | 1 - pkgs/html/pubspec.yaml | 16 ++-- pkgs/html/test/dom_compat_test.dart | 1 - pkgs/html/test/dom_test.dart | 1 - pkgs/html/test/parser_feature_test.dart | 2 - pkgs/html/test/parser_test.dart | 3 - pkgs/html/test/run_all.dart | 1 - pkgs/html/test/support.dart | 1 - pkgs/html/test/tokenizer_test.dart | 3 - 16 files changed, 70 insertions(+), 93 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 1c0b6de94..0507c702b 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -11,7 +11,6 @@ import 'src/constants.dart'; import 'src/list_proxy.dart'; import 'src/token.dart'; import 'src/tokenizer.dart'; -import 'src/treebuilder.dart'; import 'src/utils.dart'; import 'dom_parsing.dart'; import 'parser.dart'; diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 363db7dfc..3ff74bb98 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -4,8 +4,6 @@ */ library dom_parsing; -import 'dart:math'; -import 'package:utf/utf.dart' show codepointsToString; import 'dom.dart'; /** A simple tree visitor for the DOM nodes. */ diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 268053a78..4e5e6d563 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -26,7 +26,6 @@ import 'src/token.dart'; import 'src/tokenizer.dart'; import 'src/utils.dart'; import 'dom.dart'; -import 'dom_parsing.dart'; /** * Parse the [input] html5 document into a tree. The [input] can be diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 319ef3e6d..9cc03ad80 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -1,7 +1,6 @@ library constants; import 'utils.dart'; -import 'token.dart'; // TODO(jmesserly): fix up the const lists. For the bigger ones, we need faster // lookup than linear search "contains". In the Python code they were @@ -22,7 +21,7 @@ class ReparseException implements Exception { * string formatting, as implemented by [formatStr]. That function only supports * the subset of format functionality used here. */ -final Map<String, String> errorMessages = const { +const Map<String, String> errorMessages = const { "null-character": "Null character in input stream, replaced with U+FFFD.", "invalid-codepoint": @@ -324,7 +323,7 @@ class Namespaces { } } -final List scopingElements = const [ +const List scopingElements = const [ const Pair(Namespaces.html, "applet"), const Pair(Namespaces.html, "caption"), const Pair(Namespaces.html, "html"), @@ -345,7 +344,7 @@ final List scopingElements = const [ ]; -final formattingElements = const [ +const formattingElements = const [ const Pair(Namespaces.html, "a"), const Pair(Namespaces.html, "b"), const Pair(Namespaces.html, "big"), @@ -362,7 +361,7 @@ final formattingElements = const [ const Pair(Namespaces.html, "") ]; -final specialElements = const [ +const specialElements = const [ const Pair(Namespaces.html, "address"), const Pair(Namespaces.html, "applet"), const Pair(Namespaces.html, "area"), @@ -445,14 +444,14 @@ final specialElements = const [ const Pair(Namespaces.svg, "foreignObject") ]; -final htmlIntegrationPointElements = const [ +const htmlIntegrationPointElements = const [ const Pair(Namespaces.mathml, "annotaion-xml"), const Pair(Namespaces.svg, "foreignObject"), const Pair(Namespaces.svg, "desc"), const Pair(Namespaces.svg, "title") ]; -final mathmlTextIntegrationPointElements = const [ +const mathmlTextIntegrationPointElements = const [ const Pair(Namespaces.mathml, "mi"), const Pair(Namespaces.mathml, "mo"), const Pair(Namespaces.mathml, "mn"), @@ -460,7 +459,7 @@ final mathmlTextIntegrationPointElements = const [ const Pair(Namespaces.mathml, "mtext") ]; -final spaceCharacters = " \n\r\t\u000C"; +const spaceCharacters = " \n\r\t\u000C"; const int NEWLINE = 10; const int RETURN = 13; @@ -482,7 +481,7 @@ bool isWhitespaceCC(int charCode) { return false; } -final List<String> tableInsertModeElements = const [ +const List<String> tableInsertModeElements = const [ "table", "tbody", "tfoot", @@ -491,13 +490,13 @@ final List<String> tableInsertModeElements = const [ ]; // TODO(jmesserly): remove these in favor of the test functions -final asciiLetters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; +const asciiLetters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; -final ZERO = 48; -final LOWER_A = 97; -final LOWER_Z = 122; -final UPPER_A = 65; -final UPPER_Z = 90; +const ZERO = 48; +const LOWER_A = 97; +const LOWER_Z = 122; +const UPPER_A = 65; +const UPPER_Z = 90; bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char); @@ -542,7 +541,7 @@ String asciiUpper2Lower(String text) { } // Heading elements need to be ordered -final headingElements = const [ +const headingElements = const [ "h1", "h2", "h3", @@ -551,9 +550,9 @@ final headingElements = const [ "h6" ]; -final cdataElements = const ['title', 'textarea']; +const cdataElements = const ['title', 'textarea']; -final rcdataElements = const [ +const rcdataElements = const [ 'style', 'script', 'xmp', @@ -563,7 +562,7 @@ final rcdataElements = const [ 'noscript' ]; -final Map<String, List<String>> booleanAttributes = const { +const Map<String, List<String>> booleanAttributes = const { "": const ["irrelevant",], "style": const ["scoped",], "img": const ["ismap",], @@ -586,7 +585,7 @@ final Map<String, List<String>> booleanAttributes = const { // entitiesWindows1252 has to be _ordered_ and needs to have an index. It // therefore can't be a frozenset. -final List<int> entitiesWindows1252 = const [ +const List<int> entitiesWindows1252 = const [ 8364, // 0x80 0x20AC EURO SIGN 65533, // 0x81 UNDEFINED 8218, // 0x82 0x201A SINGLE LOW-9 QUOTATION MARK @@ -621,9 +620,9 @@ final List<int> entitiesWindows1252 = const [ 376 // 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS ]; -final xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; +const xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; -final Map<String, String> entities = const { +const Map<String, String> entities = const { "AElig": "\xc6", "AElig;": "\xc6", "AMP": "&", @@ -2857,48 +2856,44 @@ final Map<String, String> entities = const { "zwnj;": "\u200c", }; -Map<int, String> replacementCharacters = (() { - // TODO(jmesserly): fix this when Dart has literal maps with int keys. - var r = new Map<int, String>(); - r[0x00] = "\uFFFD"; - r[0x0d] = "\u000D"; - r[0x80] = "\u20AC"; - r[0x81] = "\u0081"; - r[0x81] = "\u0081"; - r[0x82] = "\u201A"; - r[0x83] = "\u0192"; - r[0x84] = "\u201E"; - r[0x85] = "\u2026"; - r[0x86] = "\u2020"; - r[0x87] = "\u2021"; - r[0x88] = "\u02C6"; - r[0x89] = "\u2030"; - r[0x8A] = "\u0160"; - r[0x8B] = "\u2039"; - r[0x8C] = "\u0152"; - r[0x8D] = "\u008D"; - r[0x8E] = "\u017D"; - r[0x8F] = "\u008F"; - r[0x90] = "\u0090"; - r[0x91] = "\u2018"; - r[0x92] = "\u2019"; - r[0x93] = "\u201C"; - r[0x94] = "\u201D"; - r[0x95] = "\u2022"; - r[0x96] = "\u2013"; - r[0x97] = "\u2014"; - r[0x98] = "\u02DC"; - r[0x99] = "\u2122"; - r[0x9A] = "\u0161"; - r[0x9B] = "\u203A"; - r[0x9C] = "\u0153"; - r[0x9D] = "\u009D"; - r[0x9E] = "\u017E"; - r[0x9F] = "\u0178"; - return r; -})(); +const Map<int, String> replacementCharacters = const { + 0x00: "\uFFFD", + 0x0d: "\u000D", + 0x80: "\u20AC", + 0x81: "\u0081", + 0x82: "\u201A", + 0x83: "\u0192", + 0x84: "\u201E", + 0x85: "\u2026", + 0x86: "\u2020", + 0x87: "\u2021", + 0x88: "\u02C6", + 0x89: "\u2030", + 0x8A: "\u0160", + 0x8B: "\u2039", + 0x8C: "\u0152", + 0x8D: "\u008D", + 0x8E: "\u017D", + 0x8F: "\u008F", + 0x90: "\u0090", + 0x91: "\u2018", + 0x92: "\u2019", + 0x93: "\u201C", + 0x94: "\u201D", + 0x95: "\u2022", + 0x96: "\u2013", + 0x97: "\u2014", + 0x98: "\u02DC", + 0x99: "\u2122", + 0x9A: "\u0161", + 0x9B: "\u203A", + 0x9C: "\u0153", + 0x9D: "\u009D", + 0x9E: "\u017E", + 0x9F: "\u0178" +}; -final Map<String, String> encodings = const { +const Map<String, String> encodings = const { '437': 'cp437', '850': 'cp850', '852': 'cp852', diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 7b0edb8ad..297e3f585 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -3,7 +3,6 @@ library encoding_parser; import 'dart:collection'; import 'constants.dart'; import 'inputstream.dart'; -import 'utils.dart'; // TODO(jmesserly): I converted StopIteration to StateError("No more elements"). // Seems strange to throw this from outside of an iterator though. diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 2c2ada79d..3f398e997 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1,7 +1,6 @@ library tokenizer; import 'dart:collection'; -import 'dart:math'; import 'package:html5lib/parser.dart' show HtmlParser; import 'package:source_maps/span.dart' show Span, FileSpan; import 'constants.dart'; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index bb53d5850..adde3bf15 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -12,7 +12,7 @@ import 'utils.dart'; // The scope markers are inserted when entering object elements, // marquees, table cells, and table captions, and are used to prevent formatting // from "leaking" into tables, object elements, and marquees. -final Node Marker = null; +const Node Marker = null; // TODO(jmesserly): this should extend ListBase<Node>, but my simple attempt // didn't work. @@ -130,7 +130,8 @@ class TreeBuilder { const Pair(Namespaces.html, "option")]; invert = true; break; - default: assert(false); break; + default: + throw new StateError('We should never reach this point'); } } @@ -145,7 +146,7 @@ class TreeBuilder { } } - assert(false); // We should never reach this point + throw new StateError('We should never reach this point'); } void reconstructActiveFormattingElements() { diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index ca81a414c..1a2bb9d6d 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -1,7 +1,6 @@ /** Misc things that were useful when porting the code from Python. */ library utils; -import 'dart:collection'; import 'constants.dart'; typedef bool Predicate(); diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 955132dfd..1ce662479 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,14 +1,14 @@ name: html5lib -version: 0.9.1 +version: 0.9.2-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib +environment: + sdk: '>=1.0.0 <2.0.0' dependencies: - source_maps: ">=0.9.0 <0.10.0" - utf: ">=0.9.0 <0.10.0" + source_maps: '>=0.9.0 <0.10.0' + utf: '>=0.9.0 <0.10.0' dev_dependencies: - browser: ">=0.9.0 <0.10.0" - path: ">=0.9.0 <0.10.0" - unittest: ">=0.9.0 <0.10.0" -environment: - sdk: ">=1.0.0 <2.0.0" + browser: '>=0.9.0 <0.10.0' + path: '>=0.9.0 <2.0.0' + unittest: '>=0.9.0 <0.11.0' diff --git a/pkgs/html/test/dom_compat_test.dart b/pkgs/html/test/dom_compat_test.dart index f95659bc0..896576e31 100644 --- a/pkgs/html/test/dom_compat_test.dart +++ b/pkgs/html/test/dom_compat_test.dart @@ -1,6 +1,5 @@ library dom_compat_test; -import 'dart:async'; import 'dart:io'; import 'package:unittest/unittest.dart'; import 'package:unittest/compact_vm_config.dart'; diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 8b339f0da..5d026e269 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -3,7 +3,6 @@ library dom_test; import 'package:unittest/unittest.dart'; import 'package:html5lib/parser.dart'; -import 'package:html5lib/dom.dart'; main() { group('Node.query type selectors', () { diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 32269c324..ddcc0ca01 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -3,10 +3,8 @@ library parser_feature_test; import 'package:unittest/unittest.dart'; import 'package:html5lib/dom.dart'; -import 'package:html5lib/dom_parsing.dart'; import 'package:html5lib/parser.dart'; import 'package:html5lib/src/constants.dart'; -import 'package:html5lib/src/tokenizer.dart'; import 'package:html5lib/src/treebuilder.dart'; main() { diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 060359c37..dbfb3fc0b 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -7,10 +7,7 @@ import 'package:unittest/unittest.dart'; import 'package:html5lib/dom.dart'; import 'package:html5lib/parser.dart'; import 'package:html5lib/parser_console.dart' as parser_console; -import 'package:html5lib/src/constants.dart'; import 'package:html5lib/src/inputstream.dart' as inputstream; -import 'package:html5lib/src/tokenizer.dart'; -import 'package:html5lib/src/utils.dart'; import 'support.dart'; // Run the parse error checks diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart index b1490983c..f6fff1b04 100644 --- a/pkgs/html/test/run_all.dart +++ b/pkgs/html/test/run_all.dart @@ -5,7 +5,6 @@ library test.run_all; -import 'dart:io' show Options; import 'package:unittest/compact_vm_config.dart'; import 'package:unittest/unittest.dart'; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index f894aa4a4..11466797a 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -1,7 +1,6 @@ /** Support code for the tests in this directory. */ library support; -import 'dart:async'; import 'dart:io'; import 'dart:collection'; import 'package:path/path.dart' as path; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index b9e43fedb..439e44000 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -1,17 +1,14 @@ library tokenizer_test; // Note: mirrors used to match the getattr usage in the original test -import 'dart:async'; import 'dart:convert'; import 'dart:io'; import 'dart:mirrors'; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; import 'package:html5lib/src/char_encodings.dart'; -import 'package:html5lib/src/constants.dart' as constants; import 'package:html5lib/src/token.dart'; import 'package:html5lib/src/tokenizer.dart'; -import 'package:html5lib/src/utils.dart'; import 'package:utf/utf.dart'; import 'support.dart'; From a1f8e6b7644cff0478d70b5ff8bf177510535211 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Tue, 11 Feb 2014 01:15:05 +0000 Subject: [PATCH 020/212] introduce web_components pkg to replace shadow_dom, html_import, custom_element. This new package is 100% compatible with the polyfills used by http://www.polymer-project.org/ Deletes: pkg/shadow_dom pkg/custom_element (except web_ui stuff) pkg/html_import Adds: pkg/web_components, with README.md and build instructions Changes: pkg/html5lib -- deprecate queryAll/query in favor of *Selector pkg/polymer -- test fixes & a few small changes to work with new polyfills, mostly in build tests/html/custom -- can't load the CE polyfill at runtime, must now be injected statically via an HTML page, similar to the style @blois used for some custom element tests. R=blois@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//158083002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32533 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 8 ++++++++ pkgs/html/lib/dom.dart | 19 +++++++++++++++---- pkgs/html/test/dom_test.dart | 12 ++++++------ pkgs/html/test/parser_feature_test.dart | 20 ++++++++++---------- 4 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 pkgs/html/CHANGELOG.md diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md new file mode 100644 index 000000000..9bba04d1e --- /dev/null +++ b/pkgs/html/CHANGELOG.md @@ -0,0 +1,8 @@ +# changelog + +This file contains highlights of what changes on each version of the html5lib +package. + +#### Pub version 0.10.0-dev + * added querySelector/querySelectorAll, deprecated query/queryAll. + This matches the current APIs in dart:html. diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 0507c702b..9f70694c1 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -240,19 +240,29 @@ abstract class Node { nodes.clear(); } + /** *Deprecated* use [querySelector] instead. */ + @deprecated + Element query(String selectors) => querySelector(selectors); + + /** *Deprecated* use [querySelectorAll] instead. */ + @deprecated + List<Element> queryAll(String selectors) => querySelectorAll(selectors); + /** * Seaches for the first descendant node matching the given selectors, using a * preorder traversal. NOTE: right now, this supports only a single type * selectors, e.g. `node.query('div')`. */ - Element query(String selectors) => _queryType(_typeSelector(selectors)); + + Element querySelector(String selectors) => + _queryType(_typeSelector(selectors)); /** * Returns all descendant nodes matching the given selectors, using a * preorder traversal. NOTE: right now, this supports only a single type * selectors, e.g. `node.queryAll('div')`. */ - List<Element> queryAll(String selectors) { + List<Element> querySelectorAll(String selectors) { var results = new List<Element>(); _queryAllType(_typeSelector(selectors), results); return results; @@ -366,8 +376,9 @@ class Document extends Node { int get nodeType => Node.DOCUMENT_NODE; // TODO(jmesserly): optmize this if needed - Element get head => query('html').query('head'); - Element get body => query('html').query('body'); + Element get documentElement => querySelector('html'); + Element get head => documentElement.querySelector('head'); + Element get body => documentElement.querySelector('body'); String toString() => "#document"; diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 5d026e269..301e82298 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -5,29 +5,29 @@ import 'package:unittest/unittest.dart'; import 'package:html5lib/parser.dart'; main() { - group('Node.query type selectors', () { + group('Node.querySelector type selectors', () { test('x-foo', () { - expect(parse('<x-foo>').body.query('x-foo'), isNotNull); + expect(parse('<x-foo>').body.querySelector('x-foo'), isNotNull); }); test('-x-foo', () { var doc = parse('<body><-x-foo>'); expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>')); - expect(doc.body.query('-x-foo'), isNull); + expect(doc.body.querySelector('-x-foo'), isNull); }); test('foo123', () { - expect(parse('<foo123>').body.query('foo123'), isNotNull); + expect(parse('<foo123>').body.querySelector('foo123'), isNotNull); }); test('123 - invalid', () { var doc = parse('<123>'); - expect(() => doc.body.query('123'), throwsUnimplementedError); + expect(() => doc.body.querySelector('123'), throwsUnimplementedError); }); test('x\\ny - not implemented', () { var doc = parse('<x\\ny>'); - expect(() => doc.body.query('x\\ny'), throwsUnimplementedError); + expect(() => doc.body.querySelector('x\\ny'), throwsUnimplementedError); }); }); } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index ddcc0ca01..f6ac344ff 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -91,7 +91,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('attribute spans', () { var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; var doc = parse(text, generateSpans: true); - var elem = doc.query('element'); + var elem = doc.querySelector('element'); expect(elem.sourceSpan.start.offset, 0); expect(elem.sourceSpan.end.offset, text.length); expect(elem.sourceSpan.text, text); @@ -106,7 +106,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('attribute value spans', () { var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; var doc = parse(text, generateSpans: true); - var elem = doc.query('element'); + var elem = doc.querySelector('element'); expect(elem.attributeValueSpans['quux'], null); @@ -118,7 +118,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('attribute spans if no attributes', () { var text = '<element>'; var doc = parse(text, generateSpans: true); - var elem = doc.query('element'); + var elem = doc.querySelector('element'); expect(elem.attributeSpans['quux'], null); expect(elem.attributeValueSpans['quux'], null); @@ -127,7 +127,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('attribute spans if no attribute value', () { var text = '<foo template>'; var doc = parse(text, generateSpans: true); - var elem = doc.query('foo'); + var elem = doc.querySelector('foo'); expect(elem.attributeSpans['template'].start.offset, text.indexOf('template')); @@ -137,7 +137,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('attribute spans null if code parsed without spans', () { var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; var doc = parse(text); - var elem = doc.query('element'); + var elem = doc.querySelector('element'); expect(elem.sourceSpan, null); expect(elem.attributeSpans['quux'], null); expect(elem.attributeSpans['extends'], null); @@ -172,9 +172,9 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. // However, we preserve the input order via LinkedHashMap var doc = parseFragment('<foo d=1 a=2 c=3 b=4>'); expect(doc.outerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); - expect(doc.query('foo').attributes.remove('a'), '2'); + expect(doc.querySelector('foo').attributes.remove('a'), '2'); expect(doc.outerHtml, '<foo d="1" c="3" b="4"></foo>'); - doc.query('foo').attributes['a'] = '0'; + doc.querySelector('foo').attributes['a'] = '0'; expect(doc.outerHtml, '<foo d="1" c="3" b="4" a="0"></foo>'); }); @@ -204,11 +204,11 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('Newline after <pre>', () { var doc = parseFragment('<pre>\n\nsome text</span>'); - expect(doc.query('pre').nodes[0].value, '\nsome text'); + expect(doc.querySelector('pre').nodes[0].value, '\nsome text'); expect(doc.outerHtml, '<pre>\n\nsome text</pre>'); doc = parseFragment('<pre>\nsome text</span>'); - expect(doc.query('pre').nodes[0].value, 'some text'); + expect(doc.querySelector('pre').nodes[0].value, 'some text'); expect(doc.outerHtml, '<pre>some text</pre>'); }); @@ -222,7 +222,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. xlink:href="http://example.com/logo.png" xlink:show="new"></desc> '''); - var n = doc.query('desc'); + var n = doc.querySelector('desc'); var keys = n.attributes.keys.toList(); expect(keys[0], new isInstanceOf<AttributeName>()); expect(keys[0].prefix, 'xlink'); From ee270dfa4f6fe30a440f92676de5152f2b6e346a Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Thu, 13 Feb 2014 23:22:48 +0000 Subject: [PATCH 021/212] fix imports link rel=stylesheet fixes https://code.google.com/p/dart/issues/detail?id=16648 also: * adds a few DOM APIs to html5lib that it was missing * removes a broken test from html5lib * fixes polymer's dependency on analyzer R=sigmund@google.com Review URL: https://codereview.chromium.org//162093002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32679 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 65 ++++++++++++++----- pkgs/html/lib/parser.dart | 37 ++++++++++- pkgs/html/lib/src/encoding_parser.dart | 2 + pkgs/html/lib/src/treebuilder.dart | 4 +- pkgs/html/test/browser/browser_test.dart | 14 ---- pkgs/html/test/browser/browser_test.html | 28 -------- pkgs/html/test/dom_compat_test.dart | 30 --------- .../test/dom_compat_test_definitions.dart | 10 --- pkgs/html/test/parser_feature_test.dart | 49 ++++++++++++-- pkgs/html/test/run_all.dart | 2 - 10 files changed, 134 insertions(+), 107 deletions(-) delete mode 100644 pkgs/html/test/browser/browser_test.dart delete mode 100644 pkgs/html/test/browser/browser_test.html delete mode 100644 pkgs/html/test/dom_compat_test.dart delete mode 100644 pkgs/html/test/dom_compat_test_definitions.dart diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 9f70694c1..66fa1b364 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -152,13 +152,6 @@ abstract class Node { String get namespace => null; - // TODO(jmesserly): do we need this here? - /** The value of the current node (applies to text nodes and comments). */ - String get value => null; - - // TODO(jmesserly): this is a workaround for http://dartbug.com/4754 - int get $dom_nodeType => nodeType; - int get nodeType; String get outerHtml { @@ -180,6 +173,12 @@ abstract class Node { nodes.addAll(parseFragment(value, container: tagName).nodes); } + // Implemented per: http://dom.spec.whatwg.org/#dom-node-textcontent + String get text => null; + set text(String value) {} + + void append(Node node) => nodes.add(node); + Node get firstChild => nodes.isNotEmpty ? nodes[0] : null; void _addOuterHtml(StringBuffer str); @@ -396,6 +395,9 @@ class DocumentFragment extends Document { String toString() => "#document-fragment"; DocumentFragment clone() => new DocumentFragment(); + + String get text => _getText(this); + set text(String value) => _setText(this, value); } class DocumentType extends Node { @@ -427,26 +429,28 @@ class DocumentType extends Node { } class Text extends Node { - // TODO(jmesserly): this should be text? - String value; + String data; - Text(this.value) : super(null); + Text(this.data) : super(null); int get nodeType => Node.TEXT_NODE; - String toString() => '"$value"'; + String toString() => '"$data"'; void _addOuterHtml(StringBuffer str) { // Don't escape text for certain elements, notably <script>. if (rcdataElements.contains(parent.tagName) || parent.tagName == 'plaintext') { - str.write(value); + str.write(data); } else { - str.write(htmlSerializeEscape(value)); + str.write(htmlSerializeEscape(data)); } } - Text clone() => new Text(value); + Text clone() => new Text(data); + + String get text => data; + set text(String value) { data = value; } } class Element extends Node { @@ -518,6 +522,9 @@ class Element extends Node { return "<${Namespaces.getPrefix(namespace)} $tagName>"; } + String get text => _getText(this); + set text(String value) => _setText(this, value); + void _addOuterHtml(StringBuffer str) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments // Element is the most complicated one. @@ -544,7 +551,8 @@ class Element extends Node { if (nodes.length > 0) { if (tagName == 'pre' || tagName == 'textarea' || tagName == 'listing') { - if (nodes[0] is Text && nodes[0].value.startsWith('\n')) { + final first = nodes[0]; + if (first is Text && first.data.startsWith('\n')) { // These nodes will remove a leading \n at parse time, so if we still // have one, it means we started with two. Add it back. str.write('\n'); @@ -577,7 +585,7 @@ class Element extends Node { } class Comment extends Node { - final String data; + String data; Comment(this.data) : super(null); @@ -590,6 +598,11 @@ class Comment extends Node { } Comment clone() => new Comment(data); + + String get text => data; + set text(String value) { + this.data = value; + } } @@ -881,3 +894,23 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> Element get single => _filtered.single; } + +// http://dom.spec.whatwg.org/#dom-node-textcontent +// For Element and DocumentFragment +String _getText(Node node) => + (new _ConcatTextVisitor()..visit(node)).toString(); + +void _setText(Node node, String value) { + node.nodes.clear(); + node.append(new Text(value)); +} + +class _ConcatTextVisitor extends TreeVisitor { + final _str = new StringBuffer(); + + String toString() => _str.toString(); + + visitText(Text node) { + _str.write(node.data); + } +} diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 4e5e6d563..8bfa5c5ed 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -592,18 +592,22 @@ class Phase { // For most phases the following is correct. Where it's not it will be // overridden. tree.insertComment(token, tree.openElements.last); + return null; } Token processDoctype(DoctypeToken token) { parser.parseError(token.span, "unexpected-doctype"); + return null; } Token processCharacters(CharactersToken token) { tree.insertText(token.data, token.span); + return null; } Token processSpaceCharacters(SpaceCharactersToken token) { tree.insertText(token.data, token.span); + return null; } Token processStartTag(StartTagToken token) { @@ -620,6 +624,7 @@ class Phase { tree.openElements[0].attributes.putIfAbsent(attr, () => value); }); parser.firstStartTag = false; + return null; } Token processEndTag(EndTagToken token) { @@ -639,10 +644,12 @@ class InitialPhase extends Phase { InitialPhase(parser) : super(parser); Token processSpaceCharacters(SpaceCharactersToken token) { + return null; } Token processComment(CommentToken token) { tree.insertComment(token, tree.document); + return null; } Token processDoctype(DoctypeToken token) { @@ -743,6 +750,7 @@ class InitialPhase extends Phase { parser.compatMode = "limited quirks"; } parser.phase = parser._beforeHtmlPhase; + return null; } void anythingElse() { @@ -795,9 +803,11 @@ class BeforeHtmlPhase extends Phase { Token processComment(CommentToken token) { tree.insertComment(token, tree.document); + return null; } Token processSpaceCharacters(SpaceCharactersToken token) { + return null; } Token processCharacters(CharactersToken token) { @@ -852,6 +862,7 @@ class BeforeHeadPhase extends Phase { } Token processSpaceCharacters(SpaceCharactersToken token) { + return null; } Token processCharacters(CharactersToken token) { @@ -1444,6 +1455,7 @@ class InBodyPhase extends Phase { tree.insertElement(token); parser.framesetOK = false; } + return null; } void startTagAppletMarqueeObject(StartTagToken token) { @@ -1640,6 +1652,7 @@ class InBodyPhase extends Phase { Token startTagOther(StartTagToken token) { tree.reconstructActiveFormattingElements(); tree.insertElement(token); + return null; } void endTagP(EndTagToken token) { @@ -1683,6 +1696,7 @@ class InBodyPhase extends Phase { endTagBody(new EndTagToken("body")); return token; } + return null; } void endTagBlock(EndTagToken token) { @@ -1956,6 +1970,7 @@ class TextPhase extends Phase { Token processCharacters(CharactersToken token) { tree.insertText(token.data, token.span); + return null; } bool processEOF() { @@ -2040,6 +2055,7 @@ class InTablePhase extends Phase { parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; parser.phase.processSpaceCharacters(token); + return null; } Token processCharacters(CharactersToken token) { @@ -2047,6 +2063,7 @@ class InTablePhase extends Phase { parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; parser.phase.processCharacters(token); + return null; } void insertText(CharactersToken token) { @@ -2093,6 +2110,7 @@ class InTablePhase extends Phase { if (!parser.innerHTMLMode) { return token; } + return null; } Token startTagStyleScript(StartTagToken token) { @@ -2208,12 +2226,14 @@ class InTableTextPhase extends Phase { return null; } characterTokens.add(token); + return null; } Token processSpaceCharacters(SpaceCharactersToken token) { //pretty sure we should never reach here characterTokens.add(token); // XXX assert(false); + return null; } Token processStartTag(StartTagToken token) { @@ -2683,6 +2703,7 @@ class InCellPhase extends Phase { // innerHTML case assert(parser.innerHTMLMode); parser.parseError(token.span, "undefined-error"); + return null; } } @@ -2719,6 +2740,7 @@ class InCellPhase extends Phase { // sometimes innerHTML case parser.parseError(token.span, "undefined-error"); } + return null; } Token endTagOther(EndTagToken token) { @@ -2767,6 +2789,7 @@ class InSelectPhase extends Phase { return null; } tree.insertText(token.data, token.span); + return null; } void startTagOption(StartTagToken token) { @@ -2800,6 +2823,7 @@ class InSelectPhase extends Phase { } else { assert(parser.innerHTMLMode); } + return null; } Token startTagScript(StartTagToken token) { @@ -2809,6 +2833,7 @@ class InSelectPhase extends Phase { Token startTagOther(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag-in-select", {"name": token.name}); + return null; } void endTagOption(EndTagToken token) { @@ -2904,6 +2929,7 @@ class InSelectInTablePhase extends Phase { endTagOther(new EndTagToken("select")); return token; } + return null; } Token endTagOther(EndTagToken token) { @@ -2976,7 +3002,7 @@ class InForeignContentPhase extends Phase { } else if (parser.framesetOK && !allWhitespace(token.data)) { parser.framesetOK = false; } - super.processCharacters(token); + return super.processCharacters(token); } Token processStartTag(StartTagToken token) { @@ -3011,6 +3037,7 @@ class InForeignContentPhase extends Phase { tree.openElements.removeLast(); token.selfClosingAcknowledged = true; } + return null; } } @@ -3071,6 +3098,7 @@ class AfterBodyPhase extends Phase { // This is needed because data is to be appended to the <html> element // here and not to whatever is currently open. tree.insertComment(token, tree.openElements[0]); + return null; } Token processCharacters(CharactersToken token) { @@ -3139,6 +3167,7 @@ class InFramesetPhase extends Phase { Token processCharacters(CharactersToken token) { parser.parseError(token.span, "unexpected-char-in-frameset"); + return null; } void startTagFrameset(StartTagToken token) { @@ -3157,6 +3186,7 @@ class InFramesetPhase extends Phase { Token startTagOther(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag-in-frameset", {"name": token.name}); + return null; } void endTagFrameset(EndTagToken token) { @@ -3205,6 +3235,7 @@ class AfterFramesetPhase extends Phase { Token processCharacters(CharactersToken token) { parser.parseError(token.span, "unexpected-char-after-frameset"); + return null; } Token startTagNoframes(StartTagToken token) { @@ -3239,6 +3270,7 @@ class AfterAfterBodyPhase extends Phase { Token processComment(CommentToken token) { tree.insertComment(token, tree.document); + return null; } Token processSpaceCharacters(SpaceCharactersToken token) { @@ -3285,6 +3317,7 @@ class AfterAfterFramesetPhase extends Phase { Token processComment(CommentToken token) { tree.insertComment(token, tree.document); + return null; } Token processSpaceCharacters(SpaceCharactersToken token) { @@ -3293,6 +3326,7 @@ class AfterAfterFramesetPhase extends Phase { Token processCharacters(CharactersToken token) { parser.parseError(token.span, "expected-eof-but-got-char"); + return null; } Token startTagHtml(StartTagToken token) { @@ -3311,6 +3345,7 @@ class AfterAfterFramesetPhase extends Phase { Token processEndTag(EndTagToken token) { parser.parseError(token.span, "expected-eof-but-got-end-tag", {"name": token.name}); + return null; } } diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 297e3f585..390e433b8 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -204,6 +204,7 @@ class EncodingParser { } } } + return true; // unreachable } bool handlePossibleStartTag() => handlePossibleTag(false); @@ -327,6 +328,7 @@ class EncodingParser { attrValue.add(c); } } + return null; // unreachable } } diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index adde3bf15..03707b572 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -324,7 +324,7 @@ class TreeBuilder { if (refNode == null) { if (nodes.length > 0 && nodes.last is Text) { Text last = nodes.last; - last.value = '${last.value}$data'; + last.data = '${last.data}$data'; if (span != null) { last.sourceSpan = span.file.span(last.sourceSpan.start.offset, @@ -337,7 +337,7 @@ class TreeBuilder { int index = nodes.indexOf(refNode); if (index > 0 && nodes[index - 1] is Text) { Text last = nodes[index - 1]; - last.value = '${last.value}$data'; + last.data = '${last.data}$data'; } else { nodes.insert(index, new Text(data)..sourceSpan = span); } diff --git a/pkgs/html/test/browser/browser_test.dart b/pkgs/html/test/browser/browser_test.dart deleted file mode 100644 index 8339f485e..000000000 --- a/pkgs/html/test/browser/browser_test.dart +++ /dev/null @@ -1,14 +0,0 @@ -library dom_compat_test; - -import 'dart:html'; -import 'package:unittest/html_config.dart'; -import 'package:unittest/unittest.dart'; - -part '../dom_compat_test_definitions.dart'; - -main() { - groupSep = ' - '; - useHtmlConfiguration(); - - registerDomCompatTests(); -} diff --git a/pkgs/html/test/browser/browser_test.html b/pkgs/html/test/browser/browser_test.html deleted file mode 100644 index bf8d29769..000000000 --- a/pkgs/html/test/browser/browser_test.html +++ /dev/null @@ -1,28 +0,0 @@ -<!DOCTYPE html> - -<html> - <head> - <title>Run the unit tests</title> - </head> - <body> - <script> - // Webkit is migrating from layoutTestController to testRunner, we use - // layoutTestController as a fallback until that settles in. - var runner = window.testRunner || window.layoutTestController; - if (runner) { - runner.dumpAsText(); - runner.waitUntilDone(); - window.addEventListener("message", receiveMessage, false); - } - - function receiveMessage(e) { - console.log(e.data); - if (e.data == 'unittest-suite-done' && runner) { - runner.notifyDone(); - } - } - </script> - <script type="application/dart" src="browser_test.dart"></script> - <script src="packages/browser/dart.js"></script> - </body> -</html> diff --git a/pkgs/html/test/dom_compat_test.dart b/pkgs/html/test/dom_compat_test.dart deleted file mode 100644 index 896576e31..000000000 --- a/pkgs/html/test/dom_compat_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -library dom_compat_test; - -import 'dart:io'; -import 'package:unittest/unittest.dart'; -import 'package:unittest/compact_vm_config.dart'; -import 'package:html5lib/dom.dart'; - -part 'dom_compat_test_definitions.dart'; - -main() { - useCompactVMConfiguration(); - - registerDomCompatTests(); - - test('content_shell', () { - _runDrt('test/browser/browser_test.html'); - }); -} - -void _runDrt(String htmlFile) { - final allPassedRegExp = new RegExp('All \\d+ tests passed'); - - final future = Process.run('content_shell', ['--dump-render-tree', htmlFile]) - .then((ProcessResult pr) { - expect(pr.exitCode, 0); - expect(pr.stdout, matches(allPassedRegExp), reason: pr.stdout); - }); - - expect(future, completion(isNull)); -} diff --git a/pkgs/html/test/dom_compat_test_definitions.dart b/pkgs/html/test/dom_compat_test_definitions.dart deleted file mode 100644 index f1d83e7a9..000000000 --- a/pkgs/html/test/dom_compat_test_definitions.dart +++ /dev/null @@ -1,10 +0,0 @@ -part of dom_compat_test; - -void registerDomCompatTests() { - group('Element', () { - test('outerHtml', () { - final element = new Element.tag('div'); - expect(element.outerHtml, '<div></div>'); - }); - }); -} diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index f6ac344ff..0071a1f12 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -81,9 +81,9 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. var textContent = '\n hello {{name}}'; var html = '<body><div>$textContent</div>'; var doc = parse(html, generateSpans: true); - var text = doc.body.nodes[0].nodes[0]; + Text text = doc.body.nodes[0].nodes[0]; expect(text, new isInstanceOf<Text>()); - expect(text.value, textContent); + expect(text.data, textContent); expect(text.sourceSpan.start.offset, html.indexOf(textContent)); expect(text.sourceSpan.length, textContent.length); }); @@ -204,11 +204,11 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('Newline after <pre>', () { var doc = parseFragment('<pre>\n\nsome text</span>'); - expect(doc.querySelector('pre').nodes[0].value, '\nsome text'); + expect(doc.querySelector('pre').nodes[0].data, '\nsome text'); expect(doc.outerHtml, '<pre>\n\nsome text</pre>'); doc = parseFragment('<pre>\nsome text</span>'); - expect(doc.querySelector('pre').nodes[0].value, 'some text'); + expect(doc.querySelector('pre').nodes[0].data, 'some text'); expect(doc.outerHtml, '<pre>some text</pre>'); }); @@ -246,4 +246,45 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. 'ParserError:1:4: Unexpected non-space characters. ' 'Expected DOCTYPE.'); }); + + test('Element.text', () { + var doc = parseFragment('<div>foo<div>bar</div>baz</div>'); + var e = doc.firstChild; + var text = e.firstChild; + expect((text as Text).data, 'foo'); + expect(e.text, 'foobarbaz'); + + e.text = 'FOO'; + expect(e.nodes.length, 1); + expect(e.firstChild, isNot(text), reason: 'should create a new tree'); + expect((e.firstChild as Text).data, 'FOO'); + expect(e.text, 'FOO'); + }); + + test('Text.text', () { + var doc = parseFragment('<div>foo<div>bar</div>baz</div>'); + var e = doc.firstChild; + Text text = e.firstChild; + expect(text.data, 'foo'); + expect(text.text, 'foo'); + + text.text = 'FOO'; + expect(text.data, 'FOO'); + expect(e.text, 'FOObarbaz'); + expect(text.text, 'FOO'); + }); + + test('Comment.text', () { + var doc = parseFragment('<div><!--foo-->bar</div>'); + var e = doc.firstChild; + var c = e.firstChild; + expect((c as Comment).data, 'foo'); + expect(c.text, 'foo'); + expect(e.text, 'bar'); + + c.text = 'qux'; + expect(c.data, 'qux'); + expect(c.text, 'qux'); + expect(e.text, 'bar'); + }); } diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart index f6fff1b04..14e6b34ff 100644 --- a/pkgs/html/test/run_all.dart +++ b/pkgs/html/test/run_all.dart @@ -12,7 +12,6 @@ import 'dom_test.dart' as dom_test; import 'parser_feature_test.dart' as parser_feature_test; import 'parser_test.dart' as parser_test; import 'tokenizer_test.dart' as tokenizer_test; -import 'dom_compat_test.dart' as dom_compat_test; main(List<String> args) { var pattern = new RegExp(args.length > 0 ? args[0] : '.'); @@ -25,7 +24,6 @@ main(List<String> args) { } addGroup('dom_test.dart', dom_test.main); - addGroup('dom_compat_test.dart', dom_compat_test.main); addGroup('parser_feature_test.dart', parser_feature_test.main); addGroup('parser_test.dart', parser_test.main); addGroup('tokenizer_test.dart', tokenizer_test.main); From 3a508c444e1f0aedb5cdd26cb5ebb11128f4ee78 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Thu, 13 Feb 2014 23:50:46 +0000 Subject: [PATCH 022/212] fix accidental breaking changes in html5lib, deprecate instead R=kevmoo@google.com Review URL: https://codereview.chromium.org//165353002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32680 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 5 ++++- pkgs/html/lib/dom.dart | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 9bba04d1e..7c9728088 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html5lib package. -#### Pub version 0.10.0-dev +#### Pub version 0.9.2-dev + * add Node.text, Node.append, Document.documentElement + * add Text.data, deprecate Node.value and Text.value. + * deprecate Node.$dom_nodeType * added querySelector/querySelectorAll, deprecated query/queryAll. This matches the current APIs in dart:html. diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 66fa1b364..6fceb65ac 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -154,6 +154,12 @@ abstract class Node { int get nodeType; + /** *Deprecated* use [text], [Text.data] or [Comment.data]. */ + @deprecated String get value => null; + + /** *Deprecated* use [nodeType]. */ + @deprecated int get $dom_nodeType => nodeType; + String get outerHtml { var str = new StringBuffer(); _addOuterHtml(str); @@ -433,6 +439,10 @@ class Text extends Node { Text(this.data) : super(null); + /** *Deprecated* use [data]. */ + @deprecated String get value => data; + @deprecated set value(String x) { data = x; } + int get nodeType => Node.TEXT_NODE; String toString() => '"$data"'; From 55a22fe3e0d75d7737083537230949791ac5d462 Mon Sep 17 00:00:00 2001 From: "sigmund@google.com" <sigmund@google.com> Date: Fri, 21 Feb 2014 23:36:57 +0000 Subject: [PATCH 023/212] small fix in html5lib warning message R=jmesserly@google.com Review URL: https://codereview.chromium.org//174633003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32945 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 8bfa5c5ed..013ebcd98 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1683,7 +1683,7 @@ class InBodyPhase extends Phase { } // Not sure this is the correct name for the parse error parser.parseError(token.span, "expected-one-end-tag-but-got-another", - {"expectedName": "body", "gotName": node.tagName}); + {"gotName": "body", "expectedName": node.tagName}); break; } } From 4d19bb32e17d629039680d49b87f7fdf7368264e Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Tue, 25 Feb 2014 00:36:13 +0000 Subject: [PATCH 024/212] [html5lib] triple slash comment style Also improves ./tools/line_doc_comments.dart to warn about lines >= 80 chars, to make it easier to catch these. R=sigmund@google.com Review URL: https://codereview.chromium.org//178843003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@32997 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 144 ++++++++---------- pkgs/html/lib/dom_parsing.dart | 74 ++++------ pkgs/html/lib/parser.dart | 186 +++++++++++------------- pkgs/html/lib/parser_console.dart | 18 +-- pkgs/html/lib/src/char_encodings.dart | 56 +++---- pkgs/html/lib/src/constants.dart | 8 +- pkgs/html/lib/src/encoding_parser.dart | 36 ++--- pkgs/html/lib/src/inputstream.dart | 92 +++++------- pkgs/html/lib/src/list_proxy.dart | 12 +- pkgs/html/lib/src/token.dart | 24 ++- pkgs/html/lib/src/tokenizer.dart | 58 +++----- pkgs/html/lib/src/treebuilder.dart | 40 ++--- pkgs/html/lib/src/utils.dart | 10 +- pkgs/html/test/dom_test.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 2 +- pkgs/html/test/parser_test.dart | 2 +- pkgs/html/test/support.dart | 14 +- pkgs/html/test/tokenizer_test.dart | 10 +- 18 files changed, 325 insertions(+), 463 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 6fceb65ac..12d664790 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -1,7 +1,5 @@ -/** - * A simple tree API that results from parsing html. Intended to be compatible - * with dart:html, but right now it resembles the classic JS DOM. - */ +/// A simple tree API that results from parsing html. Intended to be compatible +/// with dart:html, but right now it resembles the classic JS DOM. library dom; import 'dart:collection'; @@ -18,13 +16,13 @@ import 'parser.dart'; // TODO(jmesserly): this needs to be replaced by an AttributeMap for attributes // that exposes namespace info. class AttributeName implements Comparable { - /** The namespace prefix, e.g. `xlink`. */ + /// The namespace prefix, e.g. `xlink`. final String prefix; - /** The attribute name, e.g. `title`. */ + /// The attribute name, e.g. `title`. final String name; - /** The namespace url, e.g. `http://www.w3.org/1999/xlink` */ + /// The namespace url, e.g. `http://www.w3.org/1999/xlink` final String namespace; const AttributeName(this.prefix, this.name, this.namespace); @@ -62,7 +60,7 @@ class AttributeName implements Comparable { } } -/** Really basic implementation of a DOM-core like Node. */ +/// Really basic implementation of a DOM-core like Node. abstract class Node { static const int ATTRIBUTE_NODE = 2; static const int CDATA_SECTION_NODE = 4; @@ -78,35 +76,31 @@ abstract class Node { static const int TEXT_NODE = 3; // TODO(jmesserly): this should be on Element - /** The tag name associated with the node. */ + /// The tag name associated with the node. final String tagName; - /** The parent of the current node (or null for the document node). */ + /// The parent of the current node (or null for the document node). Node parent; // TODO(jmesserly): should move to Element. - /** - * A map holding name, value pairs for attributes of the node. - * - * Note that attribute order needs to be stable for serialization, so we use a - * LinkedHashMap. Each key is a [String] or [AttributeName]. - */ + /// A map holding name, value pairs for attributes of the node. + /// + /// Note that attribute order needs to be stable for serialization, so we use + /// a LinkedHashMap. Each key is a [String] or [AttributeName]. LinkedHashMap<dynamic, String> attributes = new LinkedHashMap(); - /** - * A list of child nodes of the current node. This must - * include all elements but not necessarily other node types. - */ + /// A list of child nodes of the current node. This must + /// include all elements but not necessarily other node types. final NodeList nodes = new NodeList._(); List<Element> _elements; // TODO(jmesserly): consider using an Expando for this, and put it in // dom_parsing. Need to check the performance affect. - /** The source span of this node, if it was created by the [HtmlParser]. */ + /// The source span of this node, if it was created by the [HtmlParser]. FileSpan sourceSpan; - /** The attribute spans if requested. Otherwise null. */ + /// The attribute spans if requested. Otherwise null. LinkedHashMap<dynamic, FileSpan> _attributeSpans; LinkedHashMap<dynamic, FileSpan> _attributeValueSpans; @@ -114,23 +108,19 @@ abstract class Node { nodes._parent = this; } - /** - * If [sourceSpan] is available, this contains the spans of each attribute. - * The span of an attribute is the entire attribute, including the name and - * quotes (if any). For example, the span of "attr" in `<a attr="value">` - * would be the text `attr="value"`. - */ + /// If [sourceSpan] is available, this contains the spans of each attribute. + /// The span of an attribute is the entire attribute, including the name and + /// quotes (if any). For example, the span of "attr" in `<a attr="value">` + /// would be the text `attr="value"`. LinkedHashMap<dynamic, FileSpan> get attributeSpans { _ensureAttributeSpans(); return _attributeSpans; } - /** - * If [sourceSpan] is available, this contains the spans of each attribute's - * value. Unlike [attributeSpans], this span will inlcude only the value. - * For example, the value span of "attr" in `<a attr="value">` would be the - * text `value`. - */ + /// If [sourceSpan] is available, this contains the spans of each attribute's + /// value. Unlike [attributeSpans], this span will inlcude only the value. + /// For example, the value span of "attr" in `<a attr="value">` would be the + /// text `value`. LinkedHashMap<dynamic, FileSpan> get attributeValueSpans { _ensureAttributeSpans(); return _attributeValueSpans; @@ -144,20 +134,18 @@ abstract class Node { } // TODO(jmesserly): needs to support deep clone. - /** - * Return a shallow copy of the current node i.e. a node with the same - * name and attributes but with no parent or child nodes. - */ + /// Return a shallow copy of the current node i.e. a node with the same + /// name and attributes but with no parent or child nodes. Node clone(); String get namespace => null; int get nodeType; - /** *Deprecated* use [text], [Text.data] or [Comment.data]. */ + /// *Deprecated* use [text], [Text.data] or [Comment.data]. @deprecated String get value => null; - /** *Deprecated* use [nodeType]. */ + /// *Deprecated* use [nodeType]. @deprecated int get $dom_nodeType => nodeType; String get outerHtml { @@ -203,12 +191,10 @@ abstract class Node { return this; } - /** - * Insert [node] as a child of the current node, before [refNode] in the - * list of child nodes. Raises [UnsupportedOperationException] if [refNode] - * is not a child of the current node. If refNode is null, this adds to the - * end of the list. - */ + /// Insert [node] as a child of the current node, before [refNode] in the + /// list of child nodes. Raises [UnsupportedOperationException] if [refNode] + /// is not a child of the current node. If refNode is null, this adds to the + /// end of the list. void insertBefore(Node node, Node refNode) { if (refNode == null) { nodes.add(node); @@ -217,7 +203,7 @@ abstract class Node { } } - /** Replaces this node with another node. */ + /// Replaces this node with another node. Node replaceWith(Node otherNode) { if (parent == null) { throw new UnsupportedError('Node must have a parent to replace it.'); @@ -227,7 +213,7 @@ abstract class Node { } // TODO(jmesserly): should this be a property or remove? - /** Return true if the node has children or text. */ + /// Return true if the node has children or text. bool hasContent() => nodes.length > 0; Pair<String, String> get nameTuple { @@ -235,38 +221,32 @@ abstract class Node { return new Pair(ns, tagName); } - /** - * Move all the children of the current node to [newParent]. - * This is needed so that trees that don't store text as nodes move the - * text in the correct way. - */ + /// Move all the children of the current node to [newParent]. + /// This is needed so that trees that don't store text as nodes move the + /// text in the correct way. void reparentChildren(Node newParent) { newParent.nodes.addAll(nodes); nodes.clear(); } - /** *Deprecated* use [querySelector] instead. */ + /// *Deprecated* use [querySelector] instead. @deprecated Element query(String selectors) => querySelector(selectors); - /** *Deprecated* use [querySelectorAll] instead. */ + /// *Deprecated* use [querySelectorAll] instead. @deprecated List<Element> queryAll(String selectors) => querySelectorAll(selectors); - /** - * Seaches for the first descendant node matching the given selectors, using a - * preorder traversal. NOTE: right now, this supports only a single type - * selectors, e.g. `node.query('div')`. - */ + /// Seaches for the first descendant node matching the given selectors, using a + /// preorder traversal. NOTE: right now, this supports only a single type + /// selectors, e.g. `node.query('div')`. Element querySelector(String selectors) => _queryType(_typeSelector(selectors)); - /** - * Returns all descendant nodes matching the given selectors, using a - * preorder traversal. NOTE: right now, this supports only a single type - * selectors, e.g. `node.queryAll('div')`. - */ + /// Returns all descendant nodes matching the given selectors, using a + /// preorder traversal. NOTE: right now, this supports only a single type + /// selectors, e.g. `node.queryAll('div')`. List<Element> querySelectorAll(String selectors) { var results = new List<Element>(); _queryAllType(_typeSelector(selectors), results); @@ -285,12 +265,10 @@ abstract class Node { return selectors; } - /** - * Checks if this is a type selector. - * See <http://www.w3.org/TR/CSS2/grammar.html>. - * Note: this doesn't support '*', the universal selector, non-ascii chars or - * escape chars. - */ + /// Checks if this is a type selector. + /// See <http://www.w3.org/TR/CSS2/grammar.html>. + /// Note: this doesn't support '*', the universal selector, non-ascii chars or + /// escape chars. bool _isTypeSelector(String selector) { // Parser: @@ -345,7 +323,7 @@ abstract class Node { } } - /** Initialize [attributeSpans] using [sourceSpan]. */ + /// Initialize [attributeSpans] using [sourceSpan]. void _ensureAttributeSpans() { if (_attributeSpans != null) return; @@ -439,7 +417,7 @@ class Text extends Node { Text(this.data) : super(null); - /** *Deprecated* use [data]. */ + /// *Deprecated* use [data]. @deprecated String get value => data; @deprecated set value(String x) { data = x; } @@ -720,10 +698,8 @@ class NodeList extends ListProxy<Node> { } -/** - * An indexable collection of a node's descendants in the document tree, - * filtered so that only elements are in the collection. - */ +/// An indexable collection of a node's descendants in the document tree, +/// filtered so that only elements are in the collection. // TODO(jmesserly): this was copied from dart:html // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. class FilteredElementList extends IterableBase<Element> with ListMixin<Element> @@ -732,14 +708,12 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> final Node _node; final List<Node> _childNodes; - /** - * Creates a collection of the elements that descend from a node. - * - * Example usage: - * - * var filteredElements = new FilteredElementList(query("#container")); - * // filteredElements is [a, b, c]. - */ + /// Creates a collection of the elements that descend from a node. + /// + /// Example usage: + /// + /// var filteredElements = new FilteredElementList(query("#container")); + /// // filteredElements is [a, b, c]. FilteredElementList(Node node): _childNodes = node.nodes, _node = node; // We can't memoize this, since it's possible that children will be messed diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 3ff74bb98..fa13261ee 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -1,12 +1,10 @@ -/** - * This library contains extra APIs that aren't in the DOM, but are useful - * when interacting with the parse tree. - */ +/// This library contains extra APIs that aren't in the DOM, but are useful +/// when interacting with the parse tree. library dom_parsing; import 'dom.dart'; -/** A simple tree visitor for the DOM nodes. */ +/// A simple tree visitor for the DOM nodes. class TreeVisitor { visit(Node node) { switch (node.nodeType) { @@ -25,11 +23,9 @@ class TreeVisitor { for (var child in node.nodes.toList()) visit(child); } - /** - * The fallback handler if the more specific visit method hasn't been - * overriden. Only use this from a subclass of [TreeVisitor], otherwise - * call [visit] instead. - */ + /// The fallback handler if the more specific visit method hasn't been + /// overriden. Only use this from a subclass of [TreeVisitor], otherwise + /// call [visit] instead. visitNodeFallback(Node node) => visitChildren(node); visitDocument(Document node) => visitNodeFallback(node); @@ -47,20 +43,16 @@ class TreeVisitor { visitDocumentFragment(DocumentFragment node) => visitDocument(node); } -/** - * Converts the DOM tree into an HTML string with code markup suitable for - * displaying the HTML's source code with CSS colors for different parts of the - * markup. See also [CodeMarkupVisitor]. - */ +/// Converts the DOM tree into an HTML string with code markup suitable for +/// displaying the HTML's source code with CSS colors for different parts of the +/// markup. See also [CodeMarkupVisitor]. String htmlToCodeMarkup(Node node) { return (new CodeMarkupVisitor()..visit(node)).toString(); } -/** - * Converts the DOM tree into an HTML string with code markup suitable for - * displaying the HTML's source code with CSS colors for different parts of the - * markup. See also [htmlToCodeMarkup]. - */ +/// Converts the DOM tree into an HTML string with code markup suitable for +/// displaying the HTML's source code with CSS colors for different parts of the +/// markup. See also [htmlToCodeMarkup]. class CodeMarkupVisitor extends TreeVisitor { final StringBuffer _str; @@ -113,23 +105,21 @@ class CodeMarkupVisitor extends TreeVisitor { // TODO(jmesserly): reconcile this with dart:web htmlEscape. // This one might be more useful, as it is HTML5 spec compliant. -/** - * Escapes [text] for use in the - * [HTML fragment serialization algorithm][1]. In particular, as described - * in the [specification][2]: - * - * - Replace any occurrence of the `&` character by the string `&amp;`. - * - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the - * string `&nbsp;`. - * - If the algorithm was invoked in [attributeMode], replace any occurrences of - * the `"` character by the string `&quot;`. - * - If the algorithm was not invoked in [attributeMode], replace any - * occurrences of the `<` character by the string `&lt;`, and any occurrences - * of the `>` character by the string `&gt;`. - * - * [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments - * [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString - */ +/// Escapes [text] for use in the +/// [HTML fragment serialization algorithm][1]. In particular, as described +/// in the [specification][2]: +/// +/// - Replace any occurrence of the `&` character by the string `&amp;`. +/// - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the +/// string `&nbsp;`. +/// - If the algorithm was invoked in [attributeMode], replace any occurrences +/// of the `"` character by the string `&quot;`. +/// - If the algorithm was not invoked in [attributeMode], replace any +/// occurrences of the `<` character by the string `&lt;`, and any occurrences +/// of the `>` character by the string `&gt;`. +/// +/// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments +/// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString String htmlSerializeEscape(String text, {bool attributeMode: false}) { // TODO(jmesserly): is it faster to build up a list of codepoints? // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. @@ -156,12 +146,10 @@ String htmlSerializeEscape(String text, {bool attributeMode: false}) { } -/** - * Returns true if this tag name is a void element. - * This method is useful to a pretty printer, because void elements must not - * have an end tag. - * See <http://dev.w3.org/html5/markup/syntax.html#void-elements> for more info. - */ +/// Returns true if this tag name is a void element. +/// This method is useful to a pretty printer, because void elements must not +/// have an end tag. +/// See also: <http://dev.w3.org/html5/markup/syntax.html#void-elements>. bool isVoidElement(String tagName) { switch (tagName) { case "area": case "base": case "br": case "col": case "command": diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 013ebcd98..c388019e3 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1,18 +1,16 @@ -/** - * This library has a parser for HTML5 documents, that lets you parse HTML - * easily from a script or server side application: - * - * import 'package:html5lib/parser.dart' show parse; - * import 'package:html5lib/dom.dart'; - * main() { - * var document = parse( - * '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); - * print(document.outerHtml); - * } - * - * The resulting document you get back has a DOM-like API for easy tree - * traversal and manipulation. - */ +/// This library has a parser for HTML5 documents, that lets you parse HTML +/// easily from a script or server side application: +/// +/// import 'package:html5lib/parser.dart' show parse; +/// import 'package:html5lib/dom.dart'; +/// main() { +/// var document = parse( +/// '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); +/// print(document.outerHtml); +/// } +/// +/// The resulting document you get back has a DOM-like API for easy tree +/// traversal and manipulation. library parser; import 'dart:collection'; @@ -27,19 +25,17 @@ import 'src/tokenizer.dart'; import 'src/utils.dart'; import 'dom.dart'; -/** - * Parse the [input] html5 document into a tree. The [input] can be - * a [String], [List<int>] of bytes or an [HtmlTokenizer]. - * - * If [input] is not a [HtmlTokenizer], you can optionally specify the file's - * [encoding], which must be a string. If specified, that encoding will be used, - * regardless of any BOM or later declaration (such as in a meta element). - * - * Set [generateSpans] if you want to generate [Span]s, otherwise the - * [Node.sourceSpan] property will be `null`. When using [generateSpans] you can - * additionally pass [sourceUrl] to indicate where the [input] was extracted - * from. - */ +/// Parse the [input] html5 document into a tree. The [input] can be +/// a [String], [List<int>] of bytes or an [HtmlTokenizer]. +/// +/// If [input] is not a [HtmlTokenizer], you can optionally specify the file's +/// [encoding], which must be a string. If specified that encoding will be +/// used regardless of any BOM or later declaration (such as in a meta element). +/// +/// Set [generateSpans] if you want to generate [Span]s, otherwise the +/// [Node.sourceSpan] property will be `null`. When using [generateSpans] you +/// can additionally pass [sourceUrl] to indicate where the [input] was +/// extracted from. Document parse(input, {String encoding, bool generateSpans: false, String sourceUrl}) { var p = new HtmlParser(input, encoding: encoding, @@ -48,20 +44,18 @@ Document parse(input, {String encoding, bool generateSpans: false, } -/** - * Parse the [input] html5 document fragment into a tree. The [input] can be - * a [String], [List<int>] of bytes or an [HtmlTokenizer]. The [container] - * element can optionally be specified, otherwise it defaults to "div". - * - * If [input] is not a [HtmlTokenizer], you can optionally specify the file's - * [encoding], which must be a string. If specified, that encoding will be used, - * regardless of any BOM or later declaration (such as in a meta element). - * - * Set [generateSpans] if you want to generate [Span]s, otherwise the - * [Node.sourceSpan] property will be `null`. When using [generateSpans] you can - * additionally pass [sourceUrl] to indicate where the [input] was extracted - * from. - */ +/// Parse the [input] html5 document fragment into a tree. The [input] can be +/// a [String], [List<int>] of bytes or an [HtmlTokenizer]. The [container] +/// element can optionally be specified, otherwise it defaults to "div". +/// +/// If [input] is not a [HtmlTokenizer], you can optionally specify the file's +/// [encoding], which must be a string. If specified, that encoding will be used, +/// regardless of any BOM or later declaration (such as in a meta element). +/// +/// Set [generateSpans] if you want to generate [Span]s, otherwise the +/// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can +/// additionally pass [sourceUrl] to indicate where the [input] was extracted +/// from. DocumentFragment parseFragment(input, {String container: "div", String encoding, bool generateSpans: false, String sourceUrl}) { var p = new HtmlParser(input, encoding: encoding, @@ -70,15 +64,13 @@ DocumentFragment parseFragment(input, {String container: "div", } -/** - * Parser for HTML, which generates a tree structure from a stream of - * (possibly malformed) characters. - */ +/// Parser for HTML, which generates a tree structure from a stream of +/// (possibly malformed) characters. class HtmlParser { - /** Raise an exception on the first error encountered. */ + /// Raise an exception on the first error encountered. final bool strict; - /** True to generate [Span]s for the [Node.sourceSpan] property. */ + /// True to generate [Span]s for the [Node.sourceSpan] property. final bool generateSpans; final HtmlTokenizer tokenizer; @@ -92,10 +84,10 @@ class HtmlParser { bool firstStartTag = false; // TODO(jmesserly): use enum? - /** "quirks" / "limited quirks" / "no quirks" */ + /// "quirks" / "limited quirks" / "no quirks" String compatMode = "no quirks"; - /** innerHTML container when parsing document fragment. */ + /// innerHTML container when parsing document fragment. String innerHTML; Phase phase; @@ -133,23 +125,21 @@ class HtmlParser { AfterAfterBodyPhase _afterAfterBodyPhase; AfterAfterFramesetPhase _afterAfterFramesetPhase; - /** - * Create a new HtmlParser and configure the [tree] builder and [strict] mode. - * The [input] can be a [String], [List<int>] of bytes or an [HtmlTokenizer]. - * - * If [input] is not a [HtmlTokenizer], you can specify a few more arguments. - * - * The [encoding] must be a string that indicates the encoding. If specified, - * that encoding will be used, regardless of any BOM or later declaration - * (such as in a meta element). - * - * Set [parseMeta] to false if you want to disable parsing the meta element. - * - * Set [lowercaseElementName] or [lowercaseAttrName] to false to disable the - * automatic conversion of element and attribute names to lower case. Note - * that standard way to parse HTML is to lowercase, which is what the browser - * DOM will do if you request [Node.outerHTML], for example. - */ + /// Create an HtmlParser and configure the [tree] builder and [strict] mode. + /// The [input] can be a [String], [List<int>] of bytes or an [HtmlTokenizer]. + /// + /// If [input] is not a [HtmlTokenizer], you can specify a few more arguments. + /// + /// The [encoding] must be a string that indicates the encoding. If specified, + /// that encoding will be used, regardless of any BOM or later declaration + /// (such as in a meta element). + /// + /// Set [parseMeta] to false if you want to disable parsing the meta element. + /// + /// Set [lowercaseElementName] or [lowercaseAttrName] to false to disable the + /// automatic conversion of element and attribute names to lower case. Note + /// that standard way to parse HTML is to lowercase, which is what the browser + /// DOM will do if you request [Node.outerHTML], for example. HtmlParser(input, {String encoding, bool parseMeta: true, bool lowercaseElementName: true, bool lowercaseAttrName: true, this.strict: false, bool generateSpans: false, String sourceUrl, @@ -194,21 +184,17 @@ class HtmlParser { bool get innerHTMLMode => innerHTML != null; - /** - * Parse an html5 document into a tree. - * After parsing, [errors] will be populated with parse errors, if any. - */ + /// Parse an html5 document into a tree. + /// After parsing, [errors] will be populated with parse errors, if any. Document parse() { innerHTML = null; _parse(); return tree.getDocument(); } - /** - * Parse an html5 document fragment into a tree. - * Pass a [container] to change the type of the containing element. - * After parsing, [errors] will be populated with parse errors, if any. - */ + /// Parse an html5 document fragment into a tree. + /// Pass a [container] to change the type of the containing element. + /// After parsing, [errors] will be populated with parse errors, if any. DocumentFragment parseFragment([String container = "div"]) { if (container == null) throw new ArgumentError('container'); innerHTML = container.toLowerCase(); @@ -375,10 +361,8 @@ class HtmlParser { } } - /** - * The last span available. Used for EOF errors if we don't have something - * better. - */ + /// The last span available. Used for EOF errors if we don't have something + /// better. Span get _lastSpan { var pos = tokenizer.stream.position; return new FileSpan(tokenizer.stream.fileInfo, pos, pos); @@ -544,10 +528,8 @@ class HtmlParser { phase = _inBodyPhase; } - /** - * Generic RCDATA/RAWTEXT Parsing algorithm - * [contentType] - RCDATA or RAWTEXT - */ + /// Generic RCDATA/RAWTEXT Parsing algorithm + /// [contentType] - RCDATA or RAWTEXT void parseRCDataRawtext(Token token, String contentType) { assert(contentType == "RAWTEXT" || contentType == "RCDATA"); @@ -565,7 +547,7 @@ class HtmlParser { } -/** Base class for helper object that implements each phase of processing. */ +/// Base class for helper object that implements each phase of processing. class Phase { // Order should be (they can be omitted): // * EOF @@ -631,7 +613,7 @@ class Phase { throw new UnimplementedError(); } - /** Helper method for popping openElements. */ + /// Helper method for popping openElements. void popOpenElementsUntil(String name) { var node = tree.openElements.removeLast(); while (node.tagName != name) { @@ -1568,7 +1550,7 @@ class InBodyPhase extends Phase { startTagRawtext(token); } - /** iframe, noembed noframes, noscript(if scripting enabled). */ + /// iframe, noembed noframes, noscript(if scripting enabled). void startTagRawtext(StartTagToken token) { parser.parseRCDataRawtext(token, "RAWTEXT"); } @@ -1637,13 +1619,11 @@ class InBodyPhase extends Phase { } } - /** - * Elements that should be children of other elements that have a - * different insertion mode; here they are ignored - * "caption", "col", "colgroup", "frame", "frameset", "head", - * "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", - * "tr", "noscript" - */ + /// Elements that should be children of other elements that have a + /// different insertion mode; here they are ignored + /// "caption", "col", "colgroup", "frame", "frameset", "head", + /// "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", + /// "tr", "noscript" void startTagMisplaced(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag-ignored", {"name": token.name}); @@ -1770,7 +1750,7 @@ class InBodyPhase extends Phase { } } - /** The much-feared adoption agency algorithm. */ + /// The much-feared adoption agency algorithm. endTagFormatting(EndTagToken token) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency // TODO(jmesserly): the comments here don't match the numbered steps in the @@ -3350,7 +3330,7 @@ class AfterAfterFramesetPhase extends Phase { } -/** Error in parsed document. */ +/// Error in parsed document. class ParseError implements Exception { final String errorCode; final Span span; @@ -3362,14 +3342,12 @@ class ParseError implements Exception { int get column => span.start.column; - /** - * Gets the human readable error message for this error. Use - * [span.getLocationMessage] or [toString] to get a message including span - * information. If there is a file associated with the span, both - * [span.getLocationMessage] and [toString] are equivalent. Otherwise, - * [span.getLocationMessage] will not show any source url information, but - * [toString] will include 'ParserError:' as a prefix. - */ + /// Gets the human readable error message for this error. Use + /// [span.getLocationMessage] or [toString] to get a message including span + /// information. If there is a file associated with the span, both + /// [span.getLocationMessage] and [toString] are equivalent. Otherwise, + /// [span.getLocationMessage] will not show any source url information, but + /// [toString] will include 'ParserError:' as a prefix. String get message => formatStr(errorMessages[errorCode], data); String toString() { diff --git a/pkgs/html/lib/parser_console.dart b/pkgs/html/lib/parser_console.dart index 7858ab2e0..515f891c4 100644 --- a/pkgs/html/lib/parser_console.dart +++ b/pkgs/html/lib/parser_console.dart @@ -1,19 +1,15 @@ -/** - * This library adds `dart:io` support to the HTML5 parser. Call - * [initDartIOSupport] before calling the [parse] methods and they will accept - * a [RandomAccessFile] as input, in addition to the other input types. - */ +/// This library adds `dart:io` support to the HTML5 parser. Call +/// [initDartIOSupport] before calling the [parse] methods and they will accept +/// a [RandomAccessFile] as input, in addition to the other input types. library parser_console; import 'dart:io'; import 'parser.dart'; import 'src/inputstream.dart' as inputstream; -/** - * Adds support to the [HtmlParser] for running on a console VM. In particular - * this means it will be able to handle `dart:io` and [RandomAccessFile]s as - * input to the various [parse] methods. - */ +/// Adds support to the [HtmlParser] for running on a console VM. In particular +/// this means it will be able to handle `dart:io` and [RandomAccessFile]s as +/// input to the various [parse] methods. void useConsole() { inputstream.consoleSupport = new _ConsoleSupport(); } @@ -26,7 +22,7 @@ class _ConsoleSupport extends inputstream.ConsoleSupport { } // TODO(jmesserly): this should be `RandomAccessFile.readAllBytes`. -/** Synchronously reads all bytes from the [file]. */ +/// Synchronously reads all bytes from the [file]. List<int> readAllBytesFromFile(RandomAccessFile file) { int length = file.lengthSync(); var bytes = new List<int>(length); diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 7fce8fdc3..9c04999b9 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -1,15 +1,13 @@ -/** Decodes bytes using the correct name. See [decodeBytes]. */ +/// Decodes bytes using the correct name. See [decodeBytes]. library char_encodings; import 'dart:collection'; import 'package:utf/utf.dart'; // TODO(jmesserly): this function is conspicuously absent from dart:utf. -/** - * Returns true if the [bytes] starts with a UTF-8 byte order mark. - * Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is - * used in HTML to detect the UTF- - */ +/// Returns true if the [bytes] starts with a UTF-8 byte order mark. +/// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is +/// used in HTML to detect the UTF- bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { int end = length != null ? offset + length : bytes.length; return (offset + 3) <= end && @@ -20,11 +18,9 @@ bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { // TODO(jmesserly): it's unfortunate that this has to be one-shot on the entire // file, but dart:utf does not expose stream-based decoders yet. -/** - * Decodes the [bytes] with the provided [encoding] and returns an iterable for - * the codepoints. Supports the major unicode encodings as well as ascii and - * and windows-1252 encodings. - */ +/// Decodes the [bytes] with the provided [encoding] and returns an iterable for +/// the codepoints. Supports the major unicode encodings as well as ascii and +/// and windows-1252 encodings. Iterable<int> decodeBytes(String encoding, List<int> bytes, [int offset = 0, int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { @@ -78,10 +74,8 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes, // TODO(jmesserly): use dart:utf once http://dartbug.com/6476 is fixed. -/** - * Returns the code points for the [input]. This works like [String.charCodes] - * but it decodes UTF-16 surrogate pairs. - */ +/// Returns the code points for the [input]. This works like [String.charCodes] +/// but it decodes UTF-16 surrogate pairs. List<int> toCodepoints(String input) { var newCodes = <int>[]; for (int i = 0; i < input.length; i++) { @@ -102,12 +96,10 @@ List<int> toCodepoints(String input) { } -/** - * Decodes [windows-1252](http://en.wikipedia.org/wiki/Windows-1252) bytes as an - * iterable. Thus, the consumer can only convert as much of the input as needed. - * Set the [replacementCharacter] to null to throw an [ArgumentError] - * rather than replace the bad value. - */ +/// Decodes [windows-1252](http://en.wikipedia.org/wiki/Windows-1252) bytes as +/// an iterable. Thus, the consumer can only convert as much of the input as +/// needed. Set the [replacementCharacter] to null to throw an [ArgumentError] +/// rather than replace the bad value. IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, [int offset = 0, int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { @@ -116,11 +108,9 @@ IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, } -/** - * Return type of [decodeWindows1252AsIterable] and variants. The Iterable type - * provides an iterator on demand and the iterator will only translate bytes - * as requested by the user of the iterator. (Note: results are not cached.) - */ +/// Return type of [decodeWindows1252AsIterable] and variants. The Iterable type +/// provides an iterator on demand and the iterator will only translate bytes +/// as requested by the user of the iterator. (Note: results are not cached.) class IterableWindows1252Decoder extends IterableBase<int> { final List<int> bytes; final int offset; @@ -136,14 +126,12 @@ class IterableWindows1252Decoder extends IterableBase<int> { } -/** - * Provides an iterator of Unicode codepoints from windows-1252 encoded bytes. - * The parameters can set an offset into a list of bytes (as int), limit the - * length of the values to be decoded, and override the default Unicode - * replacement character. Set the replacementCharacter to null to throw an - * ArgumentError rather than replace the bad value. The return value - * from this method can be used as an Iterable (e.g. in a for-loop). - */ +/// Provides an iterator of Unicode codepoints from windows-1252 encoded bytes. +/// The parameters can set an offset into a list of bytes (as int), limit the +/// length of the values to be decoded, and override the default Unicode +/// replacement character. Set the replacementCharacter to null to throw an +/// ArgumentError rather than replace the bad value. The return value +/// from this method can be used as an Iterable (e.g. in a for-loop). class Windows1252Decoder implements Iterator<int> { final int replacementCodepoint; final List<int> _bytes; diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 9cc03ad80..b8e4dbd2f 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -16,11 +16,9 @@ class ReparseException implements Exception { // TODO(jmesserly): assuming the programmatic name is not important, it would be // good to make these "static const" fields on an ErrorMessage class. -/** - * These are error messages emitted by [HtmlParser]. The values use Python style - * string formatting, as implemented by [formatStr]. That function only supports - * the subset of format functionality used here. - */ +/// These are error messages emitted by [HtmlParser]. The values use Python +/// style string formatting, as implemented by [formatStr]. That function only +/// supports the subset of format functionality used here. const Map<String, String> errorMessages = const { "null-character": "Null character in input stream, replaced with U+FFFD.", diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 390e433b8..8bb861c42 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -6,11 +6,9 @@ import 'inputstream.dart'; // TODO(jmesserly): I converted StopIteration to StateError("No more elements"). // Seems strange to throw this from outside of an iterator though. -/** - * String-like object with an associated position and various extra methods - * If the position is ever greater than the string length then an exception is - * raised. - */ +/// String-like object with an associated position and various extra methods +/// If the position is ever greater than the string length then an exception is +/// raised. class EncodingBytes extends IterableBase<String> { final String _bytes; int _position = -1; @@ -62,7 +60,7 @@ class EncodingBytes extends IterableBase<String> { String get currentByte => _bytes[position]; - /** Skip past a list of characters. Defaults to skipping [isWhitespace]. */ + /// Skip past a list of characters. Defaults to skipping [isWhitespace]. String skipChars([CharPreciate skipChars]) { if (skipChars == null) skipChars = isWhitespace; var p = position; // use property for the error-checking @@ -91,11 +89,9 @@ class EncodingBytes extends IterableBase<String> { return null; } - /** - * Look for a sequence of bytes at the start of a string. If the bytes - * are found return true and advance the position to the byte after the - * match. Otherwise return false and leave the position alone. - */ + /// Look for a sequence of bytes at the start of a string. If the bytes + /// are found return true and advance the position to the byte after the + /// match. Otherwise return false and leave the position alone. bool matchBytes(String bytes) { var p = position; if (_bytes.length < p + bytes.length) { @@ -109,10 +105,8 @@ class EncodingBytes extends IterableBase<String> { return false; } - /** - * Look for the next sequence of bytes matching a given sequence. If - * a match is found advance the position to the last byte of the match - */ + /// Look for the next sequence of bytes matching a given sequence. If + /// a match is found advance the position to the last byte of the match bool jumpTo(String bytes) { var newPosition = _bytes.indexOf(bytes, position); if (newPosition >= 0) { @@ -130,12 +124,12 @@ class EncodingBytes extends IterableBase<String> { } } -/** Mini parser for detecting character encoding from meta elements. */ +/// Mini parser for detecting character encoding from meta elements. class EncodingParser { final EncodingBytes data; String encoding; - /** [bytes] - the data to work on for encoding detection. */ + /// [bytes] - the data to work on for encoding detection. EncodingParser(List<int> bytes) // Note: this is intentionally interpreting bytes as codepoints. : data = new EncodingBytes(new String.fromCharCodes(bytes).toLowerCase()); @@ -173,7 +167,7 @@ class EncodingParser { return encoding; } - /** Skip over comments. */ + /// Skip over comments. bool handleComment() => data.jumpTo("-->"); bool handleMeta() { @@ -243,10 +237,8 @@ class EncodingParser { bool handleOther() => data.jumpTo(">"); - /** - * Return a name,value pair for the next attribute in the stream, - * if one is found, or null - */ + /// Return a name,value pair for the next attribute in the stream, + /// if one is found, or null List<String> getAttribute() { // Step 1 (skip chars) var c = data.skipChars((x) => x == "/" || isWhitespace(x)); diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index a3d604674..5686abf75 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -8,7 +8,7 @@ import 'constants.dart'; import 'utils.dart'; import 'encoding_parser.dart'; -/** Hooks to call into dart:io without directly referencing it. */ +/// Hooks to call into dart:io without directly referencing it. class ConsoleSupport { List<int> bytesFromFile(source) => null; } @@ -16,36 +16,32 @@ class ConsoleSupport { // TODO(jmesserly): use lazy init here when supported. ConsoleSupport consoleSupport = new ConsoleSupport(); -/** - * Provides a unicode stream of characters to the HtmlTokenizer. - * - * This class takes care of character encoding and removing or replacing - * incorrect byte-sequences and also provides column and line tracking. - */ +/// Provides a unicode stream of characters to the HtmlTokenizer. +/// +/// This class takes care of character encoding and removing or replacing +/// incorrect byte-sequences and also provides column and line tracking. class HtmlInputStream { - /** - * Number of bytes to use when looking for a meta element with - * encoding information. - */ + /// Number of bytes to use when looking for a meta element with + /// encoding information. static const int numBytesMeta = 512; - /** Encoding to use if no other information can be found. */ + /// Encoding to use if no other information can be found. static const String defaultEncoding = 'windows-1252'; - /** The name of the character encoding. */ + /// The name of the character encoding. String charEncodingName; - /** True if we are certain about [charEncodingName], false for tenative. */ + /// True if we are certain about [charEncodingName], false for tenative. bool charEncodingCertain = true; final bool generateSpans; - /** Location where the contents of the stream were found. */ + /// Location where the contents of the stream were found. final String sourceUrl; List<int> _rawBytes; - /** Raw UTF-16 codes, used if a Dart String is passed in. */ + /// Raw UTF-16 codes, used if a Dart String is passed in. Iterable<int> _rawChars; Queue<String> errors; @@ -58,22 +54,20 @@ class HtmlInputStream { int _offset; - /** - * Initialises the HtmlInputStream. - * - * HtmlInputStream(source, [encoding]) -> Normalized stream from source - * for use by html5lib. - * - * [source] can be either a [String] or a [List<int>] containing the raw - * bytes, or a file if [consoleSupport] is initialized. - * - * The optional encoding parameter must be a string that indicates - * the encoding. If specified, that encoding will be used, - * regardless of any BOM or later declaration (such as in a meta - * element) - * - * [parseMeta] - Look for a <meta> element containing encoding information - */ + /// Initialises the HtmlInputStream. + /// + /// HtmlInputStream(source, [encoding]) -> Normalized stream from source + /// for use by html5lib. + /// + /// [source] can be either a [String] or a [List<int>] containing the raw + /// bytes, or a file if [consoleSupport] is initialized. + /// + /// The optional encoding parameter must be a string that indicates + /// the encoding. If specified, that encoding will be used, + /// regardless of any BOM or later declaration (such as in a meta + /// element) + /// + /// [parseMeta] - Look for a <meta> element containing encoding information HtmlInputStream(source, [String encoding, bool parseMeta = true, this.generateSpans = false, this.sourceUrl]) : charEncodingName = codecName(encoding) { @@ -195,11 +189,9 @@ class HtmlInputStream { } } - /** - * Attempts to detect at BOM at the start of the stream. If - * an encoding can be determined from the BOM return the name of the - * encoding otherwise return null. - */ + /// Attempts to detect at BOM at the start of the stream. If + /// an encoding can be determined from the BOM return the name of the + /// encoding otherwise return null. String detectBOM() { // Try detecting the BOM using bytes from the string if (hasUtf8Bom(_rawBytes)) { @@ -216,7 +208,7 @@ class HtmlInputStream { return null; } - /** Report the encoding declared by the meta element. */ + /// Report the encoding declared by the meta element. String detectEncodingMeta() { var parser = new EncodingParser(slice(_rawBytes, 0, numBytesMeta)); var encoding = parser.getEncoding(); @@ -228,16 +220,12 @@ class HtmlInputStream { return encoding; } - /** - * Returns the current offset in the stream, i.e. the number of codepoints - * since the start of the file. - */ + /// Returns the current offset in the stream, i.e. the number of codepoints + /// since the start of the file. int get position => _offset; - /** - * Read one character from the stream or queue if available. Return - * EOF when EOF is reached. - */ + /// Read one character from the stream or queue if available. Return + /// EOF when EOF is reached. String char() { if (_offset >= _chars.length) return EOF; return new String.fromCharCodes([_chars[_offset++]]); @@ -248,10 +236,8 @@ class HtmlInputStream { return new String.fromCharCodes([_chars[_offset]]); } - /** - * Returns a string of characters from the stream up to but not - * including any character in 'characters' or EOF. - */ + /// Returns a string of characters from the stream up to but not + /// including any character in 'characters' or EOF. String charsUntil(String characters, [bool opposite = false]) { int start = _offset; String c; @@ -296,10 +282,8 @@ bool invalidUnicode(int c) { return false; } -/** - * Return the python codec name corresponding to an encoding or null if the - * string doesn't correspond to a valid encoding. - */ +/// Return the python codec name corresponding to an encoding or null if the +/// string doesn't correspond to a valid encoding. String codecName(String encoding) { final asciiPunctuation = new RegExp( "[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]"); diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index d779043cd..0ba70733b 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -1,7 +1,7 @@ // TODO(jmesserly): remove this once we have a subclassable growable list // in our libraries. -/** A [List] proxy that you can subclass. */ +/// A [List] proxy that you can subclass. library list_proxy; import 'dart:collection'; @@ -10,14 +10,12 @@ import 'dart:math' show Random; // TOOD(jmesserly): this needs to be removed, but fixing NodeList is tricky. class ListProxy<E> extends IterableBase<E> implements List<E> { - /** The inner [List<T>] with the actual storage. */ + /// The inner [List<T>] with the actual storage. final List<E> _list; - /** - * Creates a list proxy. - * You can optionally specify the list to use for [storage] of the items, - * otherwise this will create a [List<E>]. - */ + /// Creates a list proxy. + /// You can optionally specify the list to use for [storage] of the items, + /// otherwise this will create a [List<E>]. ListProxy([List<E> storage]) : _list = storage != null ? storage : <E>[]; diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 1e790da85..b1ec1de34 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -1,10 +1,10 @@ -/** This library contains token types used by the html5 tokenizer. */ +/// This library contains token types used by the html5 tokenizer. library token; import 'dart:collection'; import 'package:source_maps/span.dart' show FileSpan; -/** An html5 token. */ +/// An html5 token. abstract class Token { FileSpan span; @@ -20,18 +20,16 @@ abstract class TagToken extends Token { } class StartTagToken extends TagToken { - /** - * The tag's attributes. A map from the name to the value, where the name - * can be a [String] or [AttributeName]. - */ + /// The tag's attributes. A map from the name to the value, where the name + /// can be a [String] or [AttributeName]. LinkedHashMap<dynamic, String> data; - /** The attribute spans if requested. Otherwise null. */ + /// The attribute spans if requested. Otherwise null. List<TagAttribute> attributeSpans; bool selfClosingAcknowledged; - /** The namespace. This is filled in later during tree building. */ + /// The namespace. This is filled in later during tree building. String namespace; StartTagToken(String name, {this.data, bool selfClosing: false, @@ -54,7 +52,7 @@ abstract class StringToken extends Token { } class ParseErrorToken extends StringToken { - /** Extra information that goes along with the error message. */ + /// Extra information that goes along with the error message. Map messageParams; ParseErrorToken(String data, {this.messageParams}) : super(data); @@ -91,11 +89,9 @@ class DoctypeToken extends Token { int get kind => TokenKind.doctype; } -/** - * These are used by the tokenizer to build up the attribute map. - * They're also used by [StartTagToken.attributeSpans] if attribute spans are - * requested. - */ +/// These are used by the tokenizer to build up the attribute map. +/// They're also used by [StartTagToken.attributeSpans] if attribute spans are +/// requested. class TagAttribute { String name; String value; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 3f398e997..24873baa9 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -26,9 +26,7 @@ Map<String, List<String>> entitiesByFirstChar = (() { // - use switch instead of the sequential if tests // - avoid string concat -/** - * This class takes care of tokenizing HTML. - */ +/// This class takes care of tokenizing HTML. class HtmlTokenizer implements Iterator<Token> { // TODO(jmesserly): a lot of these could be made private @@ -38,26 +36,22 @@ class HtmlTokenizer implements Iterator<Token> { final bool lowercaseAttrName; - /** True to generate spans in for [Token.span]. */ + /// True to generate spans in for [Token.span]. final bool generateSpans; - /** True to generate spans for attributes. */ + /// True to generate spans for attributes. final bool attributeSpans; - /** - * This reference to the parser is used for correct CDATA handling. - * The [HtmlParser] will set this at construction time. - */ + /// This reference to the parser is used for correct CDATA handling. + /// The [HtmlParser] will set this at construction time. HtmlParser parser; final Queue<Token> tokenQueue; - /** Holds the token that is currently being processed. */ + /// Holds the token that is currently being processed. Token currentToken; - /** - * Holds a reference to the method to be invoked for the next parser state. - */ + /// Holds a reference to the method to be invoked for the next parser state. // TODO(jmesserly): the type should be "Predicate" but a dart2js checked mode // bug prevents us from doing that. See http://dartbug.com/12465 Function state; @@ -124,13 +118,11 @@ class HtmlTokenizer implements Iterator<Token> { if (attributeSpans) attr.start = stream.position - name.length; } - /** - * This is where the magic happens. - * - * We do our usually processing through the states and when we have a token - * to return we yield the token which pauses processing until the next token - * is requested. - */ + /// This is where the magic happens. + /// + /// We do our usually processing through the states and when we have a token + /// to return we yield the token which pauses processing until the next token + /// is requested. bool moveNext() { // Start processing. When EOF is reached state will return false; // instead of true and the loop will terminate. @@ -149,10 +141,8 @@ class HtmlTokenizer implements Iterator<Token> { return true; } - /** - * Resets the tokenizer state. Calling this does not reset the [stream] or - * the [parser]. - */ + /// Resets the tokenizer state. Calling this does not reset the [stream] or + /// the [parser]. void reset() { _lastOffset = 0; tokenQueue.clear(); @@ -163,7 +153,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } - /** Adds a token to the queue. Sets the span if needed. */ + /// Adds a token to the queue. Sets the span if needed. void _addToken(Token token) { if (generateSpans && token.span == null) { int offset = stream.position; @@ -175,11 +165,9 @@ class HtmlTokenizer implements Iterator<Token> { tokenQueue.add(token); } - /** - * This function returns either U+FFFD or the character based on the - * decimal or hexadecimal representation. It also discards ";" if present. - * If not present it will add a [ParseErrorToken]. - */ + /// This function returns either U+FFFD or the character based on the + /// decimal or hexadecimal representation. It also discards ";" if present. + /// If not present it will add a [ParseErrorToken]. String consumeNumberEntity(bool isHex) { var allowed = isDigit; var radix = 10; @@ -345,16 +333,14 @@ class HtmlTokenizer implements Iterator<Token> { } } - /** This method replaces the need for "entityInAttributeValueState". */ + /// This method replaces the need for "entityInAttributeValueState". void processEntityInAttribute(String allowedChar) { consumeEntity(allowedChar: allowedChar, fromAttribute: true); } - /** - * This method is a generic handler for emitting the tags. It also sets - * the state to "data" because that's what's needed after a token has been - * emitted. - */ + /// This method is a generic handler for emitting the tags. It also sets + /// the state to "data" because that's what's needed after a token has been + /// emitted. void emitCurrentToken() { var token = currentToken; // Add token to the queue to be yielded diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 03707b572..8c4d235a1 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -1,4 +1,4 @@ -/** Internals to the tree builders. */ +/// Internals to the tree builders. library treebuilder; import 'dart:collection'; @@ -66,7 +66,7 @@ bool _nodesEqual(Node node1, Node node2) { _mapEquals(node1.attributes, node2.attributes); } -/** Basic treebuilder implementation. */ +/// Basic treebuilder implementation. class TreeBuilder { final String defaultNamespace; @@ -80,10 +80,8 @@ class TreeBuilder { Node formPointer; - /** - * Switch the function used to insert an element from the - * normal one to the misnested table one and back again - */ + /// Switch the function used to insert an element from the + /// normal one to the misnested table one and back again bool insertFromTable; TreeBuilder(bool namespaceHTMLElements) @@ -212,11 +210,9 @@ class TreeBuilder { } } - /** - * Check if an element exists between the end of the active - * formatting elements and the last marker. If it does, return it, else - * return null. - */ + /// Check if an element exists between the end of the active + /// formatting elements and the last marker. If it does, return it, else + /// return null. Node elementInActiveFormattingElements(String name) { for (Node item in activeFormattingElements.reversed) { // Check for Marker first because if it's a Marker it doesn't have a @@ -249,7 +245,7 @@ class TreeBuilder { parent.nodes.add(new Comment(token.data)..sourceSpan = token.span); } - /** Create an element but don't insert it anywhere */ + /// Create an element but don't insert it anywhere Element createElement(StartTagToken token) { var name = token.name; var namespace = token.namespace; @@ -278,7 +274,7 @@ class TreeBuilder { } Element insertElementTable(token) { - /** Create an element and insert it into the tree */ + /// Create an element and insert it into the tree var element = createElement(token); if (!tableInsertModeElements.contains(openElements.last.tagName)) { return insertElementNormal(token); @@ -299,7 +295,7 @@ class TreeBuilder { return element; } - /** Insert text data. */ + /// Insert text data. void insertText(String data, FileSpan span) { var parent = openElements.last; @@ -314,10 +310,8 @@ class TreeBuilder { } } - /** - * Insert [data] as text in the current node, positioned before the - * start of node [refNode] or to the end of the node's text. - */ + /// Insert [data] as text in the current node, positioned before the + /// start of node [refNode] or to the end of the node's text. static void _insertText(Node parent, String data, FileSpan span, [Element refNode]) { var nodes = parent.nodes; @@ -344,10 +338,8 @@ class TreeBuilder { } } - /** - * Get the foster parent element, and sibling to insert before - * (or null) when inserting a misnested table node - */ + /// Get the foster parent element, and sibling to insert before + /// (or null) when inserting a misnested table node List<Node> getTableMisnestedNodePosition() { // The foster parent element is the one which comes before the most // recently opened table element @@ -388,10 +380,10 @@ class TreeBuilder { } } - /** Return the final tree. */ + /// Return the final tree. Document getDocument() => document; - /** Return the final fragment. */ + /// Return the final fragment. DocumentFragment getFragment() { //XXX assert innerHTML var fragment = new DocumentFragment(); diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 1a2bb9d6d..c998e0f00 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -1,4 +1,4 @@ -/** Misc things that were useful when porting the code from Python. */ +/// Misc things that were useful when porting the code from Python. library utils; import 'constants.dart'; @@ -71,11 +71,9 @@ String padWithZeros(String str, int size) { // TODO(jmesserly): this implementation is pretty wrong, but I need something // quick until dartbug.com/1694 is fixed. -/** - * Format a string like Python's % string format operator. Right now this only - * supports a [data] dictionary used with %s or %08x. Those were the only things - * needed for [errorMessages]. - */ +/// Format a string like Python's % string format operator. Right now this only +/// supports a [data] dictionary used with %s or %08x. Those were the only +/// things needed for [errorMessages]. String formatStr(String format, Map data) { if (data == null) return format; data.forEach((key, value) { diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 301e82298..43a963732 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -1,4 +1,4 @@ -/** Additional feature tests that aren't based on test data. */ +/// Additional feature tests that aren't based on test data. library dom_test; import 'package:unittest/unittest.dart'; diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 0071a1f12..f96a8e25f 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -1,4 +1,4 @@ -/** Additional feature tests that aren't based on test data. */ +/// Additional feature tests that aren't based on test data. library parser_feature_test; import 'package:unittest/unittest.dart'; diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index dbfb3fc0b..821eb2d7e 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -109,7 +109,7 @@ void main() { } } -/** Extract the name for the test based on the test input data. */ +/// Extract the name for the test based on the test input data. _nameFor(String input) { // Using JSON.decode to unescape other unicode characters var escapeQuote = input diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 11466797a..4d2cb5afc 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -1,4 +1,4 @@ -/** Support code for the tests in this directory. */ +/// Support code for the tests in this directory. library support; import 'dart:io'; @@ -72,10 +72,8 @@ class TestData extends IterableBase<Map> { return result; } - /** - * If the current heading is a test section heading return the heading, - * otherwise return null. - */ + /// If the current heading is a test section heading return the heading, + /// otherwise return null. static String sectionHeading(String line) { return line.startsWith("#") ? line.substring(1).trim() : null; } @@ -91,14 +89,12 @@ class TestData extends IterableBase<Map> { } } -/** - * Serialize the [document] into the html5 test data format. - */ +/// Serialize the [document] into the html5 test data format. testSerializer(Document document) { return (new TestSerializer()..visit(document)).toString(); } -/** Serializes the DOM into test format. See [testSerializer]. */ +/// Serializes the DOM into test format. See [testSerializer]. class TestSerializer extends TreeVisitor { final StringBuffer _str; int _indent = 0; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 439e44000..5c87e160e 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -134,12 +134,10 @@ List normalizeTokens(List tokens) { } -/** - * Test whether the test has passed or failed - * - * If the ignoreErrorOrder flag is set to true we don't test the relative - * positions of parse errors and non parse errors. - */ +/// Test whether the test has passed or failed +/// +/// If the ignoreErrorOrder flag is set to true we don't test the relative +/// positions of parse errors and non parse errors. void expectTokensMatch(List expectedTokens, List receivedTokens, bool ignoreErrorOrder, [bool ignoreErrors = false, String message]) { From 8815c84bac7b6f3e9d661d9f71b969bbfaee9264 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Tue, 25 Feb 2014 04:07:47 +0000 Subject: [PATCH 025/212] [html5lib] api updates: localName R=sigmund@google.com Review URL: https://codereview.chromium.org//178303009 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@33004 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 132 ++++++++++------- pkgs/html/lib/dom_parsing.dart | 28 +++- pkgs/html/lib/parser.dart | 182 +++++++++++++----------- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/treebuilder.dart | 47 +++--- pkgs/html/test/parser_feature_test.dart | 60 ++++---- 6 files changed, 258 insertions(+), 193 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 12d664790..b81c1ff64 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -75,9 +75,13 @@ abstract class Node { static const int PROCESSING_INSTRUCTION_NODE = 7; static const int TEXT_NODE = 3; - // TODO(jmesserly): this should be on Element - /// The tag name associated with the node. - final String tagName; + /// Note: For now we use it to implement the deprecated tagName property. + final String _tagName; + + /// *Deprecated* use [Element.localName] instead. + /// Note: after removal, this will be replaced by a correct version that + /// returns uppercase [as specified](http://dom.spec.whatwg.org/#dom-element-tagname). + @deprecated String get tagName => _tagName; /// The parent of the current node (or null for the document node). Node parent; @@ -104,7 +108,10 @@ abstract class Node { LinkedHashMap<dynamic, FileSpan> _attributeSpans; LinkedHashMap<dynamic, FileSpan> _attributeValueSpans; - Node(this.tagName) { + /// *Deprecated* use [new Element.tag] instead. + @deprecated Node(String tagName) : this._(tagName); + + Node._([this._tagName]) { nodes._parent = this; } @@ -138,7 +145,8 @@ abstract class Node { /// name and attributes but with no parent or child nodes. Node clone(); - String get namespace => null; + /// *Deprecated* use [Element.namespaceUri] instead. + @deprecated String get namespace => null; int get nodeType; @@ -148,23 +156,31 @@ abstract class Node { /// *Deprecated* use [nodeType]. @deprecated int get $dom_nodeType => nodeType; - String get outerHtml { + /// *Deprecated* use [Element.outerHtml] + @deprecated String get outerHtml => _outerHtml; + + /// *Deprecated* use [Element.innerHtml] + @deprecated String get innerHtml => _innerHtml; + @deprecated set innerHtml(String value) { _innerHtml = value; } + + // http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface + String get _outerHtml { var str = new StringBuffer(); _addOuterHtml(str); return str.toString(); } - String get innerHtml { + String get _innerHtml { var str = new StringBuffer(); _addInnerHtml(str); return str.toString(); } - set innerHtml(String value) { + set _innerHtml(String value) { nodes.clear(); // TODO(jmesserly): should be able to get the same effect by adding the // fragment directly. - nodes.addAll(parseFragment(value, container: tagName).nodes); + nodes.addAll(parseFragment(value, container: _tagName).nodes); } // Implemented per: http://dom.spec.whatwg.org/#dom-node-textcontent @@ -181,8 +197,6 @@ abstract class Node { for (Node child in nodes) child._addOuterHtml(str); } - String toString() => tagName; - Node remove() { // TODO(jmesserly): is parent == null an error? if (parent != null) { @@ -216,10 +230,9 @@ abstract class Node { /// Return true if the node has children or text. bool hasContent() => nodes.length > 0; - Pair<String, String> get nameTuple { - var ns = namespace != null ? namespace : Namespaces.html; - return new Pair(ns, tagName); - } + /// *Deprecated* construct a pair using the namespaceUri and the name. + @deprecated Pair<String, String> get nameTuple => + this is Element ? getElementNameTuple(this) : null; /// Move all the children of the current node to [newParent]. /// This is needed so that trees that don't store text as nodes move the @@ -308,7 +321,7 @@ abstract class Node { Element _queryType(String tag) { for (var node in nodes) { if (node is! Element) continue; - if (node.tagName == tag) return node; + if (node.localName == tag) return node; var result = node._queryType(tag); if (result != null) return result; } @@ -318,7 +331,7 @@ abstract class Node { void _queryAllType(String tag, List<Element> results) { for (var node in nodes) { if (node is! Element) continue; - if (node.tagName == tag) results.add(node); + if (node.localName == tag) results.add(node); node._queryAllType(tag, results); } } @@ -353,7 +366,7 @@ abstract class Node { } class Document extends Node { - Document() : super(null); + Document() : super._(); factory Document.html(String html) => parse(html); int get nodeType => Node.DOCUMENT_NODE; @@ -363,6 +376,14 @@ class Document extends Node { Element get head => documentElement.querySelector('head'); Element get body => documentElement.querySelector('body'); + /// Returns a fragment of HTML or XML that represents the element and its + /// contents. + // TODO(jmesserly): this API is not specified in: + // <http://domparsing.spec.whatwg.org/> nor is it in dart:html, instead + // only Element has outerHtml. However it is quite useful. Should we move it + // to dom_parsing, where we keep other custom APIs? + String get outerHtml => _outerHtml; + String toString() => "#document"; void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); @@ -385,10 +406,13 @@ class DocumentFragment extends Document { } class DocumentType extends Node { + final String name; final String publicId; final String systemId; - DocumentType(String name, this.publicId, this.systemId) : super(name); + DocumentType(String name, this.publicId, this.systemId) + // Note: once Node.tagName is removed, don't pass "name" to super + : name = name, super._(name); int get nodeType => Node.DOCUMENT_TYPE_NODE; @@ -398,9 +422,9 @@ class DocumentType extends Node { // it seems useful, and the parser can handle it, so for now keeping it. var pid = publicId != null ? publicId : ''; var sid = systemId != null ? systemId : ''; - return '<!DOCTYPE $tagName "$pid" "$sid">'; + return '<!DOCTYPE $name "$pid" "$sid">'; } else { - return '<!DOCTYPE $tagName>'; + return '<!DOCTYPE $name>'; } } @@ -409,13 +433,13 @@ class DocumentType extends Node { str.write(toString()); } - DocumentType clone() => new DocumentType(tagName, publicId, systemId); + DocumentType clone() => new DocumentType(name, publicId, systemId); } class Text extends Node { String data; - Text(this.data) : super(null); + Text(this.data) : super._(); /// *Deprecated* use [data]. @deprecated String get value => data; @@ -425,15 +449,7 @@ class Text extends Node { String toString() => '"$data"'; - void _addOuterHtml(StringBuffer str) { - // Don't escape text for certain elements, notably <script>. - if (rcdataElements.contains(parent.tagName) || - parent.tagName == 'plaintext') { - str.write(data); - } else { - str.write(htmlSerializeEscape(data)); - } - } + void _addOuterHtml(StringBuffer str) => writeTextNodeAsHtml(str, this); Text clone() => new Text(data); @@ -442,12 +458,19 @@ class Text extends Node { } class Element extends Node { - final String namespace; + final String namespaceUri; - // TODO(jmesserly): deprecate in favor of Element.tag? Or rename? - Element(String name, [this.namespace]) : super(name); + @deprecated String get namespace => namespaceUri; - Element.tag(String name) : namespace = null, super(name); + /// The [local name](http://dom.spec.whatwg.org/#concept-element-local-name) + /// of this element. + String get localName => _tagName; + + // TODO(jmesserly): deprecate in favor of [Document.createElementNS]. + // However we need every element to have a Document before this can work. + Element(String name, [this.namespaceUri]) : super._(name); + + Element.tag(String name) : namespaceUri = null, super._(name); static final _START_TAG_REGEXP = new RegExp('<(\\w+)'); @@ -506,25 +529,37 @@ class Element extends Node { int get nodeType => Node.ELEMENT_NODE; String toString() { - if (namespace == null) return "<$tagName>"; - return "<${Namespaces.getPrefix(namespace)} $tagName>"; + if (namespaceUri == null) return "<$localName>"; + return "<${Namespaces.getPrefix(namespaceUri)} $localName>"; } String get text => _getText(this); set text(String value) => _setText(this, value); + /// Returns a fragment of HTML or XML that represents the element and its + /// contents. + String get outerHtml => _outerHtml; + + /// Returns a fragment of HTML or XML that represents the element's contents. + /// Can be set, to replace the contents of the element with nodes parsed from + /// the given string. + String get innerHtml => _innerHtml; + // TODO(jmesserly): deprecate in favor of: + // <https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element@id_setInnerHtml> + set innerHtml(String value) { _innerHtml = value; } + void _addOuterHtml(StringBuffer str) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments // Element is the most complicated one. - if (namespace == null || - namespace == Namespaces.html || - namespace == Namespaces.mathml || - namespace == Namespaces.svg) { - str.write('<$tagName'); + if (namespaceUri == null || + namespaceUri == Namespaces.html || + namespaceUri == Namespaces.mathml || + namespaceUri == Namespaces.svg) { + str.write('<$localName'); } else { // TODO(jmesserly): the spec doesn't define "qualified name". // I'm not sure if this is correct, but it should parse reasonably. - str.write('<${Namespaces.getPrefix(namespace)}:$tagName'); + str.write('<${Namespaces.getPrefix(namespaceUri)}:$localName'); } if (attributes.length > 0) { @@ -538,7 +573,8 @@ class Element extends Node { str.write('>'); if (nodes.length > 0) { - if (tagName == 'pre' || tagName == 'textarea' || tagName == 'listing') { + if (localName == 'pre' || localName == 'textarea' || + localName == 'listing') { final first = nodes[0]; if (first is Text && first.data.startsWith('\n')) { // These nodes will remove a leading \n at parse time, so if we still @@ -552,10 +588,10 @@ class Element extends Node { // void elements must not have an end tag // http://dev.w3.org/html5/markup/syntax.html#void-elements - if (!isVoidElement(tagName)) str.write('</$tagName>'); + if (!isVoidElement(localName)) str.write('</$localName>'); } - Element clone() => new Element(tagName, namespace) + Element clone() => new Element(localName, namespaceUri) ..attributes = new LinkedHashMap.from(attributes); String get id { @@ -575,7 +611,7 @@ class Element extends Node { class Comment extends Node { String data; - Comment(this.data) : super(null); + Comment(this.data) : super._(); int get nodeType => Node.COMMENT_NODE; diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index fa13261ee..aed9fffe2 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -3,6 +3,7 @@ library dom_parsing; import 'dom.dart'; +import 'src/constants.dart' show rcdataElements; /// A simple tree visitor for the DOM nodes. class TreeVisitor { @@ -67,17 +68,17 @@ class CodeMarkupVisitor extends TreeVisitor { } visitDocumentType(DocumentType node) { - _str.write('<code class="markup doctype">&lt;!DOCTYPE ${node.tagName}>' + _str.write('<code class="markup doctype">&lt;!DOCTYPE ${node.name}>' '</code>'); } visitText(Text node) { - // TODO(jmesserly): would be nice to use _addOuterHtml directly. - _str.write(node.outerHtml); + writeTextNodeAsHtml(_str, node); } visitElement(Element node) { - _str.write('&lt;<code class="markup element-name">${node.tagName}</code>'); + final tag = node.localName; + _str.write('&lt;<code class="markup element-name">$tag</code>'); if (node.attributes.length > 0) { node.attributes.forEach((key, v) { v = htmlSerializeEscape(v, attributeMode: true); @@ -88,12 +89,12 @@ class CodeMarkupVisitor extends TreeVisitor { if (node.nodes.length > 0) { _str.write(">"); visitChildren(node); - } else if (isVoidElement(node.tagName)) { + } else if (isVoidElement(tag)) { _str.write(">"); return; } _str.write( - '&lt;/<code class="markup element-name">${node.tagName}</code>>'); + '&lt;/<code class="markup element-name">$tag</code>>'); } visitComment(Comment node) { @@ -160,3 +161,18 @@ bool isVoidElement(String tagName) { } return false; } + +/// Serialize text node according to: +/// <http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm> +void writeTextNodeAsHtml(StringBuffer str, Text node) { + // Don't escape text for certain elements, notably <script>. + final parent = node.parent; + if (parent is Element) { + var tag = parent.localName; + if (rcdataElements.contains(tag) || tag == 'plaintext') { + str.write(node.data); + return; + } + } + str.write(htmlSerializeEscape(node.data)); +} diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index c388019e3..2d04f8e8a 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -249,28 +249,28 @@ class HtmlParser { framesetOK = true; } - bool isHTMLIntegrationPoint(Node element) { - if (element.tagName == "annotation-xml" && - element.namespace == Namespaces.mathml) { + bool isHTMLIntegrationPoint(Element element) { + if (element.localName == "annotation-xml" && + element.namespaceUri == Namespaces.mathml) { var enc = element.attributes["encoding"]; if (enc != null) enc = asciiUpper2Lower(enc); return enc == "text/html" || enc == "application/xhtml+xml"; } else { return htmlIntegrationPointElements.contains( - new Pair(element.namespace, element.tagName)); + new Pair(element.namespaceUri, element.localName)); } } - bool isMathMLTextIntegrationPoint(Node element) { + bool isMathMLTextIntegrationPoint(Element element) { return mathmlTextIntegrationPointElements.contains( - new Pair(element.namespace, element.tagName)); + new Pair(element.namespaceUri, element.localName)); } bool inForeignContent(Token token, int type) { if (tree.openElements.length == 0) return false; var node = tree.openElements.last; - if (node.namespace == tree.defaultNamespace) return false; + if (node.namespaceUri == tree.defaultNamespace) return false; if (isMathMLTextIntegrationPoint(node)) { if (type == TokenKind.startTag && @@ -283,7 +283,7 @@ class HtmlParser { } } - if (node.tagName == "annotation-xml" && type == TokenKind.startTag && + if (node.localName == "annotation-xml" && type == TokenKind.startTag && (token as StartTagToken).name == "svg") { return false; } @@ -491,8 +491,8 @@ class HtmlParser { void resetInsertionMode() { // The name of this method is mostly historical. (It's also used in the // specification.) - for (Node node in tree.openElements.reversed) { - var nodeName = node.tagName; + for (var node in tree.openElements.reversed) { + var nodeName = node.localName; bool last = node == tree.openElements[0]; if (last) { assert(innerHTMLMode); @@ -505,7 +505,7 @@ class HtmlParser { assert(innerHTMLMode); break; } - if (!last && node.namespace != tree.defaultNamespace) { + if (!last && node.namespaceUri != tree.defaultNamespace) { continue; } switch (nodeName) { @@ -616,7 +616,7 @@ class Phase { /// Helper method for popping openElements. void popOpenElementsUntil(String name) { var node = tree.openElements.removeLast(); - while (node.tagName != name) { + while (node.localName != name) { node = tree.openElements.removeLast(); } } @@ -971,7 +971,7 @@ class InHeadPhase extends Phase { void endTagHead(EndTagToken token) { var node = parser.tree.openElements.removeLast(); - assert(node.tagName == "head"); + assert(node.localName == "head"); parser.phase = parser._afterHeadPhase; } @@ -1049,8 +1049,8 @@ class AfterHeadPhase extends Phase { {"name": token.name}); tree.openElements.add(tree.headPointer); parser._inHeadPhase.processStartTag(token); - for (Node node in tree.openElements.reversed) { - if (node.tagName == "head") { + for (var node in tree.openElements.reversed) { + if (node.localName == "head") { tree.openElements.remove(node); break; } @@ -1196,8 +1196,9 @@ class InBodyPhase extends Phase { } } - bool isMatchingFormattingElement(Node node1, Node node2) { - if (node1.tagName != node2.tagName || node1.namespace != node2.namespace) { + bool isMatchingFormattingElement(Element node1, Element node2) { + if (node1.localName != node2.localName || + node1.namespaceUri != node2.namespaceUri) { return false; } else if (node1.attributes.length != node2.attributes.length) { return false; @@ -1234,8 +1235,8 @@ class InBodyPhase extends Phase { // the real deal bool processEOF() { - for (Node node in tree.openElements.reversed) { - switch (node.tagName) { + for (var node in tree.openElements.reversed) { + switch (node.localName) { case "dd": case "dt": case "li": case "p": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": case "body": case "html": @@ -1255,7 +1256,7 @@ class InBodyPhase extends Phase { dropNewline = false; if (data.startsWith("\n")) { var lastOpen = tree.openElements.last; - if (const ["pre", "listing", "textarea"].contains(lastOpen.tagName) + if (const ["pre", "listing", "textarea"].contains(lastOpen.localName) && !lastOpen.hasContent()) { data = data.substring(1); } @@ -1296,7 +1297,7 @@ class InBodyPhase extends Phase { void startTagBody(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag", {"name": "body"}); if (tree.openElements.length == 1 - || tree.openElements[1].tagName != "body") { + || tree.openElements[1].localName != "body") { assert(parser.innerHTMLMode); } else { parser.framesetOK = false; @@ -1309,13 +1310,13 @@ class InBodyPhase extends Phase { void startTagFrameset(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"}); if ((tree.openElements.length == 1 || - tree.openElements[1].tagName != "body")) { + tree.openElements[1].localName != "body")) { assert(parser.innerHTMLMode); } else if (parser.framesetOK) { if (tree.openElements[1].parent != null) { tree.openElements[1].parent.nodes.remove(tree.openElements[1]); } - while (tree.openElements.last.tagName != "html") { + while (tree.openElements.last.localName != "html") { tree.openElements.removeLast(); } tree.insertElement(token); @@ -1358,13 +1359,13 @@ class InBodyPhase extends Phase { "dt": const ["dt", "dd"], "dd": const ["dt", "dd"]}; var stopNames = stopNamesMap[token.name]; - for (Node node in tree.openElements.reversed) { - if (stopNames.contains(node.tagName)) { - parser.phase.processEndTag(new EndTagToken(node.tagName)); + for (var node in tree.openElements.reversed) { + if (stopNames.contains(node.localName)) { + parser.phase.processEndTag(new EndTagToken(node.localName)); break; } - if (specialElements.contains(node.nameTuple) && - !const ["address", "div", "p"].contains(node.tagName)) { + if (specialElements.contains(getElementNameTuple(node)) && + !const ["address", "div", "p"].contains(node.localName)) { break; } } @@ -1388,7 +1389,7 @@ class InBodyPhase extends Phase { if (tree.elementInScope("p", variant: "button")) { endTagP(new EndTagToken("p")); } - if (headingElements.contains(tree.openElements.last.tagName)) { + if (headingElements.contains(tree.openElements.last.localName)) { parser.parseError(token.span, "unexpected-start-tag", {"name": token.name}); tree.openElements.removeLast(); @@ -1556,7 +1557,7 @@ class InBodyPhase extends Phase { } void startTagOpt(StartTagToken token) { - if (tree.openElements.last.tagName == "option") { + if (tree.openElements.last.localName == "option") { parser.phase.processEndTag(new EndTagToken("option")); } tree.reconstructActiveFormattingElements(); @@ -1584,7 +1585,7 @@ class InBodyPhase extends Phase { if (tree.elementInScope("ruby")) { tree.generateImpliedEndTags(); var last = tree.openElements.last; - if (last.tagName != "ruby") { + if (last.localName != "ruby") { parser.parseError(last.sourceSpan, 'undefined-error'); } } @@ -1642,7 +1643,7 @@ class InBodyPhase extends Phase { endTagP(new EndTagToken("p")); } else { tree.generateImpliedEndTags("p"); - if (tree.openElements.last.tagName != "p") { + if (tree.openElements.last.localName != "p") { parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); } popOpenElementsUntil("p"); @@ -1653,9 +1654,9 @@ class InBodyPhase extends Phase { if (!tree.elementInScope("body")) { parser.parseError(token.span, 'undefined-error'); return; - } else if (tree.openElements.last.tagName != "body") { - for (Node node in slice(tree.openElements, 2)) { - switch (node.tagName) { + } else if (tree.openElements.last.localName != "body") { + for (Element node in slice(tree.openElements, 2)) { + switch (node.localName) { case "dd": case "dt": case "li": case "optgroup": case "option": case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": case "body": case "html": @@ -1663,7 +1664,7 @@ class InBodyPhase extends Phase { } // Not sure this is the correct name for the parse error parser.parseError(token.span, "expected-one-end-tag-but-got-another", - {"gotName": "body", "expectedName": node.tagName}); + {"gotName": "body", "expectedName": node.localName}); break; } } @@ -1688,7 +1689,7 @@ class InBodyPhase extends Phase { if (inScope) { tree.generateImpliedEndTags(); } - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } if (inScope) { @@ -1721,7 +1722,7 @@ class InBodyPhase extends Phase { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } else { tree.generateImpliedEndTags(token.name); - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } popOpenElementsUntil(token.name); @@ -1735,15 +1736,15 @@ class InBodyPhase extends Phase { break; } } - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } for (var item in headingElements) { if (tree.elementInScope(item)) { - item = tree.openElements.removeLast(); - while (!headingElements.contains(item.tagName)) { - item = tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + while (!headingElements.contains(node.localName)) { + node = tree.openElements.removeLast(); } break; } @@ -1766,7 +1767,7 @@ class InBodyPhase extends Phase { token.name); if (formattingElement == null || (tree.openElements.contains(formattingElement) && - !tree.elementInScope(formattingElement.tagName))) { + !tree.elementInScope(formattingElement.localName))) { parser.parseError(token.span, "adoption-agency-1.1", {"name": token.name}); return; @@ -1789,7 +1790,7 @@ class InBodyPhase extends Phase { var afeIndex = tree.openElements.indexOf(formattingElement); Node furthestBlock = null; for (Node element in slice(tree.openElements, afeIndex)) { - if (specialElements.contains(element.nameTuple)) { + if (specialElements.contains(getElementNameTuple(element))) { furthestBlock = element; break; } @@ -1866,7 +1867,7 @@ class InBodyPhase extends Phase { } if (const ["table", "tbody", "tfoot", "thead", "tr"].contains( - commonAncestor.tagName)) { + commonAncestor.localName)) { var nodePos = tree.getTableMisnestedNodePosition(); nodePos[0].insertBefore(lastNode, nodePos[1]); } else { @@ -1898,7 +1899,7 @@ class InBodyPhase extends Phase { if (tree.elementInScope(token.name)) { tree.generateImpliedEndTags(); } - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } if (tree.elementInScope(token.name)) { @@ -1916,17 +1917,17 @@ class InBodyPhase extends Phase { } void endTagOther(EndTagToken token) { - for (Node node in tree.openElements.reversed) { - if (node.tagName == token.name) { + for (var node in tree.openElements.reversed) { + if (node.localName == token.name) { tree.generateImpliedEndTags(token.name); - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } while (tree.openElements.removeLast() != node); break; } else { - if (specialElements.contains(node.nameTuple)) { + if (specialElements.contains(getElementNameTuple(node))) { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); break; @@ -1956,7 +1957,7 @@ class TextPhase extends Phase { bool processEOF() { var last = tree.openElements.last; parser.parseError(last.sourceSpan, "expected-named-closing-tag-but-got-eof", - {'name': last.tagName}); + {'name': last.localName}); tree.openElements.removeLast(); parser.phase = parser.originalPhase; return true; @@ -1964,7 +1965,7 @@ class TextPhase extends Phase { void endTagScript(EndTagToken token) { var node = tree.openElements.removeLast(); - assert(node.tagName == "script"); + assert(node.localName == "script"); parser.phase = parser.originalPhase; //The rest of this method is all stuff that only happens if //document.write works @@ -2009,8 +2010,8 @@ class InTablePhase extends Phase { // helper methods void clearStackToTableContext() { // "clear the stack back to a table context" - while (tree.openElements.last.tagName != "table" && - tree.openElements.last.tagName != "html") { + while (tree.openElements.last.localName != "table" && + tree.openElements.last.localName != "html") { //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) tree.openElements.removeLast(); @@ -2021,7 +2022,7 @@ class InTablePhase extends Phase { // processing methods bool processEOF() { var last = tree.openElements.last; - if (last.tagName != "html") { + if (last.localName != "html") { parser.parseError(last.sourceSpan, "eof-in-table"); } else { assert(parser.innerHTMLMode); @@ -2130,11 +2131,11 @@ class InTablePhase extends Phase { if (tree.elementInScope("table", variant: "table")) { tree.generateImpliedEndTags(); var last = tree.openElements.last; - if (last.tagName != "table") { + if (last.localName != "table") { parser.parseError(token.span, "end-tag-too-early-named", - {"gotName": "table", "expectedName": last.tagName}); + {"gotName": "table", "expectedName": last.localName}); } - while (tree.openElements.last.tagName != "table") { + while (tree.openElements.last.localName != "table") { tree.openElements.removeLast(); } tree.openElements.removeLast(); @@ -2287,12 +2288,12 @@ class InCaptionPhase extends Phase { if (!ignoreEndTagCaption()) { // AT this code is quite similar to endTagTable in "InTable" tree.generateImpliedEndTags(); - if (tree.openElements.last.tagName != "caption") { + if (tree.openElements.last.localName != "caption") { parser.parseError(token.span, "expected-one-end-tag-but-got-another", {"gotName": "caption", - "expectedName": tree.openElements.last.tagName}); + "expectedName": tree.openElements.last.localName}); } - while (tree.openElements.last.tagName != "caption") { + while (tree.openElements.last.localName != "caption") { tree.openElements.removeLast(); } tree.openElements.removeLast(); @@ -2346,7 +2347,7 @@ class InColumnGroupPhase extends Phase { } bool ignoreEndTagColgroup() { - return tree.openElements.last.tagName == "html"; + return tree.openElements.last.localName == "html"; } bool processEOF() { @@ -2431,12 +2432,12 @@ class InTableBodyPhase extends Phase { // helper methods void clearStackToTableBodyContext() { var tableTags = const ["tbody", "tfoot", "thead", "html"]; - while (!tableTags.contains(tree.openElements.last.tagName)) { + while (!tableTags.contains(tree.openElements.last.localName)) { //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) tree.openElements.removeLast(); } - if (tree.openElements.last.tagName == "html") { + if (tree.openElements.last.localName == "html") { assert(parser.innerHTMLMode); } } @@ -2491,7 +2492,7 @@ class InTableBodyPhase extends Phase { tree.elementInScope("thead", variant: "table") || tree.elementInScope("tfoot", variant: "table")) { clearStackToTableBodyContext(); - endTagTableRowGroup(new EndTagToken(tree.openElements.last.tagName)); + endTagTableRowGroup(new EndTagToken(tree.openElements.last.localName)); return token; } else { // innerHTML case @@ -2544,11 +2545,11 @@ class InRowPhase extends Phase { void clearStackToTableRowContext() { while (true) { var last = tree.openElements.last; - if (last.tagName == "tr" || last.tagName == "html") break; + if (last.localName == "tr" || last.localName == "html") break; parser.parseError(last.sourceSpan, "unexpected-implied-end-tag-in-table-row", - {"name": tree.openElements.last.tagName}); + {"name": tree.openElements.last.localName}); tree.openElements.removeLast(); } } @@ -2694,7 +2695,7 @@ class InCellPhase extends Phase { void endTagTableCell(EndTagToken token) { if (tree.elementInScope(token.name, variant: "table")) { tree.generateImpliedEndTags(token.name); - if (tree.openElements.last.tagName != token.name) { + if (tree.openElements.last.localName != token.name) { parser.parseError(token.span, "unexpected-cell-end-tag", {"name": token.name}); popOpenElementsUntil(token.name); @@ -2756,7 +2757,7 @@ class InSelectPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-select bool processEOF() { var last = tree.openElements.last; - if (last.tagName != "html") { + if (last.localName != "html") { parser.parseError(last.sourceSpan, "eof-in-select"); } else { assert(parser.innerHTMLMode); @@ -2774,17 +2775,17 @@ class InSelectPhase extends Phase { void startTagOption(StartTagToken token) { // We need to imply </option> if <option> is the current node. - if (tree.openElements.last.tagName == "option") { + if (tree.openElements.last.localName == "option") { tree.openElements.removeLast(); } tree.insertElement(token); } void startTagOptgroup(StartTagToken token) { - if (tree.openElements.last.tagName == "option") { + if (tree.openElements.last.localName == "option") { tree.openElements.removeLast(); } - if (tree.openElements.last.tagName == "optgroup") { + if (tree.openElements.last.localName == "optgroup") { tree.openElements.removeLast(); } tree.insertElement(token); @@ -2817,7 +2818,7 @@ class InSelectPhase extends Phase { } void endTagOption(EndTagToken token) { - if (tree.openElements.last.tagName == "option") { + if (tree.openElements.last.localName == "option") { tree.openElements.removeLast(); } else { parser.parseError(token.span, "unexpected-end-tag-in-select", @@ -2827,12 +2828,12 @@ class InSelectPhase extends Phase { void endTagOptgroup(EndTagToken token) { // </optgroup> implicitly closes <option> - if (tree.openElements.last.tagName == "option" && - tree.openElements[tree.openElements.length - 2].tagName == "optgroup") { + if (tree.openElements.last.localName == "option" && + tree.openElements[tree.openElements.length - 2].localName == "optgroup") { tree.openElements.removeLast(); } // It also closes </optgroup> - if (tree.openElements.last.tagName == "optgroup") { + if (tree.openElements.last.localName == "optgroup") { tree.openElements.removeLast(); // But nothing else } else { @@ -2995,7 +2996,7 @@ class InForeignContentPhase extends Phase { parser.parseError(token.span, "unexpected-html-element-in-foreign-content", {'name': token.name}); - while (tree.openElements.last.namespace != + while (tree.openElements.last.namespaceUri != tree.defaultNamespace && !parser.isHTMLIntegrationPoint(tree.openElements.last) && !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { @@ -3004,14 +3005,14 @@ class InForeignContentPhase extends Phase { return token; } else { - if (currentNode.namespace == Namespaces.mathml) { + if (currentNode.namespaceUri == Namespaces.mathml) { parser.adjustMathMLAttributes(token); - } else if (currentNode.namespace == Namespaces.svg) { + } else if (currentNode.namespaceUri == Namespaces.svg) { adjustSVGTagNames(token); parser.adjustSVGAttributes(token); } parser.adjustForeignAttributes(token); - token.namespace = currentNode.namespace; + token.namespace = currentNode.namespaceUri; tree.insertElement(token); if (token.selfClosing) { tree.openElements.removeLast(); @@ -3024,13 +3025,13 @@ class InForeignContentPhase extends Phase { Token processEndTag(EndTagToken token) { var nodeIndex = tree.openElements.length - 1; var node = tree.openElements.last; - if (node.tagName != token.name) { + if (node.localName != token.name) { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } var newToken = null; while (true) { - if (asciiUpper2Lower(node.tagName) == token.name) { + if (asciiUpper2Lower(node.localName) == token.name) { //XXX this isn't in the spec but it seems necessary if (parser.phase == parser._inTableTextPhase) { InTableTextPhase inTableText = parser.phase; @@ -3046,7 +3047,7 @@ class InForeignContentPhase extends Phase { nodeIndex -= 1; node = tree.openElements[nodeIndex]; - if (node.namespace != tree.defaultNamespace) { + if (node.namespaceUri != tree.defaultNamespace) { continue; } else { newToken = parser.phase.processEndTag(token); @@ -3137,7 +3138,7 @@ class InFramesetPhase extends Phase { bool processEOF() { var last = tree.openElements.last; - if (last.tagName != "html") { + if (last.localName != "html") { parser.parseError(last.sourceSpan, "eof-in-frameset"); } else { assert(parser.innerHTMLMode); @@ -3170,14 +3171,15 @@ class InFramesetPhase extends Phase { } void endTagFrameset(EndTagToken token) { - if (tree.openElements.last.tagName == "html") { + if (tree.openElements.last.localName == "html") { // innerHTML case parser.parseError(token.span, "unexpected-frameset-in-frameset-innerhtml"); } else { tree.openElements.removeLast(); } - if (!parser.innerHTMLMode && tree.openElements.last.tagName != "frameset") { + if (!parser.innerHTMLMode && + tree.openElements.last.localName != "frameset") { // If we're not in innerHTML mode and the the current node is not a // "frameset" element (anymore) then switch. parser.phase = parser._afterFramesetPhase; @@ -3355,3 +3357,11 @@ class ParseError implements Exception { return span.sourceUrl == null ? 'ParserError$res' : res; } } + + +/// Convenience function to get the pair of namespace and localName. +Pair<String, String> getElementNameTuple(Element e) { + var ns = e.namespaceUri; + if (ns == null) ns = Namespaces.html; + return new Pair(ns, e.localName); +} diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 24873baa9..b4863753f 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1287,7 +1287,7 @@ class HtmlTokenizer implements Iterator<Token> { } } else if (charStack.last == "[" && parser != null && parser.tree.openElements.length > 0 && - parser.tree.openElements.last.namespace + parser.tree.openElements.last.namespaceUri != parser.tree.defaultNamespace) { var matched = true; for (var expected in const ["C", "D", "A", "T", "A", "["]) { diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 8c4d235a1..708c08c7b 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -3,6 +3,7 @@ library treebuilder; import 'dart:collection'; import 'package:html5lib/dom.dart'; +import 'package:html5lib/parser.dart' show getElementNameTuple; import 'package:source_maps/span.dart' show FileSpan; import 'constants.dart'; import 'list_proxy.dart'; @@ -14,18 +15,18 @@ import 'utils.dart'; // from "leaking" into tables, object elements, and marquees. const Node Marker = null; -// TODO(jmesserly): this should extend ListBase<Node>, but my simple attempt +// TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt // didn't work. -class ActiveFormattingElements extends ListProxy<Node> { +class ActiveFormattingElements extends ListProxy<Element> { ActiveFormattingElements() : super(); // Override the "add" method. // TODO(jmesserly): I'd rather not override this; can we do this in the // calling code instead? - void add(Node node) { + void add(Element node) { int equalCount = 0; if (node != Marker) { - for (Node element in reversed) { + for (var element in reversed) { if (element == Marker) { break; } @@ -61,8 +62,8 @@ bool _mapEquals(Map a, Map b) { } -bool _nodesEqual(Node node1, Node node2) { - return node1.nameTuple == node2.nameTuple && +bool _nodesEqual(Element node1, Element node2) { + return getElementNameTuple(node1) == getElementNameTuple(node2) && _mapEquals(node1.attributes, node2.attributes); } @@ -72,7 +73,7 @@ class TreeBuilder { Document document; - final openElements = <Node>[]; + final List<Element> openElements = <Element>[]; final activeFormattingElements = new ActiveFormattingElements(); @@ -105,7 +106,7 @@ class TreeBuilder { bool elementInScope(target, {String variant}) { //If we pass a node in we match that. if we pass a string //match any node with that name - bool exactNode = target is Node && target.nameTuple != null; + bool exactNode = target is Node; List listElements1 = scopingElements; List listElements2 = const []; @@ -133,13 +134,13 @@ class TreeBuilder { } } - for (Node node in openElements.reversed) { - if (node.tagName == target && !exactNode || - node == target && exactNode) { + for (var node in openElements.reversed) { + if (!exactNode && node.localName == target || + exactNode && node == target) { return true; } else if (invert != - (listElements1.contains(node.nameTuple) || - listElements2.contains(node.nameTuple))) { + (listElements1.contains(getElementNameTuple(node)) || + listElements2.contains(getElementNameTuple(node)))) { return false; } } @@ -185,8 +186,8 @@ class TreeBuilder { // TODO(jmesserly): optimize this. No need to create a token. var cloneToken = new StartTagToken( - entry.tagName, - namespace: entry.namespace, + entry.localName, + namespace: entry.namespaceUri, data: new LinkedHashMap.from(entry.attributes)) ..span = entry.sourceSpan; @@ -213,13 +214,13 @@ class TreeBuilder { /// Check if an element exists between the end of the active /// formatting elements and the last marker. If it does, return it, else /// return null. - Node elementInActiveFormattingElements(String name) { - for (Node item in activeFormattingElements.reversed) { + Element elementInActiveFormattingElements(String name) { + for (var item in activeFormattingElements.reversed) { // Check for Marker first because if it's a Marker it doesn't have a // name attribute. if (item == Marker) { break; - } else if (item.tagName == name) { + } else if (item.localName == name) { return item; } } @@ -276,7 +277,7 @@ class TreeBuilder { Element insertElementTable(token) { /// Create an element and insert it into the tree var element = createElement(token); - if (!tableInsertModeElements.contains(openElements.last.tagName)) { + if (!tableInsertModeElements.contains(openElements.last.localName)) { return insertElementNormal(token); } else { // We should be in the InTable mode. This means we want to do @@ -300,7 +301,7 @@ class TreeBuilder { var parent = openElements.last; if (!insertFromTable || insertFromTable && - !tableInsertModeElements.contains(openElements.last.tagName)) { + !tableInsertModeElements.contains(openElements.last.localName)) { _insertText(parent, data, span); } else { // We should be in the InTable mode. This means we want to do @@ -347,8 +348,8 @@ class TreeBuilder { Node lastTable = null; Node fosterParent = null; var insertBefore = null; - for (Node elm in openElements.reversed) { - if (elm.tagName == "table") { + for (var elm in openElements.reversed) { + if (elm.localName == "table") { lastTable = elm; break; } @@ -369,7 +370,7 @@ class TreeBuilder { } void generateImpliedEndTags([String exclude]) { - var name = openElements.last.tagName; + var name = openElements.last.localName; // XXX td, th and tr are not actually needed if (name != exclude && const ["dd", "dt", "li", "option", "optgroup", "p", "rp", "rt"].contains(name)) { diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index f96a8e25f..212ae0533 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -9,9 +9,9 @@ import 'package:html5lib/src/treebuilder.dart'; main() { test('doctype is cloneable', () { - var doc = parse('<!DOCTYPE HTML>'); + var doc = parse('<!doctype HTML>'); DocumentType doctype = doc.nodes[0]; - expect(doctype.clone().outerHtml, '<!DOCTYPE html>'); + expect(doctype.clone().toString(), '<!DOCTYPE html>'); }); test('line counter', () { @@ -22,12 +22,12 @@ main() { test('namespace html elements on', () { var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse(); - expect(doc.nodes[0].namespace, Namespaces.html); + expect(doc.nodes[0].namespaceUri, Namespaces.html); }); test('namespace html elements off', () { var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse(); - expect(doc.nodes[0].namespace, null); + expect(doc.nodes[0].namespaceUri, null); }); test('parse error spans - full', () { @@ -156,60 +156,62 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. test('empty document has html, body, and head', () { var doc = parse(''); - expect(doc.outerHtml, '<html><head></head><body></body></html>'); + var html = '<html><head></head><body></body></html>'; + expect(doc.outerHtml, html); + expect(doc.documentElement.outerHtml, html); expect(doc.head.outerHtml, '<head></head>'); expect(doc.body.outerHtml, '<body></body>'); }); test('strange table case', () { - var doc = parseFragment('<table><tbody><foo>'); - expect(doc.outerHtml, '<foo></foo><table><tbody></tbody></table>'); + var doc = parse('<table><tbody><foo>').body; + expect(doc.innerHtml, '<foo></foo><table><tbody></tbody></table>'); }); group('html serialization', () { test('attribute order', () { // Note: the spec only requires a stable order. // However, we preserve the input order via LinkedHashMap - var doc = parseFragment('<foo d=1 a=2 c=3 b=4>'); - expect(doc.outerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); - expect(doc.querySelector('foo').attributes.remove('a'), '2'); - expect(doc.outerHtml, '<foo d="1" c="3" b="4"></foo>'); - doc.querySelector('foo').attributes['a'] = '0'; - expect(doc.outerHtml, '<foo d="1" c="3" b="4" a="0"></foo>'); + var body = parse('<foo d=1 a=2 c=3 b=4>').body; + expect(body.innerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); + expect(body.querySelector('foo').attributes.remove('a'), '2'); + expect(body.innerHtml, '<foo d="1" c="3" b="4"></foo>'); + body.querySelector('foo').attributes['a'] = '0'; + expect(body.innerHtml, '<foo d="1" c="3" b="4" a="0"></foo>'); }); test('escaping Text node in <script>', () { - var doc = parseFragment('<script>a && b</script>'); - expect(doc.outerHtml, '<script>a && b</script>'); + Element e = parseFragment('<script>a && b</script>').firstChild; + expect(e.outerHtml, '<script>a && b</script>'); }); test('escaping Text node in <span>', () { - var doc = parseFragment('<span>a && b</span>'); - expect(doc.outerHtml, '<span>a &amp;&amp; b</span>'); + Element e = parseFragment('<span>a && b</span>').firstChild; + expect(e.outerHtml, '<span>a &amp;&amp; b</span>'); }); test('Escaping attributes', () { - var doc = parseFragment('<div class="a<b>">'); - expect(doc.outerHtml, '<div class="a<b>"></div>'); - doc = parseFragment('<div class=\'a"b\'>'); - expect(doc.outerHtml, '<div class="a&quot;b"></div>'); + Element e = parseFragment('<div class="a<b>">').firstChild; + expect(e.outerHtml, '<div class="a<b>"></div>'); + e = parseFragment('<div class=\'a"b\'>').firstChild; + expect(e.outerHtml, '<div class="a&quot;b"></div>'); }); test('Escaping non-breaking space', () { var text = '<span>foO\u00A0bar</span>'; expect(text.codeUnitAt(text.indexOf('O') + 1), 0xA0); - var doc = parseFragment(text); - expect(doc.outerHtml, '<span>foO&nbsp;bar</span>'); + Element e = parseFragment(text).firstChild; + expect(e.outerHtml, '<span>foO&nbsp;bar</span>'); }); test('Newline after <pre>', () { - var doc = parseFragment('<pre>\n\nsome text</span>'); - expect(doc.querySelector('pre').nodes[0].data, '\nsome text'); - expect(doc.outerHtml, '<pre>\n\nsome text</pre>'); + Element e = parseFragment('<pre>\n\nsome text</span>').firstChild; + expect((e.firstChild as Text).data, '\nsome text'); + expect(e.outerHtml, '<pre>\n\nsome text</pre>'); - doc = parseFragment('<pre>\nsome text</span>'); - expect(doc.querySelector('pre').nodes[0].data, 'some text'); - expect(doc.outerHtml, '<pre>some text</pre>'); + e = parseFragment('<pre>\nsome text</span>').firstChild; + expect((e.firstChild as Text).data, 'some text'); + expect(e.outerHtml, '<pre>some text</pre>'); }); test('xml namespaces', () { From 5ba848859160176653dcff78a6b7c97fd9cbd6a9 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Fri, 28 Feb 2014 22:59:23 +0000 Subject: [PATCH 026/212] [polymer] update pubspecs to prepare for -pre.0 release R=sigmund@google.com Review URL: https://codereview.chromium.org//180213007 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@33178 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 1ce662479..79f76baf6 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,14 +1,13 @@ name: html5lib -version: 0.9.2-dev +version: 0.9.2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib environment: - sdk: '>=1.0.0 <2.0.0' + sdk: '>=1.2.0 <2.0.0' dependencies: source_maps: '>=0.9.0 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: - browser: '>=0.9.0 <0.10.0' path: '>=0.9.0 <2.0.0' - unittest: '>=0.9.0 <0.11.0' + unittest: '>=0.10.0 <0.11.0' From c5a877345ad6be1cd6ec59ea12cb4df9a2edf4ed Mon Sep 17 00:00:00 2001 From: "sigmund@google.com" <sigmund@google.com> Date: Fri, 4 Apr 2014 20:19:00 +0000 Subject: [PATCH 027/212] Fix how document fragments are added on NodeList operations. The DocumentFragment node should be gone, and its children should be added in place. R=jmesserly@google.com Review URL: https://codereview.chromium.org//224733003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@34742 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 51 +++++++--- pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/dom_test.dart | 174 +++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 12 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index b81c1ff64..973e5ae1b 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -651,7 +651,11 @@ class NodeList extends ListProxy<Node> { } void add(Node value) { - super.add(_setParent(value)); + if (value is DocumentFragment) { + addAll(value.nodes); + } else { + super.add(_setParent(value)); + } } void addLast(Node value) => add(value); @@ -660,17 +664,21 @@ class NodeList extends ListProxy<Node> { // Note: we need to be careful if collection is another NodeList. // In particular: // 1. we need to copy the items before updating their parent pointers, + // _flattenDocFragments does a copy internally. // 2. we should update parent pointers in reverse order. That way they // are removed from the original NodeList (if any) from the end, which // is faster. - var list = (collection is NodeList || collection is! List) - ? collection.toList() : collection as List; + var list = _flattenDocFragments(collection); for (var node in list.reversed) _setParent(node); super.addAll(list); } void insert(int index, Node value) { - super.insert(index, _setParent(value)); + if (value is DocumentFragment) { + insertAll(index, value.nodes); + } else { + super.insert(index, _setParent(value)); + } } Node removeLast() => super.removeLast()..parent = null; @@ -683,8 +691,13 @@ class NodeList extends ListProxy<Node> { } void operator []=(int index, Node value) { - this[index].parent = null; - super[index] = _setParent(value); + if (value is DocumentFragment) { + removeAt(index); + insertAll(index, value.nodes); + } else { + this[index].parent = null; + super[index] = _setParent(value); + } } // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see @@ -698,8 +711,7 @@ class NodeList extends ListProxy<Node> { // Note: see comment in [addAll]. We need to be careful about the order of // operations if [from] is also a NodeList. for (int i = rangeLength - 1; i >= 0; i--) { - this[start + i].parent = null; - super[start + i] = _setParent(from[startFrom + i]); + this[start + i] = from[startFrom + i]; } } @@ -727,9 +739,26 @@ class NodeList extends ListProxy<Node> { super.retainWhere(test); } - void insertAll(int index, List<Node> nodes) { - for (var node in nodes) _setParent(node); - super.insertAll(index, nodes); + void insertAll(int index, Iterable<Node> collection) { + // Note: we need to be careful how we copy nodes. See note in addAll. + var list = _flattenDocFragments(collection); + for (var node in list.reversed) _setParent(node); + super.insertAll(index, list); + } + + _flattenDocFragments(Iterable<Node> collection) { + // Note: this function serves two purposes: + // * it flattens document fragments + // * it creates a copy of [collections] when `collection is NodeList`. + var result = []; + for (var node in collection) { + if (node is DocumentFragment) { + result.addAll(node.nodes); + } else { + result.add(node); + } + } + return result; } } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 79f76baf6..75038c6b9 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.9.2 +version: 0.10.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 43a963732..99dfb0147 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -20,6 +20,12 @@ main() { expect(parse('<foo123>').body.querySelector('foo123'), isNotNull); }); + test('built from fragments', () { + var doc = parse('<body>'); + doc.body.nodes.add(parseFragment('<x-foo>')); + expect(doc.body.querySelector('x-foo'), isNotNull); + }); + test('123 - invalid', () { var doc = parse('<123>'); expect(() => doc.body.querySelector('123'), throwsUnimplementedError); @@ -30,4 +36,172 @@ main() { expect(() => doc.body.querySelector('x\\ny'), throwsUnimplementedError); }); }); + + group('Node.querySelectorAll type selectors', () { + test('x-foo', () { + expect(parse('<x-foo>').body.querySelectorAll('x-foo').length, 1); + }); + + test('-x-foo', () { + var doc = parse('<body><-x-foo>'); + expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>')); + expect(doc.body.querySelectorAll('-x-foo').length, 0); + }); + + test('foo123', () { + expect(parse('<foo123>').body.querySelectorAll('foo123').length, 1); + }); + + test('built from fragments', () { + var doc = parse('<body>'); + doc.body.nodes.add(parseFragment('<x-foo></x-foo><x-foo>')); + expect(doc.body.querySelectorAll('x-foo').length, 2); + }); + + test('123 - invalid', () { + var doc = parse('<123>'); + expect(() => doc.body.querySelectorAll('123'), throwsUnimplementedError); + }); + + test('x\\ny - not implemented', () { + var doc = parse('<x\\ny>'); + expect(() => doc.body.querySelectorAll('x\\ny'), + throwsUnimplementedError); + }); + }); + + group('fragments are flattened', () { + test('add', () { + var doc = parse('<body>'); + doc.body.nodes.add(parseFragment('<x-foo>')); + expect(doc.body.nodes[0].localName, 'x-foo'); + doc.body.nodes.add(parseFragment('<x-bar>')); + expect(doc.body.nodes[1].localName, 'x-bar'); + }); + + test('addLast', () { + var doc = parse('<body>'); + doc.body.nodes.addLast(parseFragment('<x-foo>')); + expect(doc.body.nodes[0].localName, 'x-foo'); + doc.body.nodes.addLast(parseFragment('<x-bar>')); + expect(doc.body.nodes[1].localName, 'x-bar'); + }); + + test('addAll', () { + var doc = parse('<body><x-a></x-a>'); + doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'x-b'); + expect(doc.body.nodes[2].localName, 'x-c'); + }); + + test('insert', () { + var doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>')); + expect(doc.body.nodes[0].localName, 'x-b'); + expect(doc.body.nodes[1].localName, 'x-c'); + expect(doc.body.nodes[2].localName, 'x-a'); + + doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>')); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'x-b'); + expect(doc.body.nodes[2].localName, 'x-c'); + + doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insert(0, parseFragment('<x-b></x-b>')); + doc.body.nodes.insert(1, parseFragment('<x-c></x-c>')); + expect(doc.body.nodes[0].localName, 'x-b'); + expect(doc.body.nodes[1].localName, 'x-c'); + expect(doc.body.nodes[2].localName, 'x-a'); + }); + + test('insertAll', () { + var doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]); + expect(doc.body.nodes[0].localName, 'x-b'); + expect(doc.body.nodes[1].localName, 'x-c'); + expect(doc.body.nodes[2].localName, 'x-a'); + expect(doc.body.nodes.length, 3); + + doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'x-b'); + expect(doc.body.nodes[2].localName, 'x-c'); + + doc = parse('<body><x-a></x-a>'); + doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]); + doc.body.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]); + expect(doc.body.nodes[0].localName, 'x-b'); + expect(doc.body.nodes[1].localName, 'x-c'); + expect(doc.body.nodes[2].localName, 'x-a'); + }); + + test('operator []=', () { + var doc = parse('<body><x-a></x-a>'); + doc.body.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>'); + expect(doc.body.nodes[0].localName, 'x-b'); + expect(doc.body.nodes[1].localName, 'x-c'); + expect(doc.body.nodes.length, 2); + + doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>'); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes[3].localName, 'x-c'); + expect(doc.body.nodes.length, 4); + }); + + test('setRange', () { + var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes.setRange(1, 2, fragment.nodes, 0); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes.length, 3); + + fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes.setRange(1, 1, [fragment], 0); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes[3].localName, 'x-c'); + expect(doc.body.nodes.length, 4); + }); + + test('replaceRange', () { + var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes.replaceRange(1, 2, fragment.nodes); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes[3].localName, 'x-c'); + expect(doc.body.nodes.length, 4); + + fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes.replaceRange(1, 2, [fragment]); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes[3].localName, 'x-c'); + expect(doc.body.nodes.length, 4); + }); + + test('replaceWith', () { + var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + doc.body.nodes[1].replaceWith(fragment); + expect(doc.body.nodes[0].localName, 'x-a'); + expect(doc.body.nodes[1].localName, 'y-b'); + expect(doc.body.nodes[2].localName, 'y-c'); + expect(doc.body.nodes[3].localName, 'x-c'); + expect(doc.body.nodes.length, 4); + }); + }); } From 07f658b270c54dd9d3fc8c3b3a059d4667ba5478 Mon Sep 17 00:00:00 2001 From: "sigmund@google.com" <sigmund@google.com> Date: Fri, 4 Apr 2014 20:47:03 +0000 Subject: [PATCH 028/212] add CHANGELOG entry in html5lib before releasing. Review URL: https://codereview.chromium.org//226643002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@34744 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 7c9728088..dd64e8997 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html5lib package. +#### Pub version 0.10.0 + * fix how document fragments are added in NodeList.add/addAll/insertAll. + #### Pub version 0.9.2-dev * add Node.text, Node.append, Document.documentElement * add Text.data, deprecate Node.value and Text.value. From 947cc5a2e07d62569f33b618b9380c2b8378aeab Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Thu, 8 May 2014 21:41:05 +0000 Subject: [PATCH 029/212] [html5lib] implement querySelector/querySelectorAll BUG= https://code.google.com/p/dart/issues/detail?id=18508 * tests from https://github.com/w3c/web-platform-tests/tree/master/selectors-api, kept as close to original as I could. * src/query_selector.dart is most interesting file. It implements enough of selectors to pass the basic web platform tests. Ironically, it was the easiest part of this CL... * many fixes to csslib. Almost all of the selector tests were skipped (https://github.com/dart-lang/csslib-test-suite/blob/master/suite/selectors3/selectors3_test.dart) and there was a lot of things broken: unicode, escaping, incorrectly treating ident-tokens as units, probably more that I am forgetting :). Fixed as much as I could without doing major surgery. * a bunch of fixes to the htm5lib DOM to bring it closer in alignment with dom.spec.whatwg.org and dart:html. The driving force was to minimize the changes needed on the W3C tests. Note: haven't updated things that depend on html5lib like Polymer yet. R=sigmund@google.com Review URL: https://codereview.chromium.org//268623002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@35941 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 353 +++++++++------- pkgs/html/lib/dom_parsing.dart | 5 +- pkgs/html/lib/parser.dart | 16 +- pkgs/html/lib/src/constants.dart | 2 +- pkgs/html/lib/src/css_class_set.dart | 336 ++++++++++++++++ pkgs/html/lib/src/query_selector.dart | 288 +++++++++++++ pkgs/html/lib/src/treebuilder.dart | 8 +- pkgs/html/pubspec.yaml | 3 +- pkgs/html/test/dom_test.dart | 100 ++--- pkgs/html/test/parser_feature_test.dart | 2 +- pkgs/html/test/selectors/LICENSE | 9 + pkgs/html/test/selectors/README | 9 + pkgs/html/test/selectors/level1-content.html | 377 ++++++++++++++++++ .../test/selectors/level1_baseline_test.dart | 117 ++++++ pkgs/html/test/selectors/level1_lib.dart | 275 +++++++++++++ pkgs/html/test/selectors/selectors.dart | 363 +++++++++++++++++ pkgs/html/test/support.dart | 2 + 17 files changed, 2040 insertions(+), 225 deletions(-) create mode 100644 pkgs/html/lib/src/css_class_set.dart create mode 100644 pkgs/html/lib/src/query_selector.dart create mode 100644 pkgs/html/test/selectors/LICENSE create mode 100644 pkgs/html/test/selectors/README create mode 100644 pkgs/html/test/selectors/level1-content.html create mode 100644 pkgs/html/test/selectors/level1_baseline_test.dart create mode 100644 pkgs/html/test/selectors/level1_lib.dart create mode 100644 pkgs/html/test/selectors/selectors.dart diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 973e5ae1b..a87bca96e 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -1,18 +1,26 @@ /// A simple tree API that results from parsing html. Intended to be compatible -/// with dart:html, but right now it resembles the classic JS DOM. +/// with dart:html, but it is missing many types and APIs. library dom; +// TODO(jmesserly): lots to do here. Originally I wanted to generate this using +// our Blink IDL generator, but another idea is to directly use the excellent +// http://dom.spec.whatwg.org/ and http://html.spec.whatwg.org/ and just +// implement that. + import 'dart:collection'; import 'package:source_maps/span.dart' show FileSpan; import 'src/constants.dart'; +import 'src/css_class_set.dart'; import 'src/list_proxy.dart'; +import 'src/query_selector.dart' as query; import 'src/token.dart'; import 'src/tokenizer.dart'; -import 'src/utils.dart'; import 'dom_parsing.dart'; import 'parser.dart'; +export 'src/css_class_set.dart' show CssClassSet; + // TODO(jmesserly): this needs to be replaced by an AttributeMap for attributes // that exposes namespace info. class AttributeName implements Comparable { @@ -60,6 +68,55 @@ class AttributeName implements Comparable { } } +// http://dom.spec.whatwg.org/#parentnode +abstract class _ParentNode implements Node { + // TODO(jmesserly): this is only a partial implementation + + /// Seaches for the first descendant node matching the given selectors, using + /// a preorder traversal. + /// + /// NOTE: Not all selectors from + /// [selectors level 4](http://dev.w3.org/csswg/selectors-4/) + /// are implemented. For example, nth-child does not implement An+B syntax + /// and *-of-type is not implemented. If a selector is not implemented this + /// method will throw [UniplmentedError]. + Element querySelector(String selector) => + query.querySelector(this, selector); + + /// Returns all descendant nodes matching the given selectors, using a + /// preorder traversal. + /// + /// NOTE: Not all selectors from + /// [selectors level 4](http://dev.w3.org/csswg/selectors-4/) + /// are implemented. For example, nth-child does not implement An+B syntax + /// and *-of-type is not implemented. If a selector is not implemented this + /// method will throw [UniplmentedError]. + List<Element> querySelectorAll(String selector) => + query.querySelectorAll(this, selector); +} + +// http://dom.spec.whatwg.org/#interface-nonelementparentnode +abstract class _NonElementParentNode implements _ParentNode { + // TODO(jmesserly): could be faster, should throw on invalid id. + Element getElementById(String id) => querySelector('#$id'); +} + +// This doesn't exist as an interface in the spec, but it's useful to merge +// common methods from these: +// http://dom.spec.whatwg.org/#interface-document +// http://dom.spec.whatwg.org/#element +abstract class _ElementAndDocument implements _ParentNode { + // TODO(jmesserly): could be faster, should throw on invalid tag/class names. + + List<Element> getElementsByTagName(String localName) => + querySelectorAll(localName); + + List<Element> getElementsByClassName(String classNames) => + querySelectorAll(classNames.splitMapJoin(' ', + onNonMatch: (m) => m.isNotEmpty ? '.$m' : m, + onMatch: (m) => '')); +} + /// Really basic implementation of a DOM-core like Node. abstract class Node { static const int ATTRIBUTE_NODE = 2; @@ -75,16 +132,14 @@ abstract class Node { static const int PROCESSING_INSTRUCTION_NODE = 7; static const int TEXT_NODE = 3; - /// Note: For now we use it to implement the deprecated tagName property. - final String _tagName; - - /// *Deprecated* use [Element.localName] instead. - /// Note: after removal, this will be replaced by a correct version that - /// returns uppercase [as specified](http://dom.spec.whatwg.org/#dom-element-tagname). - @deprecated String get tagName => _tagName; - /// The parent of the current node (or null for the document node). - Node parent; + Node parentNode; + + /// The parent element of this node. + /// + /// Returns null if this node either does not have a parent or its parent is + /// not an element. + Element get parent => parentNode is Element ? parentNode : null; // TODO(jmesserly): should move to Element. /// A map holding name, value pairs for attributes of the node. @@ -108,10 +163,7 @@ abstract class Node { LinkedHashMap<dynamic, FileSpan> _attributeSpans; LinkedHashMap<dynamic, FileSpan> _attributeValueSpans; - /// *Deprecated* use [new Element.tag] instead. - @deprecated Node(String tagName) : this._(tagName); - - Node._([this._tagName]) { + Node._() { nodes._parent = this; } @@ -140,29 +192,14 @@ abstract class Node { return _elements; } - // TODO(jmesserly): needs to support deep clone. - /// Return a shallow copy of the current node i.e. a node with the same - /// name and attributes but with no parent or child nodes. - Node clone(); - - /// *Deprecated* use [Element.namespaceUri] instead. - @deprecated String get namespace => null; + /// Returns a copy of this node. + /// + /// If [deep] is `true`, then all of this node's children and decendents are + /// copied as well. If [deep] is `false`, then only this node is copied. + Node clone(bool deep); int get nodeType; - /// *Deprecated* use [text], [Text.data] or [Comment.data]. - @deprecated String get value => null; - - /// *Deprecated* use [nodeType]. - @deprecated int get $dom_nodeType => nodeType; - - /// *Deprecated* use [Element.outerHtml] - @deprecated String get outerHtml => _outerHtml; - - /// *Deprecated* use [Element.innerHtml] - @deprecated String get innerHtml => _innerHtml; - @deprecated set innerHtml(String value) { _innerHtml = value; } - // http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface String get _outerHtml { var str = new StringBuffer(); @@ -176,13 +213,6 @@ abstract class Node { return str.toString(); } - set _innerHtml(String value) { - nodes.clear(); - // TODO(jmesserly): should be able to get the same effect by adding the - // fragment directly. - nodes.addAll(parseFragment(value, container: _tagName).nodes); - } - // Implemented per: http://dom.spec.whatwg.org/#dom-node-textcontent String get text => null; set text(String value) {} @@ -199,8 +229,8 @@ abstract class Node { Node remove() { // TODO(jmesserly): is parent == null an error? - if (parent != null) { - parent.nodes.remove(this); + if (parentNode != null) { + parentNode.nodes.remove(this); } return this; } @@ -219,10 +249,10 @@ abstract class Node { /// Replaces this node with another node. Node replaceWith(Node otherNode) { - if (parent == null) { + if (parentNode == null) { throw new UnsupportedError('Node must have a parent to replace it.'); } - parent.nodes[parent.nodes.indexOf(this)] = otherNode; + parentNode.nodes[parentNode.nodes.indexOf(this)] = otherNode; return this; } @@ -230,10 +260,6 @@ abstract class Node { /// Return true if the node has children or text. bool hasContent() => nodes.length > 0; - /// *Deprecated* construct a pair using the namespaceUri and the name. - @deprecated Pair<String, String> get nameTuple => - this is Element ? getElementNameTuple(this) : null; - /// Move all the children of the current node to [newParent]. /// This is needed so that trees that don't store text as nodes move the /// text in the correct way. @@ -242,42 +268,10 @@ abstract class Node { nodes.clear(); } - /// *Deprecated* use [querySelector] instead. - @deprecated - Element query(String selectors) => querySelector(selectors); - - /// *Deprecated* use [querySelectorAll] instead. - @deprecated - List<Element> queryAll(String selectors) => querySelectorAll(selectors); - - /// Seaches for the first descendant node matching the given selectors, using a - /// preorder traversal. NOTE: right now, this supports only a single type - /// selectors, e.g. `node.query('div')`. - - Element querySelector(String selectors) => - _queryType(_typeSelector(selectors)); - - /// Returns all descendant nodes matching the given selectors, using a - /// preorder traversal. NOTE: right now, this supports only a single type - /// selectors, e.g. `node.queryAll('div')`. - List<Element> querySelectorAll(String selectors) { - var results = new List<Element>(); - _queryAllType(_typeSelector(selectors), results); - return results; - } - bool hasChildNodes() => !nodes.isEmpty; bool contains(Node node) => nodes.contains(node); - String _typeSelector(String selectors) { - selectors = selectors.trim(); - if (!_isTypeSelector(selectors)) { - throw new UnimplementedError('only type selectors are implemented'); - } - return selectors; - } - /// Checks if this is a type selector. /// See <http://www.w3.org/TR/CSS2/grammar.html>. /// Note: this doesn't support '*', the universal selector, non-ascii chars or @@ -318,24 +312,6 @@ abstract class Node { return true; } - Element _queryType(String tag) { - for (var node in nodes) { - if (node is! Element) continue; - if (node.localName == tag) return node; - var result = node._queryType(tag); - if (result != null) return result; - } - return null; - } - - void _queryAllType(String tag, List<Element> results) { - for (var node in nodes) { - if (node is! Element) continue; - if (node.localName == tag) results.add(node); - node._queryAllType(tag, results); - } - } - /// Initialize [attributeSpans] using [sourceSpan]. void _ensureAttributeSpans() { if (_attributeSpans != null) return; @@ -363,9 +339,20 @@ abstract class Node { } } } + + _clone(Node shallowClone, bool deep) { + if (deep) { + for (var child in nodes) { + shallowClone.append(child.clone(true)); + } + } + return shallowClone; + } } -class Document extends Node { +class Document extends Node + with _ParentNode, _NonElementParentNode, _ElementAndDocument { + Document() : super._(); factory Document.html(String html) => parse(html); @@ -388,18 +375,41 @@ class Document extends Node { void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); - Document clone() => new Document(); + Document clone(bool deep) => _clone(new Document(), deep); + + Element createElement(String tag) => new Element.tag(tag); + + // TODO(jmesserly): this is only a partial implementation of: + // http://dom.spec.whatwg.org/#dom-document-createelementns + Element createElementNS(String namespaceUri, String tag) { + if (namespaceUri == '') namespaceUri = null; + return new Element._(tag, namespaceUri); + } + + DocumentFragment createDocumentFragment() => new DocumentFragment(); } -class DocumentFragment extends Document { - DocumentFragment(); +class DocumentFragment extends Node + with _ParentNode, _NonElementParentNode { + + DocumentFragment() : super._(); factory DocumentFragment.html(String html) => parseFragment(html); int get nodeType => Node.DOCUMENT_FRAGMENT_NODE; + /// Returns a fragment of HTML or XML that represents the element and its + /// contents. + // TODO(jmesserly): this API is not specified in: + // <http://domparsing.spec.whatwg.org/> nor is it in dart:html, instead + // only Element has outerHtml. However it is quite useful. Should we move it + // to dom_parsing, where we keep other custom APIs? + String get outerHtml => _outerHtml; + String toString() => "#document-fragment"; - DocumentFragment clone() => new DocumentFragment(); + DocumentFragment clone(bool deep) => _clone(new DocumentFragment(), deep); + + void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); String get text => _getText(this); set text(String value) => _setText(this, value); @@ -412,7 +422,7 @@ class DocumentType extends Node { DocumentType(String name, this.publicId, this.systemId) // Note: once Node.tagName is removed, don't pass "name" to super - : name = name, super._(name); + : name = name, super._(); int get nodeType => Node.DOCUMENT_TYPE_NODE; @@ -433,7 +443,7 @@ class DocumentType extends Node { str.write(toString()); } - DocumentType clone() => new DocumentType(name, publicId, systemId); + DocumentType clone(bool deep) => new DocumentType(name, publicId, systemId); } class Text extends Node { @@ -441,36 +451,29 @@ class Text extends Node { Text(this.data) : super._(); - /// *Deprecated* use [data]. - @deprecated String get value => data; - @deprecated set value(String x) { data = x; } - int get nodeType => Node.TEXT_NODE; String toString() => '"$data"'; void _addOuterHtml(StringBuffer str) => writeTextNodeAsHtml(str, this); - Text clone() => new Text(data); + Text clone(bool deep) => new Text(data); String get text => data; set text(String value) { data = value; } } -class Element extends Node { +// TODO(jmesserly): Elements should have a pointer back to their document +class Element extends Node with _ParentNode, _ElementAndDocument { final String namespaceUri; - @deprecated String get namespace => namespaceUri; - /// The [local name](http://dom.spec.whatwg.org/#concept-element-local-name) /// of this element. - String get localName => _tagName; + final String localName; - // TODO(jmesserly): deprecate in favor of [Document.createElementNS]. - // However we need every element to have a Document before this can work. - Element(String name, [this.namespaceUri]) : super._(name); + Element._(this.localName, [this.namespaceUri]) : super._(); - Element.tag(String name) : namespaceUri = null, super._(name); + Element.tag(this.localName) : namespaceUri = Namespaces.html, super._(); static final _START_TAG_REGEXP = new RegExp('<(\\w+)'); @@ -528,9 +531,30 @@ class Element extends Node { int get nodeType => Node.ELEMENT_NODE; + // TODO(jmesserly): we can make this faster + Element get previousElementSibling { + if (parentNode == null) return null; + var siblings = parentNode.nodes; + for (int i = siblings.indexOf(this) - 1; i >= 0; i--) { + var s = siblings[i]; + if (s is Element) return s; + } + return null; + } + + Element get nextElementSibling { + if (parentNode == null) return null; + var siblings = parentNode.nodes; + for (int i = siblings.indexOf(this) + 1; i < siblings.length; i++) { + var s = siblings[i]; + if (s is Element) return s; + } + return null; + } + String toString() { - if (namespaceUri == null) return "<$localName>"; - return "<${Namespaces.getPrefix(namespaceUri)} $localName>"; + var prefix = Namespaces.getPrefix(namespaceUri); + return "<${prefix == null ? '' : '$prefix '}$localName>"; } String get text => _getText(this); @@ -546,21 +570,17 @@ class Element extends Node { String get innerHtml => _innerHtml; // TODO(jmesserly): deprecate in favor of: // <https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element@id_setInnerHtml> - set innerHtml(String value) { _innerHtml = value; } + set innerHtml(String value) { + nodes.clear(); + // TODO(jmesserly): should be able to get the same effect by adding the + // fragment directly. + nodes.addAll(parseFragment(value, container: localName).nodes); + } void _addOuterHtml(StringBuffer str) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments // Element is the most complicated one. - if (namespaceUri == null || - namespaceUri == Namespaces.html || - namespaceUri == Namespaces.mathml || - namespaceUri == Namespaces.svg) { - str.write('<$localName'); - } else { - // TODO(jmesserly): the spec doesn't define "qualified name". - // I'm not sure if this is correct, but it should parse reasonably. - str.write('<${Namespaces.getPrefix(namespaceUri)}:$localName'); - } + str.write('<${_getSerializationPrefix(namespaceUri)}$localName'); if (attributes.length > 0) { attributes.forEach((key, v) { @@ -591,21 +611,56 @@ class Element extends Node { if (!isVoidElement(localName)) str.write('</$localName>'); } - Element clone() => new Element(localName, namespaceUri) - ..attributes = new LinkedHashMap.from(attributes); + static String _getSerializationPrefix(String uri) { + if (uri == null || + uri == Namespaces.html || + uri == Namespaces.mathml || + uri == Namespaces.svg) { + return ''; + } + var prefix = Namespaces.getPrefix(uri); + // TODO(jmesserly): the spec doesn't define "qualified name". + // I'm not sure if this is correct, but it should parse reasonably. + return prefix == null ? '' : '$prefix:'; + } + + Element clone(bool deep) { + var result = new Element._(localName, namespaceUri) + ..attributes = new LinkedHashMap.from(attributes); + return _clone(result, deep); + } + // http://dom.spec.whatwg.org/#dom-element-id String get id { var result = attributes['id']; return result != null ? result : ''; } set id(String value) { - if (value == null) { - attributes.remove('id'); - } else { - attributes['id'] = value; - } + attributes['id'] = '$value'; } + + // http://dom.spec.whatwg.org/#dom-element-classname + String get className { + var result = attributes['class']; + return result != null ? result : ''; + } + + set className(String value) { + attributes['class'] = '$value'; + } + + /** + * The set of CSS classes applied to this element. + * + * This set makes it easy to add, remove or toggle the classes applied to + * this element. + * + * element.classes.add('selected'); + * element.classes.toggle('isOnline'); + * element.classes.remove('selected'); + */ + CssClassSet get classes => new ElementCssClassSet(this); } class Comment extends Node { @@ -621,7 +676,7 @@ class Comment extends Node { str.write("<!--$data-->"); } - Comment clone() => new Comment(data); + Comment clone(bool deep) => new Comment(data); String get text => data; set text(String value) { @@ -646,7 +701,7 @@ class NodeList extends ListProxy<Node> { // Note: we need to remove the node from its previous parent node, if any, // before updating its parent pointer to point at our parent. node.remove(); - node.parent = _parent; + node.parentNode = _parent; return node; } @@ -681,12 +736,12 @@ class NodeList extends ListProxy<Node> { } } - Node removeLast() => super.removeLast()..parent = null; + Node removeLast() => super.removeLast()..parentNode = null; - Node removeAt(int i) => super.removeAt(i)..parent = null; + Node removeAt(int i) => super.removeAt(i)..parentNode = null; void clear() { - for (var node in this) node.parent = null; + for (var node in this) node.parentNode = null; super.clear(); } @@ -695,7 +750,7 @@ class NodeList extends ListProxy<Node> { removeAt(index); insertAll(index, value.nodes); } else { - this[index].parent = null; + this[index].parentNode = null; super[index] = _setParent(value); } } @@ -721,20 +776,20 @@ class NodeList extends ListProxy<Node> { } void removeRange(int start, int rangeLength) { - for (int i = start; i < rangeLength; i++) this[i].parent = null; + for (int i = start; i < rangeLength; i++) this[i].parentNode = null; super.removeRange(start, rangeLength); } void removeWhere(bool test(Element e)) { for (var node in where(test)) { - node.parent = null; + node.parentNode = null; } super.removeWhere(test); } void retainWhere(bool test(Element e)) { for (var node in where((n) => !test(n))) { - node.parent = null; + node.parentNode = null; } super.retainWhere(test); } diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index aed9fffe2..527d9a6fa 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -40,8 +40,7 @@ class TreeVisitor { visitComment(Comment node) => visitNodeFallback(node); - // Note: visits document by default because DocumentFragment is a Document. - visitDocumentFragment(DocumentFragment node) => visitDocument(node); + visitDocumentFragment(DocumentFragment node) => visitNodeFallback(node); } /// Converts the DOM tree into an HTML string with code markup suitable for @@ -166,7 +165,7 @@ bool isVoidElement(String tagName) { /// <http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm> void writeTextNodeAsHtml(StringBuffer str, Text node) { // Don't escape text for certain elements, notably <script>. - final parent = node.parent; + final parent = node.parentNode; if (parent is Element) { var tag = parent.localName; if (rcdataElements.contains(tag) || tag == 'plaintext') { diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 2d04f8e8a..721985abe 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1313,8 +1313,8 @@ class InBodyPhase extends Phase { tree.openElements[1].localName != "body")) { assert(parser.innerHTMLMode); } else if (parser.framesetOK) { - if (tree.openElements[1].parent != null) { - tree.openElements[1].parent.nodes.remove(tree.openElements[1]); + if (tree.openElements[1].parentNode != null) { + tree.openElements[1].parentNode.nodes.remove(tree.openElements[1]); } while (tree.openElements.last.localName != "html") { tree.openElements.removeLast(); @@ -1840,7 +1840,7 @@ class InBodyPhase extends Phase { } // Step 6.5 //cite = node.parent - var clone = node.clone(); + var clone = node.clone(false); // Replace node with clone tree.activeFormattingElements[ tree.activeFormattingElements.indexOf(node)] = clone; @@ -1849,8 +1849,8 @@ class InBodyPhase extends Phase { // Step 6.6 // Remove lastNode from its parents, if any - if (lastNode.parent != null) { - lastNode.parent.nodes.remove(lastNode); + if (lastNode.parentNode != null) { + lastNode.parentNode.nodes.remove(lastNode); } node.nodes.add(lastNode); // Step 7.7 @@ -1862,8 +1862,8 @@ class InBodyPhase extends Phase { // Foster parent lastNode if commonAncestor is a // table, tbody, tfoot, thead, or tr we need to foster parent the // lastNode - if (lastNode.parent != null) { - lastNode.parent.nodes.remove(lastNode); + if (lastNode.parentNode != null) { + lastNode.parentNode.nodes.remove(lastNode); } if (const ["table", "tbody", "tfoot", "thead", "tr"].contains( @@ -1875,7 +1875,7 @@ class InBodyPhase extends Phase { } // Step 8 - var clone = formattingElement.clone(); + var clone = formattingElement.clone(false); // Step 9 furthestBlock.reparentChildren(clone); diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index b8e4dbd2f..0fd9e122f 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -316,7 +316,7 @@ class Namespaces { case xlink: return 'xlink'; case xml: return 'xml'; case xmlns: return 'xmlns'; - default: throw new ArgumentError(url); + default: return null; } } } diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart new file mode 100644 index 000000000..03136a787 --- /dev/null +++ b/pkgs/html/lib/src/css_class_set.dart @@ -0,0 +1,336 @@ +// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// TODO(jmesserly): everything in this file is copied straight from "dart:html". +library html5lib.dom.src; + +import 'dart:collection'; +import 'package:html5lib/dom.dart'; + +class ElementCssClassSet extends CssClassSetImpl { + + final Element _element; + + ElementCssClassSet(this._element); + + Set<String> readClasses() { + var s = new LinkedHashSet<String>(); + var classname = _element.className; + + for (String name in classname.split(' ')) { + String trimmed = name.trim(); + if (!trimmed.isEmpty) { + s.add(trimmed); + } + } + return s; + } + + void writeClasses(Set<String> s) { + List list = new List.from(s); + _element.className = s.join(' '); + } +} + + +/** A Set that stores the CSS class names for an element. */ +abstract class CssClassSet implements Set<String> { + + /** + * Adds the class [value] to the element if it is not on it, removes it if it + * is. + * + * If [shouldAdd] is true, then we always add that [value] to the element. If + * [shouldAdd] is false then we always remove [value] from the element. + */ + bool toggle(String value, [bool shouldAdd]); + + /** + * Returns [:true:] if classes cannot be added or removed from this + * [:CssClassSet:]. + */ + bool get frozen; + + /** + * Determine if this element contains the class [value]. + * + * This is the Dart equivalent of jQuery's + * [hasClass](http://api.jquery.com/hasClass/). + */ + bool contains(String value); + + /** + * Add the class [value] to element. + * + * This is the Dart equivalent of jQuery's + * [addClass](http://api.jquery.com/addClass/). + * + * If this corresponds to one element. Returns true if [value] was added to + * the set, otherwise false. + * + * If this corresponds to many elements, null is always returned. + */ + bool add(String value); + + /** + * Remove the class [value] from element, and return true on successful + * removal. + * + * This is the Dart equivalent of jQuery's + * [removeClass](http://api.jquery.com/removeClass/). + */ + bool remove(Object value); + + /** + * Add all classes specified in [iterable] to element. + * + * This is the Dart equivalent of jQuery's + * [addClass](http://api.jquery.com/addClass/). + */ + void addAll(Iterable<String> iterable); + + /** + * Remove all classes specified in [iterable] from element. + * + * This is the Dart equivalent of jQuery's + * [removeClass](http://api.jquery.com/removeClass/). + */ + void removeAll(Iterable<String> iterable); + + /** + * Toggles all classes specified in [iterable] on element. + * + * Iterate through [iterable]'s items, and add it if it is not on it, or + * remove it if it is. This is the Dart equivalent of jQuery's + * [toggleClass](http://api.jquery.com/toggleClass/). + * If [shouldAdd] is true, then we always add all the classes in [iterable] + * element. If [shouldAdd] is false then we always remove all the classes in + * [iterable] from the element. + */ + void toggleAll(Iterable<String> iterable, [bool shouldAdd]); +} + +abstract class CssClassSetImpl implements CssClassSet { + + String toString() { + return readClasses().join(' '); + } + + /** + * Adds the class [value] to the element if it is not on it, removes it if it + * is. + * + * If [shouldAdd] is true, then we always add that [value] to the element. If + * [shouldAdd] is false then we always remove [value] from the element. + */ + bool toggle(String value, [bool shouldAdd]) { + Set<String> s = readClasses(); + bool result = false; + if (shouldAdd == null) shouldAdd = !s.contains(value); + if (shouldAdd) { + s.add(value); + result = true; + } else { + s.remove(value); + } + writeClasses(s); + return result; + } + + /** + * Returns [:true:] if classes cannot be added or removed from this + * [:CssClassSet:]. + */ + bool get frozen => false; + + // interface Iterable - BEGIN + Iterator<String> get iterator => readClasses().iterator; + // interface Iterable - END + + // interface Collection - BEGIN + void forEach(void f(String element)) { + readClasses().forEach(f); + } + + String join([String separator = ""]) => readClasses().join(separator); + + Iterable map(f(String element)) => readClasses().map(f); + + Iterable<String> where(bool f(String element)) => readClasses().where(f); + + Iterable expand(Iterable f(String element)) => readClasses().expand(f); + + bool every(bool f(String element)) => readClasses().every(f); + + bool any(bool f(String element)) => readClasses().any(f); + + bool get isEmpty => readClasses().isEmpty; + + bool get isNotEmpty => readClasses().isNotEmpty; + + int get length => readClasses().length; + + String reduce(String combine(String value, String element)) { + return readClasses().reduce(combine); + } + + dynamic fold(dynamic initialValue, + dynamic combine(dynamic previousValue, String element)) { + return readClasses().fold(initialValue, combine); + } + // interface Collection - END + + // interface Set - BEGIN + /** + * Determine if this element contains the class [value]. + * + * This is the Dart equivalent of jQuery's + * [hasClass](http://api.jquery.com/hasClass/). + */ + bool contains(String value) => readClasses().contains(value); + + /** Lookup from the Set interface. Not interesting for a String set. */ + String lookup(String value) => contains(value) ? value : null; + + /** + * Add the class [value] to element. + * + * This is the Dart equivalent of jQuery's + * [addClass](http://api.jquery.com/addClass/). + */ + bool add(String value) { + // TODO - figure out if we need to do any validation here + // or if the browser natively does enough. + return modify((s) => s.add(value)); + } + + /** + * Remove the class [value] from element, and return true on successful + * removal. + * + * This is the Dart equivalent of jQuery's + * [removeClass](http://api.jquery.com/removeClass/). + */ + bool remove(Object value) { + if (value is! String) return false; + Set<String> s = readClasses(); + bool result = s.remove(value); + writeClasses(s); + return result; + } + + /** + * Add all classes specified in [iterable] to element. + * + * This is the Dart equivalent of jQuery's + * [addClass](http://api.jquery.com/addClass/). + */ + void addAll(Iterable<String> iterable) { + // TODO - see comment above about validation. + modify((s) => s.addAll(iterable)); + } + + /** + * Remove all classes specified in [iterable] from element. + * + * This is the Dart equivalent of jQuery's + * [removeClass](http://api.jquery.com/removeClass/). + */ + void removeAll(Iterable<String> iterable) { + modify((s) => s.removeAll(iterable)); + } + + /** + * Toggles all classes specified in [iterable] on element. + * + * Iterate through [iterable]'s items, and add it if it is not on it, or + * remove it if it is. This is the Dart equivalent of jQuery's + * [toggleClass](http://api.jquery.com/toggleClass/). + * If [shouldAdd] is true, then we always add all the classes in [iterable] + * element. If [shouldAdd] is false then we always remove all the classes in + * [iterable] from the element. + */ + void toggleAll(Iterable<String> iterable, [bool shouldAdd]) { + iterable.forEach((e) => toggle(e, shouldAdd)); + } + + void retainAll(Iterable<String> iterable) { + modify((s) => s.retainAll(iterable)); + } + + void removeWhere(bool test(String name)) { + modify((s) => s.removeWhere(test)); + } + + void retainWhere(bool test(String name)) { + modify((s) => s.retainWhere(test)); + } + + bool containsAll(Iterable<String> collection) => + readClasses().containsAll(collection); + + Set<String> intersection(Set<String> other) => + readClasses().intersection(other); + + Set<String> union(Set<String> other) => + readClasses().union(other); + + Set<String> difference(Set<String> other) => + readClasses().difference(other); + + String get first => readClasses().first; + String get last => readClasses().last; + String get single => readClasses().single; + List<String> toList({ bool growable: true }) => + readClasses().toList(growable: growable); + Set<String> toSet() => readClasses().toSet(); + Iterable<String> take(int n) => readClasses().take(n); + Iterable<String> takeWhile(bool test(String value)) => + readClasses().takeWhile(test); + Iterable<String> skip(int n) => readClasses().skip(n); + Iterable<String> skipWhile(bool test(String value)) => + readClasses().skipWhile(test); + dynamic firstWhere(bool test(String value), { Object orElse() }) => + readClasses().firstWhere(test, orElse: orElse); + dynamic lastWhere(bool test(String value), { Object orElse()}) => + readClasses().lastWhere(test, orElse: orElse); + String singleWhere(bool test(String value)) => + readClasses().singleWhere(test); + String elementAt(int index) => readClasses().elementAt(index); + + void clear() { + modify((s) => s.clear()); + } + // interface Set - END + + /** + * Helper method used to modify the set of css classes on this element. + * + * f - callback with: + * s - a Set of all the css class name currently on this element. + * + * After f returns, the modified set is written to the + * className property of this element. + */ + modify( f(Set<String> s)) { + Set<String> s = readClasses(); + var ret = f(s); + writeClasses(s); + return ret; + } + + /** + * Read the class names from the Element class property, + * and put them into a set (duplicates are discarded). + * This is intended to be overridden by specific implementations. + */ + Set<String> readClasses(); + + /** + * Join all the elements of a set into one string and write + * back to the element. + * This is intended to be overridden by specific implementations. + */ + void writeClasses(Set<String> s); +} diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart new file mode 100644 index 000000000..ededa549d --- /dev/null +++ b/pkgs/html/lib/src/query_selector.dart @@ -0,0 +1,288 @@ +/// Query selector implementation for html5lib's DOM. +library html5lib.src.query; + +import 'package:csslib/parser.dart' as css; +import 'package:csslib/parser.dart' show TokenKind; +import 'package:csslib/visitor.dart'; // the CSSOM +import 'package:html5lib/dom.dart'; +import 'package:html5lib/src/constants.dart' show isWhitespaceCC; + +bool matches(Node node, String selector) => + new SelectorEvaluator().matches(node, _parseSelectorList(selector)); + +Element querySelector(Node node, String selector) => + new SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); + +List<Element> querySelectorAll(Node node, String selector) { + var results = []; + new SelectorEvaluator() + .querySelectorAll(node, _parseSelectorList(selector), results); + return results; +} + +// http://dev.w3.org/csswg/selectors-4/#grouping +SelectorGroup _parseSelectorList(String selector) { + var errors = []; + var group = css.parseSelectorGroup(selector, errors: errors); + if (group == null || errors.isNotEmpty) { + throw new FormatException("'$selector' is not a valid selector: $errors"); + } + return group; +} + +class SelectorEvaluator extends Visitor { + /// The current HTML element to match against. + Element _element; + + bool matches(Element element, SelectorGroup selector) { + _element = element; + return visitSelectorGroup(selector); + } + + Element querySelector(Node root, SelectorGroup selector) { + for (var node in root.nodes) { + if (node is! Element) continue; + if (matches(node, selector)) return node; + var result = querySelector(node, selector); + if (result != null) return result; + } + return null; + } + + void querySelectorAll(Node root, SelectorGroup selector, + List<Element> results) { + + for (var node in root.nodes) { + if (node is! Element) continue; + if (matches(node, selector)) results.add(node); + querySelectorAll(node, selector, results); + } + } + + + bool visitSelectorGroup(SelectorGroup group) => + group.selectors.any(visitSelector); + + bool visitSelector(Selector selector) { + var old = _element; + var result = true; + + // Note: evaluate selectors right-to-left as it's more efficient. + int combinator = null; + for (var s in selector.simpleSelectorSequences.reversed) { + if (combinator == null) { + result = s.simpleSelector.visit(this); + } else if (combinator == TokenKind.COMBINATOR_DESCENDANT) { + // descendant combinator + // http://dev.w3.org/csswg/selectors-4/#descendant-combinators + do { + _element = _element.parent; + } while (_element != null && !s.simpleSelector.visit(this)); + + if (_element == null) result = false; + } else if (combinator == TokenKind.COMBINATOR_TILDE) { + // Following-sibling combinator + // http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators + do { + _element = _element.previousElementSibling; + } while (_element != null && !s.simpleSelector.visit(this)); + + if (_element == null) result = false; + } + + if (!result) break; + + switch (s.combinator) { + case TokenKind.COMBINATOR_PLUS: + // Next-sibling combinator + // http://dev.w3.org/csswg/selectors-4/#adjacent-sibling-combinators + _element = _element.previousElementSibling; + break; + case TokenKind.COMBINATOR_GREATER: + // Child combinator + // http://dev.w3.org/csswg/selectors-4/#child-combinators + _element = _element.parent; + break; + case TokenKind.COMBINATOR_DESCENDANT: + case TokenKind.COMBINATOR_TILDE: + // We need to iterate through all siblings or parents. + // For now, just remember what the combinator was. + combinator = s.combinator; + break; + case TokenKind.COMBINATOR_NONE: break; + default: throw _unsupported(selector); + } + + if (_element == null) { + result = false; + break; + } + } + + _element = old; + return result; + } + + _unimplemented(SimpleSelector selector) => + new UnimplementedError("'$selector' selector of type " + "${selector.runtimeType} is not implemented"); + + _unsupported(selector) => + new FormatException("'$selector' is not a valid selector"); + + bool visitPseudoClassSelector(PseudoClassSelector selector) { + switch (selector.name) { + // http://dev.w3.org/csswg/selectors-4/#structural-pseudos + + // http://dev.w3.org/csswg/selectors-4/#the-root-pseudo + case 'root': + // TODO(jmesserly): fix when we have a .ownerDocument pointer + // return _element == _element.ownerDocument.rootElement; + return _element.localName == 'html' && _element.parentNode == null; + + // http://dev.w3.org/csswg/selectors-4/#the-empty-pseudo + case 'empty': + return _element.nodes.any((n) => !(n is Element || + n is Text && n.text.isNotEmpty)); + + // http://dev.w3.org/csswg/selectors-4/#the-blank-pseudo + case 'blank': + return _element.nodes.any((n) => !(n is Element || + n is Text && n.text.runes.any((r) => !isWhitespaceCC(r)))); + + // http://dev.w3.org/csswg/selectors-4/#the-first-child-pseudo + case 'first-child': + return _element.previousElementSibling == null; + + // http://dev.w3.org/csswg/selectors-4/#the-last-child-pseudo + case 'last-child': + return _element.nextElementSibling == null; + + // http://dev.w3.org/csswg/selectors-4/#the-only-child-pseudo + case 'only-child': + return _element.previousElementSibling == null && + _element.nextElementSibling == null; + + // http://dev.w3.org/csswg/selectors-4/#link + case 'link': + return _element.attributes['href'] != null; + + case 'visited': + // Always return false since we aren't a browser. This is allowed per: + // http://dev.w3.org/csswg/selectors-4/#visited-pseudo + return false; + } + + // :before, :after, :first-letter/line can't match DOM elements. + if (_isLegacyPsuedoClass(selector.name)) return false; + + throw _unimplemented(selector); + } + + + bool visitPseudoElementSelector(PseudoElementSelector selector) { + // :before, :after, :first-letter/line can't match DOM elements. + if (_isLegacyPsuedoClass(selector.name)) return false; + + throw _unimplemented(selector); + } + + static bool _isLegacyPsuedoClass(String name) { + switch (name) { + case 'before': case 'after': case 'first-line': case 'first-letter': + return true; + default: return false; + } + } + + bool visitPseudoElementFunctionSelector(PseudoElementFunctionSelector s) => + throw _unimplemented(s); + + bool visitPseudoClassFunctionSelector(PseudoClassFunctionSelector selector) { + switch (selector.name) { + // http://dev.w3.org/csswg/selectors-4/#child-index + + // http://dev.w3.org/csswg/selectors-4/#the-nth-child-pseudo + case 'nth-child': + // TODO(jmesserly): support An+B syntax too. + var exprs = selector.expression.expressions; + if (exprs.length == 1 && exprs[0] is LiteralTerm) { + LiteralTerm literal = exprs[0]; + var parent = _element.parentNode; + return parent != null && literal.value > 0 && + parent.nodes.indexOf(_element) == literal.value; + } + break; + + // http://dev.w3.org/csswg/selectors-4/#the-lang-pseudo + case 'lang': + // TODO(jmesserly): shouldn't need to get the raw text here, but csslib + // gets confused by the "-" in the expression, such as in "es-AR". + var toMatch = selector.expression.span.text; + var lang = _getInheritedLanguage(_element); + // TODO(jmesserly): implement wildcards in level 4 + return lang != null && lang.startsWith(toMatch); + } + throw _unimplemented(selector); + } + + static String _getInheritedLanguage(Node node) { + while (node != null) { + var lang = node.attributes['lang']; + if (lang != null) return lang; + node = node.parent; + } + return null; + } + + bool visitNamespaceSelector(NamespaceSelector selector) { + // Match element tag name + if (!selector.nameAsSimpleSelector.visit(this)) return false; + + if (selector.isNamespaceWildcard) return true; + + if (selector.namespace == '') return _element.namespaceUri == null; + + throw _unimplemented(selector); + } + + bool visitElementSelector(ElementSelector selector) => + selector.isWildcard || _element.localName == selector.name.toLowerCase(); + + bool visitIdSelector(IdSelector selector) => _element.id == selector.name; + + bool visitClassSelector(ClassSelector selector) => + _element.classes.contains(selector.name); + + // TODO(jmesserly): negation should support any selectors in level 4, + // not just simple selectors. + // http://dev.w3.org/csswg/selectors-4/#negation + bool visitNegationSelector(NegationSelector selector) => + !selector.negationArg.visit(this); + + bool visitAttributeSelector(AttributeSelector selector) { + // Match name first + var value = _element.attributes[selector.name.toLowerCase()]; + if (value == null) return false; + + if (selector.operatorKind == TokenKind.NO_MATCH) return true; + + var select = '${selector.value}'; + switch (selector.operatorKind) { + case TokenKind.EQUALS: + return value == select; + case TokenKind.INCLUDES: + return value.split(' ').any((v) => v.isNotEmpty && v == select); + case TokenKind.DASH_MATCH: + return value.startsWith(select) && + (value.length == select.length || value[select.length] == '-'); + case TokenKind.PREFIX_MATCH: + return value.startsWith(select); + case TokenKind.SUFFIX_MATCH: + return value.endsWith(select); + case TokenKind.SUBSTRING_MATCH: + return value.contains(select); + default: throw _unsupported(selector); + } + } +} diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 708c08c7b..0e17ab5e6 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -251,7 +251,7 @@ class TreeBuilder { var name = token.name; var namespace = token.namespace; if (namespace == null) namespace = defaultNamespace; - var element = new Element(name, namespace) + var element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; return element; @@ -266,7 +266,7 @@ class TreeBuilder { var name = token.name; var namespace = token.namespace; if (namespace == null) namespace = defaultNamespace; - var element = new Element(name, namespace) + var element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; openElements.last.nodes.add(element); @@ -357,8 +357,8 @@ class TreeBuilder { if (lastTable != null) { // XXX - we should really check that this parent is actually a // node here - if (lastTable.parent != null) { - fosterParent = lastTable.parent; + if (lastTable.parentNode != null) { + fosterParent = lastTable.parentNode; insertBefore = lastTable; } else { fosterParent = openElements[openElements.indexOf(lastTable) - 1]; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 75038c6b9..56d613bbe 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,11 +1,12 @@ name: html5lib -version: 0.10.0 +version: 0.11.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib environment: sdk: '>=1.2.0 <2.0.0' dependencies: + csslib: '>=0.10.0 <0.11.0' source_maps: '>=0.9.0 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 99dfb0147..9251faf2e 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -2,71 +2,55 @@ library dom_test; import 'package:unittest/unittest.dart'; +import 'package:html5lib/dom.dart'; import 'package:html5lib/parser.dart'; main() { - group('Node.querySelector type selectors', () { - test('x-foo', () { - expect(parse('<x-foo>').body.querySelector('x-foo'), isNotNull); - }); - - test('-x-foo', () { - var doc = parse('<body><-x-foo>'); - expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>')); - expect(doc.body.querySelector('-x-foo'), isNull); - }); - - test('foo123', () { - expect(parse('<foo123>').body.querySelector('foo123'), isNotNull); - }); - - test('built from fragments', () { - var doc = parse('<body>'); - doc.body.nodes.add(parseFragment('<x-foo>')); - expect(doc.body.querySelector('x-foo'), isNotNull); - }); - - test('123 - invalid', () { - var doc = parse('<123>'); - expect(() => doc.body.querySelector('123'), throwsUnimplementedError); - }); - test('x\\ny - not implemented', () { - var doc = parse('<x\\ny>'); - expect(() => doc.body.querySelector('x\\ny'), throwsUnimplementedError); + group('Element', () { + test('classes', () { + final barBaz = new Element.html('<div class=" bar baz"></div>'); + final quxBaz = new Element.html('<div class="qux baz "></div>'); + expect(barBaz.className, ' bar baz'); + expect(quxBaz.className, 'qux baz '); + expect(barBaz.classes, ['bar', 'baz']); + expect(quxBaz.classes, ['qux', 'baz']); }); }); - group('Node.querySelectorAll type selectors', () { - test('x-foo', () { - expect(parse('<x-foo>').body.querySelectorAll('x-foo').length, 1); - }); - - test('-x-foo', () { - var doc = parse('<body><-x-foo>'); - expect(doc.body.outerHtml, equals('<body>&lt;-x-foo&gt;</body>')); - expect(doc.body.querySelectorAll('-x-foo').length, 0); - }); - - test('foo123', () { - expect(parse('<foo123>').body.querySelectorAll('foo123').length, 1); - }); - - test('built from fragments', () { - var doc = parse('<body>'); - doc.body.nodes.add(parseFragment('<x-foo></x-foo><x-foo>')); - expect(doc.body.querySelectorAll('x-foo').length, 2); - }); - - test('123 - invalid', () { - var doc = parse('<123>'); - expect(() => doc.body.querySelectorAll('123'), throwsUnimplementedError); - }); - - test('x\\ny - not implemented', () { - var doc = parse('<x\\ny>'); - expect(() => doc.body.querySelectorAll('x\\ny'), - throwsUnimplementedError); + group('Document', () { + final doc = parse('<div id=foo>' + '<div class=" bar baz"></div>' + '<div class="qux baz "></div>' + '<div id=Foo>'); + + test('getElementById', () { + var foo = doc.body.nodes[0]; + var Foo = foo.nodes[2]; + expect(foo.id, 'foo'); + expect(Foo.id, 'Foo'); + expect(doc.getElementById('foo'), foo); + expect(doc.getElementById('Foo'), Foo); + }); + + test('getElementsByClassName', () { + var foo = doc.body.nodes[0]; + var barBaz = foo.nodes[0]; + var quxBaz = foo.nodes[1]; + expect(barBaz.className, ' bar baz'); + expect(quxBaz.className, 'qux baz '); + expect(doc.getElementsByClassName('baz'), [barBaz, quxBaz]); + expect(doc.getElementsByClassName('bar '), [barBaz]); + expect(doc.getElementsByClassName(' qux'), [quxBaz]); + expect(doc.getElementsByClassName(' baz qux'), [quxBaz]); + }); + + test('getElementsByTagName', () { + var foo = doc.body.nodes[0]; + var barBaz = foo.nodes[0]; + var quxBaz = foo.nodes[1]; + var Foo = foo.nodes[2]; + expect(doc.getElementsByTagName('div'), [foo, barBaz, quxBaz, Foo]); }); }); diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 212ae0533..b21480d19 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -11,7 +11,7 @@ main() { test('doctype is cloneable', () { var doc = parse('<!doctype HTML>'); DocumentType doctype = doc.nodes[0]; - expect(doctype.clone().toString(), '<!DOCTYPE html>'); + expect(doctype.clone(false).toString(), '<!DOCTYPE html>'); }); test('line counter', () { diff --git a/pkgs/html/test/selectors/LICENSE b/pkgs/html/test/selectors/LICENSE new file mode 100644 index 000000000..0dc019382 --- /dev/null +++ b/pkgs/html/test/selectors/LICENSE @@ -0,0 +1,9 @@ +Contents of this folder are ported from +https://github.com/w3c/web-platform-tests/tree/master/selectors-api + +It is based on commit 96c61ac7c21f7f37526d1c03c4c6087734524130 + +The original code is covered by the dual-licensing approach described in: + + http://www.w3.org/Consortium/Legal/2008/04-testsuite-copyright.html + \ No newline at end of file diff --git a/pkgs/html/test/selectors/README b/pkgs/html/test/selectors/README new file mode 100644 index 000000000..d6e3852f1 --- /dev/null +++ b/pkgs/html/test/selectors/README @@ -0,0 +1,9 @@ +Contents of this folder are ported from +https://github.com/w3c/web-platform-tests/tree/master/selectors-api + +It is based on commit 96c61ac7c21f7f37526d1c03c4c6087734524130 + +It is used to test the implementation of querySelector/querySelectorAll. + +Not all code was ported; as the current implementation doesn't yet support +all features of those methods. diff --git a/pkgs/html/test/selectors/level1-content.html b/pkgs/html/test/selectors/level1-content.html new file mode 100644 index 000000000..b90d918f1 --- /dev/null +++ b/pkgs/html/test/selectors/level1-content.html @@ -0,0 +1,377 @@ +<!DOCTYPE html> +<html id="html" lang="en"> +<head id="head"> + <meta id="meta" charset="UTF-8"> + <title id="title">Selectors-API Test Suite: HTML with Selectors Level 2 using TestHarness: Test Document</title> + + <!-- Links for :link and :visited pseudo-class test --> + <link id="pseudo-link-link1" href=""> + <link id="pseudo-link-link2" href="http://example.org/"> + <link id="pseudo-link-link3"> + <style> + @namespace ns "http://www.w3.org/1999/xhtml"; + /* Declare the namespace prefix used in tests. This declaration should not be used by the API. */ + </style> +</head> +<body id="body"> +<div id="root"> + <div id="target"></div> + + <div id="universal"> + <p id="universal-p1">Universal selector tests inside element with <code id="universal-code1">id="universal"</code>.</p> + <hr id="universal-hr1"> + <pre id="universal-pre1">Some preformatted text with some <span id="universal-span1">embedded code</span></pre> + <p id="universal-p2">This is a normal link: <a id="universal-a1" href="http://www.w3.org/">W3C</a></p> + <address id="universal-address1">Some more nested elements <code id="universal-code2"><a href="#" id="universal-a2">code hyperlink</a></code></address> + </div> + + <div id="attr-presence"> + <div class="attr-presence-div1" id="attr-presence-div1" align="center"></div> + <div class="attr-presence-div2" id="attr-presence-div2" align=""></div> + <div class="attr-presence-div3" id="attr-presence-div3" valign="center"></div> + <div class="attr-presence-div4" id="attr-presence-div4" alignv="center"></div> + <p id="attr-presence-p1"><a id="attr-presence-a1" tItLe=""></a><span id="attr-presence-span1" TITLE="attr-presence-span1"></span></p> + <pre id="attr-presence-pre1" data-attr-presence="pre1"></pre> + <blockquote id="attr-presence-blockquote1" data-attr-presence="blockquote1"></blockquote> + <ul id="attr-presence-ul1" data-中文=""></ul> + + <select id="attr-presence-select1"> + <option id="attr-presence-select1-option1">A</option> + <option id="attr-presence-select1-option2">B</option> + <option id="attr-presence-select1-option3">C</option> + <option id="attr-presence-select1-option4">D</option> + </select> + <select id="attr-presence-select2"> + <option id="attr-presence-select2-option1">A</option> + <option id="attr-presence-select2-option2">B</option> + <option id="attr-presence-select2-option3">C</option> + <option id="attr-presence-select2-option4" selected="selected">D</option> + </select> + <select id="attr-presence-select3" multiple="multiple"> + <option id="attr-presence-select3-option1">A</option> + <option id="attr-presence-select3-option2" selected="">B</option> + <option id="attr-presence-select3-option3" selected="selected">C</option> + <option id="attr-presence-select3-option4">D</option> + </select> + </div> + + <div id="attr-value"> + <div id="attr-value-div1" align="center"></div> + <div id="attr-value-div2" align=""></div> + <div id="attr-value-div3" data-attr-value="&#xE9;"></div> + <div id="attr-value-div4" data-attr-value_foo="&#xE9;"></div> + + <form id="attr-value-form1"> + <input id="attr-value-input1" type="text"> + <input id="attr-value-input2" type="password"> + <input id="attr-value-input3" type="hidden"> + <input id="attr-value-input4" type="radio"> + <input id="attr-value-input5" type="checkbox"> + <input id="attr-value-input6" type="radio"> + <input id="attr-value-input7" type="text"> + <input id="attr-value-input8" type="hidden"> + <input id="attr-value-input9" type="radio"> + </form> + + <div id="attr-value-div5" data-attr-value="中文"></div> + </div> + + <div id="attr-whitespace"> + <div id="attr-whitespace-div1" class="foo div1 bar"></div> + <div id="attr-whitespace-div2" class=""></div> + <div id="attr-whitespace-div3" class="foo div3 bar"></div> + + <div id="attr-whitespace-div4" data-attr-whitespace="foo &#xE9; bar"></div> + <div id="attr-whitespace-div5" data-attr-whitespace_foo="&#xE9; foo"></div> + + <a id="attr-whitespace-a1" rel="next bookmark"></a> + <a id="attr-whitespace-a2" rel="tag nofollow"></a> + <a id="attr-whitespace-a3" rel="tag bookmark"></a> + <a id="attr-whitespace-a4" rel="book mark"></a> <!-- Intentional space in "book mark" --> + <a id="attr-whitespace-a5" rel="nofollow"></a> + <a id="attr-whitespace-a6" rev="bookmark nofollow"></a> + <a id="attr-whitespace-a7" rel="prev next tag alternate nofollow author help icon noreferrer prefetch search stylesheet tag"></a> + + <p id="attr-whitespace-p1" title="Chinese 中文 characters"></p> + </div> + + <div id="attr-hyphen"> + <div id="attr-hyphen-div1"></div> + <div id="attr-hyphen-div2" lang="fr"></div> + <div id="attr-hyphen-div3" lang="en-AU"></div> + <div id="attr-hyphen-div4" lang="es"></div> + </div> + + <div id="attr-begins"> + <a id="attr-begins-a1" href="http://www.example.org"></a> + <a id="attr-begins-a2" href="http://example.org/"></a> + <a id="attr-begins-a3" href="http://www.example.com/"></a> + + <div id="attr-begins-div1" lang="fr"></div> + <div id="attr-begins-div2" lang="en-AU"></div> + <div id="attr-begins-div3" lang="es"></div> + <div id="attr-begins-div4" lang="en-US"></div> + <div id="attr-begins-div5" lang="en"></div> + + <p id="attr-begins-p1" class=" apple"></p> <!-- Intentional space in class value " apple". --> + </div> + + <div id="attr-ends"> + <a id="attr-ends-a1" href="http://www.example.org"></a> + <a id="attr-ends-a2" href="http://example.org/"></a> + <a id="attr-ends-a3" href="http://www.example.org"></a> + + <div id="attr-ends-div1" lang="fr"></div> + <div id="attr-ends-div2" lang="de-CH"></div> + <div id="attr-ends-div3" lang="es"></div> + <div id="attr-ends-div4" lang="fr-CH"></div> + + <p id="attr-ends-p1" class="apple "></p> <!-- Intentional space in class value "apple ". --> + </div> + + <div id="attr-contains"> + <a id="attr-contains-a1" href="http://www.example.org"></a> + <a id="attr-contains-a2" href="http://example.org/"></a> + <a id="attr-contains-a3" href="http://www.example.com/"></a> + + <div id="attr-contains-div1" lang="fr"></div> + <div id="attr-contains-div2" lang="en-AU"></div> + <div id="attr-contains-div3" lang="de-CH"></div> + <div id="attr-contains-div4" lang="es"></div> + <div id="attr-contains-div5" lang="fr-CH"></div> + <div id="attr-contains-div6" lang="en-US"></div> + + <p id="attr-contains-p1" class=" apple banana orange "></p> + </div> + + <div id="pseudo-nth"> + <table id="pseudo-nth-table1"> + <tr id="pseudo-nth-tr1"><td id="pseudo-nth-td1"></td><td id="pseudo-nth-td2"></td><td id="pseudo-nth-td3"></td><td id="pseudo-nth-td4"></td><td id="pseudo-nth--td5"></td><td id="pseudo-nth-td6"></td></tr> + <tr id="pseudo-nth-tr2"><td id="pseudo-nth-td7"></td><td id="pseudo-nth-td8"></td><td id="pseudo-nth-td9"></td><td id="pseudo-nth-td10"></td><td id="pseudo-nth-td11"></td><td id="pseudo-nth-td12"></td></tr> + <tr id="pseudo-nth-tr3"><td id="pseudo-nth-td13"></td><td id="pseudo-nth-td14"></td><td id="pseudo-nth-td15"></td><td id="pseudo-nth-td16"></td><td id="pseudo-nth-td17"></td><td id="pseudo-nth-td18"></td></tr> + </table> + + <ol id="pseudo-nth-ol1"> + <li id="pseudo-nth-li1"></li> + <li id="pseudo-nth-li2"></li> + <li id="pseudo-nth-li3"></li> + <li id="pseudo-nth-li4"></li> + <li id="pseudo-nth-li5"></li> + <li id="pseudo-nth-li6"></li> + <li id="pseudo-nth-li7"></li> + <li id="pseudo-nth-li8"></li> + <li id="pseudo-nth-li9"></li> + <li id="pseudo-nth-li10"></li> + <li id="pseudo-nth-li11"></li> + <li id="pseudo-nth-li12"></li> + </ol> + + <p id="pseudo-nth-p1"> + <span id="pseudo-nth-span1">span1</span> + <em id="pseudo-nth-em1">em1</em> + <!-- comment node--> + <em id="pseudo-nth-em2">em2</em> + <span id="pseudo-nth-span2">span2</span> + <strong id="pseudo-nth-strong1">strong1</strong> + <em id="pseudo-nth-em3">em3</em> + <span id="pseudo-nth-span3">span3</span> + <span id="pseudo-nth-span4">span4</span> + <strong id="pseudo-nth-strong2">strong2</strong> + <em id="pseudo-nth-em4">em4</em> + </p> + </div> + + <div id="pseudo-first-child"> + <div id="pseudo-first-child-div1"></div> + <div id="pseudo-first-child-div2"></div> + <div id="pseudo-first-child-div3"></div> + + <p id="pseudo-first-child-p1"><span id="pseudo-first-child-span1"></span><span id="pseudo-first-child-span2"></span></p> + <p id="pseudo-first-child-p2"><span id="pseudo-first-child-span3"></span><span id="pseudo-first-child-span4"></span></p> + <p id="pseudo-first-child-p3"><span id="pseudo-first-child-span5"></span><span id="pseudo-first-child-span6"></span></p> + </div> + + <div id="pseudo-last-child"> + <p id="pseudo-last-child-p1"><span id="pseudo-last-child-span1"></span><span id="pseudo-last-child-span2"></span></p> + <p id="pseudo-last-child-p2"><span id="pseudo-last-child-span3"></span><span id="pseudo-last-child-span4"></span></p> + <p id="pseudo-last-child-p3"><span id="pseudo-last-child-span5"></span><span id="pseudo-last-child-span6"></span></p> + + <div id="pseudo-last-child-div1"></div> + <div id="pseudo-last-child-div2"></div> + <div id="pseudo-last-child-div3"></div> + </div> + + <div id="pseudo-only"> + <p id="pseudo-only-p1"> + <span id="pseudo-only-span1"></span> + </p> + <p id="pseudo-only-p2"> + <span id="pseudo-only-span2"></span> + <span id="pseudo-only-span3"></span> + </p> + <p id="pseudo-only-p3"> + <span id="pseudo-only-span4"></span> + <em id="pseudo-only-em1"></em> + <span id="pseudo-only-span5"></span> + </p> + </div>> + + <div id="pseudo-empty"> + <p id="pseudo-empty-p1"></p> + <p id="pseudo-empty-p2"><!-- comment node --></p> + <p id="pseudo-empty-p3"> </p> + <p id="pseudo-empty-p4">Text node</p> + <p id="pseudo-empty-p5"><span id="pseudo-empty-span1"></span></p> + </div> + + <div id="pseudo-link"> + <a id="pseudo-link-a1" href="">with href</a> + <a id="pseudo-link-a2" href="http://example.org/">with href</a> + <a id="pseudo-link-a3">without href</a> + <map name="pseudo-link-map1" id="pseudo-link-map1"> + <area id="pseudo-link-area1" href=""> + <area id="pseudo-link-area2"> + </map> + </div> + + <div id="pseudo-lang"> + <div id="pseudo-lang-div1"></div> + <div id="pseudo-lang-div2" lang="fr"></div> + <div id="pseudo-lang-div3" lang="en-AU"></div> + <div id="pseudo-lang-div4" lang="es"></div> + </div> + + <div id="pseudo-ui"> + <input id="pseudo-ui-input1" type="text"> + <input id="pseudo-ui-input2" type="password"> + <input id="pseudo-ui-input3" type="radio"> + <input id="pseudo-ui-input4" type="radio" checked="checked"> + <input id="pseudo-ui-input5" type="checkbox"> + <input id="pseudo-ui-input6" type="checkbox" checked="checked"> + <input id="pseudo-ui-input7" type="submit"> + <input id="pseudo-ui-input8" type="button"> + <input id="pseudo-ui-input9" type="hidden"> + <textarea id="pseudo-ui-textarea1"></textarea> + <button id="pseudo-ui-button1">Enabled</button> + + <input id="pseudo-ui-input10" disabled="disabled" type="text"> + <input id="pseudo-ui-input11" disabled="disabled" type="password"> + <input id="pseudo-ui-input12" disabled="disabled" type="radio"> + <input id="pseudo-ui-input13" disabled="disabled" type="radio" checked="checked"> + <input id="pseudo-ui-input14" disabled="disabled" type="checkbox"> + <input id="pseudo-ui-input15" disabled="disabled" type="checkbox" checked="checked"> + <input id="pseudo-ui-input16" disabled="disabled" type="submit"> + <input id="pseudo-ui-input17" disabled="disabled" type="button"> + <input id="pseudo-ui-input18" disabled="disabled" type="hidden"> + <textarea id="pseudo-ui-textarea2" disabled="disabled"></textarea> + <button id="pseudo-ui-button2" disabled="disabled">Disabled</button> + </div> + + <div id="not"> + <div id="not-div1"></div> + <div id="not-div2"></div> + <div id="not-div3"></div> + + <p id="not-p1"><span id="not-span1"></span><em id="not-em1"></em></p> + <p id="not-p2"><span id="not-span2"></span><em id="not-em2"></em></p> + <p id="not-p3"><span id="not-span3"></span><em id="not-em3"></em></p> + </div> + + <div id="pseudo-element">All pseudo-element tests</div> + + <div id="class"> + <p id="class-p1" class="foo class-p bar"></p> + <p id="class-p2" class="class-p foo bar"></p> + <p id="class-p3" class="foo bar class-p"></p> + + <!-- All permutations of the classes should match --> + <div id="class-div1" class="apple orange banana"></div> + <div id="class-div2" class="apple banana orange"></div> + <p id="class-p4" class="orange apple banana"></p> + <div id="class-div3" class="orange banana apple"></div> + <p id="class-p6" class="banana apple orange"></p> + <div id="class-div4" class="banana orange apple"></div> + <div id="class-div5" class="apple orange"></div> + <div id="class-div6" class="apple banana"></div> + <div id="class-div7" class="orange banana"></div> + + <span id="class-span1" class="台北Táiběi 台北"></span> + <span id="class-span2" class="台北"></span> + + <span id="class-span3" class="foo:bar"></span> + <span id="class-span4" class="test.foo[5]bar"></span> + </div> + + <div id="id"> + <div id="id-div1"></div> + <div id="id-div2"></div> + + <ul id="id-ul1"> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + <li id="id-li-duplicate"></li> + </ul> + + <span id="台北Táiběi"></span> + <span id="台北"></span> + + <span id="#foo:bar"></span> + <span id="test.foo[5]bar"></span> + </div> + + <div id="descendant"> + <div id="descendant-div1" class="descendant-div1"> + <div id="descendant-div2" class="descendant-div2"> + <div id="descendant-div3" class="descendant-div3"> + </div> + </div> + </div> + <div id="descendant-div4" class="descendant-div4"></div> + </div> + + <div id="child"> + <div id="child-div1" class="child-div1"> + <div id="child-div2" class="child-div2"> + <div id="child-div3" class="child-div3"> + </div> + </div> + </div> + <div id="child-div4" class="child-div4"></div> + </div> + + <div id="adjacent"> + <div id="adjacent-div1" class="adjacent-div1"></div> + <div id="adjacent-div2" class="adjacent-div2"> + <div id="adjacent-div3" class="adjacent-div3"></div> + </div> + <div id="adjacent-div4" class="adjacent-div4"> + <p id="adjacent-p1" class="adjacent-p1"></p> + <div id="adjacent-div5" class="adjacent-div5"></div> + </div> + <div id="adjacent-div6" class="adjacent-div6"></div> + <p id="adjacent-p2" class="adjacent-p2"></p> + <p id="adjacent-p3" class="adjacent-p3"></p> + </div> + + <div id="sibling"> + <div id="sibling-div1" class="sibling-div"></div> + <div id="sibling-div2" class="sibling-div"> + <div id="sibling-div3" class="sibling-div"></div> + </div> + <div id="sibling-div4" class="sibling-div"> + <p id="sibling-p1" class="sibling-p"></p> + <div id="sibling-div5" class="sibling-div"></div> + </div> + <div id="sibling-div6" class="sibling-div"></div> + <p id="sibling-p2" class="sibling-p"></p> + <p id="sibling-p3" class="sibling-p"></p> + </div> + + <div id="group"> + <em id="group-em1"></em> + <strong id="group-strong1"></strong> + </div> +</div> +</body> +</html> diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart new file mode 100644 index 000000000..cf9373cd4 --- /dev/null +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -0,0 +1,117 @@ +/// Test for the Selectors API ported from +/// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> +/// +/// Note, unlike the original we don't operate in-browser on a DOM loaded into +/// an iframe, but instead operate over a parsed DOM. +library html5lib.test.selectors.level1_baseline_test; + +import 'dart:io'; +import 'package:html5lib/dom.dart'; +import 'package:html5lib/parser.dart'; +import 'package:unittest/unittest.dart'; +import 'level1_lib.dart' hide test; +import 'selectors.dart'; + +Document getTestContentDocument() { + var testPath = Platform.script.resolve('level1-content.html').toFilePath(); + return parse(new File(testPath).readAsStringSync()); +} + +var testType = TEST_QSA_BASELINE; // Only run baseline tests. +var docType = "html"; // Only run tests suitable for HTML + +main() { + /* + * This test suite tests Selectors API methods in 4 different contexts: + * 1. Document node + * 2. In-document Element node + * 3. Detached Element node (an element with no parent, not in the document) + * 4. Document Fragment node + * + * For each context, the following tests are run: + * + * The interface check tests ensure that each type of node exposes the Selectors API methods + * + * The special selector tests verify the result of passing special values for the selector parameter, + * to ensure that the correct WebIDL processing is performed, such as stringification of null and + * undefined and missing parameter. The universal selector is also tested here, rather than with the + * rest of ordinary selectors for practical reasons. + * + * The static list verification tests ensure that the node lists returned by the method remain unchanged + * due to subsequent document modication, and that a new list is generated each time the method is + * invoked based on the current state of the document. + * + * The invalid selector tests ensure that SyntaxError is thrown for invalid forms of selectors + * + * The valid selector tests check the result from querying many different types of selectors, with a + * list of expected elements. This checks that querySelector() always returns the first result from + * querySelectorAll(), and that all matching elements are correctly returned in tree-order. The tests + * can be limited by specifying the test types to run, using the testType variable. The constants for this + * can be found in selectors.js. + * + * All the selectors tested for both the valid and invalid selector tests are found in selectors.js. + * See comments in that file for documentation of the format used. + * + * The level1-lib.js file contains all the common test functions for running each of the aforementioned tests + */ + + // Prepare the nodes for testing + //doc = frame.contentDocument; // Document Node tests + doc = getTestContentDocument(); + + var element = doc.getElementById("root"); // In-document Element Node tests + + //Setup the namespace tests + setupSpecialElements(element); + + var outOfScope = element.clone(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. + + traverse(outOfScope, (elem) { // Annotate each element as being a clone; used for verifying + elem.attributes["data-clone"] = ""; // that none of these elements ever match. + }); + + var detached = element.clone(true); // Detached Element Node tests + + var fragment = doc.createDocumentFragment(); // Fragment Node tests + fragment.append(element.clone(true)); + + // Setup Tests + interfaceCheck("Document", doc); + interfaceCheck("Detached Element", detached); + interfaceCheck("Fragment", fragment); + interfaceCheck("In-document Element", element); + + runSpecialSelectorTests("Document", doc); + runSpecialSelectorTests("Detached Element", detached); + runSpecialSelectorTests("Fragment", fragment); + runSpecialSelectorTests("In-document Element", element); + + verifyStaticList("Document", doc); + verifyStaticList("Detached Element", detached); + verifyStaticList("Fragment", fragment); + verifyStaticList("In-document Element", element); + + // TODO(jmesserly): fix negative tests + //runInvalidSelectorTest("Document", doc, invalidSelectors); + //runInvalidSelectorTest("Detached Element", detached, invalidSelectors); + //runInvalidSelectorTest("Fragment", fragment, invalidSelectors); + //runInvalidSelectorTest("In-document Element", element, invalidSelectors); + + runValidSelectorTest("Document", doc, validSelectors, testType, docType); + runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType); + runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType); + + group('out of scope', () { + setUp(() { + doc.body.append(outOfScope); // Append before in-document Element tests. + // None of these elements should match + }); + tearDown(() { + outOfScope.remove(); + }); + runValidSelectorTest("In-document Element", element, validSelectors, testType, docType); + }); +} diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart new file mode 100644 index 000000000..31e0faf54 --- /dev/null +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -0,0 +1,275 @@ +/// Test for the Selectors API ported from +/// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> +/// +/// Note: tried to make minimal changes possible here. Hence some oddities such +/// as [test] arguments having a different order, long lines, etc. +/// +/// As usual with ports: being faithful to the original style is more important +/// than other style goals, as it reduces friction to integrating changes +/// from upstream. +library html5lib.test.selectors.level1_lib; + +import 'package:html5lib/dom.dart'; +import 'package:unittest/unittest.dart' as unittest; + +Document doc; + +/* + * Create and append special elements that cannot be created correctly with HTML markup alone. + */ +setupSpecialElements(parent) { + // Setup null and undefined tests + parent.append(doc.createElement("null")); + parent.append(doc.createElement("undefined")); + + // Setup namespace tests + var anyNS = doc.createElement("div"); + var noNS = doc.createElement("div"); + anyNS.id = "any-namespace"; + noNS.id = "no-namespace"; + + var div; + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "any-namespace-div1"; + div[1].id = "any-namespace-div2"; + div[2].attributes["id"] = "any-namespace-div3"; // Non-HTML elements can't use .id property + div[3].attributes["id"] = "any-namespace-div4"; + + for (var i = 0; i < div.length; i++) { + anyNS.append(div[i]); + } + + div = [doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div")]; + + div[0].id = "no-namespace-div1"; + div[1].id = "no-namespace-div2"; + div[2].attributes["id"] = "no-namespace-div3"; // Non-HTML elements can't use .id property + div[3].attributes["id"] = "no-namespace-div4"; + + for (var i = 0; i < div.length; i++) { + noNS.append(div[i]); + } + + parent.append(anyNS); + parent.append(noNS); +} + +/* + * Check that the querySelector and querySelectorAll methods exist on the given Node + */ +interfaceCheck(type, obj) { + test(() { + var q = obj.querySelector is Function; + assert_true(q, type + " supports querySelector."); + }, type + " supports querySelector"); + + test(() { + var qa = obj.querySelectorAll is Function; + assert_true( qa, type + " supports querySelectorAll."); + }, type + " supports querySelectorAll"); + + test(() { + var list = obj.querySelectorAll("div"); + // TODO(jmesserly): testing List<Element> for now. It should return an + // ElementList which has extra properties. Needed for dart:html compat. + assert_true(list is List<Element>, "The result should be an instance of a NodeList"); + }, type + ".querySelectorAll returns NodeList instance"); +} + +/* + * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after + * each call. A static list should not be affected by subsequent changes to the DOM. + */ +verifyStaticList(type, root) { + var pre, post, preLength; + + test(() { + pre = root.querySelectorAll("div"); + preLength = pre.length; + + var div = doc.createElement("div"); + (root is Document ? root.body : root).append(div); + + assert_equals(pre.length, preLength, "The length of the NodeList should not change."); + }, type + ": static NodeList"); + + test(() { + post = root.querySelectorAll("div"); + assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list."); + }, type + ": new NodeList"); +} + +/* + * Verify handling of special values for the selector parameter, including stringification of + * null and undefined, and the handling of the empty string. + */ +runSpecialSelectorTests(type, root) { + // Dart note: changed these tests because we don't have auto conversion to + // String like JavaScript does. + test(() { // 1 + assert_equals(root.querySelectorAll('null').length, 1, "This should find one element with the tag name 'NULL'."); + }, type + ".querySelectorAll null"); + + test(() { // 2 + assert_equals(root.querySelectorAll('undefined').length, 1, "This should find one element with the tag name 'UNDEFINED'."); + }, type + ".querySelectorAll undefined"); + + test(() { // 3 + assert_throws((e) => e is NoSuchMethodError, () { + root.querySelectorAll(); + }, "This should throw a TypeError."); + }, type + ".querySelectorAll no parameter"); + + test(() { // 4 + var elm = root.querySelector('null'); + assert_not_equals(elm, null, "This should find an element."); + // TODO(jmesserly): change "localName" back to "tagName" once implemented. + assert_equals(elm.localName.toUpperCase(), "NULL", "The tag name should be 'NULL'."); + }, type + ".querySelector null"); + + test(() { // 5 + var elm = root.querySelector('undefined'); + assert_not_equals(elm, 'undefined', "This should find an element."); + // TODO(jmesserly): change "localName" back to "tagName" once implemented. + assert_equals(elm.localName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'."); + }, type + ".querySelector undefined"); + + test(() { // 6 + assert_throws((e) => e is NoSuchMethodError, () { + root.querySelector(); + }, "This should throw a TypeError."); + }, type + ".querySelector no parameter"); + + test(() { // 7 + var result = root.querySelectorAll("*"); + var i = 0; + traverse(root, (elem) { + if (!identical(elem, root)) { + assert_equals(elem, result[i], "The result in index $i should be in tree order."); + i++; + } + }); + }, type + ".querySelectorAll tree order"); +} + +/* + * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() + * Only run these tests when results are expected. Don't run for syntax error tests. + */ + runValidSelectorTest(type, root, selectors, testType, docType) { + var nodeType = ""; + switch (root.nodeType) { + case Node.DOCUMENT_NODE: + nodeType = "document"; + break; + case Node.ELEMENT_NODE: + nodeType = root.parentNode != null ? "element" : "detached"; + break; + case Node.DOCUMENT_FRAGMENT_NODE: + nodeType = "fragment"; + break; + default: + throw new StateError("Reached unreachable code path."); + } + + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + var e = s["expect"]; + + if ((s["exclude"] is! List || (s["exclude"].indexOf(nodeType) == -1 && s["exclude"].indexOf(docType) == -1)) + && (s["testType"] & testType != 0) ) { + //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) + var foundall, found; + + test(() { + foundall = root.querySelectorAll(q); + assert_not_equals(foundall, null, "The method should not return null."); + assert_equals(foundall.length, e.length, "The method should return the expected number of matches."); + + for (var i = 0; i < e.length; i++) { + assert_not_equals(foundall[i], null, "The item in index $i should not be null."); + assert_equals(foundall[i].attributes["id"], e[i], "The item in index $i should have the expected ID."); + assert_false(foundall[i].attributes.containsKey("data-clone"), "This should not be a cloned element."); + } + }, type + ".querySelectorAll: " + n + ": " + q); + + test(() { + found = root.querySelector(q); + + if (e.length > 0) { + assert_not_equals(found, null, "The method should return a match."); + assert_equals(found.attributes["id"], e[0], "The method should return the first match."); + assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll."); + assert_false(found.attributes.containsKey("data-clone"), "This should not be annotated as a cloned element."); + } else { + assert_equals(found, null, "The method should not match anything."); + } + }, type + ".querySelector: " + n + ": " + q); + } else { + //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) + } + } +} + +/* + * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() + * Only run these tests when errors are expected. Don't run for valid selector tests. + */ + runInvalidSelectorTest(type, root, selectors) { + for (var i = 0; i < selectors.length; i++) { + var s = selectors[i]; + var n = s["name"]; + var q = s["selector"]; + + // Dart note: FormatException seems a reasonable mapping of SyntaxError + test(() { + assert_throws((e) => e is FormatException, () { + root.querySelector(q); + }); + }, type + ".querySelector: " + n + ": " + q); + + test(() { + assert_throws((e) => e is FormatException, () { + root.querySelectorAll(q); + }); + }, type + ".querySelectorAll: " + n + ": " + q); + } +} + + traverse(Node elem, fn) { + if (elem.nodeType == Node.ELEMENT_NODE) { + fn(elem); + } + + // Dart note: changed this since html5lib doens't support nextNode yet. + for (var node in elem.nodes) { + traverse(node, fn); + } +} + + +test(Function body, String name) => unittest.test(name, body); + +assert_true(value, String reason) => + unittest.expect(value, true, reason: reason); + +assert_false(value, String reason) => + unittest.expect(value, false, reason: reason); + +assert_equals(x, y, reason) => + unittest.expect(x, y, reason: reason); + +assert_not_equals(x, y, reason) => + unittest.expect(x, unittest.isNot(y), reason: reason); + +assert_throws(exception, body, [reason]) => + unittest.expect(body, unittest.throwsA(exception), reason: reason); diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart new file mode 100644 index 000000000..fd8bd965f --- /dev/null +++ b/pkgs/html/test/selectors/selectors.dart @@ -0,0 +1,363 @@ +/// Test for the Selectors API ported from +/// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> +library html5lib.test.selectors.selectors; + +// Bit-mapped flags to indicate which tests the selector is suitable for +var TEST_QSA_BASELINE = 0x01; // querySelector() and querySelectorAll() baseline tests +var TEST_QSA_ADDITIONAL = 0x02; // querySelector() and querySelectorAll() additional tests +var TEST_FIND_BASELINE = 0x04; // find() and findAll() baseline tests, may be unsuitable for querySelector[All] +var TEST_FIND_ADDITIONAL = 0x08; // find() and findAll() additional tests, may be unsuitable for querySelector[All] +var TEST_MATCH_BASELINE = 0x10; // matches() baseline tests +var TEST_MATCH_ADDITIONAL = 0x20; // matches() additional tests + + +/* + * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + */ +var invalidSelectors = [ + {'name': "Empty String", 'selector': ""}, + {'name': "Invalid character", 'selector': "["}, + {'name': "Invalid character", 'selector': "]"}, + {'name': "Invalid character", 'selector': "("}, + {'name': "Invalid character", 'selector': ")"}, + {'name': "Invalid character", 'selector': "{"}, + {'name': "Invalid character", 'selector': "}"}, + {'name': "Invalid character", 'selector': "<"}, + {'name': "Invalid character", 'selector': ">"}, + {'name': "Invalid ID", 'selector': "#"}, + {'name': "Invalid group of selectors", 'selector': "div,"}, + {'name': "Invalid class", 'selector': "."}, + {'name': "Invalid class", 'selector': ".5cm"}, + {'name': "Invalid class", 'selector': "..test"}, + {'name': "Invalid class", 'selector': ".foo..quux"}, + {'name': "Invalid class", 'selector': ".bar."}, + {'name': "Invalid combinator", 'selector': "div & address, p"}, + {'name': "Invalid combinator", 'selector': "div >> address, p"}, + {'name': "Invalid combinator", 'selector': "div ++ address, p"}, + {'name': "Invalid combinator", 'selector': "div ~~ address, p"}, + {'name': "Invalid [att=value] selector", 'selector': "[*=test]"}, + {'name': "Invalid [att=value] selector", 'selector': "[*|*=test]"}, + {'name': "Invalid [att=value] selector", 'selector': "[class= space unquoted ]"}, + {'name': "Unknown pseudo-class", 'selector': "div:example"}, + {'name': "Unknown pseudo-class", 'selector': ":example"}, + {'name': "Unknown pseudo-element", 'selector': "div::example"}, + {'name': "Unknown pseudo-element", 'selector': "::example"}, + {'name': "Invalid pseudo-element", 'selector': ":::before"}, + {'name': "Undeclared namespace", 'selector': "ns|div"}, + {'name': "Undeclared namespace", 'selector': ":not(ns|div)"}, + {'name': "Invalid namespace", 'selector': "^|div"}, + {'name': "Invalid namespace", 'selector': "\$|div"} +]; + +/* + * All of these should be valid selectors, expected to match zero or more elements in the document. + * None should throw any errors. + * + * name: A descriptive name of the selector being tested + * selector: The selector to test + * 'expect': A list of IDs of the elements expected to be matched. List must be given in tree order. + * 'exclude': An array of contexts to exclude from testing. The valid values are: + * ["document", "element", "fragment", "detached", "html", "xhtml"] + * The "html" and "xhtml" values represent the type of document being queried. These are useful + * for tests that are affected by differences between HTML and XML, such as case sensitivity. + * 'level': An integer indicating the CSS or Selectors level in which the selector being tested was introduced. + * 'testType': A bit-mapped flag indicating the type of test. + * + * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. + */ +var validSelectors = [ + // Type Selector + {'name': "Type selector, matching html element", 'selector': "html", 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Type selector, matching html element", 'selector': "html", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': "Type selector, matching body element", 'selector': "body", 'expect': ["body"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Type selector, matching body element", 'selector': "body", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + + // Universal Selector + // Testing "*" for entire an entire context node is handled separately. + {'name': "Universal selector, matching all children of element with specified ID", 'selector': "#universal>*", 'expect': ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Universal selector, matching all grandchildren of element with specified ID", 'selector': "#universal>*>*", 'expect': ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Universal selector, matching all children of empty element with specified ID", 'selector': "#empty>*", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Universal selector, matching all descendants of element with specified ID", 'selector': "#universal *", 'expect': ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // Attribute Selectors + // - presence [att] + {'name': "Attribute presence selector, matching align attribute with value", 'selector': ".attr-presence-div1[align]", 'expect': ["attr-presence-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, matching align attribute with empty value", 'selector': ".attr-presence-div2[align]", 'expect': ["attr-presence-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, matching title attribute, case insensitivity", 'selector': "#attr-presence [TiTlE]", 'expect': ["attr-presence-a1", "attr-presence-span1"], 'exclude': ["xhtml"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, not matching title attribute, case sensitivity", 'selector': "#attr-presence [TiTlE]", 'expect': [], 'exclude': ["html"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, matching custom data-* attribute", 'selector': "[data-attr-presence]", 'expect': ["attr-presence-pre1", "attr-presence-blockquote1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, not matching attribute with similar name", 'selector': ".attr-presence-div3[align], .attr-presence-div4[align]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute presence selector, matching attribute with non-ASCII characters", 'selector': "ul[data-中文]", 'expect': ["attr-presence-ul1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, not matching default option without selected attribute", 'selector': "#attr-presence-select1 option[selected]", 'expect': [] /* no matches */, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute presence selector, matching option with selected attribute", 'selector': "#attr-presence-select2 option[selected]", 'expect': ["attr-presence-select2-option4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute presence selector, matching multiple options with selected attributes", 'selector': "#attr-presence-select3 option[selected]", 'expect': ["attr-presence-select3-option2", "attr-presence-select3-option3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - value [att=val] + {'name': "Attribute value selector, matching align attribute with value", 'selector': "#attr-value [align=\"center\"]", 'expect': ["attr-value-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector, matching align attribute with empty value", 'selector': "#attr-value [align=\"\"]", 'expect': ["attr-value-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector, not matching align attribute with partial value", 'selector': "#attr-value [align=\"c\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute value selector, not matching align attribute with incorrect value", 'selector': "#attr-value [align=\"centera\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute value selector, matching custom data-* attribute with unicode escaped value", 'selector': "[data-attr-value=\"\\e9\"]", 'expect': ["attr-value-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector, matching custom data-* attribute with escaped character", 'selector': "[data-attr-value\_foo=\"\\e9\"]", 'expect': ["attr-value-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type='hidden'],#attr-value input[type='radio']", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector with unquoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type=hidden],#attr-value input[type=radio]", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute value selector, matching attribute with value using non-ASCII characters", 'selector': "[data-attr-value=中文]", 'expect': ["attr-value-div5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - whitespace-separated list [att~=val] + {'name': "Attribute whitespace-separated list selector, matching class attribute with value", 'selector': "#attr-whitespace [class~=\"div1\"]", 'expect': ["attr-whitespace-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector, not matching class attribute with empty value", 'selector': "#attr-whitespace [class~=\"\"]", 'expect': [] /*no matches*/ , 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute whitespace-separated list selector, not matching class attribute with partial value", 'selector': "[data-attr-whitespace~=\"div\"]", 'expect': [] /*no matches*/ , 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", 'selector': "[data-attr-whitespace~=\"\\0000e9\"]", 'expect': ["attr-whitespace-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", 'selector': "[data-attr-whitespace\_foo~=\"\\e9\"]", 'expect': ["attr-whitespace-div5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", 'selector': "#attr-whitespace a[rel~=\"book mark\"]", 'expect': [] /* no matches */, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", 'selector': "#attr-whitespace [title~=中文]", 'expect': ["attr-whitespace-p1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - hyphen-separated list [att|=val] + {'name': "Attribute hyphen-separated list selector, not matching unspecified lang attribute", 'selector': "#attr-hyphen-div1[lang|=\"en\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Attribute hyphen-separated list selector, matching lang attribute with exact value", 'selector': "#attr-hyphen-div2[lang|=\"fr\"]", 'expect': ["attr-hyphen-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute hyphen-separated list selector, matching lang attribute with partial value", 'selector': "#attr-hyphen-div3[lang|=\"en\"]", 'expect': ["attr-hyphen-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Attribute hyphen-separated list selector, not matching incorrect value", 'selector': "#attr-hyphen-div4[lang|=\"es-AR\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + + // - substring begins-with [att^=val] (Level 3) + {'name': "Attribute begins with selector, matching href attributes beginning with specified substring", 'selector': "#attr-begins a[href^=\"http://www\"]", 'expect': ["attr-begins-a1", "attr-begins-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute begins with selector, matching lang attributes beginning with specified substring, ", 'selector': "#attr-begins [lang^=\"en-\"]", 'expect': ["attr-begins-div2", "attr-begins-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute begins with selector, not matching class attribute not beginning with specified substring", 'selector': "#attr-begins [class^=apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-begins [class^=' apple']", 'expect': ["attr-begins-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-begins [class^=\" apple\"]", 'expect': ["attr-begins-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", 'selector': "#attr-begins [class^= apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - substring ends-with [att\$=val] (Level 3) + {'name': "Attribute ends with selector, matching href attributes ending with specified substring", 'selector': "#attr-ends a[href\$=\".org\"]", 'expect': ["attr-ends-a1", "attr-ends-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute ends with selector, matching lang attributes ending with specified substring, ", 'selector': "#attr-ends [lang\$=\"-CH\"]", 'expect': ["attr-ends-div2", "attr-ends-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute ends with selector, not matching class attribute not ending with specified substring", 'selector': "#attr-ends [class\$=apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-ends [class\$='apple ']", 'expect': ["attr-ends-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-ends [class\$=\"apple \"]", 'expect': ["attr-ends-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", 'selector': "#attr-ends [class\$=apple ]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - substring contains [att*=val] (Level 3) + {'name': "Attribute contains selector, matching href attributes beginning with specified substring", 'selector': "#attr-contains a[href*=\"http://www\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector, matching href attributes ending with specified substring", 'selector': "#attr-contains a[href*=\".org\"]", 'expect': ["attr-contains-a1", "attr-contains-a2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector, matching href attributes containing specified substring", 'selector': "#attr-contains a[href*=\".example.\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector, matching lang attributes beginning with specified substring, ", 'selector': "#attr-contains [lang*=\"en-\"]", 'expect': ["attr-contains-div2", "attr-contains-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector, matching lang attributes ending with specified substring, ", 'selector': "#attr-contains [lang*=\"-CH\"]", 'expect': ["attr-contains-div3", "attr-contains-div5"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*=' apple']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*='orange ']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*='ple banana ora']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*=\" apple\"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*=\"orange \"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*=\"ple banana ora\"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*= apple]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*=orange ]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "Attribute contains selector with unquoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*= banana ]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // Pseudo-classes + // - :root (Level 3) + {'name': ":root pseudo-class selector, matching document root element", 'selector': ":root", 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":root pseudo-class selector, not matching document root element", 'selector': ":root", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - :nth-child(n) (Level 3) + {'name': ":nth-child selector, matching the third child element", 'selector': "#pseudo-nth-table1 :nth-child(3)", 'expect': ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-child selector, matching every third child element", 'selector': "#pseudo-nth li:nth-child(3n)", 'expect': ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-child selector, matching every second child element, starting from the fourth", 'selector': "#pseudo-nth li:nth-child(2n+4)", 'expect': ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-child selector, matching every fourth child element, starting from the third", 'selector': "#pseudo-nth-p1 :nth-child(4n-1)", 'expect': ["pseudo-nth-em2", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :nth-last-child (Level 3) + {'name': ":nth-last-child selector, matching the third last child element", 'selector': "#pseudo-nth-table1 :nth-last-child(3)", 'expect': ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-last-child selector, matching every third child element from the end", 'selector': "#pseudo-nth li:nth-last-child(3n)", 'expect': ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", 'selector': "#pseudo-nth li:nth-last-child(2n+4)", 'expect': ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-last-child selector, matching every fourth element from the end, starting from the third last", 'selector': "#pseudo-nth-p1 :nth-last-child(4n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :nth-of-type(n) (Level 3) + {'name': ":nth-of-type selector, matching the third em element", 'selector': "#pseudo-nth-p1 em:nth-of-type(3)", 'expect': ["pseudo-nth-em3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-of-type selector, matching every second element of their type", 'selector': "#pseudo-nth-p1 :nth-of-type(2n)", 'expect': ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-of-type selector, matching every second elemetn of their type, starting from the first", 'selector': "#pseudo-nth-p1 span:nth-of-type(2n-1)", 'expect': ["pseudo-nth-span1", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :nth-last-of-type(n) (Level 3) + {'name': ":nth-last-of-type selector, matching the thrid last em element", 'selector': "#pseudo-nth-p1 em:nth-last-of-type(3)", 'expect': ["pseudo-nth-em2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-last-of-type selector, matching every second last element of their type", 'selector': "#pseudo-nth-p1 :nth-last-of-type(2n)", 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":nth-last-of-type selector, matching every second last element of their type, starting from the last", 'selector': "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :first-of-type (Level 3) + {'name': ":first-of-type selector, matching the first em element", 'selector': "#pseudo-nth-p1 em:first-of-type", 'expect': ["pseudo-nth-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":first-of-type selector, matching the first of every type of element", 'selector': "#pseudo-nth-p1 :first-of-type", 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":first-of-type selector, matching the first td element in each table row", 'selector': "#pseudo-nth-table1 tr :first-of-type", 'expect': ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :last-of-type (Level 3) + {'name': ":last-of-type selector, matching the last em elemnet", 'selector': "#pseudo-nth-p1 em:last-of-type", 'expect': ["pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":last-of-type selector, matching the last of every type of element", 'selector': "#pseudo-nth-p1 :last-of-type", 'expect': ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":last-of-type selector, matching the last td element in each table row", 'selector': "#pseudo-nth-table1 tr :last-of-type", 'expect': ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :first-child + {'name': ":first-child pseudo-class selector, matching first child div element", 'selector': "#pseudo-first-child div:first-child", 'expect': ["pseudo-first-child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":first-child pseudo-class selector, doesn't match non-first-child elements", 'selector': ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': ":first-child pseudo-class selector, matching first-child of multiple elements", 'selector': "#pseudo-first-child span:first-child", 'expect': ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - :last-child (Level 3) + {'name': ":last-child pseudo-class selector, matching last child div element", 'selector': "#pseudo-last-child div:last-child", 'expect': ["pseudo-last-child-div3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":last-child pseudo-class selector, doesn't match non-last-child elements", 'selector': ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': ":last-child pseudo-class selector, matching first-child of multiple elements", 'selector': "#pseudo-last-child span:last-child", 'expect': ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :only-child (Level 3) + {'name': ":pseudo-only-child pseudo-class selector, matching all only-child elements", 'selector': "#pseudo-only :only-child", 'expect': ["pseudo-only-span1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":pseudo-only-child pseudo-class selector, matching only-child em elements", 'selector': "#pseudo-only em:only-child", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - :only-of-type (Level 3) + {'name': ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", 'selector': "#pseudo-only :only-of-type", 'expect': ["pseudo-only-span1", "pseudo-only-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", 'selector': "#pseudo-only em:only-of-type", 'expect': ["pseudo-only-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :empty (Level 3) + {'name': ":empty pseudo-class selector, matching empty p elements", 'selector': "#pseudo-empty p:empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":empty pseudo-class selector, matching all empty elements", 'selector': "#pseudo-empty :empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :link and :visited + // Implementations may treat all visited links as unvisited, so these cannot be tested separately. + // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. + {'name': ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", 'selector': "#pseudo-link :link, #pseudo-link :visited", 'expect': ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":link and :visited pseudo-class selectors, matching link elements with href attributes", 'selector': "#head :link, #head :visited", 'expect': ["pseudo-link-link1", "pseudo-link-link2"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":link and :visited pseudo-class selectors, not matching link elements with href attributes", 'selector': "#head :link, #head :visited", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", 'selector': ":link:visited", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + + // - :target (Level 3) + {'name': ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", 'selector': ":target", 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", 'selector': ":target", 'expect': ["target"], 'exclude': ["fragment", "detached"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :lang() + {'name': ":lang pseudo-class selector, matching inherited language", 'selector': "#pseudo-lang-div1:lang(en)", 'expect': ["pseudo-lang-div1"], 'exclude': ["detached", "fragment"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":lang pseudo-class selector, not matching element with no inherited language", 'selector': "#pseudo-lang-div1:lang(en)", 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': ":lang pseudo-class selector, matching specified language with exact value", 'selector': "#pseudo-lang-div2:lang(fr)", 'expect': ["pseudo-lang-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":lang pseudo-class selector, matching specified language with partial value", 'selector': "#pseudo-lang-div3:lang(en)", 'expect': ["pseudo-lang-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': ":lang pseudo-class selector, not matching incorrect language", 'selector': "#pseudo-lang-div4:lang(es-AR)", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + + // - :enabled (Level 3) + {'name': ":enabled pseudo-class selector, matching all enabled form controls", 'selector': "#pseudo-ui :enabled", 'expect': ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", + "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :disabled (Level 3) + {'name': ":enabled pseudo-class selector, matching all disabled form controls", 'selector': "#pseudo-ui :disabled", 'expect': ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", + "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :checked (Level 3) + {'name': ":checked pseudo-class selector, matching checked radio buttons and checkboxes", 'selector': "#pseudo-ui :checked", 'expect': ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // - :not(s) (Level 3) + {'name': ":not pseudo-class selector, matching ", 'selector': "#not>:not(div)", 'expect': ["not-p1", "not-p2", "not-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":not pseudo-class selector, matching ", 'selector': "#not * :not(:first-child)", 'expect': ["not-em1", "not-em2", "not-em3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*)", 'expect': [] /* no matches */, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*|*)", 'expect': [] /* no matches */, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // Pseudo-elements + // - ::first-line + {'name': ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:first-line", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::first-line", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - ::first-letter + {'name': ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:first-letter", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::first-letter", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - ::before + {'name': ":before pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:before", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "::before pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::before", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // - ::after + {'name': ":after pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:after", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "::after pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::after", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + + // Class Selectors + {'name': "Class selector, matching element with specified class", 'selector': ".class-p", 'expect': ["class-p1","class-p2", "class-p3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class selector, chained, matching only elements with all specified classes", 'selector': "#class .apple.orange.banana", 'expect': ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class Selector, chained, with type selector", 'selector': "div.apple.banana.orange", 'expect': ["class-div1", "class-div2", "class-div3", "class-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process. + {'name': "Class selector, matching element with class value using non-ASCII characters", 'selector': ".台北Táiběi", 'expect': ["class-span1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class selector, matching multiple elements with class value using non-ASCII characters", 'selector': ".台北", 'expect': ["class-span1","class-span2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class selector, chained, matching element with multiple class values using non-ASCII characters", 'selector': ".台北Táiběi.台北", 'expect': ["class-span1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class selector, matching element with class with escaped character", 'selector': ".foo\\:bar", 'expect': ["class-span3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Class selector, matching element with class with escaped character", 'selector': ".test\\.foo\\[5\\]bar", 'expect': ["class-span4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // ID Selectors + {'name': "ID selector, matching element with specified id", 'selector': "#id #id-div1", 'expect': ["id-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div1", 'expect': ["id-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID Selector, chained, with type selector", 'selector': "div#id-div1, div#id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID selector, not matching non-existent descendant", 'selector': "#id #none", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': "ID selector, not matching non-existent ancestor", 'selector': "#none #id-div1", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': "ID selector, matching multiple elements with duplicate id", 'selector': "#id-li-duplicate", 'expect': ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process. + {'name': "ID selector, matching id value using non-ASCII characters", 'selector': "#台北Táiběi", 'expect': ["台北Táiběi"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID selector, matching id value using non-ASCII characters", 'selector': "#台北", 'expect': ["台北"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "ID selector, matching id values using non-ASCII characters", 'selector': "#台北Táiběi, #台北", 'expect': ["台北Táiběi", "台北"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values + {'name': "ID selector, matching element with id with escaped character", 'selector': "#\\#foo\\:bar", 'expect': ["#foo:bar"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': "ID selector, matching element with id with escaped character", 'selector': "#test\\.foo\\[5\\]bar", 'expect': ["test.foo[5]bar"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + + // Namespaces + // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id + {'name': "Namespace selector, matching element with any namespace", 'selector': "#any-namespace *|div", 'expect': ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], 'level': 3, 'testType': TEST_QSA_BASELINE}, + {'name': "Namespace selector, matching div elements in no namespace only", 'selector': "#no-namespace |div", 'expect': ["no-namespace-div3"], 'level': 3, 'testType': TEST_QSA_BASELINE}, + {'name': "Namespace selector, matching any elements in no namespace only", 'selector': "#no-namespace |*", 'expect': ["no-namespace-div3"], 'level': 3, 'testType': TEST_QSA_BASELINE}, + + // Combinators + // - Descendant combinator ' ' + {'name': "Descendant combinator, matching element that is a descendant of an element with id", 'selector': "#descendant div", 'expect': ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, matching element with id that is a descendant of an element", 'selector': "body #descendant-div1", 'expect': ["descendant-div1"], 'exclude': ["detached", "fragment"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, matching element with id that is a descendant of an element", 'selector': "div #descendant-div1", 'expect': ["descendant-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, matching element with id that is a descendant of an element with id", 'selector': "#descendant #descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, matching element with class that is a descendant of an element with id", 'selector': "#descendant .descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, matching element with class that is a descendant of an element with class", 'selector': ".descendant-div1 .descendant-div3", 'expect': ["descendant-div3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Descendant combinator, not matching element with id that is not a descendant of an element with id", 'selector': "#descendant-div1 #descendant-div4", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, + {'name': "Descendant combinator, whitespace characters", 'selector': "#descendant\t\r\n#descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - Child combinator '>' + {'name': "Child combinator, matching element that is a child of an element with id", 'selector': "#child>div", 'expect': ["child-div1", "child-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, matching element with id that is a child of an element", 'selector': "div>#child-div1", 'expect': ["child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, matching element with id that is a child of an element with id", 'selector': "#child>#child-div1", 'expect': ["child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, matching element with id that is a child of an element with class", 'selector': "#child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, matching element with class that is a child of an element with class", 'selector': ".child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, not matching element with id that is not a child of an element with id", 'selector': "#child>#child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Child combinator, not matching element with id that is not a child of an element with class", 'selector': "#child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Child combinator, not matching element with class that is not a child of an element with class", 'selector': ".child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Child combinator, surrounded by whitespace", 'selector': "#child-div1\t\r\n>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, whitespace after", 'selector': "#child-div1>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, whitespace before", 'selector': "#child-div1\t\r\n>#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Child combinator, no whitespace", 'selector': "#child-div1>#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - Adjacent sibling combinator '+' + {'name': "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+div", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", 'selector': "div+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", 'selector': ".adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", 'selector': "#adjacent div+p", 'expect': ["adjacent-p2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", 'selector': "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + {'name': "Adjacent sibling combinator, surrounded by whitespace", 'selector': "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, whitespace after", 'selector': "#adjacent-p2+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, whitespace before", 'selector': "#adjacent-p2\t\r\n+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Adjacent sibling combinator, no whitespace", 'selector': "#adjacent-p2+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + + // - General sibling combinator ~ (Level 3) + {'name': "General sibling combinator, matching element that is a sibling of an element with id", 'selector': "#sibling-div2~div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, matching element with id that is a sibling of an element", 'selector': "div~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, matching element with id that is a sibling of an element with id", 'selector': "#sibling-div2~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, matching element with class that is a sibling of an element with id", 'selector': "#sibling-div2~.sibling-div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, matching p element that is a sibling of a div element", 'selector': "#sibling div~p", 'expect': ["sibling-p2", "sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, not matching element with id that is not a sibling after a p element", 'selector': "#sibling>p~div", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': "General sibling combinator, not matching element with id that is not a sibling after an element with id", 'selector': "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + {'name': "General sibling combinator, surrounded by whitespace", 'selector': "#sibling-p2\t\r\n~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, whitespace after", 'selector': "#sibling-p2~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, whitespace before", 'selector': "#sibling-p2\t\r\n~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + {'name': "General sibling combinator, no whitespace", 'selector': "#sibling-p2~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + + // Group of selectors (comma) + {'name': "Syntax, group of selectors separator, surrounded by whitespace", 'selector': "#group em\t\r \n,\t\r \n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Syntax, group of selectors separator, whitespace after", 'selector': "#group em,\t\r\n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Syntax, group of selectors separator, whitespace before", 'selector': "#group em\t\r\n,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + {'name': "Syntax, group of selectors separator, no whitespace", 'selector': "#group em,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, +]; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 4d2cb5afc..e0454747a 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -140,6 +140,8 @@ class TestSerializer extends TreeVisitor { indent -= 1; } + visitDocumentFragment(DocumentFragment node) => visitDocument(node); + visitElement(Element node) { _newline(); _str.write(node); From d8c9e44f976eb10a7227f4fc2431ffd36ee79843 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Thu, 8 May 2014 22:06:44 +0000 Subject: [PATCH 030/212] [html5lib] fix type annotation and pkg.status for angular_tests angular_tests issue is http://dartbug.com/18733 Review URL: https://codereview.chromium.org//274913002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@35945 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/support.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index e0454747a..d8891580b 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -134,7 +134,7 @@ class TestSerializer extends TreeVisitor { indent -= 2; } - visitDocument(Document node) { + visitDocument(node) { indent += 1; for (var child in node.nodes) visit(child); indent -= 1; From 2dd62e69e22ff04724c9501d018bffc597fd3bb8 Mon Sep 17 00:00:00 2001 From: "jmesserly@google.com" <jmesserly@google.com> Date: Thu, 8 May 2014 22:34:48 +0000 Subject: [PATCH 031/212] [html5lib] fix another type annotation Review URL: https://codereview.chromium.org//278693002 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@35948 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/test/support.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index d8891580b..0118ecf8d 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -90,7 +90,7 @@ class TestData extends IterableBase<Map> { } /// Serialize the [document] into the html5 test data format. -testSerializer(Document document) { +testSerializer(document) { return (new TestSerializer()..visit(document)).toString(); } From 59b22ccebeb065cbdfedac0ffc043f57d1995a37 Mon Sep 17 00:00:00 2001 From: "sigmund@google.com" <sigmund@google.com> Date: Mon, 12 May 2014 22:38:19 +0000 Subject: [PATCH 032/212] Fix status in bots. BUG= Review URL: https://codereview.chromium.org//281613003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@36083 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 56d613bbe..66ff1c021 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -6,7 +6,7 @@ homepage: http://pub.dartlang.org/packages/html5lib environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0 <0.11.0' + csslib: '>=0.10.0-dev <0.11.0' source_maps: '>=0.9.0 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From e5e90f802b3ed264c3bdfc8f8f18e17175816de2 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" <lrn@google.com> Date: Thu, 22 May 2014 08:29:59 +0000 Subject: [PATCH 033/212] The toSet operation returns a new Set with the same equality and iteration behavior, and with the same elements. R=floitsch@google.com, jmesserly@google.com, sgjesse@google.com Review URL: https://codereview.chromium.org//288103003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@36473 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 66ff1c021..911177085 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.11.0 +version: 0.12.0-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib From 09300686259525485f41c81eed8d780ae5b146e6 Mon Sep 17 00:00:00 2001 From: "sigmund@google.com" <sigmund@google.com> Date: Fri, 23 May 2014 22:01:17 +0000 Subject: [PATCH 034/212] Update versions before releasing. R=jmesserly@google.com Review URL: https://codereview.chromium.org//297973003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@36590 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 911177085..56d613bbe 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html5lib -version: 0.12.0-dev +version: 0.11.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0-dev <0.11.0' + csslib: '>=0.10.0 <0.11.0' source_maps: '>=0.9.0 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From 21b17312affcfa71625cdbad7ce0dba5d2aef442 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" <nweiz@google.com> Date: Wed, 28 May 2014 00:32:00 +0000 Subject: [PATCH 035/212] Fix a couple more tests that were relying on sourcemap message format. Review URL: https://codereview.chromium.org//297203009 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@36722 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/lib/parser.dart | 2 +- pkgs/html/pubspec.yaml | 4 ++-- pkgs/html/test/parser_feature_test.dart | 4 ++-- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index dd64e8997..7c7ebb092 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html5lib package. +#### Pub version 0.10.0+1 + * use a more recent source_maps version. + #### Pub version 0.10.0 * fix how document fragments are added in NodeList.add/addAll/insertAll. diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 721985abe..aca56617e 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -3354,7 +3354,7 @@ class ParseError implements Exception { String toString() { var res = span.getLocationMessage(message); - return span.sourceUrl == null ? 'ParserError$res' : res; + return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; } } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 56d613bbe..e4a2d9aab 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.11.0 +version: 0.11.0+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib @@ -7,7 +7,7 @@ environment: sdk: '>=1.2.0 <2.0.0' dependencies: csslib: '>=0.10.0 <0.11.0' - source_maps: '>=0.9.0 <0.10.0' + source_maps: '>=0.9.1 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: path: '>=0.9.0 <2.0.0' diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index b21480d19..e5b036f00 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -53,7 +53,7 @@ main() { expect(error.span.text, '<!DOCTYPE html>'); expect(error.toString(), ''' -ParseError:4:3: Unexpected DOCTYPE. Ignored. +On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. <!DOCTYPE html> ^^^^^^^^^^^^^^^'''); }); @@ -245,7 +245,7 @@ ParseError:4:3: Unexpected DOCTYPE. Ignored. expect(parser.errors[0].message, 'Unexpected non-space characters. Expected DOCTYPE.'); expect(parser.errors[0].toString(), - 'ParserError:1:4: Unexpected non-space characters. ' + 'ParserError on line 1, column 4: Unexpected non-space characters. ' 'Expected DOCTYPE.'); }); From 1a4f863fbef3b2a7e91b0b655fd8250a1695fd99 Mon Sep 17 00:00:00 2001 From: "lrn@google.com" <lrn@google.com> Date: Thu, 12 Jun 2014 08:11:22 +0000 Subject: [PATCH 036/212] Add "last" setter to List. This allows assigning directly as `list.last = value` instead of having to use the longer `list[list.length - 1] = value`. It's just an abbreviation, like `list.last` is for reading. If you use a List as a stack (which is a perfectly good use of it), modifying the last element like this is a natural operation. R=sgjesse@google.com Review URL: https://codereview.chromium.org//315173005 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@37255 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 4 ++++ pkgs/html/lib/src/list_proxy.dart | 1 + pkgs/html/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index a87bca96e..95652dd01 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -852,6 +852,10 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> this[index].replaceWith(value); } + void set last(Element value) { + this.last.replaceWith(value); + } + void set length(int newLength) { final len = this.length; if (newLength >= len) { diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 0ba70733b..866d0ec72 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -47,6 +47,7 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { set length(int value) { _list.length = value; } void add(E value) { _list.add(value); } + void set last(E value) { _list.last = value; } void addLast(E value) { add(value); } void addAll(Iterable<E> collection) { _list.addAll(collection); } void sort([int compare(E a, E b)]) { _list.sort(compare); } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index e4a2d9aab..267d539ec 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.11.0+1 +version: 0.11.1+0-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib From ab3235c209953466f9f7bd003f6e6d8216e6b4ef Mon Sep 17 00:00:00 2001 From: "lrn@google.com" <lrn@google.com> Date: Fri, 13 Jun 2014 09:40:22 +0000 Subject: [PATCH 037/212] Revert "Add "last" setter to List." After discussion, we decided not to change the List interface for something that is just a convenience. Also revert "Mark pkgbuild/pkg/collection as failing when using repository packages" R=sgjesse@google.com Review URL: https://codereview.chromium.org//331833003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@37307 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/lib/dom.dart | 4 ---- pkgs/html/lib/src/list_proxy.dart | 1 - pkgs/html/pubspec.yaml | 2 +- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 95652dd01..a87bca96e 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -852,10 +852,6 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> this[index].replaceWith(value); } - void set last(Element value) { - this.last.replaceWith(value); - } - void set length(int newLength) { final len = this.length; if (newLength >= len) { diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 866d0ec72..0ba70733b 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -47,7 +47,6 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { set length(int value) { _list.length = value; } void add(E value) { _list.add(value); } - void set last(E value) { _list.last = value; } void addLast(E value) { add(value); } void addAll(Iterable<E> collection) { _list.addAll(collection); } void sort([int compare(E a, E b)]) { _list.sort(compare); } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 267d539ec..e4a2d9aab 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.11.1+0-dev +version: 0.11.0+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib From bdf7b6c6877e7bd7846df5ed06317493a85d176d Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" <nweiz@google.com> Date: Wed, 30 Jul 2014 00:13:19 +0000 Subject: [PATCH 038/212] Use source_span rather than source_maps in csslib. This will release csslib 0.11.0 and html5lib 0.11.0+2. BUG=19930 R=sigmund@google.com Review URL: https://codereview.chromium.org//426053003 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@38716 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 7c7ebb092..1c7004297 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html5lib package. +#### Pub version 0.11.0+2 + * expand the version constraint for csslib. + #### Pub version 0.10.0+1 * use a more recent source_maps version. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index e4a2d9aab..086cb08c8 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html5lib -version: 0.11.0+1 +version: 0.11.0+2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0 <0.11.0' + csslib: '>=0.10.0 <0.12.0' source_maps: '>=0.9.1 <0.10.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From e1714e6deac83b6e72436d4709a8361cfd0ca997 Mon Sep 17 00:00:00 2001 From: "nweiz@google.com" <nweiz@google.com> Date: Wed, 30 Jul 2014 21:36:43 +0000 Subject: [PATCH 039/212] Switch various transformers and libraries they use over to source_span. This would release html5lib 0.12.0 and code_transformers 0.2.0. BUG=19930 R=blois@google.com, sigmund@google.com Review URL: https://codereview.chromium.org//421503004 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/third_party/html5lib@38754 260f80e4-7a28-3924-810f-c04153c831b5 --- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/lib/dom.dart | 2 +- pkgs/html/lib/parser.dart | 27 ++++++++++++------------- pkgs/html/lib/src/inputstream.dart | 7 ++++--- pkgs/html/lib/src/token.dart | 2 +- pkgs/html/lib/src/tokenizer.dart | 3 +-- pkgs/html/lib/src/treebuilder.dart | 2 +- pkgs/html/pubspec.yaml | 4 ++-- pkgs/html/test/parser_feature_test.dart | 4 +++- 9 files changed, 30 insertions(+), 25 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 1c7004297..6d485f418 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,10 @@ This file contains highlights of what changes on each version of the html5lib package. +#### Pub version 0.12.0 + * switch from `source_maps`' `Span` class to `source_span`'s + `SourceSpan` class. + #### Pub version 0.11.0+2 * expand the version constraint for csslib. diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index a87bca96e..3c5b33291 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -8,7 +8,7 @@ library dom; // implement that. import 'dart:collection'; -import 'package:source_maps/span.dart' show FileSpan; +import 'package:source_span/source_span.dart'; import 'src/constants.dart'; import 'src/css_class_set.dart'; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index aca56617e..ded6a74b6 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -15,7 +15,7 @@ library parser; import 'dart:collection'; import 'dart:math'; -import 'package:source_maps/span.dart' show Span, FileSpan; +import 'package:source_span/source_span.dart'; import 'src/treebuilder.dart'; import 'src/constants.dart'; @@ -32,7 +32,7 @@ import 'dom.dart'; /// [encoding], which must be a string. If specified that encoding will be /// used regardless of any BOM or later declaration (such as in a meta element). /// -/// Set [generateSpans] if you want to generate [Span]s, otherwise the +/// Set [generateSpans] if you want to generate [SourceSpan]s, otherwise the /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you /// can additionally pass [sourceUrl] to indicate where the [input] was /// extracted from. @@ -52,7 +52,7 @@ Document parse(input, {String encoding, bool generateSpans: false, /// [encoding], which must be a string. If specified, that encoding will be used, /// regardless of any BOM or later declaration (such as in a meta element). /// -/// Set [generateSpans] if you want to generate [Span]s, otherwise the +/// Set [generateSpans] if you want to generate [SourceSpan]s, otherwise the /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. @@ -70,7 +70,7 @@ class HtmlParser { /// Raise an exception on the first error encountered. final bool strict; - /// True to generate [Span]s for the [Node.sourceSpan] property. + /// True to generate [SourceSpan]s for the [Node.sourceSpan] property. final bool generateSpans; final HtmlTokenizer tokenizer; @@ -363,12 +363,13 @@ class HtmlParser { /// The last span available. Used for EOF errors if we don't have something /// better. - Span get _lastSpan { + SourceSpan get _lastSpan { + if (tokenizer.stream.fileInfo == null) return null; var pos = tokenizer.stream.position; - return new FileSpan(tokenizer.stream.fileInfo, pos, pos); + return tokenizer.stream.fileInfo.location(pos).pointSpan(); } - void parseError(Span span, String errorcode, + void parseError(SourceSpan span, String errorcode, [Map datavars = const {}]) { if (!generateSpans && span == null) { @@ -2177,9 +2178,7 @@ class InTableTextPhase extends Phase { var span = null; if (parser.generateSpans) { - span = new FileSpan.union( - characterTokens[0].span, - characterTokens.last.span); + span = characterTokens[0].span.expand(characterTokens.last.span); } if (!allWhitespace(data)) { @@ -3333,9 +3332,9 @@ class AfterAfterFramesetPhase extends Phase { /// Error in parsed document. -class ParseError implements Exception { +class ParseError implements SourceSpanException { final String errorCode; - final Span span; + final SourceSpan span; final Map data; ParseError(this.errorCode, this.span, this.data); @@ -3352,8 +3351,8 @@ class ParseError implements Exception { /// [toString] will include 'ParserError:' as a prefix. String get message => formatStr(errorMessages[errorCode], data); - String toString() { - var res = span.getLocationMessage(message); + String toString({color}) { + var res = span.message(message, color: color); return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; } } diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index 5686abf75..231fed0c5 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -2,7 +2,7 @@ library inputstream; import 'dart:collection'; import 'package:utf/utf.dart'; -import 'package:source_maps/span.dart' show SourceFile; +import 'package:source_span/source_span.dart'; import 'char_encodings.dart'; import 'constants.dart'; import 'utils.dart'; @@ -135,8 +135,9 @@ class HtmlInputStream { // Free decoded characters if they aren't needed anymore. if (_rawBytes != null) _rawChars = null; - fileInfo = new SourceFile(sourceUrl, _lineStarts, - generateSpans ? _chars : null); + // TODO(sigmund): Don't parse the file at all if spans aren't being + // generated. + fileInfo = new SourceFile.decoded(_chars, url: sourceUrl); } diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index b1ec1de34..934015315 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -2,7 +2,7 @@ library token; import 'dart:collection'; -import 'package:source_maps/span.dart' show FileSpan; +import 'package:source_span/source_span.dart'; /// An html5 token. abstract class Token { diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index b4863753f..1b6311497 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -2,7 +2,6 @@ library tokenizer; import 'dart:collection'; import 'package:html5lib/parser.dart' show HtmlParser; -import 'package:source_maps/span.dart' show Span, FileSpan; import 'constants.dart'; import 'inputstream.dart'; import 'token.dart'; @@ -157,7 +156,7 @@ class HtmlTokenizer implements Iterator<Token> { void _addToken(Token token) { if (generateSpans && token.span == null) { int offset = stream.position; - token.span = new FileSpan(stream.fileInfo, _lastOffset, offset); + token.span = stream.fileInfo.span(_lastOffset, offset); if (token is! ParseErrorToken) { _lastOffset = offset; } diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 0e17ab5e6..4b8dfc425 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -4,7 +4,7 @@ library treebuilder; import 'dart:collection'; import 'package:html5lib/dom.dart'; import 'package:html5lib/parser.dart' show getElementNameTuple; -import 'package:source_maps/span.dart' show FileSpan; +import 'package:source_span/source_span.dart'; import 'constants.dart'; import 'list_proxy.dart'; import 'token.dart'; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 086cb08c8..2be76779e 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html5lib -version: 0.11.0+2 +version: 0.12.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: http://pub.dartlang.org/packages/html5lib @@ -7,7 +7,7 @@ environment: sdk: '>=1.2.0 <2.0.0' dependencies: csslib: '>=0.10.0 <0.12.0' - source_maps: '>=0.9.1 <0.10.0' + source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: path: '>=0.9.0 <2.0.0' diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index e5b036f00..2950a7742 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -246,7 +246,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. 'Unexpected non-space characters. Expected DOCTYPE.'); expect(parser.errors[0].toString(), 'ParserError on line 1, column 4: Unexpected non-space characters. ' - 'Expected DOCTYPE.'); + 'Expected DOCTYPE.\n' + 'foo\n' + ' ^'); }); test('Element.text', () { From 0c08ec761c85abe26598b51472c18987e83d02c3 Mon Sep 17 00:00:00 2001 From: Sigmund Cherem <sigmund@google.com> Date: Thu, 9 Oct 2014 13:05:00 -0700 Subject: [PATCH 040/212] Add status file for html5lib Review URL: https://codereview.chromium.org//640393002 --- pkgs/html/.gitignore | 17 +++++++++++++++++ pkgs/html/.status | 28 ++++++++++++++++++++++++++++ pkgs/html/codereview.settings | 3 +++ 3 files changed, 48 insertions(+) create mode 100644 pkgs/html/.gitignore create mode 100644 pkgs/html/.status create mode 100644 pkgs/html/codereview.settings diff --git a/pkgs/html/.gitignore b/pkgs/html/.gitignore new file mode 100644 index 000000000..e97917062 --- /dev/null +++ b/pkgs/html/.gitignore @@ -0,0 +1,17 @@ +# Don’t commit the following directories created by pub. +.pub +build/ +packages + +# Or the files created by dart2js. +*.dart.js +*.dart.precompiled.js +*.js_ +*.js.deps +*.js.map +*.sw? +.idea/ +.pub/ + +# Include when developing application packages. +pubspec.lock diff --git a/pkgs/html/.status b/pkgs/html/.status new file mode 100644 index 000000000..3bfc3528b --- /dev/null +++ b/pkgs/html/.status @@ -0,0 +1,28 @@ +# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +# Don't run any test-like files that show up in packages directories. It +# shouldn't be necessary to run "pub install" in these packages, but if you do +# it shouldn't break the tests. +*/packages/*/*: Skip +*/*/packages/*/*: Skip +*/*/*/packages/*/*: Skip +*/*/*/*/packages/*/*: Skip +*/*/*/*/*/packages/*/*: Skip + +build/*: Skip # nothing requires pub-build + +[ $runtime == vm && $mode == debug] +test/tokenizer_test: Skip # Times out + +[ $runtime == vm && ( $arch == simarm || $arch == simmips ) ] +test/tokenizer_test: Pass, Slow + +[ $browser ] +test/parser_test: Skip +test/tokenizer_test: Skip +test/selectors/*: Skip + +[ $runtime == vm ] +test/browser/browser_test: Skip diff --git a/pkgs/html/codereview.settings b/pkgs/html/codereview.settings new file mode 100644 index 000000000..39ffa4fa1 --- /dev/null +++ b/pkgs/html/codereview.settings @@ -0,0 +1,3 @@ +CODE_REVIEW_SERVER: http://codereview.chromium.org/ +VIEW_VC: https://github.com/dart-lang/core-elements/commit/ +CC_LIST: reviews@dartlang.org From 737d72605f7d96c0ad80bf318c383a934359a11d Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 28 Jan 2015 11:06:59 -0800 Subject: [PATCH 041/212] updated homepage --- pkgs/html/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 2be76779e..dbffdce43 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,8 +1,8 @@ name: html5lib -version: 0.12.0 +version: 0.12.1-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. -homepage: http://pub.dartlang.org/packages/html5lib +homepage: https://github.com/dart-lang/html5lib environment: sdk: '>=1.2.0 <2.0.0' dependencies: From d4aa896e0e4a00daacfc799c0f3a8770ba5e68e6 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 28 Jan 2015 11:07:13 -0800 Subject: [PATCH 042/212] removed unused members --- pkgs/html/lib/dom.dart | 40 ---------------------------- pkgs/html/lib/parser.dart | 4 +-- pkgs/html/lib/src/css_class_set.dart | 1 - pkgs/html/test/parser_test.dart | 3 --- pkgs/html/test/support.dart | 1 - 5 files changed, 2 insertions(+), 47 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 3c5b33291..7b1442222 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -272,46 +272,6 @@ abstract class Node { bool contains(Node node) => nodes.contains(node); - /// Checks if this is a type selector. - /// See <http://www.w3.org/TR/CSS2/grammar.html>. - /// Note: this doesn't support '*', the universal selector, non-ascii chars or - /// escape chars. - bool _isTypeSelector(String selector) { - // Parser: - - // element_name - // : IDENT | '*' - // ; - - // Lexer: - - // nmstart [_a-z]|{nonascii}|{escape} - // nmchar [_a-z0-9-]|{nonascii}|{escape} - // ident -?{nmstart}{nmchar}* - // nonascii [\240-\377] - // unicode \\{h}{1,6}(\r\n|[ \t\r\n\f])? - // escape {unicode}|\\[^\r\n\f0-9a-f] - - // As mentioned above, no nonascii or escape support yet. - int len = selector.length; - if (len == 0) return false; - - int i = 0; - const int DASH = 45; - if (selector.codeUnitAt(i) == DASH) i++; - - if (i >= len || !isLetter(selector[i])) return false; - i++; - - for (; i < len; i++) { - if (!isLetterOrDigit(selector[i]) && selector.codeUnitAt(i) != DASH) { - return false; - } - } - - return true; - } - /// Initialize [attributeSpans] using [sourceSpan]. void _ensureAttributeSpans() { if (_attributeSpans != null) return; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index ded6a74b6..23f62a7ed 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -534,7 +534,7 @@ class HtmlParser { void parseRCDataRawtext(Token token, String contentType) { assert(contentType == "RAWTEXT" || contentType == "RCDATA"); - var element = tree.insertElement(token); + tree.insertElement(token); if (contentType == "RAWTEXT") { tokenizer.state = tokenizer.rawtextState; @@ -1973,7 +1973,7 @@ class TextPhase extends Phase { } void endTagOther(EndTagToken token) { - var node = tree.openElements.removeLast(); + tree.openElements.removeLast(); parser.phase = parser.originalPhase; } } diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 03136a787..ea0152d1f 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -28,7 +28,6 @@ class ElementCssClassSet extends CssClassSetImpl { } void writeClasses(Set<String> s) { - List list = new List.from(s); _element.className = s.join(' '); } } diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 821eb2d7e..aa454933c 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -84,7 +84,6 @@ void main() { var testName = pathos.basenameWithoutExtension(path); group(testName, () { - int index = 0; for (var testData in tests) { var input = testData['data']; var errors = testData['errors']; @@ -102,8 +101,6 @@ void main() { }); } } - - index++; } }); } diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 0118ecf8d..3a9959389 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -45,7 +45,6 @@ class TestData extends IterableBase<Map> { var key = null; var result = <Map>[]; var lines = _text.split('\n'); - int numLines = lines.length; // Remove trailing newline to match Python if (lines.last == '') { lines.removeLast(); From 6c5844d12109af1522b286535a164ecaac335989 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 28 Jan 2015 11:07:53 -0800 Subject: [PATCH 043/212] upgrade unittest dependency --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index dbffdce43..87d6fc74f 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -11,4 +11,4 @@ dependencies: utf: '>=0.9.0 <0.10.0' dev_dependencies: path: '>=0.9.0 <2.0.0' - unittest: '>=0.10.0 <0.11.0' + unittest: '>=0.10.0 <0.12.0' From 9ac68b301c76b1603fb1762ba806bd8380c04276 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 28 Jan 2015 11:09:09 -0800 Subject: [PATCH 044/212] fixed test script --- pkgs/html/test/run.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/test/run.sh b/pkgs/html/test/run.sh index f269bdaa0..c060bd754 100755 --- a/pkgs/html/test/run.sh +++ b/pkgs/html/test/run.sh @@ -15,8 +15,8 @@ pushd $DIR/.. # TODO(jmesserly): switch to new analyzer. Note: it's missing a lot of the # tests for implemented members; we should get that fixed before switching. echo Analyzing library for warnings or type errors -dartanalyzer --fatal-warnings --fatal-type-errors lib/*.dart || \ +dartanalyzer --fatal-warnings lib/*.dart || \ echo "ignore analyzer errors" popd -dart --enable-type-checks --enable-asserts test/run_all.dart $@ +dart --checked test/run_all.dart $@ From 10de01ac9940b0366263398273d1df11d5456538 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 28 Jan 2015 11:10:11 -0800 Subject: [PATCH 045/212] formatted source code --- pkgs/html/lib/dom.dart | 66 +- pkgs/html/lib/dom_parsing.dart | 64 +- pkgs/html/lib/parser.dart | 1475 +++++++----- pkgs/html/lib/src/char_encodings.dart | 93 +- pkgs/html/lib/src/constants.dart | 478 ++-- pkgs/html/lib/src/css_class_set.dart | 21 +- pkgs/html/lib/src/encoding_parser.dart | 7 +- pkgs/html/lib/src/inputstream.dart | 49 +- pkgs/html/lib/src/list_proxy.dart | 43 +- pkgs/html/lib/src/query_selector.dart | 41 +- pkgs/html/lib/src/token.dart | 1 - pkgs/html/lib/src/tokenizer.dart | 139 +- pkgs/html/lib/src/treebuilder.dart | 58 +- pkgs/html/lib/src/utils.dart | 8 +- pkgs/html/test/dom_test.dart | 7 +- pkgs/html/test/parser_feature_test.dart | 6 +- pkgs/html/test/parser_test.dart | 14 +- .../test/selectors/level1_baseline_test.dart | 29 +- pkgs/html/test/selectors/level1_lib.dart | 110 +- pkgs/html/test/selectors/selectors.dart | 1982 +++++++++++++++-- pkgs/html/test/support.dart | 2 +- pkgs/html/test/tokenizer_test.dart | 42 +- 22 files changed, 3392 insertions(+), 1343 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 7b1442222..6201f69db 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -54,8 +54,8 @@ class AttributeName implements Comparable { int compareTo(other) { // Not sure about this sort order if (other is! AttributeName) return 1; - int cmp = (prefix != null ? prefix : "").compareTo( - (other.prefix != null ? other.prefix : "")); + int cmp = (prefix != null ? prefix : "") + .compareTo((other.prefix != null ? other.prefix : "")); if (cmp != 0) return cmp; cmp = name.compareTo(other.name); if (cmp != 0) return cmp; @@ -80,8 +80,7 @@ abstract class _ParentNode implements Node { /// are implemented. For example, nth-child does not implement An+B syntax /// and *-of-type is not implemented. If a selector is not implemented this /// method will throw [UniplmentedError]. - Element querySelector(String selector) => - query.querySelector(this, selector); + Element querySelector(String selector) => query.querySelector(this, selector); /// Returns all descendant nodes matching the given selectors, using a /// preorder traversal. @@ -111,10 +110,9 @@ abstract class _ElementAndDocument implements _ParentNode { List<Element> getElementsByTagName(String localName) => querySelectorAll(localName); - List<Element> getElementsByClassName(String classNames) => - querySelectorAll(classNames.splitMapJoin(' ', - onNonMatch: (m) => m.isNotEmpty ? '.$m' : m, - onMatch: (m) => '')); + List<Element> getElementsByClassName(String classNames) => querySelectorAll( + classNames.splitMapJoin(' ', + onNonMatch: (m) => m.isNotEmpty ? '.$m' : m, onMatch: (m) => '')); } /// Really basic implementation of a DOM-core like Node. @@ -281,8 +279,8 @@ abstract class Node { if (sourceSpan == null) return; - var tokenizer = new HtmlTokenizer(sourceSpan.text, generateSpans: true, - attributeSpans: true); + var tokenizer = new HtmlTokenizer(sourceSpan.text, + generateSpans: true, attributeSpans: true); tokenizer.moveNext(); var token = tokenizer.current as StartTagToken; @@ -291,8 +289,8 @@ abstract class Node { for (var attr in token.attributeSpans) { var offset = sourceSpan.start.offset; - _attributeSpans[attr.name] = sourceSpan.file.span( - offset + attr.start, offset + attr.end); + _attributeSpans[attr.name] = + sourceSpan.file.span(offset + attr.start, offset + attr.end); if (attr.startValue != null) { _attributeValueSpans[attr.name] = sourceSpan.file.span( offset + attr.startValue, offset + attr.endValue); @@ -312,7 +310,6 @@ abstract class Node { class Document extends Node with _ParentNode, _NonElementParentNode, _ElementAndDocument { - Document() : super._(); factory Document.html(String html) => parse(html); @@ -349,9 +346,7 @@ class Document extends Node DocumentFragment createDocumentFragment() => new DocumentFragment(); } -class DocumentFragment extends Node - with _ParentNode, _NonElementParentNode { - +class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { DocumentFragment() : super._(); factory DocumentFragment.html(String html) => parseFragment(html); @@ -382,7 +377,8 @@ class DocumentType extends Node { DocumentType(String name, this.publicId, this.systemId) // Note: once Node.tagName is removed, don't pass "name" to super - : name = name, super._(); + : name = name, + super._(); int get nodeType => Node.DOCUMENT_TYPE_NODE; @@ -398,7 +394,6 @@ class DocumentType extends Node { } } - void _addOuterHtml(StringBuffer str) { str.write(toString()); } @@ -420,7 +415,9 @@ class Text extends Node { Text clone(bool deep) => new Text(data); String get text => data; - set text(String value) { data = value; } + set text(String value) { + data = value; + } } // TODO(jmesserly): Elements should have a pointer back to their document @@ -433,7 +430,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { Element._(this.localName, [this.namespaceUri]) : super._(); - Element.tag(this.localName) : namespaceUri = Namespaces.html, super._(); + Element.tag(this.localName) + : namespaceUri = Namespaces.html, + super._(); static final _START_TAG_REGEXP = new RegExp('<(\\w+)'); @@ -553,7 +552,8 @@ class Element extends Node with _ParentNode, _ElementAndDocument { str.write('>'); if (nodes.length > 0) { - if (localName == 'pre' || localName == 'textarea' || + if (localName == 'pre' || + localName == 'textarea' || localName == 'listing') { final first = nodes[0]; if (first is Text && first.data.startsWith('\n')) { @@ -586,7 +586,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { Element clone(bool deep) { var result = new Element._(localName, namespaceUri) - ..attributes = new LinkedHashMap.from(attributes); + ..attributes = new LinkedHashMap.from(attributes); return _clone(result, deep); } @@ -644,7 +644,6 @@ class Comment extends Node { } } - // TODO(jmesserly): fix this to extend one of the corelib classes if possible. // (The requirement to remove the node from the old node list makes it tricky.) // TODO(jmesserly): is there any way to share code with the _NodeListImpl? @@ -718,7 +717,7 @@ class NodeList extends ListProxy<Node> { // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see // http://code.google.com/p/dart/issues/detail?id=5371 void setRange(int start, int rangeLength, List<Node> from, - [int startFrom = 0]) { + [int startFrom = 0]) { if (from is NodeList) { // Note: this is presumed to make a copy from = from.sublist(startFrom, startFrom + rangeLength); @@ -777,14 +776,12 @@ class NodeList extends ListProxy<Node> { } } - /// An indexable collection of a node's descendants in the document tree, /// filtered so that only elements are in the collection. // TODO(jmesserly): this was copied from dart:html // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. class FilteredElementList extends IterableBase<Element> with ListMixin<Element> implements List<Element> { - final Node _node; final List<Node> _childNodes; @@ -794,7 +791,9 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> /// /// var filteredElements = new FilteredElementList(query("#container")); /// // filteredElements is [a, b, c]. - FilteredElementList(Node node): _childNodes = node.nodes, _node = node; + FilteredElementList(Node node) + : _childNodes = node.nodes, + _node = node; // We can't memoize this, since it's possible that children will be messed // with externally to this class. @@ -802,7 +801,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> // TODO(nweiz): we don't always need to create a new list. For example // forEach, every, any, ... could directly work on the _childNodes. List<Element> get _filtered => - new List<Element>.from(_childNodes.where((n) => n is Element)); + new List<Element>.from(_childNodes.where((n) => n is Element)); void forEach(void f(Element element)) { _filtered.forEach(f); @@ -846,7 +845,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> } void setRange(int start, int end, Iterable<Element> iterable, - [int skipCount = 0]) { + [int skipCount = 0]) { throw new UnimplementedError(); } @@ -917,7 +916,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> bool every(bool f(Element element)) => _filtered.every(f); bool any(bool f(Element element)) => _filtered.any(f); - List<Element> toList({ bool growable: true }) => + List<Element> toList({bool growable: true}) => new List<Element>.from(this, growable: growable); Set<Element> toSet() => new Set<Element>.from(this); Element firstWhere(bool test(Element value), {Element orElse()}) { @@ -940,12 +939,11 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> int get length => _filtered.length; Element operator [](int index) => _filtered[index]; Iterator<Element> get iterator => _filtered.iterator; - List<Element> sublist(int start, [int end]) => - _filtered.sublist(start, end); + List<Element> sublist(int start, [int end]) => _filtered.sublist(start, end); Iterable<Element> getRange(int start, int end) => - _filtered.getRange(start, end); + _filtered.getRange(start, end); int indexOf(Element element, [int start = 0]) => - _filtered.indexOf(element, start); + _filtered.indexOf(element, start); int lastIndexOf(Element element, [int start = null]) { if (start == null) start = length - 1; diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 527d9a6fa..5575dcd2f 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -9,13 +9,20 @@ import 'src/constants.dart' show rcdataElements; class TreeVisitor { visit(Node node) { switch (node.nodeType) { - case Node.ELEMENT_NODE: return visitElement(node); - case Node.TEXT_NODE: return visitText(node); - case Node.COMMENT_NODE: return visitComment(node); - case Node.DOCUMENT_FRAGMENT_NODE: return visitDocumentFragment(node); - case Node.DOCUMENT_NODE: return visitDocument(node); - case Node.DOCUMENT_TYPE_NODE: return visitDocumentType(node); - default: throw new UnsupportedError('DOM node type ${node.nodeType}'); + case Node.ELEMENT_NODE: + return visitElement(node); + case Node.TEXT_NODE: + return visitText(node); + case Node.COMMENT_NODE: + return visitComment(node); + case Node.DOCUMENT_FRAGMENT_NODE: + return visitDocumentFragment(node); + case Node.DOCUMENT_NODE: + return visitDocument(node); + case Node.DOCUMENT_TYPE_NODE: + return visitDocumentType(node); + default: + throw new UnsupportedError('DOM node type ${node.nodeType}'); } } @@ -92,8 +99,7 @@ class CodeMarkupVisitor extends TreeVisitor { _str.write(">"); return; } - _str.write( - '&lt;/<code class="markup element-name">$tag</code>>'); + _str.write('&lt;/<code class="markup element-name">$tag</code>>'); } visitComment(Comment node) { @@ -102,7 +108,6 @@ class CodeMarkupVisitor extends TreeVisitor { } } - // TODO(jmesserly): reconcile this with dart:web htmlEscape. // This one might be more useful, as it is HTML5 spec compliant. /// Escapes [text] for use in the @@ -128,11 +133,21 @@ String htmlSerializeEscape(String text, {bool attributeMode: false}) { var ch = text[i]; String replace = null; switch (ch) { - case '&': replace = '&amp;'; break; - case '\u00A0'/*NO-BREAK SPACE*/: replace = '&nbsp;'; break; - case '"': if (attributeMode) replace = '&quot;'; break; - case '<': if (!attributeMode) replace = '&lt;'; break; - case '>': if (!attributeMode) replace = '&gt;'; break; + case '&': + replace = '&amp;'; + break; + case '\u00A0' /*NO-BREAK SPACE*/ : + replace = '&nbsp;'; + break; + case '"': + if (attributeMode) replace = '&quot;'; + break; + case '<': + if (!attributeMode) replace = '&lt;'; + break; + case '>': + if (!attributeMode) replace = '&gt;'; + break; } if (replace != null) { if (result == null) result = new StringBuffer(text.substring(0, i)); @@ -145,16 +160,27 @@ String htmlSerializeEscape(String text, {bool attributeMode: false}) { return result != null ? result.toString() : text; } - /// Returns true if this tag name is a void element. /// This method is useful to a pretty printer, because void elements must not /// have an end tag. /// See also: <http://dev.w3.org/html5/markup/syntax.html#void-elements>. bool isVoidElement(String tagName) { switch (tagName) { - case "area": case "base": case "br": case "col": case "command": - case "embed": case "hr": case "img": case "input": case "keygen": - case "link": case "meta": case "param": case "source": case "track": + case "area": + case "base": + case "br": + case "col": + case "command": + case "embed": + case "hr": + case "img": + case "input": + case "keygen": + case "link": + case "meta": + case "param": + case "source": + case "track": case "wbr": return true; } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 23f62a7ed..a6618ab1b 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -36,14 +36,13 @@ import 'dom.dart'; /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you /// can additionally pass [sourceUrl] to indicate where the [input] was /// extracted from. -Document parse(input, {String encoding, bool generateSpans: false, - String sourceUrl}) { - var p = new HtmlParser(input, encoding: encoding, - generateSpans: generateSpans, sourceUrl: sourceUrl); +Document parse(input, + {String encoding, bool generateSpans: false, String sourceUrl}) { + var p = new HtmlParser(input, + encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parse(); } - /// Parse the [input] html5 document fragment into a tree. The [input] can be /// a [String], [List<int>] of bytes or an [HtmlTokenizer]. The [container] /// element can optionally be specified, otherwise it defaults to "div". @@ -56,14 +55,13 @@ Document parse(input, {String encoding, bool generateSpans: false, /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. -DocumentFragment parseFragment(input, {String container: "div", - String encoding, bool generateSpans: false, String sourceUrl}) { - var p = new HtmlParser(input, encoding: encoding, - generateSpans: generateSpans, sourceUrl: sourceUrl); +DocumentFragment parseFragment(input, {String container: "div", String encoding, + bool generateSpans: false, String sourceUrl}) { + var p = new HtmlParser(input, + encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parseFragment(container); } - /// Parser for HTML, which generates a tree structure from a stream of /// (possibly malformed) characters. class HtmlParser { @@ -146,12 +144,15 @@ class HtmlParser { TreeBuilder tree}) : generateSpans = generateSpans, tree = tree != null ? tree : new TreeBuilder(true), - tokenizer = (input is HtmlTokenizer ? input : - new HtmlTokenizer(input, encoding: encoding, parseMeta: parseMeta, - lowercaseElementName: lowercaseElementName, - lowercaseAttrName: lowercaseAttrName, - generateSpans: generateSpans, sourceUrl: sourceUrl)) { - + tokenizer = (input is HtmlTokenizer + ? input + : new HtmlTokenizer(input, + encoding: encoding, + parseMeta: parseMeta, + lowercaseElementName: lowercaseElementName, + lowercaseAttrName: lowercaseAttrName, + generateSpans: generateSpans, + sourceUrl: sourceUrl)) { tokenizer.parser = this; _initialPhase = new InitialPhase(this); _beforeHtmlPhase = new BeforeHtmlPhase(this); @@ -256,14 +257,14 @@ class HtmlParser { if (enc != null) enc = asciiUpper2Lower(enc); return enc == "text/html" || enc == "application/xhtml+xml"; } else { - return htmlIntegrationPointElements.contains( - new Pair(element.namespaceUri, element.localName)); + return htmlIntegrationPointElements + .contains(new Pair(element.namespaceUri, element.localName)); } } bool isMathMLTextIntegrationPoint(Element element) { - return mathmlTextIntegrationPointElements.contains( - new Pair(element.namespaceUri, element.localName)); + return mathmlTextIntegrationPointElements + .contains(new Pair(element.namespaceUri, element.localName)); } bool inForeignContent(Token token, int type) { @@ -275,7 +276,7 @@ class HtmlParser { if (isMathMLTextIntegrationPoint(node)) { if (type == TokenKind.startTag && (token as StartTagToken).name != "mglyph" && - (token as StartTagToken).name != "malignmark") { + (token as StartTagToken).name != "malignmark") { return false; } if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { @@ -283,7 +284,8 @@ class HtmlParser { } } - if (node.localName == "annotation-xml" && type == TokenKind.startTag && + if (node.localName == "annotation-xml" && + type == TokenKind.startTag && (token as StartTagToken).name == "svg") { return false; } @@ -343,8 +345,9 @@ class HtmlParser { if (token is StartTagToken) { if (token.selfClosing && !token.selfClosingAcknowledged) { - parseError(token.span, "non-void-element-with-trailing-solidus", - {"name": token.name}); + parseError(token.span, "non-void-element-with-trailing-solidus", { + "name": token.name + }); } } } @@ -371,7 +374,6 @@ class HtmlParser { void parseError(SourceSpan span, String errorcode, [Map datavars = const {}]) { - if (!generateSpans && span == null) { span = _lastSpan; } @@ -390,68 +392,68 @@ class HtmlParser { void adjustSVGAttributes(StartTagToken token) { final replacements = const { - "attributename":"attributeName", - "attributetype":"attributeType", - "basefrequency":"baseFrequency", - "baseprofile":"baseProfile", - "calcmode":"calcMode", - "clippathunits":"clipPathUnits", - "contentscripttype":"contentScriptType", - "contentstyletype":"contentStyleType", - "diffuseconstant":"diffuseConstant", - "edgemode":"edgeMode", - "externalresourcesrequired":"externalResourcesRequired", - "filterres":"filterRes", - "filterunits":"filterUnits", - "glyphref":"glyphRef", - "gradienttransform":"gradientTransform", - "gradientunits":"gradientUnits", - "kernelmatrix":"kernelMatrix", - "kernelunitlength":"kernelUnitLength", - "keypoints":"keyPoints", - "keysplines":"keySplines", - "keytimes":"keyTimes", - "lengthadjust":"lengthAdjust", - "limitingconeangle":"limitingConeAngle", - "markerheight":"markerHeight", - "markerunits":"markerUnits", - "markerwidth":"markerWidth", - "maskcontentunits":"maskContentUnits", - "maskunits":"maskUnits", - "numoctaves":"numOctaves", - "pathlength":"pathLength", - "patterncontentunits":"patternContentUnits", - "patterntransform":"patternTransform", - "patternunits":"patternUnits", - "pointsatx":"pointsAtX", - "pointsaty":"pointsAtY", - "pointsatz":"pointsAtZ", - "preservealpha":"preserveAlpha", - "preserveaspectratio":"preserveAspectRatio", - "primitiveunits":"primitiveUnits", - "refx":"refX", - "refy":"refY", - "repeatcount":"repeatCount", - "repeatdur":"repeatDur", - "requiredextensions":"requiredExtensions", - "requiredfeatures":"requiredFeatures", - "specularconstant":"specularConstant", - "specularexponent":"specularExponent", - "spreadmethod":"spreadMethod", - "startoffset":"startOffset", - "stddeviation":"stdDeviation", - "stitchtiles":"stitchTiles", - "surfacescale":"surfaceScale", - "systemlanguage":"systemLanguage", - "tablevalues":"tableValues", - "targetx":"targetX", - "targety":"targetY", - "textlength":"textLength", - "viewbox":"viewBox", - "viewtarget":"viewTarget", - "xchannelselector":"xChannelSelector", - "ychannelselector":"yChannelSelector", - "zoomandpan":"zoomAndPan" + "attributename": "attributeName", + "attributetype": "attributeType", + "basefrequency": "baseFrequency", + "baseprofile": "baseProfile", + "calcmode": "calcMode", + "clippathunits": "clipPathUnits", + "contentscripttype": "contentScriptType", + "contentstyletype": "contentStyleType", + "diffuseconstant": "diffuseConstant", + "edgemode": "edgeMode", + "externalresourcesrequired": "externalResourcesRequired", + "filterres": "filterRes", + "filterunits": "filterUnits", + "glyphref": "glyphRef", + "gradienttransform": "gradientTransform", + "gradientunits": "gradientUnits", + "kernelmatrix": "kernelMatrix", + "kernelunitlength": "kernelUnitLength", + "keypoints": "keyPoints", + "keysplines": "keySplines", + "keytimes": "keyTimes", + "lengthadjust": "lengthAdjust", + "limitingconeangle": "limitingConeAngle", + "markerheight": "markerHeight", + "markerunits": "markerUnits", + "markerwidth": "markerWidth", + "maskcontentunits": "maskContentUnits", + "maskunits": "maskUnits", + "numoctaves": "numOctaves", + "pathlength": "pathLength", + "patterncontentunits": "patternContentUnits", + "patterntransform": "patternTransform", + "patternunits": "patternUnits", + "pointsatx": "pointsAtX", + "pointsaty": "pointsAtY", + "pointsatz": "pointsAtZ", + "preservealpha": "preserveAlpha", + "preserveaspectratio": "preserveAspectRatio", + "primitiveunits": "primitiveUnits", + "refx": "refX", + "refy": "refY", + "repeatcount": "repeatCount", + "repeatdur": "repeatDur", + "requiredextensions": "requiredExtensions", + "requiredfeatures": "requiredFeatures", + "specularconstant": "specularConstant", + "specularexponent": "specularExponent", + "spreadmethod": "spreadMethod", + "startoffset": "startOffset", + "stddeviation": "stdDeviation", + "stitchtiles": "stitchTiles", + "surfacescale": "surfaceScale", + "systemlanguage": "systemLanguage", + "tablevalues": "tableValues", + "targetx": "targetX", + "targety": "targetY", + "textlength": "textLength", + "viewbox": "viewBox", + "viewtarget": "viewTarget", + "xchannelselector": "xChannelSelector", + "ychannelselector": "yChannelSelector", + "zoomandpan": "zoomAndPan" }; for (var originalName in token.data.keys.toList()) { var svgName = replacements[originalName]; @@ -465,10 +467,10 @@ class HtmlParser { // TODO(jmesserly): I don't like mixing non-string objects with strings in // the Node.attributes Map. Is there another solution? final replacements = const { - "xlink:actuate": const AttributeName("xlink", "actuate", - Namespaces.xlink), - "xlink:arcrole": const AttributeName("xlink", "arcrole", - Namespaces.xlink), + "xlink:actuate": + const AttributeName("xlink", "actuate", Namespaces.xlink), + "xlink:arcrole": + const AttributeName("xlink", "arcrole", Namespaces.xlink), "xlink:href": const AttributeName("xlink", "href", Namespaces.xlink), "xlink:role": const AttributeName("xlink", "role", Namespaces.xlink), "xlink:show": const AttributeName("xlink", "show", Namespaces.xlink), @@ -502,7 +504,10 @@ class HtmlParser { // Check for conditions that should only happen in the innerHTML // case switch (nodeName) { - case "select": case "colgroup": case "head": case "html": + case "select": + case "colgroup": + case "head": + case "html": assert(innerHTMLMode); break; } @@ -510,20 +515,48 @@ class HtmlParser { continue; } switch (nodeName) { - case "select": phase = _inSelectPhase; return; - case "td": phase = _inCellPhase; return; - case "th": phase = _inCellPhase; return; - case "tr": phase = _inRowPhase; return; - case "tbody": phase = _inTableBodyPhase; return; - case "thead": phase = _inTableBodyPhase; return; - case "tfoot": phase = _inTableBodyPhase; return; - case "caption": phase = _inCaptionPhase; return; - case "colgroup": phase = _inColumnGroupPhase; return; - case "table": phase = _inTablePhase; return; - case "head": phase = _inBodyPhase; return; - case "body": phase = _inBodyPhase; return; - case "frameset": phase = _inFramesetPhase; return; - case "html": phase = _beforeHeadPhase; return; + case "select": + phase = _inSelectPhase; + return; + case "td": + phase = _inCellPhase; + return; + case "th": + phase = _inCellPhase; + return; + case "tr": + phase = _inRowPhase; + return; + case "tbody": + phase = _inTableBodyPhase; + return; + case "thead": + phase = _inTableBodyPhase; + return; + case "tfoot": + phase = _inTableBodyPhase; + return; + case "caption": + phase = _inCaptionPhase; + return; + case "colgroup": + phase = _inColumnGroupPhase; + return; + case "table": + phase = _inTablePhase; + return; + case "head": + phase = _inBodyPhase; + return; + case "body": + phase = _inBodyPhase; + return; + case "frameset": + phase = _inFramesetPhase; + return; + case "html": + phase = _beforeHeadPhase; + return; } } phase = _inBodyPhase; @@ -547,7 +580,6 @@ class HtmlParser { } } - /// Base class for helper object that implements each phase of processing. class Phase { // Order should be (they can be omitted): @@ -565,7 +597,9 @@ class Phase { final TreeBuilder tree; - Phase(HtmlParser parser) : parser = parser, tree = parser.tree; + Phase(HtmlParser parser) + : parser = parser, + tree = parser.tree; bool processEOF() { throw new UnimplementedError(); @@ -599,7 +633,7 @@ class Phase { Token startTagHtml(StartTagToken token) { if (parser.firstStartTag == false && token.name == "html") { - parser.parseError(token.span, "non-html-root"); + parser.parseError(token.span, "non-html-root"); } // XXX Need a check here to see if the first start tag token emitted is // this token... If it's not, invoke parser.parseError(). @@ -641,7 +675,8 @@ class InitialPhase extends Phase { var systemId = token.systemId; var correct = token.correct; - if ((name != "html" || publicId != null || + if ((name != "html" || + publicId != null || systemId != null && systemId != "about:legacy-compat")) { parser.parseError(token.span, "unknown-doctype"); } @@ -656,80 +691,86 @@ class InitialPhase extends Phase { publicId = asciiUpper2Lower(publicId); } - if (!correct || token.name != "html" - || startsWithAny(publicId, const [ - "+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//"]) - || const ["-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html"].contains(publicId) - || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//"]) && systemId == null - || systemId != null && systemId.toLowerCase() == - "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") { - + if (!correct || token.name != "html" || startsWithAny(publicId, const [ + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//" + ]) || + const [ + "-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html" + ].contains(publicId) || + startsWithAny(publicId, const [ + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]) && + systemId == null || + systemId != null && + systemId.toLowerCase() == + "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") { parser.compatMode = "quirks"; } else if (startsWithAny(publicId, const [ - "-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//"]) - || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//"]) && - systemId != null) { + "-//w3c//dtd xhtml 1.0 frameset//", + "-//w3c//dtd xhtml 1.0 transitional//" + ]) || + startsWithAny(publicId, const [ + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]) && + systemId != null) { parser.compatMode = "limited quirks"; } parser.phase = parser._beforeHtmlPhase; @@ -748,15 +789,15 @@ class InitialPhase extends Phase { } Token processStartTag(StartTagToken token) { - parser.parseError(token.span, "expected-doctype-but-got-start-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-doctype-but-got-start-tag", {"name": token.name}); anythingElse(); return token; } Token processEndTag(EndTagToken token) { - parser.parseError(token.span, "expected-doctype-but-got-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-doctype-but-got-end-tag", {"name": token.name}); anythingElse(); return token; } @@ -768,7 +809,6 @@ class InitialPhase extends Phase { } } - class BeforeHtmlPhase extends Phase { BeforeHtmlPhase(parser) : super(parser); @@ -808,34 +848,43 @@ class BeforeHtmlPhase extends Phase { Token processEndTag(EndTagToken token) { switch (token.name) { - case "head": case "body": case "html": case "br": + case "head": + case "body": + case "html": + case "br": insertHtmlElement(); return token; default: - parser.parseError(token.span, "unexpected-end-tag-before-html", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-before-html", {"name": token.name}); return null; } } } - class BeforeHeadPhase extends Phase { BeforeHeadPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case 'html': return startTagHtml(token); - case 'head': return startTagHead(token); - default: return startTagOther(token); + case 'html': + return startTagHtml(token); + case 'head': + return startTagHead(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "head": case "body": case "html": case "br": + case "head": + case "body": + case "html": + case "br": return endTagImplyHead(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -874,8 +923,8 @@ class BeforeHeadPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "end-tag-after-implied-root", - {"name": token.name}); + parser.parseError( + token.span, "end-tag-after-implied-root", {"name": token.name}); } } @@ -884,24 +933,41 @@ class InHeadPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "title": return startTagTitle(token); - case "noscript": case "noframes": case "style": + case "html": + return startTagHtml(token); + case "title": + return startTagTitle(token); + case "noscript": + case "noframes": + case "style": return startTagNoScriptNoFramesStyle(token); - case "script": return startTagScript(token); - case "base": case "basefont": case "bgsound": case "command": case "link": + case "script": + return startTagScript(token); + case "base": + case "basefont": + case "bgsound": + case "command": + case "link": return startTagBaseLinkCommand(token); - case "meta": return startTagMeta(token); - case "head": return startTagHead(token); - default: return startTagOther(token); + case "meta": + return startTagMeta(token); + case "head": + return startTagHead(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "head": return endTagHead(token); - case "br": case "html": case "body": return endTagHtmlBodyBr(token); - default: return endTagOther(token); + case "head": + return endTagHead(token); + case "br": + case "html": + case "body": + return endTagHtmlBodyBr(token); + default: + return endTagOther(token); } } @@ -990,7 +1056,6 @@ class InHeadPhase extends Phase { } } - // XXX If we implement a parser for which scripting is disabled we need to // implement this phase. // @@ -1001,22 +1066,37 @@ class AfterHeadPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "body": return startTagBody(token); - case "frameset": return startTagFrameset(token); - case "base": case "basefont": case "bgsound": case "link": case "meta": - case "noframes": case "script": case "style": case "title": + case "html": + return startTagHtml(token); + case "body": + return startTagBody(token); + case "frameset": + return startTagFrameset(token); + case "base": + case "basefont": + case "bgsound": + case "link": + case "meta": + case "noframes": + case "script": + case "style": + case "title": return startTagFromHead(token); - case "head": return startTagHead(token); - default: return startTagOther(token); + case "head": + return startTagHead(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "body": case "html": case "br": + case "body": + case "html": + case "br": return endTagHtmlBodyBr(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -1046,8 +1126,9 @@ class AfterHeadPhase extends Phase { } void startTagFromHead(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", - {"name": token.name}); + parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", { + "name": token.name + }); tree.openElements.add(tree.headPointer); parser._inHeadPhase.processStartTag(token); for (var node in tree.openElements.reversed) { @@ -1096,48 +1177,101 @@ class InBodyPhase extends Phase { switch (token.name) { case "html": return startTagHtml(token); - case "base": case "basefont": case "bgsound": case "command": case "link": - case "meta": case "noframes": case "script": case "style": case "title": + case "base": + case "basefont": + case "bgsound": + case "command": + case "link": + case "meta": + case "noframes": + case "script": + case "style": + case "title": return startTagProcessInHead(token); case "body": return startTagBody(token); case "frameset": return startTagFrameset(token); - case "address": case "article": case "aside": case "blockquote": - case "center": case "details": case "details": case "dir": case "div": - case "dl": case "fieldset": case "figcaption": case "figure": - case "footer": case "header": case "hgroup": case "menu": case "nav": - case "ol": case "p": case "section": case "summary": case "ul": + case "address": + case "article": + case "aside": + case "blockquote": + case "center": + case "details": + case "details": + case "dir": + case "div": + case "dl": + case "fieldset": + case "figcaption": + case "figure": + case "footer": + case "header": + case "hgroup": + case "menu": + case "nav": + case "ol": + case "p": + case "section": + case "summary": + case "ul": return startTagCloseP(token); // headingElements - case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": return startTagHeading(token); - case "pre": case "listing": + case "pre": + case "listing": return startTagPreListing(token); case "form": return startTagForm(token); - case "li": case "dd": case "dt": + case "li": + case "dd": + case "dt": return startTagListItem(token); case "plaintext": return startTagPlaintext(token); - case "a": return startTagA(token); - case "b": case "big": case "code": case "em": case "font": case "i": - case "s": case "small": case "strike": case "strong": case "tt": case "u": + case "a": + return startTagA(token); + case "b": + case "big": + case "code": + case "em": + case "font": + case "i": + case "s": + case "small": + case "strike": + case "strong": + case "tt": + case "u": return startTagFormatting(token); case "nobr": return startTagNobr(token); case "button": return startTagButton(token); - case "applet": case "marquee": case "object": + case "applet": + case "marquee": + case "object": return startTagAppletMarqueeObject(token); case "xmp": return startTagXmp(token); case "table": return startTagTable(token); - case "area": case "br": case "embed": case "img": case "keygen": + case "area": + case "br": + case "embed": + case "img": + case "keygen": case "wbr": return startTagVoidFormatting(token); - case "param": case "source": case "track": + case "param": + case "source": + case "track": return startTagParamSource(token); case "input": return startTagInput(token); @@ -1151,49 +1285,108 @@ class InBodyPhase extends Phase { return startTagTextarea(token); case "iframe": return startTagIFrame(token); - case "noembed": case "noframes": case "noscript": + case "noembed": + case "noframes": + case "noscript": return startTagRawtext(token); case "select": return startTagSelect(token); - case "rp": case "rt": + case "rp": + case "rt": return startTagRpRt(token); - case "option": case "optgroup": + case "option": + case "optgroup": return startTagOpt(token); case "math": return startTagMath(token); case "svg": return startTagSvg(token); - case "caption": case "col": case "colgroup": case "frame": case "head": - case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": + case "caption": + case "col": + case "colgroup": + case "frame": + case "head": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": return startTagMisplaced(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "body": return endTagBody(token); - case "html": return endTagHtml(token); - case "address": case "article": case "aside": case "blockquote": - case "center": case "details": case "dir": case "div": case "dl": - case "fieldset": case "figcaption": case "figure": case "footer": - case "header": case "hgroup": case "listing": case "menu": case "nav": - case "ol": case "pre": case "section": case "summary": case "ul": + case "body": + return endTagBody(token); + case "html": + return endTagHtml(token); + case "address": + case "article": + case "aside": + case "blockquote": + case "center": + case "details": + case "dir": + case "div": + case "dl": + case "fieldset": + case "figcaption": + case "figure": + case "footer": + case "header": + case "hgroup": + case "listing": + case "menu": + case "nav": + case "ol": + case "pre": + case "section": + case "summary": + case "ul": return endTagBlock(token); - case "form": return endTagForm(token); - case "p": return endTagP(token); - case "dd": case "dt": case "li": return endTagListItem(token); + case "form": + return endTagForm(token); + case "p": + return endTagP(token); + case "dd": + case "dt": + case "li": + return endTagListItem(token); // headingElements - case "h1": case "h2": case "h3": case "h4": case "h5": case "h6": + case "h1": + case "h2": + case "h3": + case "h4": + case "h5": + case "h6": return endTagHeading(token); - case "a": case "b": case "big": case "code": case "em": case "font": - case "i": case "nobr": case "s": case "small": case "strike": - case "strong": case "tt": case "u": + case "a": + case "b": + case "big": + case "code": + case "em": + case "font": + case "i": + case "nobr": + case "s": + case "small": + case "strike": + case "strong": + case "tt": + case "u": return endTagFormatting(token); - case "applet": case "marquee": case "object": + case "applet": + case "marquee": + case "object": return endTagAppletMarqueeObject(token); - case "br": return endTagBr(token); - default: return endTagOther(token); + case "br": + return endTagBr(token); + default: + return endTagOther(token); } } @@ -1238,8 +1431,17 @@ class InBodyPhase extends Phase { bool processEOF() { for (var node in tree.openElements.reversed) { switch (node.localName) { - case "dd": case "dt": case "li": case "p": case "tbody": case "td": - case "tfoot": case "th": case "thead": case "tr": case "body": + case "dd": + case "dt": + case "li": + case "p": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + case "body": case "html": continue; } @@ -1257,8 +1459,8 @@ class InBodyPhase extends Phase { dropNewline = false; if (data.startsWith("\n")) { var lastOpen = tree.openElements.last; - if (const ["pre", "listing", "textarea"].contains(lastOpen.localName) - && !lastOpen.hasContent()) { + if (const ["pre", "listing", "textarea"].contains(lastOpen.localName) && + !lastOpen.hasContent()) { data = data.substring(1); } } @@ -1297,8 +1499,8 @@ class InBodyPhase extends Phase { void startTagBody(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag", {"name": "body"}); - if (tree.openElements.length == 1 - || tree.openElements[1].localName != "body") { + if (tree.openElements.length == 1 || + tree.openElements[1].localName != "body") { assert(parser.innerHTMLMode); } else { parser.framesetOK = false; @@ -1356,9 +1558,11 @@ class InBodyPhase extends Phase { void startTagListItem(StartTagToken token) { parser.framesetOK = false; - final stopNamesMap = const {"li": const ["li"], - "dt": const ["dt", "dd"], - "dd": const ["dt", "dd"]}; + final stopNamesMap = const { + "li": const ["li"], + "dt": const ["dt", "dd"], + "dd": const ["dt", "dd"] + }; var stopNames = stopNamesMap[token.name]; for (var node in tree.openElements.reversed) { if (stopNames.contains(node.localName)) { @@ -1391,8 +1595,8 @@ class InBodyPhase extends Phase { endTagP(new EndTagToken("p")); } if (headingElements.contains(tree.openElements.last.localName)) { - parser.parseError(token.span, "unexpected-start-tag", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-start-tag", {"name": token.name}); tree.openElements.removeLast(); } tree.insertElement(token); @@ -1401,8 +1605,10 @@ class InBodyPhase extends Phase { void startTagA(StartTagToken token) { var afeAElement = tree.elementInActiveFormattingElements("a"); if (afeAElement != null) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "a", "endName": "a"}); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { + "startName": "a", + "endName": "a" + }); endTagFormatting(new EndTagToken("a")); tree.openElements.remove(afeAElement); tree.activeFormattingElements.remove(afeAElement); @@ -1419,8 +1625,10 @@ class InBodyPhase extends Phase { void startTagNobr(StartTagToken token) { tree.reconstructActiveFormattingElements(); if (tree.elementInScope("nobr")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "nobr", "endName": "nobr"}); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { + "startName": "nobr", + "endName": "nobr" + }); processEndTag(new EndTagToken("nobr")); // XXX Need tests that trigger the following tree.reconstructActiveFormattingElements(); @@ -1430,8 +1638,10 @@ class InBodyPhase extends Phase { Token startTagButton(StartTagToken token) { if (tree.elementInScope("button")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "button", "endName": "button"}); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { + "startName": "button", + "endName": "button" + }); processEndTag(new EndTagToken("button")); return token; } else { @@ -1504,10 +1714,12 @@ class InBodyPhase extends Phase { void startTagImage(StartTagToken token) { // No really... - parser.parseError(token.span, "unexpected-start-tag-treated-as", - {"originalName": "image", "newName": "img"}); - processStartTag(new StartTagToken("img", data: token.data, - selfClosing: token.selfClosing)); + parser.parseError(token.span, "unexpected-start-tag-treated-as", { + "originalName": "image", + "newName": "img" + }); + processStartTag(new StartTagToken("img", + data: token.data, selfClosing: token.selfClosing)); } void startTagIsIndex(StartTagToken token) { @@ -1533,8 +1745,8 @@ class InBodyPhase extends Phase { attributes.remove('action'); attributes.remove('prompt'); attributes["name"] = "isindex"; - processStartTag(new StartTagToken("input", - data: attributes, selfClosing: token.selfClosing)); + processStartTag(new StartTagToken( + "input", data: attributes, selfClosing: token.selfClosing)); processEndTag(new EndTagToken("label")); processStartTag(new StartTagToken("hr", data: {})); processEndTag(new EndTagToken("form")); @@ -1627,8 +1839,8 @@ class InBodyPhase extends Phase { /// "option", "optgroup", "tbody", "td", "tfoot", "th", "thead", /// "tr", "noscript" void startTagMisplaced(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-ignored", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-start-tag-ignored", {"name": token.name}); } Token startTagOther(StartTagToken token) { @@ -1658,14 +1870,29 @@ class InBodyPhase extends Phase { } else if (tree.openElements.last.localName != "body") { for (Element node in slice(tree.openElements, 2)) { switch (node.localName) { - case "dd": case "dt": case "li": case "optgroup": case "option": - case "p": case "rp": case "rt": case "tbody": case "td": case "tfoot": - case "th": case "thead": case "tr": case "body": case "html": + case "dd": + case "dt": + case "li": + case "optgroup": + case "option": + case "p": + case "rp": + case "rt": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": + case "body": + case "html": continue; } // Not sure this is the correct name for the parse error - parser.parseError(token.span, "expected-one-end-tag-but-got-another", - {"gotName": "body", "expectedName": node.localName}); + parser.parseError(token.span, "expected-one-end-tag-but-got-another", { + "gotName": "body", + "expectedName": node.localName + }); break; } } @@ -1706,7 +1933,8 @@ class InBodyPhase extends Phase { } else { tree.generateImpliedEndTags(); if (tree.openElements.last != node) { - parser.parseError(token.span, "end-tag-too-early-ignored", {"name": "form"}); + parser.parseError( + token.span, "end-tag-too-early-ignored", {"name": "form"}); } tree.openElements.remove(node); } @@ -1724,7 +1952,8 @@ class InBodyPhase extends Phase { } else { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); + parser.parseError( + token.span, "end-tag-too-early", {"name": token.name}); } popOpenElementsUntil(token.name); } @@ -1764,26 +1993,26 @@ class InBodyPhase extends Phase { outerLoopCounter += 1; // Step 1 paragraph 1 - var formattingElement = tree.elementInActiveFormattingElements( - token.name); + var formattingElement = + tree.elementInActiveFormattingElements(token.name); if (formattingElement == null || (tree.openElements.contains(formattingElement) && - !tree.elementInScope(formattingElement.localName))) { - parser.parseError(token.span, "adoption-agency-1.1", - {"name": token.name}); + !tree.elementInScope(formattingElement.localName))) { + parser.parseError( + token.span, "adoption-agency-1.1", {"name": token.name}); return; - // Step 1 paragraph 2 + // Step 1 paragraph 2 } else if (!tree.openElements.contains(formattingElement)) { - parser.parseError(token.span, "adoption-agency-1.2", - {"name": token.name}); + parser.parseError( + token.span, "adoption-agency-1.2", {"name": token.name}); tree.activeFormattingElements.remove(formattingElement); return; } // Step 1 paragraph 3 if (formattingElement != tree.openElements.last) { - parser.parseError(token.span, "adoption-agency-1.3", - {"name": token.name}); + parser.parseError( + token.span, "adoption-agency-1.3", {"name": token.name}); } // Step 2 @@ -1867,8 +2096,13 @@ class InBodyPhase extends Phase { lastNode.parentNode.nodes.remove(lastNode); } - if (const ["table", "tbody", "tfoot", "thead", "tr"].contains( - commonAncestor.localName)) { + if (const [ + "table", + "tbody", + "tfoot", + "thead", + "tr" + ].contains(commonAncestor.localName)) { var nodePos = tree.getTableMisnestedNodePosition(); nodePos[0].insertBefore(lastNode, nodePos[1]); } else { @@ -1910,8 +2144,10 @@ class InBodyPhase extends Phase { } void endTagBr(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-treated-as", - {"originalName": "br", "newName": "br element"}); + parser.parseError(token.span, "unexpected-end-tag-treated-as", { + "originalName": "br", + "newName": "br element" + }); tree.reconstructActiveFormattingElements(); tree.insertElement(new StartTagToken("br", data: {})); tree.openElements.removeLast(); @@ -1922,15 +2158,15 @@ class InBodyPhase extends Phase { if (node.localName == token.name) { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "unexpected-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag", {"name": token.name}); } while (tree.openElements.removeLast() != node); break; } else { if (specialElements.contains(getElementNameTuple(node))) { - parser.parseError(token.span, "unexpected-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag", {"name": token.name}); break; } } @@ -1938,12 +2174,13 @@ class InBodyPhase extends Phase { } } - class TextPhase extends Phase { TextPhase(parser) : super(parser); // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name - processStartTag(StartTagToken token) { assert(false); } + processStartTag(StartTagToken token) { + assert(false); + } processEndTag(EndTagToken token) { if (token.name == 'script') return endTagScript(token); @@ -1984,27 +2221,54 @@ class InTablePhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "caption": return startTagCaption(token); - case "colgroup": return startTagColgroup(token); - case "col": return startTagCol(token); - case "tbody": case "tfoot": case "thead": return startTagRowGroup(token); - case "td": case "th": case "tr": return startTagImplyTbody(token); - case "table": return startTagTable(token); - case "style": case "script": return startTagStyleScript(token); - case "input": return startTagInput(token); - case "form": return startTagForm(token); - default: return startTagOther(token); + case "html": + return startTagHtml(token); + case "caption": + return startTagCaption(token); + case "colgroup": + return startTagColgroup(token); + case "col": + return startTagCol(token); + case "tbody": + case "tfoot": + case "thead": + return startTagRowGroup(token); + case "td": + case "th": + case "tr": + return startTagImplyTbody(token); + case "table": + return startTagTable(token); + case "style": + case "script": + return startTagStyleScript(token); + case "input": + return startTagInput(token); + case "form": + return startTagForm(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "table": return endTagTable(token); - case "body": case "caption": case "col": case "colgroup": case "html": - case "tbody": case "td": case "tfoot": case "th": case "thead": case "tr": + case "table": + return endTagTable(token); + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": return endTagIgnore(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2012,7 +2276,7 @@ class InTablePhase extends Phase { void clearStackToTableContext() { // "clear the stack back to a table context" while (tree.openElements.last.localName != "table" && - tree.openElements.last.localName != "html") { + tree.openElements.last.localName != "html") { //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) tree.openElements.removeLast(); @@ -2086,8 +2350,10 @@ class InTablePhase extends Phase { } Token startTagTable(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "table", "endName": "table"}); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { + "startName": "table", + "endName": "table" + }); parser.phase.processEndTag(new EndTagToken("table")); if (!parser.innerHTMLMode) { return token; @@ -2120,8 +2386,9 @@ class InTablePhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", - {"name": token.name}); + parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", { + "name": token.name + }); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processStartTag(token); @@ -2133,8 +2400,10 @@ class InTablePhase extends Phase { tree.generateImpliedEndTags(); var last = tree.openElements.last; if (last.localName != "table") { - parser.parseError(token.span, "end-tag-too-early-named", - {"gotName": "table", "expectedName": last.localName}); + parser.parseError(token.span, "end-tag-too-early-named", { + "gotName": "table", + "expectedName": last.localName + }); } while (tree.openElements.last.localName != "table") { tree.openElements.removeLast(); @@ -2153,8 +2422,9 @@ class InTablePhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-implies-table-voodoo", - {"name": token.name}); + parser.parseError(token.span, "unexpected-end-tag-implies-table-voodoo", { + "name": token.name + }); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processEndTag(token); @@ -2229,29 +2499,48 @@ class InTableTextPhase extends Phase { } } - class InCaptionPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-caption InCaptionPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "caption": case "col": case "colgroup": case "tbody": case "td": - case "tfoot": case "th": case "thead": case "tr": + case "html": + return startTagHtml(token); + case "caption": + case "col": + case "colgroup": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": return startTagTableElement(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "caption": return endTagCaption(token); - case "table": return endTagTable(token); - case "body": case "col": case "colgroup": case "html": case "tbody": - case "td": case "tfoot": case "th": case "thead": case "tr": + case "caption": + return endTagCaption(token); + case "table": + return endTagTable(token); + case "body": + case "col": + case "colgroup": + case "html": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": return endTagIgnore(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2288,9 +2577,10 @@ class InCaptionPhase extends Phase { // AT this code is quite similar to endTagTable in "InTable" tree.generateImpliedEndTags(); if (tree.openElements.last.localName != "caption") { - parser.parseError(token.span, "expected-one-end-tag-but-got-another", - {"gotName": "caption", - "expectedName": tree.openElements.last.localName}); + parser.parseError(token.span, "expected-one-end-tag-but-got-another", { + "gotName": "caption", + "expectedName": tree.openElements.last.localName + }); } while (tree.openElements.last.localName != "caption") { tree.openElements.removeLast(); @@ -2324,24 +2614,29 @@ class InCaptionPhase extends Phase { } } - class InColumnGroupPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-column InColumnGroupPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "col": return startTagCol(token); - default: return startTagOther(token); + case "html": + return startTagHtml(token); + case "col": + return startTagCol(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "colgroup": return endTagColgroup(token); - case "col": return endTagCol(token); - default: return endTagOther(token); + case "colgroup": + return endTagColgroup(token); + case "col": + return endTagCol(token); + default: + return endTagOther(token); } } @@ -2399,32 +2694,50 @@ class InColumnGroupPhase extends Phase { } } - class InTableBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table0 InTableBodyPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "tr": return startTagTr(token); - case "td": case "th": return startTagTableCell(token); - case "caption": case "col": case "colgroup": case "tbody": case "tfoot": + case "html": + return startTagHtml(token); + case "tr": + return startTagTr(token); + case "td": + case "th": + return startTagTableCell(token); + case "caption": + case "col": + case "colgroup": + case "tbody": + case "tfoot": case "thead": return startTagTableOther(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "tbody": case "tfoot": case "thead": + case "tbody": + case "tfoot": + case "thead": return endTagTableRowGroup(token); - case "table": return endTagTable(token); - case "body": case "caption": case "col": case "colgroup": case "html": - case "td": case "th": case "tr": + case "table": + return endTagTable(token); + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "td": + case "th": + case "tr": return endTagIgnore(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2462,8 +2775,8 @@ class InTableBodyPhase extends Phase { } Token startTagTableCell(StartTagToken token) { - parser.parseError(token.span, "unexpected-cell-in-table-body", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-cell-in-table-body", {"name": token.name}); startTagTr(new StartTagToken("tr", data: {})); return token; } @@ -2480,8 +2793,8 @@ class InTableBodyPhase extends Phase { tree.openElements.removeLast(); parser.phase = parser._inTablePhase; } else { - parser.parseError(token.span, "unexpected-end-tag-in-table-body", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-in-table-body", {"name": token.name}); } } @@ -2502,8 +2815,8 @@ class InTableBodyPhase extends Phase { } void endTagIgnore(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-in-table-body", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-in-table-body", {"name": token.name}); } Token endTagOther(EndTagToken token) { @@ -2511,32 +2824,50 @@ class InTableBodyPhase extends Phase { } } - class InRowPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-row InRowPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "td": case "th": return startTagTableCell(token); - case "caption": case "col": case "colgroup": case "tbody": case "tfoot": - case "thead": case "tr": + case "html": + return startTagHtml(token); + case "td": + case "th": + return startTagTableCell(token); + case "caption": + case "col": + case "colgroup": + case "tbody": + case "tfoot": + case "thead": + case "tr": return startTagTableOther(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "tr": return endTagTr(token); - case "table": return endTagTable(token); - case "tbody": case "tfoot": case "thead": + case "tr": + return endTagTr(token); + case "table": + return endTagTable(token); + case "tbody": + case "tfoot": + case "thead": return endTagTableRowGroup(token); - case "body": case "caption": case "col": case "colgroup": case "html": - case "td": case "th": + case "body": + case "caption": + case "col": + case "colgroup": + case "html": + case "td": + case "th": return endTagIgnore(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2547,8 +2878,9 @@ class InRowPhase extends Phase { if (last.localName == "tr" || last.localName == "html") break; parser.parseError(last.sourceSpan, - "unexpected-implied-end-tag-in-table-row", - {"name": tree.openElements.last.localName}); + "unexpected-implied-end-tag-in-table-row", { + "name": tree.openElements.last.localName + }); tree.openElements.removeLast(); } } @@ -2620,8 +2952,8 @@ class InRowPhase extends Phase { } void endTagIgnore(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-in-table-row", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-in-table-row", {"name": token.name}); } Token endTagOther(EndTagToken token) { @@ -2635,23 +2967,42 @@ class InCellPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "caption": case "col": case "colgroup": case "tbody": case "td": - case "tfoot": case "th": case "thead": case "tr": + case "html": + return startTagHtml(token); + case "caption": + case "col": + case "colgroup": + case "tbody": + case "td": + case "tfoot": + case "th": + case "thead": + case "tr": return startTagTableOther(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "td": case "th": + case "td": + case "th": return endTagTableCell(token); - case "body": case "caption": case "col": case "colgroup": case "html": + case "body": + case "caption": + case "col": + case "colgroup": + case "html": return endTagIgnore(token); - case "table": case "tbody": case "tfoot": case "thead": case "tr": + case "table": + case "tbody": + case "tfoot": + case "thead": + case "tr": return endTagImply(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2676,7 +3027,7 @@ class InCellPhase extends Phase { Token startTagTableOther(StartTagToken token) { if (tree.elementInScope("td", variant: "table") || - tree.elementInScope("th", variant: "table")) { + tree.elementInScope("th", variant: "table")) { closeCell(); return token; } else { @@ -2695,8 +3046,8 @@ class InCellPhase extends Phase { if (tree.elementInScope(token.name, variant: "table")) { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "unexpected-cell-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-cell-end-tag", {"name": token.name}); popOpenElementsUntil(token.name); } else { tree.openElements.removeLast(); @@ -2733,23 +3084,35 @@ class InSelectPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "option": return startTagOption(token); - case "optgroup": return startTagOptgroup(token); - case "select": return startTagSelect(token); - case "input": case "keygen": case "textarea": + case "html": + return startTagHtml(token); + case "option": + return startTagOption(token); + case "optgroup": + return startTagOptgroup(token); + case "select": + return startTagSelect(token); + case "input": + case "keygen": + case "textarea": return startTagInput(token); - case "script": return startTagScript(token); - default: return startTagOther(token); + case "script": + return startTagScript(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "option": return endTagOption(token); - case "optgroup": return endTagOptgroup(token); - case "select": return endTagSelect(token); - default: return endTagOther(token); + case "option": + return endTagOption(token); + case "optgroup": + return endTagOptgroup(token); + case "select": + return endTagSelect(token); + default: + return endTagOther(token); } } @@ -2811,8 +3174,8 @@ class InSelectPhase extends Phase { } Token startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-in-select", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-start-tag-in-select", {"name": token.name}); return null; } @@ -2820,24 +3183,25 @@ class InSelectPhase extends Phase { if (tree.openElements.last.localName == "option") { tree.openElements.removeLast(); } else { - parser.parseError(token.span, "unexpected-end-tag-in-select", - {"name": "option"}); + parser.parseError( + token.span, "unexpected-end-tag-in-select", {"name": "option"}); } } void endTagOptgroup(EndTagToken token) { // </optgroup> implicitly closes <option> if (tree.openElements.last.localName == "option" && - tree.openElements[tree.openElements.length - 2].localName == "optgroup") { + tree.openElements[tree.openElements.length - 2].localName == + "optgroup") { tree.openElements.removeLast(); } // It also closes </optgroup> if (tree.openElements.last.localName == "optgroup") { tree.openElements.removeLast(); - // But nothing else + // But nothing else } else { - parser.parseError(token.span, "unexpected-end-tag-in-select", - {"name": "optgroup"}); + parser.parseError( + token.span, "unexpected-end-tag-in-select", {"name": "optgroup"}); } } @@ -2853,30 +3217,43 @@ class InSelectPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-in-select", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-in-select", {"name": token.name}); } } - class InSelectInTablePhase extends Phase { InSelectInTablePhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "caption": case "table": case "tbody": case "tfoot": case "thead": - case "tr": case "td": case "th": + case "caption": + case "table": + case "tbody": + case "tfoot": + case "thead": + case "tr": + case "td": + case "th": return startTagTable(token); - default: return startTagOther(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "caption": case "table": case "tbody": case "tfoot": case "thead": - case "tr": case "td": case "th": + case "caption": + case "table": + case "tbody": + case "tfoot": + case "thead": + case "tr": + case "td": + case "th": return endTagTable(token); - default: return endTagOther(token); + default: + return endTagOther(token); } } @@ -2891,8 +3268,9 @@ class InSelectInTablePhase extends Phase { Token startTagTable(StartTagToken token) { parser.parseError(token.span, - "unexpected-table-element-start-tag-in-select-in-table", - {"name": token.name}); + "unexpected-table-element-start-tag-in-select-in-table", { + "name": token.name + }); endTagOther(new EndTagToken("select")); return token; } @@ -2903,8 +3281,9 @@ class InSelectInTablePhase extends Phase { Token endTagTable(EndTagToken token) { parser.parseError(token.span, - "unexpected-table-element-end-tag-in-select-in-table", - {"name": token.name}); + "unexpected-table-element-end-tag-in-select-in-table", { + "name": token.name + }); if (tree.elementInScope(token.name, variant: "table")) { endTagOther(new EndTagToken("select")); return token; @@ -2917,57 +3296,95 @@ class InSelectInTablePhase extends Phase { } } - class InForeignContentPhase extends Phase { // TODO(jmesserly): this is sorted so we could binary search. static const breakoutElements = const [ - 'b', 'big', 'blockquote', 'body', 'br','center', 'code', 'dd', 'div', 'dl', - 'dt', 'em', 'embed', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'hr', 'i', - 'img', 'li', 'listing', 'menu', 'meta', 'nobr', 'ol', 'p', 'pre', 'ruby', - 's', 'small', 'span', 'strike', 'strong', 'sub', 'sup', 'table', 'tt', 'u', - 'ul', 'var' + 'b', + 'big', + 'blockquote', + 'body', + 'br', + 'center', + 'code', + 'dd', + 'div', + 'dl', + 'dt', + 'em', + 'embed', + 'h1', + 'h2', + 'h3', + 'h4', + 'h5', + 'h6', + 'head', + 'hr', + 'i', + 'img', + 'li', + 'listing', + 'menu', + 'meta', + 'nobr', + 'ol', + 'p', + 'pre', + 'ruby', + 's', + 'small', + 'span', + 'strike', + 'strong', + 'sub', + 'sup', + 'table', + 'tt', + 'u', + 'ul', + 'var' ]; InForeignContentPhase(parser) : super(parser); void adjustSVGTagNames(token) { final replacements = const { - "altglyph":"altGlyph", - "altglyphdef":"altGlyphDef", - "altglyphitem":"altGlyphItem", - "animatecolor":"animateColor", - "animatemotion":"animateMotion", - "animatetransform":"animateTransform", - "clippath":"clipPath", - "feblend":"feBlend", - "fecolormatrix":"feColorMatrix", - "fecomponenttransfer":"feComponentTransfer", - "fecomposite":"feComposite", - "feconvolvematrix":"feConvolveMatrix", - "fediffuselighting":"feDiffuseLighting", - "fedisplacementmap":"feDisplacementMap", - "fedistantlight":"feDistantLight", - "feflood":"feFlood", - "fefunca":"feFuncA", - "fefuncb":"feFuncB", - "fefuncg":"feFuncG", - "fefuncr":"feFuncR", - "fegaussianblur":"feGaussianBlur", - "feimage":"feImage", - "femerge":"feMerge", - "femergenode":"feMergeNode", - "femorphology":"feMorphology", - "feoffset":"feOffset", - "fepointlight":"fePointLight", - "fespecularlighting":"feSpecularLighting", - "fespotlight":"feSpotLight", - "fetile":"feTile", - "feturbulence":"feTurbulence", - "foreignobject":"foreignObject", - "glyphref":"glyphRef", - "lineargradient":"linearGradient", - "radialgradient":"radialGradient", - "textpath":"textPath" + "altglyph": "altGlyph", + "altglyphdef": "altGlyphDef", + "altglyphitem": "altGlyphItem", + "animatecolor": "animateColor", + "animatemotion": "animateMotion", + "animatetransform": "animateTransform", + "clippath": "clipPath", + "feblend": "feBlend", + "fecolormatrix": "feColorMatrix", + "fecomponenttransfer": "feComponentTransfer", + "fecomposite": "feComposite", + "feconvolvematrix": "feConvolveMatrix", + "fediffuselighting": "feDiffuseLighting", + "fedisplacementmap": "feDisplacementMap", + "fedistantlight": "feDistantLight", + "feflood": "feFlood", + "fefunca": "feFuncA", + "fefuncb": "feFuncB", + "fefuncg": "feFuncG", + "fefuncr": "feFuncR", + "fegaussianblur": "feGaussianBlur", + "feimage": "feImage", + "femerge": "feMerge", + "femergenode": "feMergeNode", + "femorphology": "feMorphology", + "feoffset": "feOffset", + "fepointlight": "fePointLight", + "fespecularlighting": "feSpecularLighting", + "fespotlight": "feSpotLight", + "fetile": "feTile", + "feturbulence": "feTurbulence", + "foreignobject": "foreignObject", + "glyphref": "glyphRef", + "lineargradient": "linearGradient", + "radialgradient": "radialGradient", + "textpath": "textPath" }; var replace = replacements[token.name]; @@ -2989,20 +3406,17 @@ class InForeignContentPhase extends Phase { var currentNode = tree.openElements.last; if (breakoutElements.contains(token.name) || (token.name == "font" && - (token.data.containsKey("color") || - token.data.containsKey("face") || - token.data.containsKey("size")))) { - + (token.data.containsKey("color") || + token.data.containsKey("face") || + token.data.containsKey("size")))) { parser.parseError(token.span, "unexpected-html-element-in-foreign-content", {'name': token.name}); - while (tree.openElements.last.namespaceUri != - tree.defaultNamespace && - !parser.isHTMLIntegrationPoint(tree.openElements.last) && - !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { + while (tree.openElements.last.namespaceUri != tree.defaultNamespace && + !parser.isHTMLIntegrationPoint(tree.openElements.last) && + !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { tree.openElements.removeLast(); } return token; - } else { if (currentNode.namespaceUri == Namespaces.mathml) { parser.adjustMathMLAttributes(token); @@ -3057,7 +3471,6 @@ class InForeignContentPhase extends Phase { } } - class AfterBodyPhase extends Phase { AfterBodyPhase(parser) : super(parser); @@ -3092,8 +3505,8 @@ class AfterBodyPhase extends Phase { } Token startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-after-body", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-start-tag-after-body", {"name": token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3107,8 +3520,8 @@ class AfterBodyPhase extends Phase { } Token endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-after-body", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-after-body", {"name": token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3120,18 +3533,25 @@ class InFramesetPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "frameset": return startTagFrameset(token); - case "frame": return startTagFrame(token); - case "noframes": return startTagNoframes(token); - default: return startTagOther(token); + case "html": + return startTagHtml(token); + case "frameset": + return startTagFrameset(token); + case "frame": + return startTagFrame(token); + case "noframes": + return startTagNoframes(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "frameset": return endTagFrameset(token); - default: return endTagOther(token); + case "frameset": + return endTagFrameset(token); + default: + return endTagOther(token); } } @@ -3164,16 +3584,16 @@ class InFramesetPhase extends Phase { } Token startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-in-frameset", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-start-tag-in-frameset", {"name": token.name}); return null; } void endTagFrameset(EndTagToken token) { if (tree.openElements.last.localName == "html") { // innerHTML case - parser.parseError(token.span, - "unexpected-frameset-in-frameset-innerhtml"); + parser.parseError( + token.span, "unexpected-frameset-in-frameset-innerhtml"); } else { tree.openElements.removeLast(); } @@ -3186,28 +3606,32 @@ class InFramesetPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-in-frameset", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-in-frameset", {"name": token.name}); } } - class AfterFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///after3 AfterFramesetPhase(parser) : super(parser); processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "noframes": return startTagNoframes(token); - default: return startTagOther(token); + case "html": + return startTagHtml(token); + case "noframes": + return startTagNoframes(token); + default: + return startTagOther(token); } } processEndTag(EndTagToken token) { switch (token.name) { - case "html": return endTagHtml(token); - default: return endTagOther(token); + case "html": + return endTagHtml(token); + default: + return endTagOther(token); } } @@ -3224,8 +3648,9 @@ class AfterFramesetPhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-after-frameset", - {"name": token.name}); + parser.parseError(token.span, "unexpected-start-tag-after-frameset", { + "name": token.name + }); } void endTagHtml(EndTagToken token) { @@ -3233,12 +3658,11 @@ class AfterFramesetPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-after-frameset", - {"name": token.name}); + parser.parseError( + token.span, "unexpected-end-tag-after-frameset", {"name": token.name}); } } - class AfterAfterBodyPhase extends Phase { AfterAfterBodyPhase(parser) : super(parser); @@ -3269,15 +3693,15 @@ class AfterAfterBodyPhase extends Phase { } Token startTagOther(StartTagToken token) { - parser.parseError(token.span, "expected-eof-but-got-start-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-eof-but-got-start-tag", {"name": token.name}); parser.phase = parser._inBodyPhase; return token; } Token processEndTag(EndTagToken token) { - parser.parseError(token.span, "expected-eof-but-got-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-eof-but-got-end-tag", {"name": token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3288,9 +3712,12 @@ class AfterAfterFramesetPhase extends Phase { processStartTag(StartTagToken token) { switch (token.name) { - case "html": return startTagHtml(token); - case "noframes": return startTagNoFrames(token); - default: return startTagOther(token); + case "html": + return startTagHtml(token); + case "noframes": + return startTagNoFrames(token); + default: + return startTagOther(token); } } @@ -3319,18 +3746,17 @@ class AfterAfterFramesetPhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "expected-eof-but-got-start-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-eof-but-got-start-tag", {"name": token.name}); } Token processEndTag(EndTagToken token) { - parser.parseError(token.span, "expected-eof-but-got-end-tag", - {"name": token.name}); + parser.parseError( + token.span, "expected-eof-but-got-end-tag", {"name": token.name}); return null; } } - /// Error in parsed document. class ParseError implements SourceSpanException { final String errorCode; @@ -3357,7 +3783,6 @@ class ParseError implements SourceSpanException { } } - /// Convenience function to get the pair of namespace and localName. Pair<String, String> getElementNameTuple(Element e) { var ns = e.namespaceUri; diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 9c04999b9..5ddf72796 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -21,8 +21,8 @@ bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { /// Decodes the [bytes] with the provided [encoding] and returns an iterable for /// the codepoints. Supports the major unicode encodings as well as ascii and /// and windows-1252 encodings. -Iterable<int> decodeBytes(String encoding, List<int> bytes, - [int offset = 0, int length, +Iterable<int> decodeBytes(String encoding, List<int> bytes, [int offset = 0, + int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { if (length == null) length = bytes.length; final replace = replacementCodepoint; @@ -72,7 +72,6 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes, } } - // TODO(jmesserly): use dart:utf once http://dartbug.com/6476 is fixed. /// Returns the code points for the [input]. This works like [String.charCodes] /// but it decodes UTF-16 surrogate pairs. @@ -95,7 +94,6 @@ List<int> toCodepoints(String input) { return newCodes; } - /// Decodes [windows-1252](http://en.wikipedia.org/wiki/Windows-1252) bytes as /// an iterable. Thus, the consumer can only convert as much of the input as /// needed. Set the [replacementCharacter] to null to throw an [ArgumentError] @@ -103,11 +101,10 @@ List<int> toCodepoints(String input) { IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, [int offset = 0, int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { - return new IterableWindows1252Decoder(bytes, offset, length, - replacementCodepoint); + return new IterableWindows1252Decoder( + bytes, offset, length, replacementCodepoint); } - /// Return type of [decodeWindows1252AsIterable] and variants. The Iterable type /// provides an iterator on demand and the iterator will only translate bytes /// as requested by the user of the iterator. (Note: results are not cached.) @@ -125,7 +122,6 @@ class IterableWindows1252Decoder extends IterableBase<int> { new Windows1252Decoder(bytes, offset, length, replacementCodepoint); } - /// Provides an iterator of Unicode codepoints from windows-1252 encoded bytes. /// The parameters can set an offset into a list of bytes (as int), limit the /// length of the values to be decoded, and override the default Unicode @@ -156,33 +152,60 @@ class Windows1252Decoder implements Iterator<int> { // TODO(jmesserly): this is duplicating entitiesWindows1252 and // replacementCharacters from constants.dart switch (char) { - case 0x80: return 0x20AC; // EURO SIGN - case 0x82: return 0x201A; // SINGLE LOW-9 QUOTATION MARK - case 0x83: return 0x0192; // LATIN SMALL LETTER F WITH HOOK - case 0x84: return 0x201E; // DOUBLE LOW-9 QUOTATION MARK - case 0x85: return 0x2026; // HORIZONTAL ELLIPSIS - case 0x86: return 0x2020; // DAGGER - case 0x87: return 0x2021; // DOUBLE DAGGER - case 0x88: return 0x02C6; // MODIFIER LETTER CIRCUMFLEX ACCENT - case 0x89: return 0x2030; // PER MILLE SIGN - case 0x8A: return 0x0160; // LATIN CAPITAL LETTER S WITH CARON - case 0x8B: return 0x2039; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - case 0x8C: return 0x0152; // LATIN CAPITAL LIGATURE OE - case 0x8E: return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON - case 0x91: return 0x2018; // LEFT SINGLE QUOTATION MARK - case 0x92: return 0x2019; // RIGHT SINGLE QUOTATION MARK - case 0x93: return 0x201C; // LEFT DOUBLE QUOTATION MARK - case 0x94: return 0x201D; // RIGHT DOUBLE QUOTATION MARK - case 0x95: return 0x2022; // BULLET - case 0x96: return 0x2013; // EN DASH - case 0x97: return 0x2014; // EM DASH - case 0x98: return 0x02DC; // SMALL TILDE - case 0x99: return 0x2122; // TRADE MARK SIGN - case 0x9A: return 0x0161; // LATIN SMALL LETTER S WITH CARON - case 0x9B: return 0x203A; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - case 0x9C: return 0x0153; // LATIN SMALL LIGATURE OE - case 0x9E: return 0x017E; // LATIN SMALL LETTER Z WITH CARON - case 0x9F: return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS + case 0x80: + return 0x20AC; // EURO SIGN + case 0x82: + return 0x201A; // SINGLE LOW-9 QUOTATION MARK + case 0x83: + return 0x0192; // LATIN SMALL LETTER F WITH HOOK + case 0x84: + return 0x201E; // DOUBLE LOW-9 QUOTATION MARK + case 0x85: + return 0x2026; // HORIZONTAL ELLIPSIS + case 0x86: + return 0x2020; // DAGGER + case 0x87: + return 0x2021; // DOUBLE DAGGER + case 0x88: + return 0x02C6; // MODIFIER LETTER CIRCUMFLEX ACCENT + case 0x89: + return 0x2030; // PER MILLE SIGN + case 0x8A: + return 0x0160; // LATIN CAPITAL LETTER S WITH CARON + case 0x8B: + return 0x2039; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK + case 0x8C: + return 0x0152; // LATIN CAPITAL LIGATURE OE + case 0x8E: + return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON + case 0x91: + return 0x2018; // LEFT SINGLE QUOTATION MARK + case 0x92: + return 0x2019; // RIGHT SINGLE QUOTATION MARK + case 0x93: + return 0x201C; // LEFT DOUBLE QUOTATION MARK + case 0x94: + return 0x201D; // RIGHT DOUBLE QUOTATION MARK + case 0x95: + return 0x2022; // BULLET + case 0x96: + return 0x2013; // EN DASH + case 0x97: + return 0x2014; // EM DASH + case 0x98: + return 0x02DC; // SMALL TILDE + case 0x99: + return 0x2122; // TRADE MARK SIGN + case 0x9A: + return 0x0161; // LATIN SMALL LETTER S WITH CARON + case 0x9B: + return 0x203A; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + case 0x9C: + return 0x0153; // LATIN SMALL LIGATURE OE + case 0x9E: + return 0x017E; // LATIN SMALL LETTER Z WITH CARON + case 0x9F: + return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS case 0x81: case 0x8D: diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 0fd9e122f..e85e43a31 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -20,283 +20,219 @@ class ReparseException implements Exception { /// style string formatting, as implemented by [formatStr]. That function only /// supports the subset of format functionality used here. const Map<String, String> errorMessages = const { - "null-character": - "Null character in input stream, replaced with U+FFFD.", - "invalid-codepoint": - "Invalid codepoint in stream.", - "incorrectly-placed-solidus": - "Solidus (/) incorrectly placed in tag.", + "null-character": "Null character in input stream, replaced with U+FFFD.", + "invalid-codepoint": "Invalid codepoint in stream.", + "incorrectly-placed-solidus": "Solidus (/) incorrectly placed in tag.", "incorrect-cr-newline-entity": - "Incorrect CR newline entity, replaced with LF.", + "Incorrect CR newline entity, replaced with LF.", "illegal-windows-1252-entity": - "Entity used with illegal number (windows-1252 reference).", + "Entity used with illegal number (windows-1252 reference).", "cant-convert-numeric-entity": - "Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x).", + "Numeric entity couldn't be converted to character " + "(codepoint U+%(charAsInt)08x).", "illegal-codepoint-for-numeric-entity": - "Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x.", - "numeric-entity-without-semicolon": - "Numeric entity didn't end with ';'.", + "Numeric entity represents an illegal codepoint: " + "U+%(charAsInt)08x.", + "numeric-entity-without-semicolon": "Numeric entity didn't end with ';'.", "expected-numeric-entity-but-got-eof": - "Numeric entity expected. Got end of file instead.", - "expected-numeric-entity": - "Numeric entity expected but none found.", - "named-entity-without-semicolon": - "Named entity didn't end with ';'.", - "expected-named-entity": - "Named entity expected. Got none.", - "attributes-in-end-tag": - "End tag contains unexpected attributes.", + "Numeric entity expected. Got end of file instead.", + "expected-numeric-entity": "Numeric entity expected but none found.", + "named-entity-without-semicolon": "Named entity didn't end with ';'.", + "expected-named-entity": "Named entity expected. Got none.", + "attributes-in-end-tag": "End tag contains unexpected attributes.", 'self-closing-flag-on-end-tag': "End tag contains unexpected self-closing flag.", "expected-tag-name-but-got-right-bracket": - "Expected tag name. Got '>' instead.", + "Expected tag name. Got '>' instead.", "expected-tag-name-but-got-question-mark": - "Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)", - "expected-tag-name": - "Expected tag name. Got something else instead", + "Expected tag name. Got '?' instead. (HTML doesn't " + "support processing instructions.)", + "expected-tag-name": "Expected tag name. Got something else instead", "expected-closing-tag-but-got-right-bracket": - "Expected closing tag. Got '>' instead. Ignoring '</>'.", + "Expected closing tag. Got '>' instead. Ignoring '</>'.", "expected-closing-tag-but-got-eof": - "Expected closing tag. Unexpected end of file.", + "Expected closing tag. Unexpected end of file.", "expected-closing-tag-but-got-char": - "Expected closing tag. Unexpected character '%(data)s' found.", - "eof-in-tag-name": - "Unexpected end of file in the tag name.", + "Expected closing tag. Unexpected character '%(data)s' found.", + "eof-in-tag-name": "Unexpected end of file in the tag name.", "expected-attribute-name-but-got-eof": - "Unexpected end of file. Expected attribute name instead.", - "eof-in-attribute-name": - "Unexpected end of file in attribute name.", - "invalid-character-in-attribute-name": - "Invalid character in attribute name", - "duplicate-attribute": - "Dropped duplicate attribute on tag.", + "Unexpected end of file. Expected attribute name instead.", + "eof-in-attribute-name": "Unexpected end of file in attribute name.", + "invalid-character-in-attribute-name": "Invalid character in attribute name", + "duplicate-attribute": "Dropped duplicate attribute on tag.", "expected-end-of-tag-name-but-got-eof": - "Unexpected end of file. Expected = or end of tag.", + "Unexpected end of file. Expected = or end of tag.", "expected-attribute-value-but-got-eof": - "Unexpected end of file. Expected attribute value.", + "Unexpected end of file. Expected attribute value.", "expected-attribute-value-but-got-right-bracket": - "Expected attribute value. Got '>' instead.", - 'equals-in-unquoted-attribute-value': - "Unexpected = in unquoted attribute", + "Expected attribute value. Got '>' instead.", + 'equals-in-unquoted-attribute-value': "Unexpected = in unquoted attribute", 'unexpected-character-in-unquoted-attribute-value': "Unexpected character in unquoted attribute", "invalid-character-after-attribute-name": - "Unexpected character after attribute name.", + "Unexpected character after attribute name.", "unexpected-character-after-attribute-value": - "Unexpected character after attribute value.", + "Unexpected character after attribute value.", "eof-in-attribute-value-double-quote": - "Unexpected end of file in attribute value (\".", + "Unexpected end of file in attribute value (\".", "eof-in-attribute-value-single-quote": - "Unexpected end of file in attribute value (').", + "Unexpected end of file in attribute value (').", "eof-in-attribute-value-no-quotes": - "Unexpected end of file in attribute value.", + "Unexpected end of file in attribute value.", "unexpected-EOF-after-solidus-in-tag": "Unexpected end of file in tag. Expected >", "unexpected-character-after-soldius-in-tag": "Unexpected character after / in tag. Expected >", - "expected-dashes-or-doctype": - "Expected '--' or 'DOCTYPE'. Not found.", + "expected-dashes-or-doctype": "Expected '--' or 'DOCTYPE'. Not found.", "unexpected-bang-after-double-dash-in-comment": "Unexpected ! after -- in comment", "unexpected-space-after-double-dash-in-comment": "Unexpected space after -- in comment", - "incorrect-comment": - "Incorrect comment.", - "eof-in-comment": - "Unexpected end of file in comment.", - "eof-in-comment-end-dash": - "Unexpected end of file in comment (-)", + "incorrect-comment": "Incorrect comment.", + "eof-in-comment": "Unexpected end of file in comment.", + "eof-in-comment-end-dash": "Unexpected end of file in comment (-)", "unexpected-dash-after-double-dash-in-comment": - "Unexpected '-' after '--' found in comment.", - "eof-in-comment-double-dash": - "Unexpected end of file in comment (--).", - "eof-in-comment-end-space-state": - "Unexpected end of file in comment.", - "eof-in-comment-end-bang-state": - "Unexpected end of file in comment.", - "unexpected-char-in-comment": - "Unexpected character in comment found.", - "need-space-after-doctype": - "No space after literal string 'DOCTYPE'.", + "Unexpected '-' after '--' found in comment.", + "eof-in-comment-double-dash": "Unexpected end of file in comment (--).", + "eof-in-comment-end-space-state": "Unexpected end of file in comment.", + "eof-in-comment-end-bang-state": "Unexpected end of file in comment.", + "unexpected-char-in-comment": "Unexpected character in comment found.", + "need-space-after-doctype": "No space after literal string 'DOCTYPE'.", "expected-doctype-name-but-got-right-bracket": - "Unexpected > character. Expected DOCTYPE name.", + "Unexpected > character. Expected DOCTYPE name.", "expected-doctype-name-but-got-eof": - "Unexpected end of file. Expected DOCTYPE name.", - "eof-in-doctype-name": - "Unexpected end of file in DOCTYPE name.", - "eof-in-doctype": - "Unexpected end of file in DOCTYPE.", + "Unexpected end of file. Expected DOCTYPE name.", + "eof-in-doctype-name": "Unexpected end of file in DOCTYPE name.", + "eof-in-doctype": "Unexpected end of file in DOCTYPE.", "expected-space-or-right-bracket-in-doctype": - "Expected space or '>'. Got '%(data)s'", - "unexpected-end-of-doctype": - "Unexpected end of DOCTYPE.", - "unexpected-char-in-doctype": - "Unexpected character in DOCTYPE.", - "eof-in-innerhtml": - "XXX innerHTML EOF", - "unexpected-doctype": - "Unexpected DOCTYPE. Ignored.", - "non-html-root": - "html needs to be the first start tag.", - "expected-doctype-but-got-eof": - "Unexpected End of file. Expected DOCTYPE.", - "unknown-doctype": - "Erroneous DOCTYPE.", + "Expected space or '>'. Got '%(data)s'", + "unexpected-end-of-doctype": "Unexpected end of DOCTYPE.", + "unexpected-char-in-doctype": "Unexpected character in DOCTYPE.", + "eof-in-innerhtml": "XXX innerHTML EOF", + "unexpected-doctype": "Unexpected DOCTYPE. Ignored.", + "non-html-root": "html needs to be the first start tag.", + "expected-doctype-but-got-eof": "Unexpected End of file. Expected DOCTYPE.", + "unknown-doctype": "Erroneous DOCTYPE.", "expected-doctype-but-got-chars": - "Unexpected non-space characters. Expected DOCTYPE.", + "Unexpected non-space characters. Expected DOCTYPE.", "expected-doctype-but-got-start-tag": - "Unexpected start tag (%(name)s). Expected DOCTYPE.", + "Unexpected start tag (%(name)s). Expected DOCTYPE.", "expected-doctype-but-got-end-tag": - "Unexpected end tag (%(name)s). Expected DOCTYPE.", + "Unexpected end tag (%(name)s). Expected DOCTYPE.", "end-tag-after-implied-root": - "Unexpected end tag (%(name)s) after the (implied) root element.", + "Unexpected end tag (%(name)s) after the (implied) root element.", "expected-named-closing-tag-but-got-eof": - "Unexpected end of file. Expected end tag (%(name)s).", + "Unexpected end of file. Expected end tag (%(name)s).", "two-heads-are-not-better-than-one": - "Unexpected start tag head in existing head. Ignored.", - "unexpected-end-tag": - "Unexpected end tag (%(name)s). Ignored.", + "Unexpected start tag head in existing head. Ignored.", + "unexpected-end-tag": "Unexpected end tag (%(name)s). Ignored.", "unexpected-start-tag-out-of-my-head": - "Unexpected start tag (%(name)s) that can be in head. Moved.", - "unexpected-start-tag": - "Unexpected start tag (%(name)s).", - "missing-end-tag": - "Missing end tag (%(name)s).", - "missing-end-tags": - "Missing end tags (%(name)s).", + "Unexpected start tag (%(name)s) that can be in head. Moved.", + "unexpected-start-tag": "Unexpected start tag (%(name)s).", + "missing-end-tag": "Missing end tag (%(name)s).", + "missing-end-tags": "Missing end tags (%(name)s).", "unexpected-start-tag-implies-end-tag": - "Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s).", + "Unexpected start tag (%(startName)s) " + "implies end tag (%(endName)s).", "unexpected-start-tag-treated-as": - "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", - "deprecated-tag": - "Unexpected start tag %(name)s. Don't use it!", - "unexpected-start-tag-ignored": - "Unexpected start tag %(name)s. Ignored.", - "expected-one-end-tag-but-got-another": - "Unexpected end tag (%(gotName)s). " - "Missing end tag (%(expectedName)s).", + "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", + "deprecated-tag": "Unexpected start tag %(name)s. Don't use it!", + "unexpected-start-tag-ignored": "Unexpected start tag %(name)s. Ignored.", + "expected-one-end-tag-but-got-another": "Unexpected end tag (%(gotName)s). " + "Missing end tag (%(expectedName)s).", "end-tag-too-early": - "End tag (%(name)s) seen too early. Expected other end tag.", + "End tag (%(name)s) seen too early. Expected other end tag.", "end-tag-too-early-named": - "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", - "end-tag-too-early-ignored": - "End tag (%(name)s) seen too early. Ignored.", - "adoption-agency-1.1": - "End tag (%(name)s) violates step 1, " - "paragraph 1 of the adoption agency algorithm.", - "adoption-agency-1.2": - "End tag (%(name)s) violates step 1, " - "paragraph 2 of the adoption agency algorithm.", - "adoption-agency-1.3": - "End tag (%(name)s) violates step 1, " - "paragraph 3 of the adoption agency algorithm.", + "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", + "end-tag-too-early-ignored": "End tag (%(name)s) seen too early. Ignored.", + "adoption-agency-1.1": "End tag (%(name)s) violates step 1, " + "paragraph 1 of the adoption agency algorithm.", + "adoption-agency-1.2": "End tag (%(name)s) violates step 1, " + "paragraph 2 of the adoption agency algorithm.", + "adoption-agency-1.3": "End tag (%(name)s) violates step 1, " + "paragraph 3 of the adoption agency algorithm.", "unexpected-end-tag-treated-as": - "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", - "no-end-tag": - "This element (%(name)s) has no end tag.", + "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", + "no-end-tag": "This element (%(name)s) has no end tag.", "unexpected-implied-end-tag-in-table": - "Unexpected implied end tag (%(name)s) in the table phase.", + "Unexpected implied end tag (%(name)s) in the table phase.", "unexpected-implied-end-tag-in-table-body": - "Unexpected implied end tag (%(name)s) in the table body phase.", - "unexpected-char-implies-table-voodoo": - "Unexpected non-space characters in " - "table context caused voodoo mode.", + "Unexpected implied end tag (%(name)s) in the table body phase.", + "unexpected-char-implies-table-voodoo": "Unexpected non-space characters in " + "table context caused voodoo mode.", "unexpected-hidden-input-in-table": - "Unexpected input with type hidden in table context.", - "unexpected-form-in-table": - "Unexpected form in table context.", + "Unexpected input with type hidden in table context.", + "unexpected-form-in-table": "Unexpected form in table context.", "unexpected-start-tag-implies-table-voodoo": - "Unexpected start tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-end-tag-implies-table-voodoo": - "Unexpected end tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-cell-in-table-body": - "Unexpected table cell start tag (%(name)s) " - "in the table body phase.", - "unexpected-cell-end-tag": - "Got table cell end tag (%(name)s) " - "while required end tags are missing.", + "Unexpected start tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-end-tag-implies-table-voodoo": "Unexpected end tag (%(name)s) in " + "table context caused voodoo mode.", + "unexpected-cell-in-table-body": "Unexpected table cell start tag (%(name)s) " + "in the table body phase.", + "unexpected-cell-end-tag": "Got table cell end tag (%(name)s) " + "while required end tags are missing.", "unexpected-end-tag-in-table-body": - "Unexpected end tag (%(name)s) in the table body phase. Ignored.", + "Unexpected end tag (%(name)s) in the table body phase. Ignored.", "unexpected-implied-end-tag-in-table-row": - "Unexpected implied end tag (%(name)s) in the table row phase.", + "Unexpected implied end tag (%(name)s) in the table row phase.", "unexpected-end-tag-in-table-row": - "Unexpected end tag (%(name)s) in the table row phase. Ignored.", + "Unexpected end tag (%(name)s) in the table row phase. Ignored.", "unexpected-select-in-select": - "Unexpected select start tag in the select phase " - "treated as select end tag.", + "Unexpected select start tag in the select phase " + "treated as select end tag.", "unexpected-input-in-select": - "Unexpected input start tag in the select phase.", + "Unexpected input start tag in the select phase.", "unexpected-start-tag-in-select": - "Unexpected start tag token (%(name)s in the select phase. " - "Ignored.", + "Unexpected start tag token (%(name)s in the select phase. " + "Ignored.", "unexpected-end-tag-in-select": - "Unexpected end tag (%(name)s) in the select phase. Ignored.", + "Unexpected end tag (%(name)s) in the select phase. Ignored.", "unexpected-table-element-start-tag-in-select-in-table": - "Unexpected table element start tag (%(name)s) in the select in table phase.", + "Unexpected table element start tag (%(name)s) in the select in table phase.", "unexpected-table-element-end-tag-in-select-in-table": - "Unexpected table element end tag (%(name)s) in the select in table phase.", + "Unexpected table element end tag (%(name)s) in the select in table phase.", "unexpected-char-after-body": - "Unexpected non-space characters in the after body phase.", - "unexpected-start-tag-after-body": - "Unexpected start tag token (%(name)s)" - " in the after body phase.", - "unexpected-end-tag-after-body": - "Unexpected end tag token (%(name)s)" - " in the after body phase.", + "Unexpected non-space characters in the after body phase.", + "unexpected-start-tag-after-body": "Unexpected start tag token (%(name)s)" + " in the after body phase.", + "unexpected-end-tag-after-body": "Unexpected end tag token (%(name)s)" + " in the after body phase.", "unexpected-char-in-frameset": - "Unepxected characters in the frameset phase. Characters ignored.", - "unexpected-start-tag-in-frameset": - "Unexpected start tag token (%(name)s)" - " in the frameset phase. Ignored.", + "Unepxected characters in the frameset phase. Characters ignored.", + "unexpected-start-tag-in-frameset": "Unexpected start tag token (%(name)s)" + " in the frameset phase. Ignored.", "unexpected-frameset-in-frameset-innerhtml": - "Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML).", - "unexpected-end-tag-in-frameset": - "Unexpected end tag token (%(name)s)" - " in the frameset phase. Ignored.", - "unexpected-char-after-frameset": - "Unexpected non-space characters in the " - "after frameset phase. Ignored.", - "unexpected-start-tag-after-frameset": - "Unexpected start tag (%(name)s)" - " in the after frameset phase. Ignored.", - "unexpected-end-tag-after-frameset": - "Unexpected end tag (%(name)s)" - " in the after frameset phase. Ignored.", + "Unexpected end tag token (frameset) " + "in the frameset phase (innerHTML).", + "unexpected-end-tag-in-frameset": "Unexpected end tag token (%(name)s)" + " in the frameset phase. Ignored.", + "unexpected-char-after-frameset": "Unexpected non-space characters in the " + "after frameset phase. Ignored.", + "unexpected-start-tag-after-frameset": "Unexpected start tag (%(name)s)" + " in the after frameset phase. Ignored.", + "unexpected-end-tag-after-frameset": "Unexpected end tag (%(name)s)" + " in the after frameset phase. Ignored.", "unexpected-end-tag-after-body-innerhtml": - "Unexpected end tag after body(innerHtml)", + "Unexpected end tag after body(innerHtml)", "expected-eof-but-got-char": - "Unexpected non-space characters. Expected end of file.", - "expected-eof-but-got-start-tag": - "Unexpected start tag (%(name)s)" - ". Expected end of file.", - "expected-eof-but-got-end-tag": - "Unexpected end tag (%(name)s)" - ". Expected end of file.", - "eof-in-table": - "Unexpected end of file. Expected table content.", - "eof-in-select": - "Unexpected end of file. Expected select content.", - "eof-in-frameset": - "Unexpected end of file. Expected frameset content.", - "eof-in-script-in-script": - "Unexpected end of file. Expected script content.", - "eof-in-foreign-lands": - "Unexpected end of file. Expected foreign content", + "Unexpected non-space characters. Expected end of file.", + "expected-eof-but-got-start-tag": "Unexpected start tag (%(name)s)" + ". Expected end of file.", + "expected-eof-but-got-end-tag": "Unexpected end tag (%(name)s)" + ". Expected end of file.", + "eof-in-table": "Unexpected end of file. Expected table content.", + "eof-in-select": "Unexpected end of file. Expected select content.", + "eof-in-frameset": "Unexpected end of file. Expected frameset content.", + "eof-in-script-in-script": "Unexpected end of file. Expected script content.", + "eof-in-foreign-lands": "Unexpected end of file. Expected foreign content", "non-void-element-with-trailing-solidus": - "Trailing solidus not allowed on element %(name)s", + "Trailing solidus not allowed on element %(name)s", "unexpected-html-element-in-foreign-content": - "Element %(name)s not allowed in a non-html context", + "Element %(name)s not allowed in a non-html context", "unexpected-end-tag-before-html": "Unexpected end tag (%(name)s) before html.", - "undefined-error": - "Undefined error (this sucks and should be fixed)", + "undefined-error": "Undefined error (this sucks and should be fixed)", }; class Namespaces { @@ -310,13 +246,20 @@ class Namespaces { static String getPrefix(String url) { switch (url) { - case html: return 'html'; - case mathml: return 'math'; - case svg: return 'svg'; - case xlink: return 'xlink'; - case xml: return 'xml'; - case xmlns: return 'xmlns'; - default: return null; + case html: + return 'html'; + case mathml: + return 'math'; + case svg: + return 'svg'; + case xlink: + return 'xlink'; + case xml: + return 'xml'; + case xmlns: + return 'xmlns'; + default: + return null; } } } @@ -341,7 +284,6 @@ const List scopingElements = const [ const Pair(Namespaces.svg, "title") ]; - const formattingElements = const [ const Pair(Namespaces.html, "a"), const Pair(Namespaces.html, "b"), @@ -469,7 +411,7 @@ bool isWhitespace(String char) { bool isWhitespaceCC(int charCode) { switch (charCode) { - case 9: // '\t' + case 9: // '\t' case NEWLINE: // '\n' case 12: // '\f' case RETURN: // '\r' @@ -514,10 +456,28 @@ bool isDigit(String char) { bool isHexDigit(String char) { if (char == null) return false; switch (char.codeUnitAt(0)) { - case 48: case 49: case 50: case 51: case 52: // '0' - '4' - case 53: case 54: case 55: case 56: case 57: // '5' - '9' - case 65: case 66: case 67: case 68: case 69: case 70: // 'A' - 'F' - case 97: case 98: case 99: case 100: case 101: case 102: // 'a' - 'f' + case 48: + case 49: + case 50: + case 51: + case 52: // '0' - '4' + case 53: + case 54: + case 55: + case 56: + case 57: // '5' - '9' + case 65: + case 66: + case 67: + case 68: + case 69: + case 70: // 'A' - 'F' + case 97: + case 98: + case 99: + case 100: + case 101: + case 102: // 'a' - 'f' return true; } return false; @@ -539,14 +499,7 @@ String asciiUpper2Lower(String text) { } // Heading elements need to be ordered -const headingElements = const [ - "h1", - "h2", - "h3", - "h4", - "h5", - "h6" -]; +const headingElements = const ["h1", "h2", "h3", "h4", "h5", "h6"]; const cdataElements = const ['title', 'textarea']; @@ -564,8 +517,8 @@ const Map<String, List<String>> booleanAttributes = const { "": const ["irrelevant",], "style": const ["scoped",], "img": const ["ismap",], - "audio": const ["autoplay","controls"], - "video": const ["autoplay","controls"], + "audio": const ["autoplay", "controls"], + "video": const ["autoplay", "controls"], "script": const ["defer", "async"], "details": const ["open",], "datagrid": const ["multiple", "disabled"], @@ -576,7 +529,14 @@ const Map<String, List<String>> booleanAttributes = const { "option": const ["disabled", "readonly", "selected"], "optgroup": const ["disabled", "readonly"], "button": const ["disabled", "autofocus"], - "input": const ["disabled", "readonly", "required", "autofocus", "checked", "ismap"], + "input": const [ + "disabled", + "readonly", + "required", + "autofocus", + "checked", + "ismap" + ], "select": const ["disabled", "readonly", "autofocus", "multiple"], "output": const ["disabled", "readonly"], }; @@ -584,38 +544,38 @@ const Map<String, List<String>> booleanAttributes = const { // entitiesWindows1252 has to be _ordered_ and needs to have an index. It // therefore can't be a frozenset. const List<int> entitiesWindows1252 = const [ - 8364, // 0x80 0x20AC EURO SIGN + 8364, // 0x80 0x20AC EURO SIGN 65533, // 0x81 UNDEFINED - 8218, // 0x82 0x201A SINGLE LOW-9 QUOTATION MARK - 402, // 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK - 8222, // 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK - 8230, // 0x85 0x2026 HORIZONTAL ELLIPSIS - 8224, // 0x86 0x2020 DAGGER - 8225, // 0x87 0x2021 DOUBLE DAGGER - 710, // 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT - 8240, // 0x89 0x2030 PER MILLE SIGN - 352, // 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON - 8249, // 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK - 338, // 0x8C 0x0152 LATIN CAPITAL LIGATURE OE + 8218, // 0x82 0x201A SINGLE LOW-9 QUOTATION MARK + 402, // 0x83 0x0192 LATIN SMALL LETTER F WITH HOOK + 8222, // 0x84 0x201E DOUBLE LOW-9 QUOTATION MARK + 8230, // 0x85 0x2026 HORIZONTAL ELLIPSIS + 8224, // 0x86 0x2020 DAGGER + 8225, // 0x87 0x2021 DOUBLE DAGGER + 710, // 0x88 0x02C6 MODIFIER LETTER CIRCUMFLEX ACCENT + 8240, // 0x89 0x2030 PER MILLE SIGN + 352, // 0x8A 0x0160 LATIN CAPITAL LETTER S WITH CARON + 8249, // 0x8B 0x2039 SINGLE LEFT-POINTING ANGLE QUOTATION MARK + 338, // 0x8C 0x0152 LATIN CAPITAL LIGATURE OE 65533, // 0x8D UNDEFINED - 381, // 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON + 381, // 0x8E 0x017D LATIN CAPITAL LETTER Z WITH CARON 65533, // 0x8F UNDEFINED 65533, // 0x90 UNDEFINED - 8216, // 0x91 0x2018 LEFT SINGLE QUOTATION MARK - 8217, // 0x92 0x2019 RIGHT SINGLE QUOTATION MARK - 8220, // 0x93 0x201C LEFT DOUBLE QUOTATION MARK - 8221, // 0x94 0x201D RIGHT DOUBLE QUOTATION MARK - 8226, // 0x95 0x2022 BULLET - 8211, // 0x96 0x2013 EN DASH - 8212, // 0x97 0x2014 EM DASH - 732, // 0x98 0x02DC SMALL TILDE - 8482, // 0x99 0x2122 TRADE MARK SIGN - 353, // 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON - 8250, // 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - 339, // 0x9C 0x0153 LATIN SMALL LIGATURE OE + 8216, // 0x91 0x2018 LEFT SINGLE QUOTATION MARK + 8217, // 0x92 0x2019 RIGHT SINGLE QUOTATION MARK + 8220, // 0x93 0x201C LEFT DOUBLE QUOTATION MARK + 8221, // 0x94 0x201D RIGHT DOUBLE QUOTATION MARK + 8226, // 0x95 0x2022 BULLET + 8211, // 0x96 0x2013 EN DASH + 8212, // 0x97 0x2014 EM DASH + 732, // 0x98 0x02DC SMALL TILDE + 8482, // 0x99 0x2122 TRADE MARK SIGN + 353, // 0x9A 0x0161 LATIN SMALL LETTER S WITH CARON + 8250, // 0x9B 0x203A SINGLE RIGHT-POINTING ANGLE QUOTATION MARK + 339, // 0x9C 0x0153 LATIN SMALL LIGATURE OE 65533, // 0x9D UNDEFINED - 382, // 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON - 376 // 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS + 382, // 0x9E 0x017E LATIN SMALL LETTER Z WITH CARON + 376 // 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS ]; const xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index ea0152d1f..8798cd2e1 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -9,7 +9,6 @@ import 'dart:collection'; import 'package:html5lib/dom.dart'; class ElementCssClassSet extends CssClassSetImpl { - final Element _element; ElementCssClassSet(this._element); @@ -32,7 +31,6 @@ class ElementCssClassSet extends CssClassSetImpl { } } - /** A Set that stores the CSS class names for an element. */ abstract class CssClassSet implements Set<String> { @@ -111,7 +109,6 @@ abstract class CssClassSet implements Set<String> { } abstract class CssClassSetImpl implements CssClassSet { - String toString() { return readClasses().join(' '); } @@ -267,21 +264,19 @@ abstract class CssClassSetImpl implements CssClassSet { } bool containsAll(Iterable<String> collection) => - readClasses().containsAll(collection); + readClasses().containsAll(collection); Set<String> intersection(Set<String> other) => - readClasses().intersection(other); + readClasses().intersection(other); - Set<String> union(Set<String> other) => - readClasses().union(other); + Set<String> union(Set<String> other) => readClasses().union(other); - Set<String> difference(Set<String> other) => - readClasses().difference(other); + Set<String> difference(Set<String> other) => readClasses().difference(other); String get first => readClasses().first; String get last => readClasses().last; String get single => readClasses().single; - List<String> toList({ bool growable: true }) => + List<String> toList({bool growable: true}) => readClasses().toList(growable: growable); Set<String> toSet() => readClasses().toSet(); Iterable<String> take(int n) => readClasses().take(n); @@ -290,9 +285,9 @@ abstract class CssClassSetImpl implements CssClassSet { Iterable<String> skip(int n) => readClasses().skip(n); Iterable<String> skipWhile(bool test(String value)) => readClasses().skipWhile(test); - dynamic firstWhere(bool test(String value), { Object orElse() }) => + dynamic firstWhere(bool test(String value), {Object orElse()}) => readClasses().firstWhere(test, orElse: orElse); - dynamic lastWhere(bool test(String value), { Object orElse()}) => + dynamic lastWhere(bool test(String value), {Object orElse()}) => readClasses().lastWhere(test, orElse: orElse); String singleWhere(bool test(String value)) => readClasses().singleWhere(test); @@ -312,7 +307,7 @@ abstract class CssClassSetImpl implements CssClassSet { * After f returns, the modified set is written to the * className property of this element. */ - modify( f(Set<String> s)) { + modify(f(Set<String> s)) { Set<String> s = readClasses(); var ret = f(s); writeClasses(s); diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 8bb861c42..04ffa0c36 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -63,7 +63,7 @@ class EncodingBytes extends IterableBase<String> { /// Skip past a list of characters. Defaults to skipping [isWhitespace]. String skipChars([CharPreciate skipChars]) { if (skipChars == null) skipChars = isWhitespace; - var p = position; // use property for the error-checking + var p = position; // use property for the error-checking while (p < length) { var c = _bytes[p]; if (!skipChars(c)) { @@ -141,7 +141,8 @@ class EncodingParser { ["</", handlePossibleEndTag], ["<!", handleOther], ["<?", handleOther], - ["<", handlePossibleStartTag]]; + ["<", handlePossibleStartTag] + ]; try { for (var byte in data) { @@ -324,7 +325,6 @@ class EncodingParser { } } - class ContentAttrParser { final EncodingBytes data; @@ -370,7 +370,6 @@ class ContentAttrParser { } } - bool isSpaceOrAngleBracket(String char) { return char == ">" || char == "<" || isWhitespace(char); } diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index 231fed0c5..fce5b2194 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -69,9 +69,8 @@ class HtmlInputStream { /// /// [parseMeta] - Look for a <meta> element containing encoding information HtmlInputStream(source, [String encoding, bool parseMeta = true, - this.generateSpans = false, this.sourceUrl]) + this.generateSpans = false, this.sourceUrl]) : charEncodingName = codecName(encoding) { - if (source is String) { _rawChars = toCodepoints(source); charEncodingName = 'utf-8'; @@ -140,7 +139,6 @@ class HtmlInputStream { fileInfo = new SourceFile.decoded(_chars, url: sourceUrl); } - void detectEncoding([bool parseMeta = true]) { // First look for a BOM // This will also read past the BOM if present @@ -259,7 +257,6 @@ class HtmlInputStream { } } - // TODO(jmesserly): the Python code used a regex to check for this. But // Dart doesn't let you create a regexp with invalid characters. bool invalidUnicode(int c) { @@ -269,15 +266,41 @@ bool invalidUnicode(int c) { if (0xD800 <= c && c <= 0xDFFF) return true; if (0xFDD0 <= c && c <= 0xFDEF) return true; switch (c) { - case 0x000B: case 0xFFFE: case 0xFFFF: case 0x01FFFE: case 0x01FFFF: - case 0x02FFFE: case 0x02FFFF: case 0x03FFFE: case 0x03FFFF: - case 0x04FFFE: case 0x04FFFF: case 0x05FFFE: case 0x05FFFF: - case 0x06FFFE: case 0x06FFFF: case 0x07FFFE: case 0x07FFFF: - case 0x08FFFE: case 0x08FFFF: case 0x09FFFE: case 0x09FFFF: - case 0x0AFFFE: case 0x0AFFFF: case 0x0BFFFE: case 0x0BFFFF: - case 0x0CFFFE: case 0x0CFFFF: case 0x0DFFFE: case 0x0DFFFF: - case 0x0EFFFE: case 0x0EFFFF: case 0x0FFFFE: case 0x0FFFFF: - case 0x10FFFE: case 0x10FFFF: + case 0x000B: + case 0xFFFE: + case 0xFFFF: + case 0x01FFFE: + case 0x01FFFF: + case 0x02FFFE: + case 0x02FFFF: + case 0x03FFFE: + case 0x03FFFF: + case 0x04FFFE: + case 0x04FFFF: + case 0x05FFFE: + case 0x05FFFF: + case 0x06FFFE: + case 0x06FFFF: + case 0x07FFFE: + case 0x07FFFF: + case 0x08FFFE: + case 0x08FFFF: + case 0x09FFFE: + case 0x09FFFF: + case 0x0AFFFE: + case 0x0AFFFF: + case 0x0BFFFE: + case 0x0BFFFF: + case 0x0CFFFE: + case 0x0CFFFF: + case 0x0DFFFE: + case 0x0DFFFF: + case 0x0EFFFE: + case 0x0EFFFF: + case 0x0FFFFE: + case 0x0FFFFF: + case 0x10FFFE: + case 0x10FFFF: return true; } return false; diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 0ba70733b..99acdb673 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -16,8 +16,7 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { /// Creates a list proxy. /// You can optionally specify the list to use for [storage] of the items, /// otherwise this will create a [List<E>]. - ListProxy([List<E> storage]) - : _list = storage != null ? storage : <E>[]; + ListProxy([List<E> storage]) : _list = storage != null ? storage : <E>[]; // TODO(jmesserly): This should be on List. // See http://code.google.com/p/dart/issues/detail?id=947 @@ -43,18 +42,34 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { // From List E operator [](int index) => _list[index]; - operator []=(int index, E value) { _list[index] = value; } - set length(int value) { _list.length = value; } - void add(E value) { _list.add(value); } + operator []=(int index, E value) { + _list[index] = value; + } + set length(int value) { + _list.length = value; + } + void add(E value) { + _list.add(value); + } - void addLast(E value) { add(value); } - void addAll(Iterable<E> collection) { _list.addAll(collection); } - void sort([int compare(E a, E b)]) { _list.sort(compare); } - void shuffle([Random random]) { _list.shuffle(random); } + void addLast(E value) { + add(value); + } + void addAll(Iterable<E> collection) { + _list.addAll(collection); + } + void sort([int compare(E a, E b)]) { + _list.sort(compare); + } + void shuffle([Random random]) { + _list.shuffle(random); + } int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); - void clear() { _list.clear(); } + void clear() { + _list.clear(); + } E removeAt(int index) => _list.removeAt(index); E removeLast() => _list.removeLast(); @@ -69,7 +84,9 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void setRange(int start, int length, List<E> from, [int startFrom = 0]) { _list.setRange(start, length, from, startFrom); } - void removeRange(int start, int length) { _list.removeRange(start, length); } + void removeRange(int start, int length) { + _list.removeRange(start, length); + } void insertAll(int index, Iterable<E> iterable) { _list.insertAll(index, iterable); } @@ -83,6 +100,6 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void setAll(int index, Iterable<E> iterable) => _list.setAll(index, iterable); - void fillRange(int start, int end, [E fillValue]) - => _list.fillRange(start, end, fillValue); + void fillRange(int start, int end, [E fillValue]) => + _list.fillRange(start, end, fillValue); } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index ededa549d..556eeb064 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -15,8 +15,8 @@ Element querySelector(Node node, String selector) => List<Element> querySelectorAll(Node node, String selector) { var results = []; - new SelectorEvaluator() - .querySelectorAll(node, _parseSelectorList(selector), results); + new SelectorEvaluator().querySelectorAll( + node, _parseSelectorList(selector), results); return results; } @@ -49,9 +49,8 @@ class SelectorEvaluator extends Visitor { return null; } - void querySelectorAll(Node root, SelectorGroup selector, - List<Element> results) { - + void querySelectorAll( + Node root, SelectorGroup selector, List<Element> results) { for (var node in root.nodes) { if (node is! Element) continue; if (matches(node, selector)) results.add(node); @@ -59,7 +58,6 @@ class SelectorEvaluator extends Visitor { } } - bool visitSelectorGroup(SelectorGroup group) => group.selectors.any(visitSelector); @@ -109,8 +107,10 @@ class SelectorEvaluator extends Visitor { // For now, just remember what the combinator was. combinator = s.combinator; break; - case TokenKind.COMBINATOR_NONE: break; - default: throw _unsupported(selector); + case TokenKind.COMBINATOR_NONE: + break; + default: + throw _unsupported(selector); } if (_element == null) { @@ -123,9 +123,9 @@ class SelectorEvaluator extends Visitor { return result; } - _unimplemented(SimpleSelector selector) => - new UnimplementedError("'$selector' selector of type " - "${selector.runtimeType} is not implemented"); + _unimplemented(SimpleSelector selector) => new UnimplementedError( + "'$selector' selector of type " + "${selector.runtimeType} is not implemented"); _unsupported(selector) => new FormatException("'$selector' is not a valid selector"); @@ -142,8 +142,8 @@ class SelectorEvaluator extends Visitor { // http://dev.w3.org/csswg/selectors-4/#the-empty-pseudo case 'empty': - return _element.nodes.any((n) => !(n is Element || - n is Text && n.text.isNotEmpty)); + return _element.nodes + .any((n) => !(n is Element || n is Text && n.text.isNotEmpty)); // http://dev.w3.org/csswg/selectors-4/#the-blank-pseudo case 'blank': @@ -179,7 +179,6 @@ class SelectorEvaluator extends Visitor { throw _unimplemented(selector); } - bool visitPseudoElementSelector(PseudoElementSelector selector) { // :before, :after, :first-letter/line can't match DOM elements. if (_isLegacyPsuedoClass(selector.name)) return false; @@ -189,9 +188,13 @@ class SelectorEvaluator extends Visitor { static bool _isLegacyPsuedoClass(String name) { switch (name) { - case 'before': case 'after': case 'first-line': case 'first-letter': + case 'before': + case 'after': + case 'first-line': + case 'first-letter': return true; - default: return false; + default: + return false; } } @@ -209,7 +212,8 @@ class SelectorEvaluator extends Visitor { if (exprs.length == 1 && exprs[0] is LiteralTerm) { LiteralTerm literal = exprs[0]; var parent = _element.parentNode; - return parent != null && literal.value > 0 && + return parent != null && + literal.value > 0 && parent.nodes.indexOf(_element) == literal.value; } break; @@ -282,7 +286,8 @@ class SelectorEvaluator extends Visitor { return value.endsWith(select); case TokenKind.SUBSTRING_MATCH: return value.contains(select); - default: throw _unsupported(selector); + default: + throw _unsupported(selector); } } } diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 934015315..e4f25e5db 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -106,7 +106,6 @@ class TagAttribute { TagAttribute(this.name, [this.value = '']); } - class TokenKind { static const int spaceCharacters = 0; static const int characters = 1; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 1b6311497..a7ebcf81a 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -69,7 +69,7 @@ class HtmlTokenizer implements Iterator<Token> { this.lowercaseElementName: true, this.lowercaseAttrName: true, bool generateSpans: false, String sourceUrl, this.attributeSpans: false}) : stream = new HtmlInputStream( - doc, encoding, parseMeta, generateSpans, sourceUrl), + doc, encoding, parseMeta, generateSpans, sourceUrl), tokenQueue = new Queue(), generateSpans = generateSpans { reset(); @@ -134,7 +134,7 @@ class HtmlTokenizer implements Iterator<Token> { if (stream.errors.length > 0) { _current = new ParseErrorToken(stream.errors.removeFirst()); } else { - assert (tokenQueue.length > 0); + assert(tokenQueue.length > 0); _current = tokenQueue.removeFirst(); } return true; @@ -191,14 +191,12 @@ class HtmlTokenizer implements Iterator<Token> { // Certain characters get replaced with others var char = replacementCharacters[charAsInt]; if (char != null) { - _addToken(new ParseErrorToken( - "illegal-codepoint-for-numeric-entity", + _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); - } else if ((0xD800 <= charAsInt && charAsInt <= 0xDFFF) - || (charAsInt > 0x10FFFF)) { + } else if ((0xD800 <= charAsInt && charAsInt <= 0xDFFF) || + (charAsInt > 0x10FFFF)) { char = "\uFFFD"; - _addToken(new ParseErrorToken( - "illegal-codepoint-for-numeric-entity", + _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } else { // Should speed up this check somehow (e.g. move the set to a constant) @@ -206,17 +204,44 @@ class HtmlTokenizer implements Iterator<Token> { (0x000E <= charAsInt && charAsInt <= 0x001F) || (0x007F <= charAsInt && charAsInt <= 0x009F) || (0xFDD0 <= charAsInt && charAsInt <= 0xFDEF) || - const [0x000B, 0xFFFE, 0xFFFF, 0x1FFFE, - 0x1FFFF, 0x2FFFE, 0x2FFFF, 0x3FFFE, - 0x3FFFF, 0x4FFFE, 0x4FFFF, 0x5FFFE, - 0x5FFFF, 0x6FFFE, 0x6FFFF, 0x7FFFE, - 0x7FFFF, 0x8FFFE, 0x8FFFF, 0x9FFFE, - 0x9FFFF, 0xAFFFE, 0xAFFFF, 0xBFFFE, - 0xBFFFF, 0xCFFFE, 0xCFFFF, 0xDFFFE, - 0xDFFFF, 0xEFFFE, 0xEFFFF, 0xFFFFE, - 0xFFFFF, 0x10FFFE, 0x10FFFF].contains(charAsInt)) { - _addToken(new ParseErrorToken( - "illegal-codepoint-for-numeric-entity", + const [ + 0x000B, + 0xFFFE, + 0xFFFF, + 0x1FFFE, + 0x1FFFF, + 0x2FFFE, + 0x2FFFF, + 0x3FFFE, + 0x3FFFF, + 0x4FFFE, + 0x4FFFF, + 0x5FFFE, + 0x5FFFF, + 0x6FFFE, + 0x6FFFF, + 0x7FFFE, + 0x7FFFF, + 0x8FFFE, + 0x8FFFF, + 0x9FFFE, + 0x9FFFF, + 0xAFFFE, + 0xAFFFF, + 0xBFFFE, + 0xBFFFF, + 0xCFFFE, + 0xCFFFF, + 0xDFFFE, + 0xDFFFF, + 0xEFFFE, + 0xEFFFF, + 0xFFFFE, + 0xFFFFF, + 0x10FFFE, + 0x10FFFF + ].contains(charAsInt)) { + _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } char = new String.fromCharCodes([charAsInt]); @@ -225,8 +250,7 @@ class HtmlTokenizer implements Iterator<Token> { // Discard the ; if present. Otherwise, put it back on the queue and // invoke parseError on parser. if (c != ";") { - _addToken(new ParseErrorToken( - "numeric-entity-without-semicolon")); + _addToken(new ParseErrorToken("numeric-entity-without-semicolon")); stream.unget(c); } return char; @@ -237,8 +261,11 @@ class HtmlTokenizer implements Iterator<Token> { var output = "&"; var charStack = [stream.char()]; - if (isWhitespace(charStack[0]) || charStack[0] == '<' || charStack[0] == '&' - || charStack[0] == EOF || allowedChar == charStack[0]) { + if (isWhitespace(charStack[0]) || + charStack[0] == '<' || + charStack[0] == '&' || + charStack[0] == EOF || + allowedChar == charStack[0]) { stream.unget(charStack[0]); } else if (charStack[0] == "#") { // Read the next character to see if it's hex or decimal @@ -272,8 +299,8 @@ class HtmlTokenizer implements Iterator<Token> { while (charStack.last != EOF) { var name = charStack.join(); - filteredEntityList = filteredEntityList.where( - (e) => e.startsWith(name)).toList(); + filteredEntityList = + filteredEntityList.where((e) => e.startsWith(name)).toList(); if (filteredEntityList.length == 0) { break; @@ -300,12 +327,12 @@ class HtmlTokenizer implements Iterator<Token> { if (entityName != null) { var lastChar = entityName[entityName.length - 1]; if (lastChar != ";") { - _addToken(new ParseErrorToken( - "named-entity-without-semicolon")); + _addToken(new ParseErrorToken("named-entity-without-semicolon")); } - if (lastChar != ";" && fromAttribute && + if (lastChar != ";" && + fromAttribute && (isLetterOrDigit(charStack[entityLen]) || - charStack[entityLen] == '=')) { + charStack[entityLen] == '=')) { stream.unget(charStack.removeLast()); output = "&${charStack.join()}"; } else { @@ -482,8 +509,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(new ParseErrorToken("invalid-codepoint")); _addToken(new CharactersToken("\uFFFD")); } else { - _addToken(new CharactersToken( - '${data}${stream.charsUntil("\u0000")}')); + _addToken(new CharactersToken('${data}${stream.charsUntil("\u0000")}')); } return true; } @@ -500,15 +526,13 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == ">") { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(new ParseErrorToken( - "expected-tag-name-but-got-right-bracket")); + _addToken(new ParseErrorToken("expected-tag-name-but-got-right-bracket")); _addToken(new CharactersToken("<>")); state = dataState; } else if (data == "?") { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(new ParseErrorToken( - "expected-tag-name-but-got-question-mark")); + _addToken(new ParseErrorToken("expected-tag-name-but-got-question-mark")); stream.unget(data); state = bogusCommentState; } else { @@ -527,18 +551,17 @@ class HtmlTokenizer implements Iterator<Token> { currentToken = new EndTagToken(data); state = tagNameState; } else if (data == ">") { - _addToken(new ParseErrorToken( - "expected-closing-tag-but-got-right-bracket")); + _addToken( + new ParseErrorToken("expected-closing-tag-but-got-right-bracket")); state = dataState; } else if (data == EOF) { - _addToken(new ParseErrorToken( - "expected-closing-tag-but-got-eof")); + _addToken(new ParseErrorToken("expected-closing-tag-but-got-eof")); _addToken(new CharactersToken("</")); state = dataState; } else { // XXX data can be _'_... - _addToken(new ParseErrorToken( - "expected-closing-tag-but-got-char", messageParams: {"data": data})); + _addToken(new ParseErrorToken("expected-closing-tag-but-got-char", + messageParams: {"data": data})); stream.unget(data); state = bogusCommentState; } @@ -1219,8 +1242,8 @@ class HtmlTokenizer implements Iterator<Token> { stream.unget(data); state = dataState; } else { - _addToken(new ParseErrorToken( - "unexpected-character-after-attribute-value")); + _addToken( + new ParseErrorToken("unexpected-character-after-attribute-value")); stream.unget(data); state = beforeAttributeNameState; } @@ -1237,8 +1260,8 @@ class HtmlTokenizer implements Iterator<Token> { stream.unget(data); state = dataState; } else { - _addToken(new ParseErrorToken( - "unexpected-character-after-soldius-in-tag")); + _addToken( + new ParseErrorToken("unexpected-character-after-soldius-in-tag")); stream.unget(data); state = beforeAttributeNameState; } @@ -1285,9 +1308,10 @@ class HtmlTokenizer implements Iterator<Token> { return true; } } else if (charStack.last == "[" && - parser != null && parser.tree.openElements.length > 0 && - parser.tree.openElements.last.namespaceUri - != parser.tree.defaultNamespace) { + parser != null && + parser.tree.openElements.length > 0 && + parser.tree.openElements.last.namespaceUri != + parser.tree.defaultNamespace) { var matched = true; for (var expected in const ["C", "D", "A", "T", "A", "["]) { charStack.add(stream.char()); @@ -1402,12 +1426,12 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.data = '${currentStringToken.data}--\uFFFD'; state = commentState; } else if (data == "!") { - _addToken(new ParseErrorToken( - "unexpected-bang-after-double-dash-in-comment")); + _addToken( + new ParseErrorToken("unexpected-bang-after-double-dash-in-comment")); state = commentEndBangState; } else if (data == "-") { - _addToken(new ParseErrorToken( - "unexpected-dash-after-double-dash-in-comment")); + _addToken( + new ParseErrorToken("unexpected-dash-after-double-dash-in-comment")); currentStringToken.data = '${currentStringToken.data}$data'; } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-comment-double-dash")); @@ -1450,8 +1474,7 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypeNameState; } else if (data == EOF) { - _addToken(new ParseErrorToken( - "expected-doctype-name-but-got-eof")); + _addToken(new ParseErrorToken("expected-doctype-name-but-got-eof")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1468,8 +1491,8 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == ">") { - _addToken(new ParseErrorToken( - "expected-doctype-name-but-got-right-bracket")); + _addToken( + new ParseErrorToken("expected-doctype-name-but-got-right-bracket")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1478,8 +1501,7 @@ class HtmlTokenizer implements Iterator<Token> { currentDoctypeToken.name = "\uFFFD"; state = doctypeNameState; } else if (data == EOF) { - _addToken(new ParseErrorToken( - "expected-doctype-name-but-got-eof")); + _addToken(new ParseErrorToken("expected-doctype-name-but-got-eof")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1883,4 +1905,3 @@ class HtmlTokenizer implements Iterator<Token> { return true; } } - diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 4b8dfc425..edd183dab 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -61,7 +61,6 @@ bool _mapEquals(Map a, Map b) { return true; } - bool _nodesEqual(Element node1, Element node2) { return getElementNameTuple(node1) == getElementNameTuple(node2) && _mapEquals(node1.attributes, node2.attributes); @@ -117,16 +116,22 @@ class TreeBuilder { listElements2 = const [const Pair(Namespaces.html, "button")]; break; case "list": - listElements2 = const [const Pair(Namespaces.html, "ol"), - const Pair(Namespaces.html, "ul")]; + listElements2 = const [ + const Pair(Namespaces.html, "ol"), + const Pair(Namespaces.html, "ul") + ]; break; case "table": - listElements1 = const [const Pair(Namespaces.html, "html"), - const Pair(Namespaces.html, "table")]; + listElements1 = const [ + const Pair(Namespaces.html, "html"), + const Pair(Namespaces.html, "table") + ]; break; case "select": - listElements1 = const [const Pair(Namespaces.html, "optgroup"), - const Pair(Namespaces.html, "option")]; + listElements1 = const [ + const Pair(Namespaces.html, "optgroup"), + const Pair(Namespaces.html, "option") + ]; invert = true; break; default: @@ -140,7 +145,7 @@ class TreeBuilder { return true; } else if (invert != (listElements1.contains(getElementNameTuple(node)) || - listElements2.contains(getElementNameTuple(node)))) { + listElements2.contains(getElementNameTuple(node)))) { return false; } } @@ -185,11 +190,10 @@ class TreeBuilder { entry = activeFormattingElements[i]; // TODO(jmesserly): optimize this. No need to create a token. - var cloneToken = new StartTagToken( - entry.localName, + var cloneToken = new StartTagToken(entry.localName, namespace: entry.namespaceUri, data: new LinkedHashMap.from(entry.attributes)) - ..span = entry.sourceSpan; + ..span = entry.sourceSpan; // Step 9 var element = insertElement(cloneToken); @@ -235,7 +239,7 @@ class TreeBuilder { void insertDoctype(DoctypeToken token) { var doctype = new DocumentType(token.name, token.publicId, token.systemId) - ..sourceSpan = token.span; + ..sourceSpan = token.span; document.nodes.add(doctype); } @@ -252,8 +256,8 @@ class TreeBuilder { var namespace = token.namespace; if (namespace == null) namespace = defaultNamespace; var element = document.createElementNS(namespace, name) - ..attributes = token.data - ..sourceSpan = token.span; + ..attributes = token.data + ..sourceSpan = token.span; return element; } @@ -267,8 +271,8 @@ class TreeBuilder { var namespace = token.namespace; if (namespace == null) namespace = defaultNamespace; var element = document.createElementNS(namespace, name) - ..attributes = token.data - ..sourceSpan = token.span; + ..attributes = token.data + ..sourceSpan = token.span; openElements.last.nodes.add(element); openElements.add(element); return element; @@ -300,8 +304,9 @@ class TreeBuilder { void insertText(String data, FileSpan span) { var parent = openElements.last; - if (!insertFromTable || insertFromTable && - !tableInsertModeElements.contains(openElements.last.localName)) { + if (!insertFromTable || + insertFromTable && + !tableInsertModeElements.contains(openElements.last.localName)) { _insertText(parent, data, span); } else { // We should be in the InTable mode. This means we want to do @@ -322,8 +327,8 @@ class TreeBuilder { last.data = '${last.data}$data'; if (span != null) { - last.sourceSpan = span.file.span(last.sourceSpan.start.offset, - span.end.offset); + last.sourceSpan = + span.file.span(last.sourceSpan.start.offset, span.end.offset); } } else { nodes.add(new Text(data)..sourceSpan = span); @@ -372,8 +377,17 @@ class TreeBuilder { void generateImpliedEndTags([String exclude]) { var name = openElements.last.localName; // XXX td, th and tr are not actually needed - if (name != exclude && const ["dd", "dt", "li", "option", "optgroup", "p", - "rp", "rt"].contains(name)) { + if (name != exclude && + const [ + "dd", + "dt", + "li", + "option", + "optgroup", + "p", + "rp", + "rt" + ].contains(name)) { openElements.removeLast(); // XXX This is not entirely what the specification says. We should // investigate it more closely. diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index c998e0f00..fb58cf144 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -79,7 +79,8 @@ String formatStr(String format, Map data) { data.forEach((key, value) { var result = new StringBuffer(); var search = '%($key)'; - int last = 0, match; + int last = 0, + match; while ((match = format.indexOf(search, last)) >= 0) { result.write(format.substring(last, match)); match += search.length; @@ -106,8 +107,9 @@ String formatStr(String format, Map data) { var number = value.toRadixString(16); result.write(padWithZeros(number, numberSize)); break; - default: throw "not implemented: formatStr does not support format " - "character ${format[match]}"; + default: + throw "not implemented: formatStr does not support format " + "character ${format[match]}"; } last = match + 1; diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 9251faf2e..14b095bed 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -6,7 +6,6 @@ import 'package:html5lib/dom.dart'; import 'package:html5lib/parser.dart'; main() { - group('Element', () { test('classes', () { final barBaz = new Element.html('<div class=" bar baz"></div>'); @@ -20,9 +19,9 @@ main() { group('Document', () { final doc = parse('<div id=foo>' - '<div class=" bar baz"></div>' - '<div class="qux baz "></div>' - '<div id=Foo>'); + '<div class=" bar baz"></div>' + '<div class="qux baz "></div>' + '<div id=Foo>'); test('getElementById', () { var foo = doc.body.nodes[0]; diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 2950a7742..ddc8a743f 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -129,8 +129,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. var doc = parse(text, generateSpans: true); var elem = doc.querySelector('foo'); - expect(elem.attributeSpans['template'].start.offset, - text.indexOf('template')); + expect( + elem.attributeSpans['template'].start.offset, text.indexOf('template')); expect(elem.attributeValueSpans.containsKey('template'), false); }); @@ -246,7 +246,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. 'Unexpected non-space characters. Expected DOCTYPE.'); expect(parser.errors[0].toString(), 'ParserError on line 1, column 4: Unexpected non-space characters. ' - 'Expected DOCTYPE.\n' + 'Expected DOCTYPE.\n' 'foo\n' ' ^'); }); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index aa454933c..ed1198249 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -20,7 +20,7 @@ String namespaceHtml(String expected) { // final namespaceExpected = new RegExp(@"^(\s*)<(\S+)>", multiLine: true); // return expected.replaceAll(namespaceExpected, @"$1<html $2>"); final namespaceExpected = new RegExp(r"^(\|\s*)<(\S+)>"); - var lines = expected.split("\n"); + var lines = expected.split("\n"); for (int i = 0; i < lines.length; i++) { var match = namespaceExpected.firstMatch(lines[i]); if (match != null) { @@ -52,21 +52,19 @@ void runParserTest(String groupName, String innerHTML, String input, expected = namespaceHtml(expected); } - expect(output, equals(expected), reason: - "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); + expect(output, equals(expected), + reason: "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); if (checkParseErrors) { - expect(parser.errors.length, equals(errors.length), reason: - "\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n" + expect(parser.errors.length, equals(errors.length), + reason: "\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n" "${errors.join('\n')}\n\n" "Actual errors (${parser.errors.length}):\n" "${parser.errors.map((e) => '$e').join('\n')}"); } } - void main() { - test('dart:io', () { // ensure IO support is unregistered expect(inputstream.consoleSupport, @@ -113,6 +111,6 @@ _nameFor(String input) { .replaceAll(new RegExp('\\\\.'), '_') .replaceAll(new RegExp('\u0000'), '_') .replaceAll('"', '\\"') - .replaceAll(new RegExp('[\n\r\t]'),'_'); + .replaceAll(new RegExp('[\n\r\t]'), '_'); return JSON.decode('"$escapeQuote"'); } diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index cf9373cd4..2a2f2f038 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -18,7 +18,7 @@ Document getTestContentDocument() { } var testType = TEST_QSA_BASELINE; // Only run baseline tests. -var docType = "html"; // Only run tests suitable for HTML +var docType = "html"; // Only run tests suitable for HTML main() { /* @@ -59,21 +59,24 @@ main() { //doc = frame.contentDocument; // Document Node tests doc = getTestContentDocument(); - var element = doc.getElementById("root"); // In-document Element Node tests + var element = doc.getElementById("root"); // In-document Element Node tests //Setup the namespace tests setupSpecialElements(element); - var outOfScope = element.clone(true); // Append this to the body before running the in-document - // Element tests, but after running the Document tests. This - // tests that no elements that are not descendants of element - // are selected. + var outOfScope = element + .clone(true); // Append this to the body before running the in-document + // Element tests, but after running the Document tests. This + // tests that no elements that are not descendants of element + // are selected. - traverse(outOfScope, (elem) { // Annotate each element as being a clone; used for verifying - elem.attributes["data-clone"] = ""; // that none of these elements ever match. + traverse(outOfScope, (elem) { + // Annotate each element as being a clone; used for verifying + elem.attributes["data-clone"] = + ""; // that none of these elements ever match. }); - var detached = element.clone(true); // Detached Element Node tests + var detached = element.clone(true); // Detached Element Node tests var fragment = doc.createDocumentFragment(); // Fragment Node tests fragment.append(element.clone(true)); @@ -101,17 +104,19 @@ main() { //runInvalidSelectorTest("In-document Element", element, invalidSelectors); runValidSelectorTest("Document", doc, validSelectors, testType, docType); - runValidSelectorTest("Detached Element", detached, validSelectors, testType, docType); + runValidSelectorTest( + "Detached Element", detached, validSelectors, testType, docType); runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType); group('out of scope', () { setUp(() { doc.body.append(outOfScope); // Append before in-document Element tests. - // None of these elements should match + // None of these elements should match }); tearDown(() { outOfScope.remove(); }); - runValidSelectorTest("In-document Element", element, validSelectors, testType, docType); + runValidSelectorTest( + "In-document Element", element, validSelectors, testType, docType); }); } diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 31e0faf54..30ef1a133 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -29,28 +29,34 @@ setupSpecialElements(parent) { noNS.id = "no-namespace"; var div; - div = [doc.createElement("div"), - doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), - doc.createElementNS("", "div"), - doc.createElementNS("http://www.example.org/ns", "div")]; + div = [ + doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div") + ]; div[0].id = "any-namespace-div1"; div[1].id = "any-namespace-div2"; - div[2].attributes["id"] = "any-namespace-div3"; // Non-HTML elements can't use .id property + div[2].attributes["id"] = + "any-namespace-div3"; // Non-HTML elements can't use .id property div[3].attributes["id"] = "any-namespace-div4"; for (var i = 0; i < div.length; i++) { anyNS.append(div[i]); } - div = [doc.createElement("div"), - doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), - doc.createElementNS("", "div"), - doc.createElementNS("http://www.example.org/ns", "div")]; + div = [ + doc.createElement("div"), + doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), + doc.createElementNS("", "div"), + doc.createElementNS("http://www.example.org/ns", "div") + ]; div[0].id = "no-namespace-div1"; div[1].id = "no-namespace-div2"; - div[2].attributes["id"] = "no-namespace-div3"; // Non-HTML elements can't use .id property + div[2].attributes["id"] = + "no-namespace-div3"; // Non-HTML elements can't use .id property div[3].attributes["id"] = "no-namespace-div4"; for (var i = 0; i < div.length; i++) { @@ -72,14 +78,15 @@ interfaceCheck(type, obj) { test(() { var qa = obj.querySelectorAll is Function; - assert_true( qa, type + " supports querySelectorAll."); + assert_true(qa, type + " supports querySelectorAll."); }, type + " supports querySelectorAll"); test(() { var list = obj.querySelectorAll("div"); // TODO(jmesserly): testing List<Element> for now. It should return an // ElementList which has extra properties. Needed for dart:html compat. - assert_true(list is List<Element>, "The result should be an instance of a NodeList"); + assert_true(list is List<Element>, + "The result should be an instance of a NodeList"); }, type + ".querySelectorAll returns NodeList instance"); } @@ -97,12 +104,14 @@ verifyStaticList(type, root) { var div = doc.createElement("div"); (root is Document ? root.body : root).append(div); - assert_equals(pre.length, preLength, "The length of the NodeList should not change."); + assert_equals( + pre.length, preLength, "The length of the NodeList should not change."); }, type + ": static NodeList"); test(() { post = root.querySelectorAll("div"); - assert_equals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list."); + assert_equals(post.length, preLength + 1, + "The length of the new NodeList should be 1 more than the previous list."); }, type + ": new NodeList"); } @@ -113,46 +122,58 @@ verifyStaticList(type, root) { runSpecialSelectorTests(type, root) { // Dart note: changed these tests because we don't have auto conversion to // String like JavaScript does. - test(() { // 1 - assert_equals(root.querySelectorAll('null').length, 1, "This should find one element with the tag name 'NULL'."); + test(() { + // 1 + assert_equals(root.querySelectorAll('null').length, 1, + "This should find one element with the tag name 'NULL'."); }, type + ".querySelectorAll null"); - test(() { // 2 - assert_equals(root.querySelectorAll('undefined').length, 1, "This should find one element with the tag name 'UNDEFINED'."); + test(() { + // 2 + assert_equals(root.querySelectorAll('undefined').length, 1, + "This should find one element with the tag name 'UNDEFINED'."); }, type + ".querySelectorAll undefined"); - test(() { // 3 + test(() { + // 3 assert_throws((e) => e is NoSuchMethodError, () { root.querySelectorAll(); }, "This should throw a TypeError."); }, type + ".querySelectorAll no parameter"); - test(() { // 4 + test(() { + // 4 var elm = root.querySelector('null'); assert_not_equals(elm, null, "This should find an element."); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assert_equals(elm.localName.toUpperCase(), "NULL", "The tag name should be 'NULL'."); + assert_equals( + elm.localName.toUpperCase(), "NULL", "The tag name should be 'NULL'."); }, type + ".querySelector null"); - test(() { // 5 + test(() { + // 5 var elm = root.querySelector('undefined'); assert_not_equals(elm, 'undefined', "This should find an element."); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assert_equals(elm.localName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'."); + assert_equals(elm.localName.toUpperCase(), + "UNDEFINED", "The tag name should be 'UNDEFINED'."); }, type + ".querySelector undefined"); - test(() { // 6 + test(() { + // 6 assert_throws((e) => e is NoSuchMethodError, () { root.querySelector(); }, "This should throw a TypeError."); }, type + ".querySelector no parameter"); - test(() { // 7 + test(() { + // 7 var result = root.querySelectorAll("*"); var i = 0; traverse(root, (elem) { if (!identical(elem, root)) { - assert_equals(elem, result[i], "The result in index $i should be in tree order."); + assert_equals( + elem, result[i], "The result in index $i should be in tree order."); i++; } }); @@ -163,7 +184,7 @@ runSpecialSelectorTests(type, root) { * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() * Only run these tests when results are expected. Don't run for syntax error tests. */ - runValidSelectorTest(type, root, selectors, testType, docType) { +runValidSelectorTest(type, root, selectors, testType, docType) { var nodeType = ""; switch (root.nodeType) { case Node.DOCUMENT_NODE: @@ -185,20 +206,26 @@ runSpecialSelectorTests(type, root) { var q = s["selector"]; var e = s["expect"]; - if ((s["exclude"] is! List || (s["exclude"].indexOf(nodeType) == -1 && s["exclude"].indexOf(docType) == -1)) - && (s["testType"] & testType != 0) ) { + if ((s["exclude"] is! List || + (s["exclude"].indexOf(nodeType) == -1 && + s["exclude"].indexOf(docType) == -1)) && + (s["testType"] & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) var foundall, found; test(() { foundall = root.querySelectorAll(q); assert_not_equals(foundall, null, "The method should not return null."); - assert_equals(foundall.length, e.length, "The method should return the expected number of matches."); + assert_equals(foundall.length, e.length, + "The method should return the expected number of matches."); for (var i = 0; i < e.length; i++) { - assert_not_equals(foundall[i], null, "The item in index $i should not be null."); - assert_equals(foundall[i].attributes["id"], e[i], "The item in index $i should have the expected ID."); - assert_false(foundall[i].attributes.containsKey("data-clone"), "This should not be a cloned element."); + assert_not_equals( + foundall[i], null, "The item in index $i should not be null."); + assert_equals(foundall[i].attributes["id"], e[i], + "The item in index $i should have the expected ID."); + assert_false(foundall[i].attributes.containsKey("data-clone"), + "This should not be a cloned element."); } }, type + ".querySelectorAll: " + n + ": " + q); @@ -207,9 +234,12 @@ runSpecialSelectorTests(type, root) { if (e.length > 0) { assert_not_equals(found, null, "The method should return a match."); - assert_equals(found.attributes["id"], e[0], "The method should return the first match."); - assert_equals(found, foundall[0], "The result should match the first item from querySelectorAll."); - assert_false(found.attributes.containsKey("data-clone"), "This should not be annotated as a cloned element."); + assert_equals(found.attributes["id"], e[0], + "The method should return the first match."); + assert_equals(found, foundall[0], + "The result should match the first item from querySelectorAll."); + assert_false(found.attributes.containsKey("data-clone"), + "This should not be annotated as a cloned element."); } else { assert_equals(found, null, "The method should not match anything."); } @@ -224,7 +254,7 @@ runSpecialSelectorTests(type, root) { * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() * Only run these tests when errors are expected. Don't run for valid selector tests. */ - runInvalidSelectorTest(type, root, selectors) { +runInvalidSelectorTest(type, root, selectors) { for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; var n = s["name"]; @@ -245,7 +275,7 @@ runSpecialSelectorTests(type, root) { } } - traverse(Node elem, fn) { +traverse(Node elem, fn) { if (elem.nodeType == Node.ELEMENT_NODE) { fn(elem); } @@ -256,7 +286,6 @@ runSpecialSelectorTests(type, root) { } } - test(Function body, String name) => unittest.test(name, body); assert_true(value, String reason) => @@ -265,8 +294,7 @@ assert_true(value, String reason) => assert_false(value, String reason) => unittest.expect(value, false, reason: reason); -assert_equals(x, y, reason) => - unittest.expect(x, y, reason: reason); +assert_equals(x, y, reason) => unittest.expect(x, y, reason: reason); assert_not_equals(x, y, reason) => unittest.expect(x, unittest.isNot(y), reason: reason); diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index fd8bd965f..f6ff25d2c 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -3,14 +3,17 @@ library html5lib.test.selectors.selectors; // Bit-mapped flags to indicate which tests the selector is suitable for -var TEST_QSA_BASELINE = 0x01; // querySelector() and querySelectorAll() baseline tests -var TEST_QSA_ADDITIONAL = 0x02; // querySelector() and querySelectorAll() additional tests -var TEST_FIND_BASELINE = 0x04; // find() and findAll() baseline tests, may be unsuitable for querySelector[All] -var TEST_FIND_ADDITIONAL = 0x08; // find() and findAll() additional tests, may be unsuitable for querySelector[All] -var TEST_MATCH_BASELINE = 0x10; // matches() baseline tests +var TEST_QSA_BASELINE = + 0x01; // querySelector() and querySelectorAll() baseline tests +var TEST_QSA_ADDITIONAL = + 0x02; // querySelector() and querySelectorAll() additional tests +var TEST_FIND_BASELINE = + 0x04; // find() and findAll() baseline tests, may be unsuitable for querySelector[All] +var TEST_FIND_ADDITIONAL = + 0x08; // find() and findAll() additional tests, may be unsuitable for querySelector[All] +var TEST_MATCH_BASELINE = 0x10; // matches() baseline tests var TEST_MATCH_ADDITIONAL = 0x20; // matches() additional tests - /* * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. * @@ -18,38 +21,41 @@ var TEST_MATCH_ADDITIONAL = 0x20; // matches() additional tests * selector: The selector to test */ var invalidSelectors = [ - {'name': "Empty String", 'selector': ""}, - {'name': "Invalid character", 'selector': "["}, - {'name': "Invalid character", 'selector': "]"}, - {'name': "Invalid character", 'selector': "("}, - {'name': "Invalid character", 'selector': ")"}, - {'name': "Invalid character", 'selector': "{"}, - {'name': "Invalid character", 'selector': "}"}, - {'name': "Invalid character", 'selector': "<"}, - {'name': "Invalid character", 'selector': ">"}, - {'name': "Invalid ID", 'selector': "#"}, - {'name': "Invalid group of selectors", 'selector': "div,"}, - {'name': "Invalid class", 'selector': "."}, - {'name': "Invalid class", 'selector': ".5cm"}, - {'name': "Invalid class", 'selector': "..test"}, - {'name': "Invalid class", 'selector': ".foo..quux"}, - {'name': "Invalid class", 'selector': ".bar."}, - {'name': "Invalid combinator", 'selector': "div & address, p"}, - {'name': "Invalid combinator", 'selector': "div >> address, p"}, - {'name': "Invalid combinator", 'selector': "div ++ address, p"}, - {'name': "Invalid combinator", 'selector': "div ~~ address, p"}, + {'name': "Empty String", 'selector': ""}, + {'name': "Invalid character", 'selector': "["}, + {'name': "Invalid character", 'selector': "]"}, + {'name': "Invalid character", 'selector': "("}, + {'name': "Invalid character", 'selector': ")"}, + {'name': "Invalid character", 'selector': "{"}, + {'name': "Invalid character", 'selector': "}"}, + {'name': "Invalid character", 'selector': "<"}, + {'name': "Invalid character", 'selector': ">"}, + {'name': "Invalid ID", 'selector': "#"}, + {'name': "Invalid group of selectors", 'selector': "div,"}, + {'name': "Invalid class", 'selector': "."}, + {'name': "Invalid class", 'selector': ".5cm"}, + {'name': "Invalid class", 'selector': "..test"}, + {'name': "Invalid class", 'selector': ".foo..quux"}, + {'name': "Invalid class", 'selector': ".bar."}, + {'name': "Invalid combinator", 'selector': "div & address, p"}, + {'name': "Invalid combinator", 'selector': "div >> address, p"}, + {'name': "Invalid combinator", 'selector': "div ++ address, p"}, + {'name': "Invalid combinator", 'selector': "div ~~ address, p"}, {'name': "Invalid [att=value] selector", 'selector': "[*=test]"}, {'name': "Invalid [att=value] selector", 'selector': "[*|*=test]"}, - {'name': "Invalid [att=value] selector", 'selector': "[class= space unquoted ]"}, - {'name': "Unknown pseudo-class", 'selector': "div:example"}, - {'name': "Unknown pseudo-class", 'selector': ":example"}, - {'name': "Unknown pseudo-element", 'selector': "div::example"}, - {'name': "Unknown pseudo-element", 'selector': "::example"}, - {'name': "Invalid pseudo-element", 'selector': ":::before"}, - {'name': "Undeclared namespace", 'selector': "ns|div"}, - {'name': "Undeclared namespace", 'selector': ":not(ns|div)"}, - {'name': "Invalid namespace", 'selector': "^|div"}, - {'name': "Invalid namespace", 'selector': "\$|div"} + { + 'name': "Invalid [att=value] selector", + 'selector': "[class= space unquoted ]" + }, + {'name': "Unknown pseudo-class", 'selector': "div:example"}, + {'name': "Unknown pseudo-class", 'selector': ":example"}, + {'name': "Unknown pseudo-element", 'selector': "div::example"}, + {'name': "Unknown pseudo-element", 'selector': "::example"}, + {'name': "Invalid pseudo-element", 'selector': ":::before"}, + {'name': "Undeclared namespace", 'selector': "ns|div"}, + {'name': "Undeclared namespace", 'selector': ":not(ns|div)"}, + {'name': "Invalid namespace", 'selector': "^|div"}, + {'name': "Invalid namespace", 'selector': "\$|div"} ]; /* @@ -70,294 +76,1800 @@ var invalidSelectors = [ */ var validSelectors = [ // Type Selector - {'name': "Type selector, matching html element", 'selector': "html", 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Type selector, matching html element", 'selector': "html", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': "Type selector, matching body element", 'selector': "body", 'expect': ["body"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Type selector, matching body element", 'selector': "body", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + { + 'name': "Type selector, matching html element", + 'selector': "html", + 'expect': ["html"], + 'exclude': ["element", "fragment", "detached"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Type selector, matching html element", + 'selector': "html", + 'expect': [] /*no matches*/, + 'exclude': ["document"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Type selector, matching body element", + 'selector': "body", + 'expect': ["body"], + 'exclude': ["element", "fragment", "detached"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Type selector, matching body element", + 'selector': "body", + 'expect': [] /*no matches*/, + 'exclude': ["document"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, // Universal Selector // Testing "*" for entire an entire context node is handled separately. - {'name': "Universal selector, matching all children of element with specified ID", 'selector': "#universal>*", 'expect': ["universal-p1", "universal-hr1", "universal-pre1", "universal-p2", "universal-address1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Universal selector, matching all grandchildren of element with specified ID", 'selector': "#universal>*>*", 'expect': ["universal-code1", "universal-span1", "universal-a1", "universal-code2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Universal selector, matching all children of empty element with specified ID", 'selector': "#empty>*", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Universal selector, matching all descendants of element with specified ID", 'selector': "#universal *", 'expect': ["universal-p1", "universal-code1", "universal-hr1", "universal-pre1", "universal-span1", "universal-p2", "universal-a1", "universal-address1", "universal-code2", "universal-a2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Universal selector, matching all children of element with specified ID", + 'selector': "#universal>*", + 'expect': [ + "universal-p1", + "universal-hr1", + "universal-pre1", + "universal-p2", + "universal-address1" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Universal selector, matching all grandchildren of element with specified ID", + 'selector': "#universal>*>*", + 'expect': [ + "universal-code1", + "universal-span1", + "universal-a1", + "universal-code2" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Universal selector, matching all children of empty element with specified ID", + 'selector': "#empty>*", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Universal selector, matching all descendants of element with specified ID", + 'selector': "#universal *", + 'expect': [ + "universal-p1", + "universal-code1", + "universal-hr1", + "universal-pre1", + "universal-span1", + "universal-p2", + "universal-a1", + "universal-address1", + "universal-code2", + "universal-a2" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // Attribute Selectors // - presence [att] - {'name': "Attribute presence selector, matching align attribute with value", 'selector': ".attr-presence-div1[align]", 'expect': ["attr-presence-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, matching align attribute with empty value", 'selector': ".attr-presence-div2[align]", 'expect': ["attr-presence-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, matching title attribute, case insensitivity", 'selector': "#attr-presence [TiTlE]", 'expect': ["attr-presence-a1", "attr-presence-span1"], 'exclude': ["xhtml"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, not matching title attribute, case sensitivity", 'selector': "#attr-presence [TiTlE]", 'expect': [], 'exclude': ["html"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, matching custom data-* attribute", 'selector': "[data-attr-presence]", 'expect': ["attr-presence-pre1", "attr-presence-blockquote1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, not matching attribute with similar name", 'selector': ".attr-presence-div3[align], .attr-presence-div4[align]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute presence selector, matching attribute with non-ASCII characters", 'selector': "ul[data-中文]", 'expect': ["attr-presence-ul1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, not matching default option without selected attribute", 'selector': "#attr-presence-select1 option[selected]", 'expect': [] /* no matches */, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute presence selector, matching option with selected attribute", 'selector': "#attr-presence-select2 option[selected]", 'expect': ["attr-presence-select2-option4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute presence selector, matching multiple options with selected attributes", 'selector': "#attr-presence-select3 option[selected]", 'expect': ["attr-presence-select3-option2", "attr-presence-select3-option3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "Attribute presence selector, matching align attribute with value", + 'selector': ".attr-presence-div1[align]", + 'expect': ["attr-presence-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, matching align attribute with empty value", + 'selector': ".attr-presence-div2[align]", + 'expect': ["attr-presence-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, matching title attribute, case insensitivity", + 'selector': "#attr-presence [TiTlE]", + 'expect': ["attr-presence-a1", "attr-presence-span1"], + 'exclude': ["xhtml"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, not matching title attribute, case sensitivity", + 'selector': "#attr-presence [TiTlE]", + 'expect': [], + 'exclude': ["html"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Attribute presence selector, matching custom data-* attribute", + 'selector': "[data-attr-presence]", + 'expect': ["attr-presence-pre1", "attr-presence-blockquote1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, not matching attribute with similar name", + 'selector': ".attr-presence-div3[align], .attr-presence-div4[align]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute presence selector, matching attribute with non-ASCII characters", + 'selector': "ul[data-中文]", + 'expect': ["attr-presence-ul1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, not matching default option without selected attribute", + 'selector': "#attr-presence-select1 option[selected]", + 'expect': [] /* no matches */, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute presence selector, matching option with selected attribute", + 'selector': "#attr-presence-select2 option[selected]", + 'expect': ["attr-presence-select2-option4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute presence selector, matching multiple options with selected attributes", + 'selector': "#attr-presence-select3 option[selected]", + 'expect': [ + "attr-presence-select3-option2", + "attr-presence-select3-option3" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - value [att=val] - {'name': "Attribute value selector, matching align attribute with value", 'selector': "#attr-value [align=\"center\"]", 'expect': ["attr-value-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector, matching align attribute with empty value", 'selector': "#attr-value [align=\"\"]", 'expect': ["attr-value-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector, not matching align attribute with partial value", 'selector': "#attr-value [align=\"c\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute value selector, not matching align attribute with incorrect value", 'selector': "#attr-value [align=\"centera\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute value selector, matching custom data-* attribute with unicode escaped value", 'selector': "[data-attr-value=\"\\e9\"]", 'expect': ["attr-value-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector, matching custom data-* attribute with escaped character", 'selector': "[data-attr-value\_foo=\"\\e9\"]", 'expect': ["attr-value-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type='hidden'],#attr-value input[type='radio']", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector with unquoted value, matching multiple inputs with type attributes", 'selector': "#attr-value input[type=hidden],#attr-value input[type=radio]", 'expect': ["attr-value-input3", "attr-value-input4", "attr-value-input6", "attr-value-input8", "attr-value-input9"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute value selector, matching attribute with value using non-ASCII characters", 'selector': "[data-attr-value=中文]", 'expect': ["attr-value-div5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "Attribute value selector, matching align attribute with value", + 'selector': "#attr-value [align=\"center\"]", + 'expect': ["attr-value-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector, matching align attribute with empty value", + 'selector': "#attr-value [align=\"\"]", + 'expect': ["attr-value-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector, not matching align attribute with partial value", + 'selector': "#attr-value [align=\"c\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute value selector, not matching align attribute with incorrect value", + 'selector': "#attr-value [align=\"centera\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute value selector, matching custom data-* attribute with unicode escaped value", + 'selector': "[data-attr-value=\"\\e9\"]", + 'expect': ["attr-value-div3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector, matching custom data-* attribute with escaped character", + 'selector': "[data-attr-value\_foo=\"\\e9\"]", + 'expect': ["attr-value-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", + 'selector': + "#attr-value input[type='hidden'],#attr-value input[type='radio']", + 'expect': [ + "attr-value-input3", + "attr-value-input4", + "attr-value-input6", + "attr-value-input8", + "attr-value-input9" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", + 'selector': + "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", + 'expect': [ + "attr-value-input3", + "attr-value-input4", + "attr-value-input6", + "attr-value-input8", + "attr-value-input9" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector with unquoted value, matching multiple inputs with type attributes", + 'selector': "#attr-value input[type=hidden],#attr-value input[type=radio]", + 'expect': [ + "attr-value-input3", + "attr-value-input4", + "attr-value-input6", + "attr-value-input8", + "attr-value-input9" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute value selector, matching attribute with value using non-ASCII characters", + 'selector': "[data-attr-value=中文]", + 'expect': ["attr-value-div5"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - whitespace-separated list [att~=val] - {'name': "Attribute whitespace-separated list selector, matching class attribute with value", 'selector': "#attr-whitespace [class~=\"div1\"]", 'expect': ["attr-whitespace-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector, not matching class attribute with empty value", 'selector': "#attr-whitespace [class~=\"\"]", 'expect': [] /*no matches*/ , 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute whitespace-separated list selector, not matching class attribute with partial value", 'selector': "[data-attr-whitespace~=\"div\"]", 'expect': [] /*no matches*/ , 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", 'selector': "[data-attr-whitespace~=\"\\0000e9\"]", 'expect': ["attr-whitespace-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", 'selector': "[data-attr-whitespace\_foo~=\"\\e9\"]", 'expect': ["attr-whitespace-div5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", 'selector': "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", 'expect': ["attr-whitespace-a1", "attr-whitespace-a2", "attr-whitespace-a3", "attr-whitespace-a5", "attr-whitespace-a7"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", 'selector': "#attr-whitespace a[rel~=\"book mark\"]", 'expect': [] /* no matches */, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", 'selector': "#attr-whitespace [title~=中文]", 'expect': ["attr-whitespace-p1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Attribute whitespace-separated list selector, matching class attribute with value", + 'selector': "#attr-whitespace [class~=\"div1\"]", + 'expect': ["attr-whitespace-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector, not matching class attribute with empty value", + 'selector': "#attr-whitespace [class~=\"\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector, not matching class attribute with partial value", + 'selector': "[data-attr-whitespace~=\"div\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", + 'selector': "[data-attr-whitespace~=\"\\0000e9\"]", + 'expect': ["attr-whitespace-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", + 'selector': "[data-attr-whitespace\_foo~=\"\\e9\"]", + 'expect': ["attr-whitespace-div5"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", + 'selector': + "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", + 'expect': [ + "attr-whitespace-a1", + "attr-whitespace-a2", + "attr-whitespace-a3", + "attr-whitespace-a5", + "attr-whitespace-a7" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", + 'selector': + "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", + 'expect': [ + "attr-whitespace-a1", + "attr-whitespace-a2", + "attr-whitespace-a3", + "attr-whitespace-a5", + "attr-whitespace-a7" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", + 'selector': + "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", + 'expect': [ + "attr-whitespace-a1", + "attr-whitespace-a2", + "attr-whitespace-a3", + "attr-whitespace-a5", + "attr-whitespace-a7" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", + 'selector': "#attr-whitespace a[rel~=\"book mark\"]", + 'expect': [] /* no matches */, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", + 'selector': "#attr-whitespace [title~=中文]", + 'expect': ["attr-whitespace-p1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - hyphen-separated list [att|=val] - {'name': "Attribute hyphen-separated list selector, not matching unspecified lang attribute", 'selector': "#attr-hyphen-div1[lang|=\"en\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Attribute hyphen-separated list selector, matching lang attribute with exact value", 'selector': "#attr-hyphen-div2[lang|=\"fr\"]", 'expect': ["attr-hyphen-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute hyphen-separated list selector, matching lang attribute with partial value", 'selector': "#attr-hyphen-div3[lang|=\"en\"]", 'expect': ["attr-hyphen-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Attribute hyphen-separated list selector, not matching incorrect value", 'selector': "#attr-hyphen-div4[lang|=\"es-AR\"]", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + { + 'name': + "Attribute hyphen-separated list selector, not matching unspecified lang attribute", + 'selector': "#attr-hyphen-div1[lang|=\"en\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Attribute hyphen-separated list selector, matching lang attribute with exact value", + 'selector': "#attr-hyphen-div2[lang|=\"fr\"]", + 'expect': ["attr-hyphen-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute hyphen-separated list selector, matching lang attribute with partial value", + 'selector': "#attr-hyphen-div3[lang|=\"en\"]", + 'expect': ["attr-hyphen-div3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute hyphen-separated list selector, not matching incorrect value", + 'selector': "#attr-hyphen-div4[lang|=\"es-AR\"]", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, // - substring begins-with [att^=val] (Level 3) - {'name': "Attribute begins with selector, matching href attributes beginning with specified substring", 'selector': "#attr-begins a[href^=\"http://www\"]", 'expect': ["attr-begins-a1", "attr-begins-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute begins with selector, matching lang attributes beginning with specified substring, ", 'selector': "#attr-begins [lang^=\"en-\"]", 'expect': ["attr-begins-div2", "attr-begins-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute begins with selector, not matching class attribute not beginning with specified substring", 'selector': "#attr-begins [class^=apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-begins [class^=' apple']", 'expect': ["attr-begins-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-begins [class^=\" apple\"]", 'expect': ["attr-begins-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", 'selector': "#attr-begins [class^= apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + "Attribute begins with selector, matching href attributes beginning with specified substring", + 'selector': "#attr-begins a[href^=\"http://www\"]", + 'expect': ["attr-begins-a1", "attr-begins-a3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute begins with selector, matching lang attributes beginning with specified substring, ", + 'selector': "#attr-begins [lang^=\"en-\"]", + 'expect': ["attr-begins-div2", "attr-begins-div4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute begins with selector, not matching class attribute not beginning with specified substring", + 'selector': "#attr-begins [class^=apple]", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': + "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", + 'selector': "#attr-begins [class^=' apple']", + 'expect': ["attr-begins-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", + 'selector': "#attr-begins [class^=\" apple\"]", + 'expect': ["attr-begins-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", + 'selector': "#attr-begins [class^= apple]", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - substring ends-with [att\$=val] (Level 3) - {'name': "Attribute ends with selector, matching href attributes ending with specified substring", 'selector': "#attr-ends a[href\$=\".org\"]", 'expect': ["attr-ends-a1", "attr-ends-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute ends with selector, matching lang attributes ending with specified substring, ", 'selector': "#attr-ends [lang\$=\"-CH\"]", 'expect': ["attr-ends-div2", "attr-ends-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute ends with selector, not matching class attribute not ending with specified substring", 'selector': "#attr-ends [class\$=apple]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-ends [class\$='apple ']", 'expect': ["attr-ends-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-ends [class\$=\"apple \"]", 'expect': ["attr-ends-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", 'selector': "#attr-ends [class\$=apple ]", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + "Attribute ends with selector, matching href attributes ending with specified substring", + 'selector': "#attr-ends a[href\$=\".org\"]", + 'expect': ["attr-ends-a1", "attr-ends-a3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute ends with selector, matching lang attributes ending with specified substring, ", + 'selector': "#attr-ends [lang\$=\"-CH\"]", + 'expect': ["attr-ends-div2", "attr-ends-div4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute ends with selector, not matching class attribute not ending with specified substring", + 'selector': "#attr-ends [class\$=apple]", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': + "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", + 'selector': "#attr-ends [class\$='apple ']", + 'expect': ["attr-ends-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", + 'selector': "#attr-ends [class\$=\"apple \"]", + 'expect': ["attr-ends-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", + 'selector': "#attr-ends [class\$=apple ]", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - substring contains [att*=val] (Level 3) - {'name': "Attribute contains selector, matching href attributes beginning with specified substring", 'selector': "#attr-contains a[href*=\"http://www\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector, matching href attributes ending with specified substring", 'selector': "#attr-contains a[href*=\".org\"]", 'expect': ["attr-contains-a1", "attr-contains-a2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector, matching href attributes containing specified substring", 'selector': "#attr-contains a[href*=\".example.\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector, matching lang attributes beginning with specified substring, ", 'selector': "#attr-contains [lang*=\"en-\"]", 'expect': ["attr-contains-div2", "attr-contains-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector, matching lang attributes ending with specified substring, ", 'selector': "#attr-contains [lang*=\"-CH\"]", 'expect': ["attr-contains-div3", "attr-contains-div5"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*=' apple']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*='orange ']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*='ple banana ora']", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*=\" apple\"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*=\"orange \"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*=\"ple banana ora\"]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", 'selector': "#attr-contains [class*= apple]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", 'selector': "#attr-contains [class*=orange ]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "Attribute contains selector with unquoted value, matching class attribute containing specified substring", 'selector': "#attr-contains [class*= banana ]", 'expect': ["attr-contains-p1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + "Attribute contains selector, matching href attributes beginning with specified substring", + 'selector': "#attr-contains a[href*=\"http://www\"]", + 'expect': ["attr-contains-a1", "attr-contains-a3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector, matching href attributes ending with specified substring", + 'selector': "#attr-contains a[href*=\".org\"]", + 'expect': ["attr-contains-a1", "attr-contains-a2"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector, matching href attributes containing specified substring", + 'selector': "#attr-contains a[href*=\".example.\"]", + 'expect': ["attr-contains-a1", "attr-contains-a3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector, matching lang attributes beginning with specified substring, ", + 'selector': "#attr-contains [lang*=\"en-\"]", + 'expect': ["attr-contains-div2", "attr-contains-div6"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector, matching lang attributes ending with specified substring, ", + 'selector': "#attr-contains [lang*=\"-CH\"]", + 'expect': ["attr-contains-div3", "attr-contains-div5"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", + 'selector': "#attr-contains [class*=' apple']", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", + 'selector': "#attr-contains [class*='orange ']", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", + 'selector': "#attr-contains [class*='ple banana ora']", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", + 'selector': "#attr-contains [class*=\" apple\"]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", + 'selector': "#attr-contains [class*=\"orange \"]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", + 'selector': "#attr-contains [class*=\"ple banana ora\"]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", + 'selector': "#attr-contains [class*= apple]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", + 'selector': "#attr-contains [class*=orange ]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "Attribute contains selector with unquoted value, matching class attribute containing specified substring", + 'selector': "#attr-contains [class*= banana ]", + 'expect': ["attr-contains-p1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // Pseudo-classes // - :root (Level 3) - {'name': ":root pseudo-class selector, matching document root element", 'selector': ":root", 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":root pseudo-class selector, not matching document root element", 'selector': ":root", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': ":root pseudo-class selector, matching document root element", + 'selector': ":root", + 'expect': ["html"], + 'exclude': ["element", "fragment", "detached"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': ":root pseudo-class selector, not matching document root element", + 'selector': ":root", + 'expect': [] /*no matches*/, + 'exclude': ["document"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - :nth-child(n) (Level 3) - {'name': ":nth-child selector, matching the third child element", 'selector': "#pseudo-nth-table1 :nth-child(3)", 'expect': ["pseudo-nth-td3", "pseudo-nth-td9", "pseudo-nth-tr3", "pseudo-nth-td15"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-child selector, matching every third child element", 'selector': "#pseudo-nth li:nth-child(3n)", 'expect': ["pseudo-nth-li3", "pseudo-nth-li6", "pseudo-nth-li9", "pseudo-nth-li12"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-child selector, matching every second child element, starting from the fourth", 'selector': "#pseudo-nth li:nth-child(2n+4)", 'expect': ["pseudo-nth-li4", "pseudo-nth-li6", "pseudo-nth-li8", "pseudo-nth-li10", "pseudo-nth-li12"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-child selector, matching every fourth child element, starting from the third", 'selector': "#pseudo-nth-p1 :nth-child(4n-1)", 'expect': ["pseudo-nth-em2", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":nth-child selector, matching the third child element", + 'selector': "#pseudo-nth-table1 :nth-child(3)", + 'expect': [ + "pseudo-nth-td3", + "pseudo-nth-td9", + "pseudo-nth-tr3", + "pseudo-nth-td15" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': ":nth-child selector, matching every third child element", + 'selector': "#pseudo-nth li:nth-child(3n)", + 'expect': [ + "pseudo-nth-li3", + "pseudo-nth-li6", + "pseudo-nth-li9", + "pseudo-nth-li12" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-child selector, matching every second child element, starting from the fourth", + 'selector': "#pseudo-nth li:nth-child(2n+4)", + 'expect': [ + "pseudo-nth-li4", + "pseudo-nth-li6", + "pseudo-nth-li8", + "pseudo-nth-li10", + "pseudo-nth-li12" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-child selector, matching every fourth child element, starting from the third", + 'selector': "#pseudo-nth-p1 :nth-child(4n-1)", + 'expect': ["pseudo-nth-em2", "pseudo-nth-span3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :nth-last-child (Level 3) - {'name': ":nth-last-child selector, matching the third last child element", 'selector': "#pseudo-nth-table1 :nth-last-child(3)", 'expect': ["pseudo-nth-tr1", "pseudo-nth-td4", "pseudo-nth-td10", "pseudo-nth-td16"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-last-child selector, matching every third child element from the end", 'selector': "#pseudo-nth li:nth-last-child(3n)", 'expect': ["pseudo-nth-li1", "pseudo-nth-li4", "pseudo-nth-li7", "pseudo-nth-li10"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", 'selector': "#pseudo-nth li:nth-last-child(2n+4)", 'expect': ["pseudo-nth-li1", "pseudo-nth-li3", "pseudo-nth-li5", "pseudo-nth-li7", "pseudo-nth-li9"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-last-child selector, matching every fourth element from the end, starting from the third last", 'selector': "#pseudo-nth-p1 :nth-last-child(4n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":nth-last-child selector, matching the third last child element", + 'selector': "#pseudo-nth-table1 :nth-last-child(3)", + 'expect': [ + "pseudo-nth-tr1", + "pseudo-nth-td4", + "pseudo-nth-td10", + "pseudo-nth-td16" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-last-child selector, matching every third child element from the end", + 'selector': "#pseudo-nth li:nth-last-child(3n)", + 'expect': [ + "pseudo-nth-li1", + "pseudo-nth-li4", + "pseudo-nth-li7", + "pseudo-nth-li10" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", + 'selector': "#pseudo-nth li:nth-last-child(2n+4)", + 'expect': [ + "pseudo-nth-li1", + "pseudo-nth-li3", + "pseudo-nth-li5", + "pseudo-nth-li7", + "pseudo-nth-li9" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-last-child selector, matching every fourth element from the end, starting from the third last", + 'selector': "#pseudo-nth-p1 :nth-last-child(4n-1)", + 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :nth-of-type(n) (Level 3) - {'name': ":nth-of-type selector, matching the third em element", 'selector': "#pseudo-nth-p1 em:nth-of-type(3)", 'expect': ["pseudo-nth-em3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-of-type selector, matching every second element of their type", 'selector': "#pseudo-nth-p1 :nth-of-type(2n)", 'expect': ["pseudo-nth-em2", "pseudo-nth-span2", "pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-of-type selector, matching every second elemetn of their type, starting from the first", 'selector': "#pseudo-nth-p1 span:nth-of-type(2n-1)", 'expect': ["pseudo-nth-span1", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":nth-of-type selector, matching the third em element", + 'selector': "#pseudo-nth-p1 em:nth-of-type(3)", + 'expect': ["pseudo-nth-em3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-of-type selector, matching every second element of their type", + 'selector': "#pseudo-nth-p1 :nth-of-type(2n)", + 'expect': [ + "pseudo-nth-em2", + "pseudo-nth-span2", + "pseudo-nth-span4", + "pseudo-nth-strong2", + "pseudo-nth-em4" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-of-type selector, matching every second elemetn of their type, starting from the first", + 'selector': "#pseudo-nth-p1 span:nth-of-type(2n-1)", + 'expect': ["pseudo-nth-span1", "pseudo-nth-span3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :nth-last-of-type(n) (Level 3) - {'name': ":nth-last-of-type selector, matching the thrid last em element", 'selector': "#pseudo-nth-p1 em:nth-last-of-type(3)", 'expect': ["pseudo-nth-em2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-last-of-type selector, matching every second last element of their type", 'selector': "#pseudo-nth-p1 :nth-last-of-type(2n)", 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1", "pseudo-nth-em3", "pseudo-nth-span3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":nth-last-of-type selector, matching every second last element of their type, starting from the last", 'selector': "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":nth-last-of-type selector, matching the thrid last em element", + 'selector': "#pseudo-nth-p1 em:nth-last-of-type(3)", + 'expect': ["pseudo-nth-em2"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-last-of-type selector, matching every second last element of their type", + 'selector': "#pseudo-nth-p1 :nth-last-of-type(2n)", + 'expect': [ + "pseudo-nth-span1", + "pseudo-nth-em1", + "pseudo-nth-strong1", + "pseudo-nth-em3", + "pseudo-nth-span3" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":nth-last-of-type selector, matching every second last element of their type, starting from the last", + 'selector': "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", + 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :first-of-type (Level 3) - {'name': ":first-of-type selector, matching the first em element", 'selector': "#pseudo-nth-p1 em:first-of-type", 'expect': ["pseudo-nth-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":first-of-type selector, matching the first of every type of element", 'selector': "#pseudo-nth-p1 :first-of-type", 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":first-of-type selector, matching the first td element in each table row", 'selector': "#pseudo-nth-table1 tr :first-of-type", 'expect': ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":first-of-type selector, matching the first em element", + 'selector': "#pseudo-nth-p1 em:first-of-type", + 'expect': ["pseudo-nth-em1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":first-of-type selector, matching the first of every type of element", + 'selector': "#pseudo-nth-p1 :first-of-type", + 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":first-of-type selector, matching the first td element in each table row", + 'selector': "#pseudo-nth-table1 tr :first-of-type", + 'expect': ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :last-of-type (Level 3) - {'name': ":last-of-type selector, matching the last em elemnet", 'selector': "#pseudo-nth-p1 em:last-of-type", 'expect': ["pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":last-of-type selector, matching the last of every type of element", 'selector': "#pseudo-nth-p1 :last-of-type", 'expect': ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":last-of-type selector, matching the last td element in each table row", 'selector': "#pseudo-nth-table1 tr :last-of-type", 'expect': ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":last-of-type selector, matching the last em elemnet", + 'selector': "#pseudo-nth-p1 em:last-of-type", + 'expect': ["pseudo-nth-em4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":last-of-type selector, matching the last of every type of element", + 'selector': "#pseudo-nth-p1 :last-of-type", + 'expect': ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":last-of-type selector, matching the last td element in each table row", + 'selector': "#pseudo-nth-table1 tr :last-of-type", + 'expect': ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :first-child - {'name': ":first-child pseudo-class selector, matching first child div element", 'selector': "#pseudo-first-child div:first-child", 'expect': ["pseudo-first-child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":first-child pseudo-class selector, doesn't match non-first-child elements", 'selector': ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': ":first-child pseudo-class selector, matching first-child of multiple elements", 'selector': "#pseudo-first-child span:first-child", 'expect': ["pseudo-first-child-span1", "pseudo-first-child-span3", "pseudo-first-child-span5"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + ":first-child pseudo-class selector, matching first child div element", + 'selector': "#pseudo-first-child div:first-child", + 'expect': ["pseudo-first-child-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + ":first-child pseudo-class selector, doesn't match non-first-child elements", + 'selector': + ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + ":first-child pseudo-class selector, matching first-child of multiple elements", + 'selector': "#pseudo-first-child span:first-child", + 'expect': [ + "pseudo-first-child-span1", + "pseudo-first-child-span3", + "pseudo-first-child-span5" + ], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - :last-child (Level 3) - {'name': ":last-child pseudo-class selector, matching last child div element", 'selector': "#pseudo-last-child div:last-child", 'expect': ["pseudo-last-child-div3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":last-child pseudo-class selector, doesn't match non-last-child elements", 'selector': ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': ":last-child pseudo-class selector, matching first-child of multiple elements", 'selector': "#pseudo-last-child span:last-child", 'expect': ["pseudo-last-child-span2", "pseudo-last-child-span4", "pseudo-last-child-span6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":last-child pseudo-class selector, matching last child div element", + 'selector': "#pseudo-last-child div:last-child", + 'expect': ["pseudo-last-child-div3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":last-child pseudo-class selector, doesn't match non-last-child elements", + 'selector': + ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': + ":last-child pseudo-class selector, matching first-child of multiple elements", + 'selector': "#pseudo-last-child span:last-child", + 'expect': [ + "pseudo-last-child-span2", + "pseudo-last-child-span4", + "pseudo-last-child-span6" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :only-child (Level 3) - {'name': ":pseudo-only-child pseudo-class selector, matching all only-child elements", 'selector': "#pseudo-only :only-child", 'expect': ["pseudo-only-span1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":pseudo-only-child pseudo-class selector, matching only-child em elements", 'selector': "#pseudo-only em:only-child", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + ":pseudo-only-child pseudo-class selector, matching all only-child elements", + 'selector': "#pseudo-only :only-child", + 'expect': ["pseudo-only-span1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":pseudo-only-child pseudo-class selector, matching only-child em elements", + 'selector': "#pseudo-only em:only-child", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - :only-of-type (Level 3) - {'name': ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", 'selector': "#pseudo-only :only-of-type", 'expect': ["pseudo-only-span1", "pseudo-only-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", 'selector': "#pseudo-only em:only-of-type", 'expect': ["pseudo-only-em1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", + 'selector': "#pseudo-only :only-of-type", + 'expect': ["pseudo-only-span1", "pseudo-only-em1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", + 'selector': "#pseudo-only em:only-of-type", + 'expect': ["pseudo-only-em1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :empty (Level 3) - {'name': ":empty pseudo-class selector, matching empty p elements", 'selector': "#pseudo-empty p:empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":empty pseudo-class selector, matching all empty elements", 'selector': "#pseudo-empty :empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': ":empty pseudo-class selector, matching empty p elements", + 'selector': "#pseudo-empty p:empty", + 'expect': ["pseudo-empty-p1", "pseudo-empty-p2"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': ":empty pseudo-class selector, matching all empty elements", + 'selector': "#pseudo-empty :empty", + 'expect': ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :link and :visited // Implementations may treat all visited links as unvisited, so these cannot be tested separately. // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. - {'name': ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", 'selector': "#pseudo-link :link, #pseudo-link :visited", 'expect': ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":link and :visited pseudo-class selectors, matching link elements with href attributes", 'selector': "#head :link, #head :visited", 'expect': ["pseudo-link-link1", "pseudo-link-link2"], 'exclude': ["element", "fragment", "detached"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":link and :visited pseudo-class selectors, not matching link elements with href attributes", 'selector': "#head :link, #head :visited", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", 'selector': ":link:visited", 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + { + 'name': + ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", + 'selector': "#pseudo-link :link, #pseudo-link :visited", + 'expect': ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + ":link and :visited pseudo-class selectors, matching link elements with href attributes", + 'selector': "#head :link, #head :visited", + 'expect': ["pseudo-link-link1", "pseudo-link-link2"], + 'exclude': ["element", "fragment", "detached"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + ":link and :visited pseudo-class selectors, not matching link elements with href attributes", + 'selector': "#head :link, #head :visited", + 'expect': [] /*no matches*/, + 'exclude': ["document"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", + 'selector': ":link:visited", + 'expect': [] /*no matches*/, + 'exclude': ["document"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, // - :target (Level 3) - {'name': ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", 'selector': ":target", 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", 'selector': ":target", 'expect': ["target"], 'exclude': ["fragment", "detached"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", + 'selector': ":target", + 'expect': [] /*no matches*/, + 'exclude': ["document", "element"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': + ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", + 'selector': ":target", + 'expect': ["target"], + 'exclude': ["fragment", "detached"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :lang() - {'name': ":lang pseudo-class selector, matching inherited language", 'selector': "#pseudo-lang-div1:lang(en)", 'expect': ["pseudo-lang-div1"], 'exclude': ["detached", "fragment"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":lang pseudo-class selector, not matching element with no inherited language", 'selector': "#pseudo-lang-div1:lang(en)", 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': ":lang pseudo-class selector, matching specified language with exact value", 'selector': "#pseudo-lang-div2:lang(fr)", 'expect': ["pseudo-lang-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":lang pseudo-class selector, matching specified language with partial value", 'selector': "#pseudo-lang-div3:lang(en)", 'expect': ["pseudo-lang-div3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': ":lang pseudo-class selector, not matching incorrect language", 'selector': "#pseudo-lang-div4:lang(es-AR)", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, + { + 'name': ":lang pseudo-class selector, matching inherited language", + 'selector': "#pseudo-lang-div1:lang(en)", + 'expect': ["pseudo-lang-div1"], + 'exclude': ["detached", "fragment"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + ":lang pseudo-class selector, not matching element with no inherited language", + 'selector': "#pseudo-lang-div1:lang(en)", + 'expect': [] /*no matches*/, + 'exclude': ["document", "element"], + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + ":lang pseudo-class selector, matching specified language with exact value", + 'selector': "#pseudo-lang-div2:lang(fr)", + 'expect': ["pseudo-lang-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + ":lang pseudo-class selector, matching specified language with partial value", + 'selector': "#pseudo-lang-div3:lang(en)", + 'expect': ["pseudo-lang-div3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': ":lang pseudo-class selector, not matching incorrect language", + 'selector': "#pseudo-lang-div4:lang(es-AR)", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, // - :enabled (Level 3) - {'name': ":enabled pseudo-class selector, matching all enabled form controls", 'selector': "#pseudo-ui :enabled", 'expect': ["pseudo-ui-input1", "pseudo-ui-input2", "pseudo-ui-input3", "pseudo-ui-input4", "pseudo-ui-input5", "pseudo-ui-input6", - "pseudo-ui-input7", "pseudo-ui-input8", "pseudo-ui-input9", "pseudo-ui-textarea1", "pseudo-ui-button1"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":enabled pseudo-class selector, matching all enabled form controls", + 'selector': "#pseudo-ui :enabled", + 'expect': [ + "pseudo-ui-input1", + "pseudo-ui-input2", + "pseudo-ui-input3", + "pseudo-ui-input4", + "pseudo-ui-input5", + "pseudo-ui-input6", + "pseudo-ui-input7", + "pseudo-ui-input8", + "pseudo-ui-input9", + "pseudo-ui-textarea1", + "pseudo-ui-button1" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :disabled (Level 3) - {'name': ":enabled pseudo-class selector, matching all disabled form controls", 'selector': "#pseudo-ui :disabled", 'expect': ["pseudo-ui-input10", "pseudo-ui-input11", "pseudo-ui-input12", "pseudo-ui-input13", "pseudo-ui-input14", "pseudo-ui-input15", - "pseudo-ui-input16", "pseudo-ui-input17", "pseudo-ui-input18", "pseudo-ui-textarea2", "pseudo-ui-button2"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":enabled pseudo-class selector, matching all disabled form controls", + 'selector': "#pseudo-ui :disabled", + 'expect': [ + "pseudo-ui-input10", + "pseudo-ui-input11", + "pseudo-ui-input12", + "pseudo-ui-input13", + "pseudo-ui-input14", + "pseudo-ui-input15", + "pseudo-ui-input16", + "pseudo-ui-input17", + "pseudo-ui-input18", + "pseudo-ui-textarea2", + "pseudo-ui-button2" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :checked (Level 3) - {'name': ":checked pseudo-class selector, matching checked radio buttons and checkboxes", 'selector': "#pseudo-ui :checked", 'expect': ["pseudo-ui-input4", "pseudo-ui-input6", "pseudo-ui-input13", "pseudo-ui-input15"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + ":checked pseudo-class selector, matching checked radio buttons and checkboxes", + 'selector': "#pseudo-ui :checked", + 'expect': [ + "pseudo-ui-input4", + "pseudo-ui-input6", + "pseudo-ui-input13", + "pseudo-ui-input15" + ], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // - :not(s) (Level 3) - {'name': ":not pseudo-class selector, matching ", 'selector': "#not>:not(div)", 'expect': ["not-p1", "not-p2", "not-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":not pseudo-class selector, matching ", 'selector': "#not * :not(:first-child)", 'expect': ["not-em1", "not-em2", "not-em3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*)", 'expect': [] /* no matches */, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*|*)", 'expect': [] /* no matches */, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': ":not pseudo-class selector, matching ", + 'selector': "#not>:not(div)", + 'expect': ["not-p1", "not-p2", "not-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': ":not pseudo-class selector, matching ", + 'selector': "#not * :not(:first-child)", + 'expect': ["not-em1", "not-em2", "not-em3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': ":not pseudo-class selector, matching nothing", + 'selector': ":not(*)", + 'expect': [] /* no matches */, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': ":not pseudo-class selector, matching nothing", + 'selector': ":not(*|*)", + 'expect': [] /* no matches */, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // Pseudo-elements // - ::first-line - {'name': ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:first-line", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::first-line", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element:first-line", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element::first-line", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - ::first-letter - {'name': ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:first-letter", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::first-letter", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element:first-letter", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element::first-letter", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - ::before - {'name': ":before pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:before", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "::before pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::before", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + ":before pseudo-element (one-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element:before", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "::before pseudo-element (two-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element::before", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // - ::after - {'name': ":after pseudo-element (one-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element:after", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "::after pseudo-element (two-colon syntax) selector, not matching any elements", 'selector': "#pseudo-element::after", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, + { + 'name': + ":after pseudo-element (one-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element:after", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "::after pseudo-element (two-colon syntax) selector, not matching any elements", + 'selector': "#pseudo-element::after", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, // Class Selectors - {'name': "Class selector, matching element with specified class", 'selector': ".class-p", 'expect': ["class-p1","class-p2", "class-p3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class selector, chained, matching only elements with all specified classes", 'selector': "#class .apple.orange.banana", 'expect': ["class-div1", "class-div2", "class-p4", "class-div3", "class-p6", "class-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class Selector, chained, with type selector", 'selector': "div.apple.banana.orange", 'expect': ["class-div1", "class-div2", "class-div3", "class-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "Class selector, matching element with specified class", + 'selector': ".class-p", + 'expect': ["class-p1", "class-p2", "class-p3"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Class selector, chained, matching only elements with all specified classes", + 'selector': "#class .apple.orange.banana", + 'expect': [ + "class-div1", + "class-div2", + "class-p4", + "class-div3", + "class-p6", + "class-div4" + ], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Class Selector, chained, with type selector", + 'selector': "div.apple.banana.orange", + 'expect': ["class-div1", "class-div2", "class-div3", "class-div4"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process. - {'name': "Class selector, matching element with class value using non-ASCII characters", 'selector': ".台北Táiběi", 'expect': ["class-span1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class selector, matching multiple elements with class value using non-ASCII characters", 'selector': ".台北", 'expect': ["class-span1","class-span2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class selector, chained, matching element with multiple class values using non-ASCII characters", 'selector': ".台北Táiběi.台北", 'expect': ["class-span1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class selector, matching element with class with escaped character", 'selector': ".foo\\:bar", 'expect': ["class-span3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Class selector, matching element with class with escaped character", 'selector': ".test\\.foo\\[5\\]bar", 'expect': ["class-span4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Class selector, matching element with class value using non-ASCII characters", + 'selector': ".台北Táiběi", + 'expect': ["class-span1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Class selector, matching multiple elements with class value using non-ASCII characters", + 'selector': ".台北", + 'expect': ["class-span1", "class-span2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Class selector, chained, matching element with multiple class values using non-ASCII characters", + 'selector': ".台北Táiběi.台北", + 'expect': ["class-span1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Class selector, matching element with class with escaped character", + 'selector': ".foo\\:bar", + 'expect': ["class-span3"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Class selector, matching element with class with escaped character", + 'selector': ".test\\.foo\\[5\\]bar", + 'expect': ["class-span4"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // ID Selectors - {'name': "ID selector, matching element with specified id", 'selector': "#id #id-div1", 'expect': ["id-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div1", 'expect': ["id-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID Selector, chained, with type selector", 'selector': "div#id-div1, div#id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID selector, not matching non-existent descendant", 'selector': "#id #none", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': "ID selector, not matching non-existent ancestor", 'selector': "#none #id-div1", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': "ID selector, matching multiple elements with duplicate id", 'selector': "#id-li-duplicate", 'expect': ["id-li-duplicate", "id-li-duplicate", "id-li-duplicate", "id-li-duplicate"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "ID selector, matching element with specified id", + 'selector': "#id #id-div1", + 'expect': ["id-div1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID selector, chained, matching element with specified id", + 'selector': "#id-div1, #id-div1", + 'expect': ["id-div1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID selector, chained, matching element with specified id", + 'selector': "#id-div1, #id-div2", + 'expect': ["id-div1", "id-div2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID Selector, chained, with type selector", + 'selector': "div#id-div1, div#id-div2", + 'expect': ["id-div1", "id-div2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID selector, not matching non-existent descendant", + 'selector': "#id #none", + 'expect': [] /*no matches*/, + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "ID selector, not matching non-existent ancestor", + 'selector': "#none #id-div1", + 'expect': [] /*no matches*/, + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "ID selector, matching multiple elements with duplicate id", + 'selector': "#id-li-duplicate", + 'expect': [ + "id-li-duplicate", + "id-li-duplicate", + "id-li-duplicate", + "id-li-duplicate" + ], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process. - {'name': "ID selector, matching id value using non-ASCII characters", 'selector': "#台北Táiběi", 'expect': ["台北Táiběi"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID selector, matching id value using non-ASCII characters", 'selector': "#台北", 'expect': ["台北"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "ID selector, matching id values using non-ASCII characters", 'selector': "#台北Táiběi, #台北", 'expect': ["台北Táiběi", "台北"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "ID selector, matching id value using non-ASCII characters", + 'selector': "#台北Táiběi", + 'expect': ["台北Táiběi"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID selector, matching id value using non-ASCII characters", + 'selector': "#台北", + 'expect': ["台北"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "ID selector, matching id values using non-ASCII characters", + 'selector': "#台北Táiběi, #台北", + 'expect': ["台北Táiběi", "台北"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values - {'name': "ID selector, matching element with id with escaped character", 'selector': "#\\#foo\\:bar", 'expect': ["#foo:bar"], 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': "ID selector, matching element with id with escaped character", 'selector': "#test\\.foo\\[5\\]bar", 'expect': ["test.foo[5]bar"], 'level': 1, 'testType': TEST_QSA_BASELINE}, + { + 'name': "ID selector, matching element with id with escaped character", + 'selector': "#\\#foo\\:bar", + 'expect': ["#foo:bar"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "ID selector, matching element with id with escaped character", + 'selector': "#test\\.foo\\[5\\]bar", + 'expect': ["test.foo[5]bar"], + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, // Namespaces // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id - {'name': "Namespace selector, matching element with any namespace", 'selector': "#any-namespace *|div", 'expect': ["any-namespace-div1", "any-namespace-div2", "any-namespace-div3", "any-namespace-div4"], 'level': 3, 'testType': TEST_QSA_BASELINE}, - {'name': "Namespace selector, matching div elements in no namespace only", 'selector': "#no-namespace |div", 'expect': ["no-namespace-div3"], 'level': 3, 'testType': TEST_QSA_BASELINE}, - {'name': "Namespace selector, matching any elements in no namespace only", 'selector': "#no-namespace |*", 'expect': ["no-namespace-div3"], 'level': 3, 'testType': TEST_QSA_BASELINE}, + { + 'name': "Namespace selector, matching element with any namespace", + 'selector': "#any-namespace *|div", + 'expect': [ + "any-namespace-div1", + "any-namespace-div2", + "any-namespace-div3", + "any-namespace-div4" + ], + 'level': 3, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Namespace selector, matching div elements in no namespace only", + 'selector': "#no-namespace |div", + 'expect': ["no-namespace-div3"], + 'level': 3, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Namespace selector, matching any elements in no namespace only", + 'selector': "#no-namespace |*", + 'expect': ["no-namespace-div3"], + 'level': 3, + 'testType': TEST_QSA_BASELINE + }, // Combinators // - Descendant combinator ' ' - {'name': "Descendant combinator, matching element that is a descendant of an element with id", 'selector': "#descendant div", 'expect': ["descendant-div1", "descendant-div2", "descendant-div3", "descendant-div4"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, matching element with id that is a descendant of an element", 'selector': "body #descendant-div1", 'expect': ["descendant-div1"], 'exclude': ["detached", "fragment"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, matching element with id that is a descendant of an element", 'selector': "div #descendant-div1", 'expect': ["descendant-div1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, matching element with id that is a descendant of an element with id", 'selector': "#descendant #descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, matching element with class that is a descendant of an element with id", 'selector': "#descendant .descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, matching element with class that is a descendant of an element with class", 'selector': ".descendant-div1 .descendant-div3", 'expect': ["descendant-div3"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Descendant combinator, not matching element with id that is not a descendant of an element with id", 'selector': "#descendant-div1 #descendant-div4", 'expect': [] /*no matches*/, 'level': 1, 'testType': TEST_QSA_BASELINE}, - {'name': "Descendant combinator, whitespace characters", 'selector': "#descendant\t\r\n#descendant-div2", 'expect': ["descendant-div2"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Descendant combinator, matching element that is a descendant of an element with id", + 'selector': "#descendant div", + 'expect': [ + "descendant-div1", + "descendant-div2", + "descendant-div3", + "descendant-div4" + ], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, matching element with id that is a descendant of an element", + 'selector': "body #descendant-div1", + 'expect': ["descendant-div1"], + 'exclude': ["detached", "fragment"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, matching element with id that is a descendant of an element", + 'selector': "div #descendant-div1", + 'expect': ["descendant-div1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, matching element with id that is a descendant of an element with id", + 'selector': "#descendant #descendant-div2", + 'expect': ["descendant-div2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, matching element with class that is a descendant of an element with id", + 'selector': "#descendant .descendant-div2", + 'expect': ["descendant-div2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, matching element with class that is a descendant of an element with class", + 'selector': ".descendant-div1 .descendant-div3", + 'expect': ["descendant-div3"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Descendant combinator, not matching element with id that is not a descendant of an element with id", + 'selector': "#descendant-div1 #descendant-div4", + 'expect': [] /*no matches*/, + 'level': 1, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Descendant combinator, whitespace characters", + 'selector': "#descendant\t\r\n#descendant-div2", + 'expect': ["descendant-div2"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - Child combinator '>' - {'name': "Child combinator, matching element that is a child of an element with id", 'selector': "#child>div", 'expect': ["child-div1", "child-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, matching element with id that is a child of an element", 'selector': "div>#child-div1", 'expect': ["child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, matching element with id that is a child of an element with id", 'selector': "#child>#child-div1", 'expect': ["child-div1"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, matching element with id that is a child of an element with class", 'selector': "#child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, matching element with class that is a child of an element with class", 'selector': ".child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, not matching element with id that is not a child of an element with id", 'selector': "#child>#child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Child combinator, not matching element with id that is not a child of an element with class", 'selector': "#child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Child combinator, not matching element with class that is not a child of an element with class", 'selector': ".child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Child combinator, surrounded by whitespace", 'selector': "#child-div1\t\r\n>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, whitespace after", 'selector': "#child-div1>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, whitespace before", 'selector': "#child-div1\t\r\n>#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Child combinator, no whitespace", 'selector': "#child-div1>#child-div2", 'expect': ["child-div2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Child combinator, matching element that is a child of an element with id", + 'selector': "#child>div", + 'expect': ["child-div1", "child-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Child combinator, matching element with id that is a child of an element", + 'selector': "div>#child-div1", + 'expect': ["child-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Child combinator, matching element with id that is a child of an element with id", + 'selector': "#child>#child-div1", + 'expect': ["child-div1"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Child combinator, matching element with id that is a child of an element with class", + 'selector': "#child-div1>.child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Child combinator, matching element with class that is a child of an element with class", + 'selector': ".child-div1>.child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Child combinator, not matching element with id that is not a child of an element with id", + 'selector': "#child>#child-div3", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Child combinator, not matching element with id that is not a child of an element with class", + 'selector': "#child-div1>.child-div3", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': + "Child combinator, not matching element with class that is not a child of an element with class", + 'selector': ".child-div1>.child-div3", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Child combinator, surrounded by whitespace", + 'selector': "#child-div1\t\r\n>\t\r\n#child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Child combinator, whitespace after", + 'selector': "#child-div1>\t\r\n#child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Child combinator, whitespace before", + 'selector': "#child-div1\t\r\n>#child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Child combinator, no whitespace", + 'selector': "#child-div1>#child-div2", + 'expect': ["child-div2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - Adjacent sibling combinator '+' - {'name': "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+div", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", 'selector': "div+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", 'selector': "#adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", 'selector': ".adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", 'selector': "#adjacent div+p", 'expect': ["adjacent-p2"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", 'selector': "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", 'expect': [] /*no matches*/, 'level': 2, 'testType': TEST_QSA_BASELINE}, - {'name': "Adjacent sibling combinator, surrounded by whitespace", 'selector': "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, whitespace after", 'selector': "#adjacent-p2+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, whitespace before", 'selector': "#adjacent-p2\t\r\n+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Adjacent sibling combinator, no whitespace", 'selector': "#adjacent-p2+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': + "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", + 'selector': "#adjacent-div2+div", + 'expect': ["adjacent-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", + 'selector': "div+#adjacent-div4", + 'expect': ["adjacent-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", + 'selector': "#adjacent-div2+#adjacent-div4", + 'expect': ["adjacent-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", + 'selector': "#adjacent-div2+.adjacent-div4", + 'expect': ["adjacent-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", + 'selector': ".adjacent-div2+.adjacent-div4", + 'expect': ["adjacent-div4"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", + 'selector': "#adjacent div+p", + 'expect': ["adjacent-p2"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': + "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", + 'selector': "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", + 'expect': [] /*no matches*/, + 'level': 2, + 'testType': TEST_QSA_BASELINE + }, + { + 'name': "Adjacent sibling combinator, surrounded by whitespace", + 'selector': "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", + 'expect': ["adjacent-p3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Adjacent sibling combinator, whitespace after", + 'selector': "#adjacent-p2+\t\r\n#adjacent-p3", + 'expect': ["adjacent-p3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Adjacent sibling combinator, whitespace before", + 'selector': "#adjacent-p2\t\r\n+#adjacent-p3", + 'expect': ["adjacent-p3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Adjacent sibling combinator, no whitespace", + 'selector': "#adjacent-p2+#adjacent-p3", + 'expect': ["adjacent-p3"], + 'level': 2, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, // - General sibling combinator ~ (Level 3) - {'name': "General sibling combinator, matching element that is a sibling of an element with id", 'selector': "#sibling-div2~div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, matching element with id that is a sibling of an element", 'selector': "div~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, matching element with id that is a sibling of an element with id", 'selector': "#sibling-div2~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, matching element with class that is a sibling of an element with id", 'selector': "#sibling-div2~.sibling-div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, matching p element that is a sibling of a div element", 'selector': "#sibling div~p", 'expect': ["sibling-p2", "sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, not matching element with id that is not a sibling after a p element", 'selector': "#sibling>p~div", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': "General sibling combinator, not matching element with id that is not a sibling after an element with id", 'selector': "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", 'expect': [] /*no matches*/, 'level': 3, 'testType': TEST_QSA_ADDITIONAL}, - {'name': "General sibling combinator, surrounded by whitespace", 'selector': "#sibling-p2\t\r\n~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, whitespace after", 'selector': "#sibling-p2~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, whitespace before", 'selector': "#sibling-p2\t\r\n~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, - {'name': "General sibling combinator, no whitespace", 'selector': "#sibling-p2~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE}, + { + 'name': + "General sibling combinator, matching element that is a sibling of an element with id", + 'selector': "#sibling-div2~div", + 'expect': ["sibling-div4", "sibling-div6"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "General sibling combinator, matching element with id that is a sibling of an element", + 'selector': "div~#sibling-div4", + 'expect': ["sibling-div4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "General sibling combinator, matching element with id that is a sibling of an element with id", + 'selector': "#sibling-div2~#sibling-div4", + 'expect': ["sibling-div4"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "General sibling combinator, matching element with class that is a sibling of an element with id", + 'selector': "#sibling-div2~.sibling-div", + 'expect': ["sibling-div4", "sibling-div6"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "General sibling combinator, matching p element that is a sibling of a div element", + 'selector': "#sibling div~p", + 'expect': ["sibling-p2", "sibling-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': + "General sibling combinator, not matching element with id that is not a sibling after a p element", + 'selector': "#sibling>p~div", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': + "General sibling combinator, not matching element with id that is not a sibling after an element with id", + 'selector': "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", + 'expect': [] /*no matches*/, + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL + }, + { + 'name': "General sibling combinator, surrounded by whitespace", + 'selector': "#sibling-p2\t\r\n~\t\r\n#sibling-p3", + 'expect': ["sibling-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': "General sibling combinator, whitespace after", + 'selector': "#sibling-p2~\t\r\n#sibling-p3", + 'expect': ["sibling-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': "General sibling combinator, whitespace before", + 'selector': "#sibling-p2\t\r\n~#sibling-p3", + 'expect': ["sibling-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, + { + 'name': "General sibling combinator, no whitespace", + 'selector': "#sibling-p2~#sibling-p3", + 'expect': ["sibling-p3"], + 'level': 3, + 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + }, // Group of selectors (comma) - {'name': "Syntax, group of selectors separator, surrounded by whitespace", 'selector': "#group em\t\r \n,\t\r \n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Syntax, group of selectors separator, whitespace after", 'selector': "#group em,\t\r\n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Syntax, group of selectors separator, whitespace before", 'selector': "#group em\t\r\n,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, - {'name': "Syntax, group of selectors separator, no whitespace", 'selector': "#group em,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE}, + { + 'name': "Syntax, group of selectors separator, surrounded by whitespace", + 'selector': "#group em\t\r \n,\t\r \n#group strong", + 'expect': ["group-em1", "group-strong1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Syntax, group of selectors separator, whitespace after", + 'selector': "#group em,\t\r\n#group strong", + 'expect': ["group-em1", "group-strong1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Syntax, group of selectors separator, whitespace before", + 'selector': "#group em\t\r\n,#group strong", + 'expect': ["group-em1", "group-strong1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, + { + 'name': "Syntax, group of selectors separator, no whitespace", + 'selector': "#group em,#group strong", + 'expect': ["group-em1", "group-strong1"], + 'level': 1, + 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + }, ]; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 3a9959389..d8f66b1c9 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -14,7 +14,7 @@ Map _treeTypes; Map<String, TreeBuilderFactory> get treeTypes { if (_treeTypes == null) { // TODO(jmesserly): add DOM here once it's implemented - _treeTypes = { "simpletree": (useNs) => new TreeBuilder(useNs) }; + _treeTypes = {"simpletree": (useNs) => new TreeBuilder(useNs)}; } return _treeTypes; } diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 5c87e160e..6b6a1ea1a 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -30,8 +30,7 @@ class TokenizerTestParser { // Note: we can't get a closure of the state method. However, we can // create a new closure to invoke it via mirrors. var mtok = reflect(tokenizer); - tokenizer.state = () => - mtok.invoke(new Symbol(_state), const []).reflectee; + tokenizer.state = () => mtok.invoke(new Symbol(_state), const []).reflectee; if (_lastStartTag != null) { tokenizer.currentToken = new StartTagToken(_lastStartTag); @@ -68,8 +67,8 @@ class TokenizerTestParser { } void processDoctype(DoctypeToken token) { - outputTokens.add(["DOCTYPE", token.name, token.publicId, - token.systemId, token.correct]); + outputTokens.add( + ["DOCTYPE", token.name, token.publicId, token.systemId, token.correct]); } void processStartTag(StartTagToken token) { @@ -92,8 +91,7 @@ class TokenizerTestParser { outputTokens.add(["Character", token.data]); } - void processEOF(token) { - } + void processEOF(token) {} void processParseError(StringToken token) { // TODO(jmesserly): when debugging test failures it can be useful to add @@ -110,7 +108,6 @@ List concatenateCharacterTokens(List tokens) { if (outputTokens.length > 0 && outputTokens.last.indexOf("ParseError") == -1 && outputTokens.last[0] == "Character") { - outputTokens.last[1] = '${outputTokens.last[1]}${token[1]}'; } else { outputTokens.add(token); @@ -133,18 +130,17 @@ List normalizeTokens(List tokens) { return tokens; } - /// Test whether the test has passed or failed /// /// If the ignoreErrorOrder flag is set to true we don't test the relative /// positions of parse errors and non parse errors. -void expectTokensMatch(List expectedTokens, List receivedTokens, - bool ignoreErrorOrder, [bool ignoreErrors = false, String message]) { - +void expectTokensMatch( + List expectedTokens, List receivedTokens, bool ignoreErrorOrder, + [bool ignoreErrors = false, String message]) { var checkSelfClosing = false; for (var token in expectedTokens) { - if (token[0] == "StartTag" && token.length == 4 - || token[0] == "EndTag" && token.length == 3) { + if (token[0] == "StartTag" && token.length == 4 || + token[0] == "EndTag" && token.length == 3) { checkSelfClosing = true; break; } @@ -185,16 +181,21 @@ void runTokenizerTest(Map testInfo) { if (!testInfo.containsKey('lastStartTag')) { testInfo['lastStartTag'] = null; } - var parser = new TokenizerTestParser(testInfo['initialState'], - testInfo['lastStartTag']); + var parser = new TokenizerTestParser( + testInfo['initialState'], testInfo['lastStartTag']); var tokens = parser.parse(testInfo['input']); tokens = concatenateCharacterTokens(tokens); var received = normalizeTokens(tokens); - var errorMsg = ["\n\nInitial state:", - testInfo['initialState'], - "\nInput:", testInfo['input'], - "\nExpected:", expected, - "\nreceived:", tokens].map((s) => '$s').join('\n'); + var errorMsg = [ + "\n\nInitial state:", + testInfo['initialState'], + "\nInput:", + testInfo['input'], + "\nExpected:", + expected, + "\nreceived:", + tokens + ].map((s) => '$s').join('\n'); var ignoreErrorOrder = testInfo['ignoreErrorOrder']; if (ignoreErrorOrder == null) ignoreErrorOrder = false; @@ -226,7 +227,6 @@ Map unescape(Map testInfo) { return testInfo; } - String camelCase(String s) { s = s.toLowerCase(); var result = new StringBuffer(); From c6b36807926f18f2033d15c3911ecb5c599de72a Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Thu, 5 Mar 2015 06:31:31 -0800 Subject: [PATCH 046/212] Update README.md the tests run standalone, dart SVN checkout not required :) --- pkgs/html/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 4a8319c7b..4c94a0aa9 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -43,10 +43,7 @@ Running Tests ------------- ```bash -# From Dart SVN checkout -./tools/build.py -m release -./tools/test.py -m release html5lib -./tools/test.py -m release -r drt html5lib +./test/run.sh ``` [dart]: http://www.dartlang.org/ From 7d8b8b47991d32030c28960f165da341ed497b85 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Thu, 5 Mar 2015 06:30:23 -0800 Subject: [PATCH 047/212] rename package to `html` --- pkgs/html/CHANGELOG.md | 5 ++++- pkgs/html/README.md | 15 ++++++--------- pkgs/html/lib/parser.dart | 4 ++-- pkgs/html/lib/src/css_class_set.dart | 4 ++-- pkgs/html/lib/src/inputstream.dart | 2 +- pkgs/html/lib/src/query_selector.dart | 8 ++++---- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/treebuilder.dart | 4 ++-- pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/dom_test.dart | 4 ++-- pkgs/html/test/parser_feature_test.dart | 8 ++++---- pkgs/html/test/parser_test.dart | 8 ++++---- .../html/test/selectors/level1_baseline_test.dart | 6 +++--- pkgs/html/test/selectors/level1_lib.dart | 6 +++--- pkgs/html/test/selectors/selectors.dart | 2 +- pkgs/html/test/support.dart | 6 +++--- pkgs/html/test/tokenizer_test.dart | 6 +++--- 17 files changed, 46 insertions(+), 46 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 6d485f418..d0f5c9ec0 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,8 +1,11 @@ # changelog -This file contains highlights of what changes on each version of the html5lib +This file contains highlights of what changes on each version of the html package. +#### Rename to package:html 0.12.0 + * package has been renamed to `html` + #### Pub version 0.12.0 * switch from `source_maps`' `Span` class to `source_span`'s `SourceSpan` class. diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 4a8319c7b..ee525add3 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -1,5 +1,5 @@ -html5lib in Pure Dart -===================== +html5 parser in dart +==================== This is a pure [Dart][dart] [html5 parser][html5parse]. It's a port of [html5lib](http://code.google.com/p/html5lib/) from Python. Since it's 100% @@ -14,7 +14,7 @@ Installation Add this to your `pubspec.yaml` (or create it): ```yaml dependencies: - html5lib: any + html: any ``` Then run the [Pub Package Manager][pub] (comes with the Dart SDK): @@ -25,8 +25,8 @@ Usage Parsing HTML is easy! ```dart -import 'package:html5lib/parser.dart' show parse; -import 'package:html5lib/dom.dart'; +import 'package:html/parser.dart' show parse; +import 'package:html/dom.dart'; main() { var document = parse( @@ -43,10 +43,7 @@ Running Tests ------------- ```bash -# From Dart SVN checkout -./tools/build.py -m release -./tools/test.py -m release html5lib -./tools/test.py -m release -r drt html5lib +./test/run.sh ``` [dart]: http://www.dartlang.org/ diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index a6618ab1b..860f3be6e 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1,8 +1,8 @@ /// This library has a parser for HTML5 documents, that lets you parse HTML /// easily from a script or server side application: /// -/// import 'package:html5lib/parser.dart' show parse; -/// import 'package:html5lib/dom.dart'; +/// import 'package:html/parser.dart' show parse; +/// import 'package:html/dom.dart'; /// main() { /// var document = parse( /// '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 8798cd2e1..2e131a538 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -3,10 +3,10 @@ // BSD-style license that can be found in the LICENSE file. // TODO(jmesserly): everything in this file is copied straight from "dart:html". -library html5lib.dom.src; +library html.dom.src; import 'dart:collection'; -import 'package:html5lib/dom.dart'; +import 'package:html/dom.dart'; class ElementCssClassSet extends CssClassSetImpl { final Element _element; diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index fce5b2194..cb40bc91a 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -87,7 +87,7 @@ class HtmlInputStream { // Unfortunately dart:io InputStream is async only, which won't work. throw new ArgumentError("'source' must be a String or " "List<int> (of bytes). You can also pass a RandomAccessFile if you" - "`import 'package:html5lib/parser_console.dart'` and call " + "`import 'package:html/parser_console.dart'` and call " "`useConsole()`."); } } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 556eeb064..e586d1aa5 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -1,11 +1,11 @@ -/// Query selector implementation for html5lib's DOM. -library html5lib.src.query; +/// Query selector implementation for our DOM. +library html.src.query; import 'package:csslib/parser.dart' as css; import 'package:csslib/parser.dart' show TokenKind; import 'package:csslib/visitor.dart'; // the CSSOM -import 'package:html5lib/dom.dart'; -import 'package:html5lib/src/constants.dart' show isWhitespaceCC; +import 'package:html/dom.dart'; +import 'package:html/src/constants.dart' show isWhitespaceCC; bool matches(Node node, String selector) => new SelectorEvaluator().matches(node, _parseSelectorList(selector)); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index a7ebcf81a..3ee89788f 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1,7 +1,7 @@ library tokenizer; import 'dart:collection'; -import 'package:html5lib/parser.dart' show HtmlParser; +import 'package:html/parser.dart' show HtmlParser; import 'constants.dart'; import 'inputstream.dart'; import 'token.dart'; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index edd183dab..0ed97407f 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -2,8 +2,8 @@ library treebuilder; import 'dart:collection'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/parser.dart' show getElementNameTuple; +import 'package:html/dom.dart'; +import 'package:html/parser.dart' show getElementNameTuple; import 'package:source_span/source_span.dart'; import 'constants.dart'; import 'list_proxy.dart'; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 87d6fc74f..35a9ba44e 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,4 +1,4 @@ -name: html5lib +name: html version: 0.12.1-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 14b095bed..d4e0809f2 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -2,8 +2,8 @@ library dom_test; import 'package:unittest/unittest.dart'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/parser.dart'; +import 'package:html/dom.dart'; +import 'package:html/parser.dart'; main() { group('Element', () { diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index ddc8a743f..1beea2a19 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -2,10 +2,10 @@ library parser_feature_test; import 'package:unittest/unittest.dart'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/parser.dart'; -import 'package:html5lib/src/constants.dart'; -import 'package:html5lib/src/treebuilder.dart'; +import 'package:html/dom.dart'; +import 'package:html/parser.dart'; +import 'package:html/src/constants.dart'; +import 'package:html/src/treebuilder.dart'; main() { test('doctype is cloneable', () { diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index ed1198249..6f810860b 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -4,10 +4,10 @@ import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/parser.dart'; -import 'package:html5lib/parser_console.dart' as parser_console; -import 'package:html5lib/src/inputstream.dart' as inputstream; +import 'package:html/dom.dart'; +import 'package:html/parser.dart'; +import 'package:html/parser_console.dart' as parser_console; +import 'package:html/src/inputstream.dart' as inputstream; import 'support.dart'; // Run the parse error checks diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 2a2f2f038..e052843d0 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -3,11 +3,11 @@ /// /// Note, unlike the original we don't operate in-browser on a DOM loaded into /// an iframe, but instead operate over a parsed DOM. -library html5lib.test.selectors.level1_baseline_test; +library html.test.selectors.level1_baseline_test; import 'dart:io'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/parser.dart'; +import 'package:html/dom.dart'; +import 'package:html/parser.dart'; import 'package:unittest/unittest.dart'; import 'level1_lib.dart' hide test; import 'selectors.dart'; diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 30ef1a133..3191353f6 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -7,9 +7,9 @@ /// As usual with ports: being faithful to the original style is more important /// than other style goals, as it reduces friction to integrating changes /// from upstream. -library html5lib.test.selectors.level1_lib; +library html.test.selectors.level1_lib; -import 'package:html5lib/dom.dart'; +import 'package:html/dom.dart'; import 'package:unittest/unittest.dart' as unittest; Document doc; @@ -280,7 +280,7 @@ traverse(Node elem, fn) { fn(elem); } - // Dart note: changed this since html5lib doens't support nextNode yet. + // Dart note: changed this since our DOM API doesn't support nextNode yet. for (var node in elem.nodes) { traverse(node, fn); } diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index f6ff25d2c..d25b14bf2 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -1,6 +1,6 @@ /// Test for the Selectors API ported from /// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> -library html5lib.test.selectors.selectors; +library html.test.selectors.selectors; // Bit-mapped flags to indicate which tests the selector is suitable for var TEST_QSA_BASELINE = diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index d8f66b1c9..1b4c0b49e 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -4,9 +4,9 @@ library support; import 'dart:io'; import 'dart:collection'; import 'package:path/path.dart' as path; -import 'package:html5lib/src/treebuilder.dart'; -import 'package:html5lib/dom.dart'; -import 'package:html5lib/dom_parsing.dart'; +import 'package:html/src/treebuilder.dart'; +import 'package:html/dom.dart'; +import 'package:html/dom_parsing.dart'; typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements); diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 6b6a1ea1a..bdac1fd31 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -6,9 +6,9 @@ import 'dart:io'; import 'dart:mirrors'; import 'package:path/path.dart' as pathos; import 'package:unittest/unittest.dart'; -import 'package:html5lib/src/char_encodings.dart'; -import 'package:html5lib/src/token.dart'; -import 'package:html5lib/src/tokenizer.dart'; +import 'package:html/src/char_encodings.dart'; +import 'package:html/src/token.dart'; +import 'package:html/src/tokenizer.dart'; import 'package:utf/utf.dart'; import 'support.dart'; From d06f76adf42fdd4f4fb1fd2bbf1f6c91b65e7682 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Thu, 5 Mar 2015 09:07:58 -0800 Subject: [PATCH 048/212] Update pubspec.yaml remove -dev --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 35a9ba44e..933b469d6 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.12.1-dev +version: 0.12.1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. homepage: https://github.com/dart-lang/html5lib From 70a1d3c24c6a31329de856a32a4135a81ec75884 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Thu, 5 Mar 2015 07:47:29 -0800 Subject: [PATCH 049/212] Fixes encoding parser to handle whitespace correctly. Caught this while investigating an unused local. In Python, the iterator would advance, but in the port it was not. --- pkgs/html/lib/src/encoding_parser.dart | 25 +++++++++--------------- pkgs/html/test/parser_feature_test.dart | 26 +++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 04ffa0c36..fd64ff9b0 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -1,6 +1,5 @@ library encoding_parser; -import 'dart:collection'; import 'constants.dart'; import 'inputstream.dart'; @@ -9,14 +8,12 @@ import 'inputstream.dart'; /// String-like object with an associated position and various extra methods /// If the position is ever greater than the string length then an exception is /// raised. -class EncodingBytes extends IterableBase<String> { +class EncodingBytes { final String _bytes; int _position = -1; EncodingBytes(this._bytes); - Iterator<String> get iterator => _bytes.split('').iterator; - int get length => _bytes.length; String next() { @@ -145,25 +142,21 @@ class EncodingParser { ]; try { - for (var byte in data) { - var keepParsing = true; + for (;;) { for (var dispatch in methodDispatch) { if (data.matchBytes(dispatch[0])) { - try { - keepParsing = dispatch[1](); - break; - } on StateError catch (e) { - keepParsing = false; - break; - } + var keepParsing = dispatch[1](); + if (keepParsing) break; + + // We found an encoding. Stop. + return encoding; } } - if (!keepParsing) { - break; - } + data.position += 1; } } on StateError catch (e) { // Catch this here to match behavior of Python's StopIteration + // TODO(jmesserly): refactor to not use exceptions } return encoding; } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 1beea2a19..538113db9 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -5,6 +5,7 @@ import 'package:unittest/unittest.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:html/src/constants.dart'; +import 'package:html/src/encoding_parser.dart'; import 'package:html/src/treebuilder.dart'; main() { @@ -291,4 +292,29 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(c.text, 'qux'); expect(e.text, 'bar'); }); + + group('Encoding pre-parser', () { + getEncoding(s) => new EncodingParser(s.codeUnits).getEncoding(); + + test('gets encoding from meta charset', () { + expect(getEncoding('<meta charset="utf-16">'), 'utf-16'); + }); + + test('gets encoding from meta in head', () { + expect(getEncoding('<head><meta charset="utf-16">'), 'utf-16'); + }); + + test('skips comments', () { + expect(getEncoding('<!--comment--><meta charset="utf-16">'), 'utf-16'); + }); + + test('stops if no match', () { + // missing closing tag + expect(getEncoding('<meta charset="utf-16"'), null); + }); + + test('ignores whitespace', () { + expect(getEncoding(' <meta charset="utf-16">'), 'utf-16'); + }); + }); } From dc10660c7ed8035277fe80b3689f2e2a88f973db Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Thu, 5 Mar 2015 15:05:19 -0800 Subject: [PATCH 050/212] remove most string concat, fixes dart-lang/html#7 This fixes most of the egregious cases of string concat in the HTML tokenizer: * attribute names/values * data/comments * script/rawtext/rcdata It also fixes adjacent text nodes in TreeBuilder, which happens whenever space characters are adjacent to characters. There's still an issue of preserving char codes for longer, but this should get out of the O(N^2) at least. R=sigmund@google.com Review URL: https://codereview.chromium.org//987433005 --- pkgs/html/lib/dom.dart | 28 ++++- pkgs/html/lib/parser.dart | 2 +- pkgs/html/lib/src/token.dart | 30 ++++- pkgs/html/lib/src/tokenizer.dart | 175 +++++++++++++++-------------- pkgs/html/lib/src/treebuilder.dart | 4 +- 5 files changed, 142 insertions(+), 97 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 6201f69db..76eb85fdd 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -402,18 +402,32 @@ class DocumentType extends Node { } class Text extends Node { - String data; + /// The text node's data, stored as either a String or StringBuffer. + /// We support storing a StringBuffer here to support fast [appendData]. + /// It will flatten back to a String on read. + var _data; - Text(this.data) : super._(); + Text(String data) : _data = data != null ? data : '', super._(); int get nodeType => Node.TEXT_NODE; + String get data => _data = _data.toString(); + set data(String value) { + _data = value != null ? value : ''; + } + String toString() => '"$data"'; void _addOuterHtml(StringBuffer str) => writeTextNodeAsHtml(str, this); Text clone(bool deep) => new Text(data); + void appendData(String data) { + if (_data is! StringBuffer) _data = new StringBuffer(_data); + StringBuffer sb = _data; + sb.write(data); + } + String get text => data; set text(String value) { data = value; @@ -539,13 +553,19 @@ class Element extends Node with _ParentNode, _ElementAndDocument { void _addOuterHtml(StringBuffer str) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments // Element is the most complicated one. - str.write('<${_getSerializationPrefix(namespaceUri)}$localName'); + str.write('<'); + str.write(_getSerializationPrefix(namespaceUri)); + str.write(localName); if (attributes.length > 0) { attributes.forEach((key, v) { // Note: AttributeName.toString handles serialization of attribute // namespace, if needed. - str.write(' $key="${htmlSerializeEscape(v, attributeMode: true)}"'); + str.write(' '); + str.write(key); + str.write('="'); + str.write(htmlSerializeEscape(v, attributeMode: true)); + str.write('"'); }); } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 860f3be6e..d81f88875 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -3395,7 +3395,7 @@ class InForeignContentPhase extends Phase { Token processCharacters(CharactersToken token) { if (token.data == "\u0000") { - token.data = "\uFFFD"; + token.replaceData("\uFFFD"); } else if (parser.framesetOK && !allWhitespace(token.data)) { parser.framesetOK = false; } diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index e4f25e5db..9a2843c5f 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -47,8 +47,25 @@ class EndTagToken extends TagToken { } abstract class StringToken extends Token { - String data; - StringToken(this.data); + StringBuffer _buffer; + + String _string; + String get data { + if (_string == null) { + _string = _buffer.toString(); + _buffer = null; + } + return _string; + } + + StringToken(string) + : _string = string, + _buffer = string == null ? new StringBuffer() : null; + + StringToken add(String data) { + _buffer.write(data); + return this; + } } class ParseErrorToken extends StringToken { @@ -64,6 +81,13 @@ class CharactersToken extends StringToken { CharactersToken([String data]) : super(data); int get kind => TokenKind.characters; + + /// Replaces the token's [data]. This should only be used to wholly replace + /// data, not to append data. + void replaceData(String newData) { + _string = newData; + _buffer = null; + } } class SpaceCharactersToken extends StringToken { @@ -103,7 +127,7 @@ class TagAttribute { int startValue; int endValue; - TagAttribute(this.name, [this.value = '']); + TagAttribute(); } class TokenKind { diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 3ee89788f..3273858fa 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -55,7 +55,7 @@ class HtmlTokenizer implements Iterator<Token> { // bug prevents us from doing that. See http://dartbug.com/12465 Function state; - String temporaryBuffer; + final StringBuffer _buffer = new StringBuffer(); int _lastOffset; @@ -82,17 +82,11 @@ class HtmlTokenizer implements Iterator<Token> { Token _current; Token get current => _current; - String get _attributeName => _attributes.last.name; - set _attributeName(String value) { - _attributes.last.name = value; - } - - String get _attributeValue => _attributes.last.value; - set _attributeValue(String value) { - _attributes.last.value = value; - } + final StringBuffer _attributeName = new StringBuffer(); + final StringBuffer _attributeValue = new StringBuffer(); void _markAttributeEnd(int offset) { + _attributes.last.value = '$_attributeValue'; if (attributeSpans) _attributes.last.end = stream.position + offset; } @@ -101,10 +95,8 @@ class HtmlTokenizer implements Iterator<Token> { } void _markAttributeValueEnd(int offset) { - if (attributeSpans) { - _attributes.last.endValue = stream.position + offset; - _markAttributeEnd(offset); - } + if (attributeSpans) _attributes.last.endValue = stream.position + offset; + _markAttributeEnd(offset); } // Note: we could track the name span here, if we need it. @@ -112,7 +104,10 @@ class HtmlTokenizer implements Iterator<Token> { void _addAttribute(String name) { if (_attributes == null) _attributes = []; - var attr = new TagAttribute(name); + _attributeName.clear(); + _attributeName.write(name); + _attributeValue.clear(); + var attr = new TagAttribute(); _attributes.add(attr); if (attributeSpans) attr.start = stream.position - name.length; } @@ -146,7 +141,7 @@ class HtmlTokenizer implements Iterator<Token> { _lastOffset = 0; tokenQueue.clear(); currentToken = null; - temporaryBuffer = null; + _buffer.clear(); _attributes = null; _attributeNames = null; state = dataState; @@ -347,7 +342,7 @@ class HtmlTokenizer implements Iterator<Token> { } } if (fromAttribute) { - _attributeValue = '$_attributeValue$output'; + _attributeValue.write(output); } else { var token; if (isWhitespace(output)) { @@ -593,7 +588,7 @@ class HtmlTokenizer implements Iterator<Token> { bool rcdataLessThanSignState() { var data = stream.char(); if (data == "/") { - temporaryBuffer = ""; + _buffer.clear(); state = rcdataEndTagOpenState; } else { _addToken(new CharactersToken("<")); @@ -606,7 +601,7 @@ class HtmlTokenizer implements Iterator<Token> { bool rcdataEndTagOpenState() { var data = stream.char(); if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); state = rcdataEndTagNameState; } else { _addToken(new CharactersToken("</")); @@ -617,27 +612,28 @@ class HtmlTokenizer implements Iterator<Token> { } bool _tokenIsAppropriate() { + // TODO(jmesserly): this should use case insensitive compare instead. return currentToken is TagToken && - currentTagToken.name.toLowerCase() == temporaryBuffer.toLowerCase(); + currentTagToken.name.toLowerCase() == '$_buffer'.toLowerCase(); } bool rcdataEndTagNameState() { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { - _addToken(new CharactersToken("</$temporaryBuffer")); + _addToken(new CharactersToken("</$_buffer")); stream.unget(data); state = rcdataState; } @@ -647,7 +643,7 @@ class HtmlTokenizer implements Iterator<Token> { bool rawtextLessThanSignState() { var data = stream.char(); if (data == "/") { - temporaryBuffer = ""; + _buffer.clear(); state = rawtextEndTagOpenState; } else { _addToken(new CharactersToken("<")); @@ -660,7 +656,7 @@ class HtmlTokenizer implements Iterator<Token> { bool rawtextEndTagOpenState() { var data = stream.char(); if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); state = rawtextEndTagNameState; } else { _addToken(new CharactersToken("</")); @@ -674,19 +670,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { - _addToken(new CharactersToken("</$temporaryBuffer")); + _addToken(new CharactersToken("</$_buffer")); stream.unget(data); state = rawtextState; } @@ -696,7 +692,7 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataLessThanSignState() { var data = stream.char(); if (data == "/") { - temporaryBuffer = ""; + _buffer.clear(); state = scriptDataEndTagOpenState; } else if (data == "!") { _addToken(new CharactersToken("<!")); @@ -712,7 +708,7 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEndTagOpenState() { var data = stream.char(); if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); state = scriptDataEndTagNameState; } else { _addToken(new CharactersToken("</")); @@ -726,19 +722,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { - _addToken(new CharactersToken("</$temporaryBuffer")); + _addToken(new CharactersToken("</$_buffer")); stream.unget(data); state = scriptDataState; } @@ -833,11 +829,12 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedLessThanSignState() { var data = stream.char(); if (data == "/") { - temporaryBuffer = ""; + _buffer.clear(); state = scriptDataEscapedEndTagOpenState; } else if (isLetter(data)) { _addToken(new CharactersToken("<$data")); - temporaryBuffer = data; + _buffer.clear(); + _buffer.write(data); state = scriptDataDoubleEscapeStartState; } else { _addToken(new CharactersToken("<")); @@ -850,7 +847,8 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedEndTagOpenState() { var data = stream.char(); if (isLetter(data)) { - temporaryBuffer = data; + _buffer.clear(); + _buffer.write(data); state = scriptDataEscapedEndTagNameState; } else { _addToken(new CharactersToken("</")); @@ -864,19 +862,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken(temporaryBuffer); + currentToken = new EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { - _addToken(new CharactersToken("</$temporaryBuffer")); + _addToken(new CharactersToken("</$_buffer")); stream.unget(data); state = scriptDataEscapedState; } @@ -887,14 +885,14 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data) || data == "/" || data == ">") { _addToken(new CharactersToken(data)); - if (temporaryBuffer.toLowerCase() == "script") { + if ('$_buffer'.toLowerCase() == "script") { state = scriptDataDoubleEscapedState; } else { state = scriptDataEscapedState; } } else if (isLetter(data)) { _addToken(new CharactersToken(data)); - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { stream.unget(data); state = scriptDataEscapedState; @@ -974,7 +972,7 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (data == "/") { _addToken(new CharactersToken("/")); - temporaryBuffer = ""; + _buffer.clear(); state = scriptDataDoubleEscapeEndState; } else { stream.unget(data); @@ -987,14 +985,14 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data) || data == "/" || data == ">") { _addToken(new CharactersToken(data)); - if (temporaryBuffer.toLowerCase() == "script") { + if ('$_buffer'.toLowerCase() == "script") { state = scriptDataEscapedState; } else { state = scriptDataDoubleEscapedState; } } else if (isLetter(data)) { _addToken(new CharactersToken(data)); - temporaryBuffer = '${temporaryBuffer}$data'; + _buffer.write(data); } else { stream.unget(data); state = scriptDataDoubleEscapedState; @@ -1038,8 +1036,8 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "=") { state = beforeAttributeValueState; } else if (isLetter(data)) { - _attributeName = '$_attributeName$data' - '${stream.charsUntil(asciiLetters, true)}'; + _attributeName.write(data); + _attributeName.write(stream.charsUntil(asciiLetters, true)); leavingThisState = false; } else if (data == ">") { // XXX If we emit here the attributes are converted to a dict @@ -1052,17 +1050,17 @@ class HtmlTokenizer implements Iterator<Token> { state = selfClosingStartTagState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - _attributeName = '${_attributeName}\uFFFD'; + _attributeName.write('\uFFFD'); leavingThisState = false; } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-attribute-name")); state = dataState; } else if ("'\"<".contains(data)) { _addToken(new ParseErrorToken("invalid-character-in-attribute-name")); - _attributeName = '$_attributeName$data'; + _attributeName.write(data); leavingThisState = false; } else { - _attributeName = '$_attributeName$data'; + _attributeName.write(data); leavingThisState = false; } @@ -1072,14 +1070,16 @@ class HtmlTokenizer implements Iterator<Token> { // Attributes are not dropped at this stage. That happens when the // start tag token is emitted so values can still be safely appended // to attributes, but we do want to report the parse error in time. + var attrName = _attributeName.toString(); if (lowercaseAttrName) { - _attributeName = asciiUpper2Lower(_attributeName); + attrName = asciiUpper2Lower(attrName); } + _attributes.last.name = attrName; if (_attributeNames == null) _attributeNames = new Set(); - if (_attributeNames.contains(_attributeName)) { + if (_attributeNames.contains(attrName)) { _addToken(new ParseErrorToken("duplicate-attribute")); } - _attributeNames.add(_attributeName); + _attributeNames.add(attrName); // XXX Fix for above XXX if (emitToken) { @@ -1141,7 +1141,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); _markAttributeValueStart(-1); - _attributeValue = '${_attributeValue}\uFFFD'; + _attributeValue.write('\uFFFD'); state = attributeValueUnQuotedState; } else if (data == EOF) { _addToken(new ParseErrorToken("expected-attribute-value-but-got-eof")); @@ -1149,11 +1149,11 @@ class HtmlTokenizer implements Iterator<Token> { } else if ("=<`".contains(data)) { _addToken(new ParseErrorToken("equals-in-unquoted-attribute-value")); _markAttributeValueStart(-1); - _attributeValue = '$_attributeValue$data'; + _attributeValue.write(data); state = attributeValueUnQuotedState; } else { _markAttributeValueStart(-1); - _attributeValue = '$_attributeValue$data'; + _attributeValue.write(data); state = attributeValueUnQuotedState; } return true; @@ -1169,13 +1169,14 @@ class HtmlTokenizer implements Iterator<Token> { processEntityInAttribute('"'); } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - _attributeValue = '${_attributeValue}\uFFFD'; + _attributeValue.write('\uFFFD'); } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-attribute-value-double-quote")); _markAttributeValueEnd(-1); state = dataState; } else { - _attributeValue = '$_attributeValue$data${stream.charsUntil("\"&")}'; + _attributeValue.write(data); + _attributeValue.write(stream.charsUntil("\"&")); } return true; } @@ -1190,13 +1191,14 @@ class HtmlTokenizer implements Iterator<Token> { processEntityInAttribute("'"); } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - _attributeValue = '${_attributeValue}\uFFFD'; + _attributeValue.write('\uFFFD'); } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-attribute-value-single-quote")); _markAttributeValueEnd(-1); state = dataState; } else { - _attributeValue = '$_attributeValue$data${stream.charsUntil("\'&")}'; + _attributeValue.write(data); + _attributeValue.write(stream.charsUntil("\'&")); } return true; } @@ -1218,13 +1220,13 @@ class HtmlTokenizer implements Iterator<Token> { } else if ('"\'=<`'.contains(data)) { _addToken(new ParseErrorToken( "unexpected-character-in-unquoted-attribute-value")); - _attributeValue = '$_attributeValue$data'; + _attributeValue.write(data); } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - _attributeValue = '${_attributeValue}\uFFFD'; + _attributeValue.write('\uFFFD'); } else { - _attributeValue = '$_attributeValue$data' - '${stream.charsUntil("&>\"\'=<`$spaceCharacters")}'; + _attributeValue.write(data); + _attributeValue.write(stream.charsUntil("&>\"\'=<`$spaceCharacters")); } return true; } @@ -1288,7 +1290,7 @@ class HtmlTokenizer implements Iterator<Token> { if (charStack.last == "-") { charStack.add(stream.char()); if (charStack.last == "-") { - currentToken = new CommentToken(""); + currentToken = new CommentToken(); state = commentStartState; return true; } @@ -1341,7 +1343,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentStartDashState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = '${currentStringToken.data}\uFFFD'; + currentStringToken.add('\uFFFD'); } else if (data == ">") { _addToken(new ParseErrorToken("incorrect-comment")); _addToken(currentToken); @@ -1351,7 +1353,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken.data = '${currentStringToken.data}$data'; + currentStringToken.add(data); state = commentState; } return true; @@ -1363,7 +1365,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = '${currentStringToken.data}-\uFFFD'; + currentStringToken.add('-\uFFFD'); } else if (data == ">") { _addToken(new ParseErrorToken("incorrect-comment")); _addToken(currentToken); @@ -1373,7 +1375,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken.data = '${currentStringToken.data}-${data}'; + currentStringToken.add('-').add(data); state = commentState; } return true; @@ -1385,14 +1387,13 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndDashState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = '${currentStringToken.data}\uFFFD'; + currentStringToken.add('\uFFFD'); } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-comment")); _addToken(currentToken); state = dataState; } else { - currentStringToken.data = '${currentStringToken.data}$data' - '${stream.charsUntil("-\u0000")}'; + currentStringToken.add(data).add(stream.charsUntil("-\u0000")); } return true; } @@ -1403,14 +1404,14 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = "${currentStringToken.data}-\uFFFD"; + currentStringToken.add('-\uFFFD'); state = commentState; } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-comment-end-dash")); _addToken(currentToken); state = dataState; } else { - currentStringToken.data = "${currentStringToken.data}-${data}"; + currentStringToken.add('-').add(data); state = commentState; } return true; @@ -1423,7 +1424,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = '${currentStringToken.data}--\uFFFD'; + currentStringToken.add('--\uFFFD'); state = commentState; } else if (data == "!") { _addToken( @@ -1432,7 +1433,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "-") { _addToken( new ParseErrorToken("unexpected-dash-after-double-dash-in-comment")); - currentStringToken.data = '${currentStringToken.data}$data'; + currentStringToken.add(data); } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-comment-double-dash")); _addToken(currentToken); @@ -1440,7 +1441,7 @@ class HtmlTokenizer implements Iterator<Token> { } else { // XXX _addToken(new ParseErrorToken("unexpected-char-in-comment")); - currentStringToken.data = "${currentStringToken.data}--${data}"; + currentStringToken.add('--').add(data); state = commentState; } return true; @@ -1452,18 +1453,18 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == "-") { - currentStringToken.data = '${currentStringToken.data}--!'; + currentStringToken.add('--!'); state = commentEndDashState; } else if (data == "\u0000") { _addToken(new ParseErrorToken("invalid-codepoint")); - currentStringToken.data = '${currentStringToken.data}--!\uFFFD'; + currentStringToken.add('--!\uFFFD'); state = commentState; } else if (data == EOF) { _addToken(new ParseErrorToken("eof-in-comment-end-bang-state")); _addToken(currentToken); state = dataState; } else { - currentStringToken.data = "${currentStringToken.data}--!${data}"; + currentStringToken.add('--!').add(data); state = commentState; } return true; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 0ed97407f..409cba429 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -324,7 +324,7 @@ class TreeBuilder { if (refNode == null) { if (nodes.length > 0 && nodes.last is Text) { Text last = nodes.last; - last.data = '${last.data}$data'; + last.appendData(data); if (span != null) { last.sourceSpan = @@ -337,7 +337,7 @@ class TreeBuilder { int index = nodes.indexOf(refNode); if (index > 0 && nodes[index - 1] is Text) { Text last = nodes[index - 1]; - last.data = '${last.data}$data'; + last.appendData(data); } else { nodes.insert(index, new Text(data)..sourceSpan = span); } From a0f34087e6ce48ade5aaaf93cd1f57ce2071951d Mon Sep 17 00:00:00 2001 From: Seth Ladd <sethladd@gmail.com> Date: Mon, 9 Mar 2015 13:48:31 -0700 Subject: [PATCH 051/212] Update homepage and description --- pkgs/html/pubspec.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 933b469d6..3562da321 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,8 +1,8 @@ name: html version: 0.12.1 author: Dart Team <misc@dartlang.org> -description: A library for working with HTML documents. -homepage: https://github.com/dart-lang/html5lib +description: A library for working with HTML documents. Previously known as html5lib. +homepage: https://github.com/dart-lang/html environment: sdk: '>=1.2.0 <2.0.0' dependencies: From ae17b039899c4c27076d8f8abb58428a3f958387 Mon Sep 17 00:00:00 2001 From: Seth Ladd <sethladd@gmail.com> Date: Mon, 9 Mar 2015 13:57:57 -0700 Subject: [PATCH 052/212] Just making things extra clear :) --- pkgs/html/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index ee525add3..c18b27664 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -8,6 +8,8 @@ Dart you can use it safely from a script or server side app. Eventually the parse tree API will be compatible with [dart:html][d_html], so the same code will work on the client and the server. +(Formally known as _html5lib_.) + Installation ------------ From 227261cbe74eddb1511c177c1ac4d3b9f29c9c08 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Fri, 3 Apr 2015 09:48:50 -0700 Subject: [PATCH 053/212] support latest csslib R=jmesserly@google.com Review URL: https://codereview.chromium.org//1059773002 --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index d0f5c9ec0..2562a13f6 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html package. +#### Pub version 0.12.0+1 + * Support `csslib` version `0.12.0`. + #### Rename to package:html 0.12.0 * package has been renamed to `html` diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 3562da321..0af845a07 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html -version: 0.12.1 +version: 0.12.1+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0 <0.12.0' + csslib: '>=0.10.0 <0.13.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From 61e396db8d4d5efff4057364520e249284e9a3ec Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Fri, 3 Apr 2015 12:36:08 -0700 Subject: [PATCH 054/212] fix code review settings R=jmesserly@google.com Review URL: https://codereview.chromium.org//1059783002 --- pkgs/html/codereview.settings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/codereview.settings b/pkgs/html/codereview.settings index 39ffa4fa1..caca72f48 100644 --- a/pkgs/html/codereview.settings +++ b/pkgs/html/codereview.settings @@ -1,3 +1,3 @@ CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/core-elements/commit/ +VIEW_VC: https://github.com/dart-lang/html/commit/ CC_LIST: reviews@dartlang.org From 706fd66f95edd9fef0170684900ed9535a0df845 Mon Sep 17 00:00:00 2001 From: Seth Ladd <sethladd@gmail.com> Date: Sat, 16 May 2015 19:42:18 -0700 Subject: [PATCH 055/212] Fix typo --- pkgs/html/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index c18b27664..55f9e237f 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -8,7 +8,7 @@ Dart you can use it safely from a script or server side app. Eventually the parse tree API will be compatible with [dart:html][d_html], so the same code will work on the client and the server. -(Formally known as _html5lib_.) +(Formerly known as _html5lib_.) Installation ------------ From 98544370f071c0cc92de4cc041a9f3fd7b5c7940 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Mon, 6 Jul 2015 09:56:37 -0700 Subject: [PATCH 056/212] fixes dart-lang/html#16, point at github link for html5lib --- pkgs/html/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 55f9e237f..27db3ceac 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -2,7 +2,7 @@ html5 parser in dart ==================== This is a pure [Dart][dart] [html5 parser][html5parse]. It's a port of -[html5lib](http://code.google.com/p/html5lib/) from Python. Since it's 100% +[html5lib](https://github.com/html5lib/html5lib-python) from Python. Since it's 100% Dart you can use it safely from a script or server side app. Eventually the parse tree API will be compatible with [dart:html][d_html], so From bc70cee78c5ceb0c3e6c5b88efbaab061d7d1891 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Mon, 6 Jul 2015 11:32:11 -0700 Subject: [PATCH 057/212] fix parse error with foreignObject end tag it appears we inherited this from html5lib: https://github.com/html5lib/html5lib-python/blob/5e3d432998b027cd2d200446f157d13a3461a92b/html5lib/html5parser.py#L2448 You'll notice the node.name.translate(asciiUpper2Lower) immediately below, in the same comparison Most likely, this is not caught because it's not common to display HTML parse errors, and the actual tree construction is correct. This fix does match the spec: https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign See "Any other end tag, step 2": > If node's tag name, converted to ASCII lowercase, is not the same as the tag name of the token, then this is a parse error. We were missing the converted to lowercase step. R=sigmund@google.com Review URL: https://codereview.chromium.org//1222713008. --- pkgs/html/lib/parser.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index d81f88875..113a1dd49 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -3438,7 +3438,7 @@ class InForeignContentPhase extends Phase { Token processEndTag(EndTagToken token) { var nodeIndex = tree.openElements.length - 1; var node = tree.openElements.last; - if (node.localName != token.name) { + if (asciiUpper2Lower(node.localName) != token.name) { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 538113db9..568819b5e 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -293,6 +293,20 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(e.text, 'bar'); }); + test('foreignObject end tag', () { + var p = new HtmlParser(''' +<svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" + version="1.1"> + <foreignObject width="320px" height="200px"> + <x-flow></x-flow> + </foreignObject> +</svg>'''); + var doc = p.parseFragment(); + expect(p.errors, isEmpty); + var svg = doc.querySelector('svg'); + expect(svg.children[0].children[0].localName, 'x-flow'); + }); + group('Encoding pre-parser', () { getEncoding(s) => new EncodingParser(s.codeUnits).getEncoding(); From 70750b6c6a51327bec634c15da52710256fd9424 Mon Sep 17 00:00:00 2001 From: John Messerly <jmesserly@google.com> Date: Mon, 6 Jul 2015 11:33:50 -0700 Subject: [PATCH 058/212] Update pubspec.yaml --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 0af845a07..7237df21f 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.12.1+1 +version: 0.12.1+2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From a43a726717d48d052b99d50aac8dfbf7300e299f Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov <scheglov@google.com> Date: Wed, 26 Aug 2015 09:47:31 -0700 Subject: [PATCH 059/212] Add Element.endSourceSpan R=jmesserly@google.com, sigmund@google.com BUG= Review URL: https://codereview.chromium.org//1312363005 . --- pkgs/html/lib/dom.dart | 6 + pkgs/html/lib/parser.dart | 69 ++++++++---- pkgs/html/lib/src/treebuilder.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 142 ++++++++++++++++++++++++ 4 files changed, 199 insertions(+), 20 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 76eb85fdd..9e6475957 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -442,6 +442,12 @@ class Element extends Node with _ParentNode, _ElementAndDocument { /// of this element. final String localName; + // TODO(jmesserly): consider using an Expando for this, and put it in + // dom_parsing. Need to check the performance affect. + /// The source span of the end tag this element, if it was created by the + /// [HtmlParser]. May be `null` if does not have an implicit end tag. + FileSpan endSourceSpan; + Element._(this.localName, [this.namespaceUri]) : super._(); Element.tag(this.localName) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 113a1dd49..dc95941df 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -637,6 +637,7 @@ class Phase { } // XXX Need a check here to see if the first start tag token emitted is // this token... If it's not, invoke parser.parseError(). + tree.openElements[0].sourceSpan = token.span; token.data.forEach((attr, value) { tree.openElements[0].attributes.putIfAbsent(attr, () => value); }); @@ -649,11 +650,15 @@ class Phase { } /// Helper method for popping openElements. - void popOpenElementsUntil(String name) { + void popOpenElementsUntil(EndTagToken token) { + String name = token.name; var node = tree.openElements.removeLast(); while (node.localName != name) { node = tree.openElements.removeLast(); } + if (node != null) { + node.endSourceSpan = token.span; + } } } @@ -1039,6 +1044,7 @@ class InHeadPhase extends Phase { void endTagHead(EndTagToken token) { var node = parser.tree.openElements.removeLast(); assert(node.localName == "head"); + node.endSourceSpan = token.span; parser.phase = parser._afterHeadPhase; } @@ -1859,7 +1865,7 @@ class InBodyPhase extends Phase { if (tree.openElements.last.localName != "p") { parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); } - popOpenElementsUntil("p"); + popOpenElementsUntil(token); } } @@ -1867,7 +1873,9 @@ class InBodyPhase extends Phase { if (!tree.elementInScope("body")) { parser.parseError(token.span, 'undefined-error'); return; - } else if (tree.openElements.last.localName != "body") { + } else if (tree.openElements.last.localName == "body") { + tree.openElements.last.endSourceSpan = token.span; + } else { for (Element node in slice(tree.openElements, 2)) { switch (node.localName) { case "dd": @@ -1921,7 +1929,7 @@ class InBodyPhase extends Phase { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } if (inScope) { - popOpenElementsUntil(token.name); + popOpenElementsUntil(token); } } @@ -1937,6 +1945,7 @@ class InBodyPhase extends Phase { token.span, "end-tag-too-early-ignored", {"name": "form"}); } tree.openElements.remove(node); + node.endSourceSpan = token.span; } } @@ -1955,7 +1964,7 @@ class InBodyPhase extends Phase { parser.parseError( token.span, "end-tag-too-early", {"name": token.name}); } - popOpenElementsUntil(token.name); + popOpenElementsUntil(token); } } @@ -1972,10 +1981,13 @@ class InBodyPhase extends Phase { for (var item in headingElements) { if (tree.elementInScope(item)) { - var node = tree.openElements.removeLast(); + Element node = tree.openElements.removeLast(); while (!headingElements.contains(node.localName)) { node = tree.openElements.removeLast(); } + if (node != null) { + node.endSourceSpan = token.span; + } break; } } @@ -2027,10 +2039,13 @@ class InBodyPhase extends Phase { } // Step 3 if (furthestBlock == null) { - var element = tree.openElements.removeLast(); + Element element = tree.openElements.removeLast(); while (element != formattingElement) { element = tree.openElements.removeLast(); } + if (element != null) { + element.endSourceSpan = token.span; + } tree.activeFormattingElements.remove(element); return; } @@ -2138,7 +2153,7 @@ class InBodyPhase extends Phase { parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); } if (tree.elementInScope(token.name)) { - popOpenElementsUntil(token.name); + popOpenElementsUntil(token); tree.clearActiveFormattingElements(); } } @@ -2162,6 +2177,7 @@ class InBodyPhase extends Phase { token.span, "unexpected-end-tag", {"name": token.name}); } while (tree.openElements.removeLast() != node); + node.endSourceSpan = token.span; break; } else { if (specialElements.contains(getElementNameTuple(node))) { @@ -2408,7 +2424,8 @@ class InTablePhase extends Phase { while (tree.openElements.last.localName != "table") { tree.openElements.removeLast(); } - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; parser.resetInsertionMode(); } else { // innerHTML case @@ -2585,7 +2602,8 @@ class InCaptionPhase extends Phase { while (tree.openElements.last.localName != "caption") { tree.openElements.removeLast(); } - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; tree.clearActiveFormattingElements(); parser.phase = parser._inTablePhase; } else { @@ -2678,7 +2696,8 @@ class InColumnGroupPhase extends Phase { assert(parser.innerHTMLMode); parser.parseError(token.span, "undefined-error"); } else { - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; parser.phase = parser._inTablePhase; } } @@ -2790,7 +2809,8 @@ class InTableBodyPhase extends Phase { void endTagTableRowGroup(EndTagToken token) { if (tree.elementInScope(token.name, variant: "table")) { clearStackToTableBodyContext(); - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; parser.phase = parser._inTablePhase; } else { parser.parseError( @@ -2924,7 +2944,8 @@ class InRowPhase extends Phase { void endTagTr(EndTagToken token) { if (!ignoreEndTagTr()) { clearStackToTableRowContext(); - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; parser.phase = parser._inTableBodyPhase; } else { // innerHTML case @@ -3048,9 +3069,10 @@ class InCellPhase extends Phase { if (tree.openElements.last.localName != token.name) { parser.parseError( token.span, "unexpected-cell-end-tag", {"name": token.name}); - popOpenElementsUntil(token.name); + popOpenElementsUntil(token); } else { - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; } tree.clearActiveFormattingElements(); parser.phase = parser._inRowPhase; @@ -3181,7 +3203,8 @@ class InSelectPhase extends Phase { void endTagOption(EndTagToken token) { if (tree.openElements.last.localName == "option") { - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; } else { parser.parseError( token.span, "unexpected-end-tag-in-select", {"name": "option"}); @@ -3197,7 +3220,8 @@ class InSelectPhase extends Phase { } // It also closes </optgroup> if (tree.openElements.last.localName == "optgroup") { - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; // But nothing else } else { parser.parseError( @@ -3207,7 +3231,7 @@ class InSelectPhase extends Phase { void endTagSelect(EndTagToken token) { if (tree.elementInScope("select", variant: "select")) { - popOpenElementsUntil("select"); + popOpenElementsUntil(token); parser.resetInsertionMode(); } else { // innerHTML case @@ -3512,6 +3536,12 @@ class AfterBodyPhase extends Phase { } void endTagHtml(Token token) { + for (var node in tree.openElements.reversed) { + if (node.localName == 'html') { + node.endSourceSpan = token.span; + break; + } + } if (parser.innerHTMLMode) { parser.parseError(token.span, "unexpected-end-tag-after-body-innerhtml"); } else { @@ -3595,7 +3625,8 @@ class InFramesetPhase extends Phase { parser.parseError( token.span, "unexpected-frameset-in-frameset-innerhtml"); } else { - tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); + node.endSourceSpan = token.span; } if (!parser.innerHTMLMode && tree.openElements.last.localName != "frameset") { diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 409cba429..83e679a7c 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -78,7 +78,7 @@ class TreeBuilder { Node headPointer; - Node formPointer; + Element formPointer; /// Switch the function used to insert an element from the /// normal one to the misnested table one and back again diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 568819b5e..54d68a945 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -7,8 +7,10 @@ import 'package:html/parser.dart'; import 'package:html/src/constants.dart'; import 'package:html/src/encoding_parser.dart'; import 'package:html/src/treebuilder.dart'; +import 'package:source_span/source_span.dart'; main() { + _testElementSpans(); test('doctype is cloneable', () { var doc = parse('<!doctype HTML>'); DocumentType doctype = doc.nodes[0]; @@ -332,3 +334,143 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); }); } + +_testElementSpans() { + assertSpan(SourceSpan span, int offset, int end, String text) { + expect(span, isNotNull); + expect(span.start.offset, offset); + expect(span.end.offset, end); + expect(span.text, text); + } + + group('element spans', () { + test('html and body', () { + var text = '<html><body>123</body></html>'; + var doc = parse(text, generateSpans: true); + { + var elem = doc.querySelector('html'); + assertSpan(elem.sourceSpan, 0, 6, '<html>'); + assertSpan(elem.endSourceSpan, 22, 29, '</html>'); + } + { + var elem = doc.querySelector('body'); + assertSpan(elem.sourceSpan, 6, 12, '<body>'); + assertSpan(elem.endSourceSpan, 15, 22, '</body>'); + } + }); + + test('normal', () { + var text = '<div><element><span></span></element></div>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('element'); + assertSpan(elem.sourceSpan, 5, 14, '<element>'); + assertSpan(elem.endSourceSpan, 27, 37, '</element>'); + }); + + test('block', () { + var text = '<div>123</div>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('div'); + assertSpan(elem.sourceSpan, 0, 5, '<div>'); + assertSpan(elem.endSourceSpan, 8, 14, '</div>'); + }); + + test('form', () { + var text = '<form>123</form>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('form'); + assertSpan(elem.sourceSpan, 0, 6, '<form>'); + assertSpan(elem.endSourceSpan, 9, 16, '</form>'); + }); + + test('p explicit end', () { + var text = '<p>123</p>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('p'); + assertSpan(elem.sourceSpan, 0, 3, '<p>'); + assertSpan(elem.endSourceSpan, 6, 10, '</p>'); + }); + + test('p implicit end', () { + var text = '<div><p>123<p>456</div>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('p'); + assertSpan(elem.sourceSpan, 5, 8, '<p>'); + expect(elem.endSourceSpan, isNull); + }); + + test('li', () { + var text = '<li>123</li>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('li'); + assertSpan(elem.sourceSpan, 0, 4, '<li>'); + assertSpan(elem.endSourceSpan, 7, 12, '</li>'); + }); + + test('heading', () { + var text = '<h1>123</h1>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('h1'); + assertSpan(elem.sourceSpan, 0, 4, '<h1>'); + assertSpan(elem.endSourceSpan, 7, 12, '</h1>'); + }); + + test('formatting', () { + var text = '<b>123</b>'; + var doc = parse(text, generateSpans: true); + var elem = doc.querySelector('b'); + assertSpan(elem.sourceSpan, 0, 3, '<b>'); + assertSpan(elem.endSourceSpan, 6, 10, '</b>'); + }); + + test('table tbody', () { + var text = '<table><tbody> </tbody></table>'; + var doc = parse(text, generateSpans: true); + { + var elem = doc.querySelector('tbody'); + assertSpan(elem.sourceSpan, 7, 14, '<tbody>'); + assertSpan(elem.endSourceSpan, 16, 24, '</tbody>'); + } + }); + + test('table tr td', () { + var text = '<table><tr><td>123</td></tr></table>'; + var doc = parse(text, generateSpans: true); + { + var elem = doc.querySelector('table'); + assertSpan(elem.sourceSpan, 0, 7, '<table>'); + assertSpan(elem.endSourceSpan, 28, 36, '</table>'); + } + { + var elem = doc.querySelector('tr'); + assertSpan(elem.sourceSpan, 7, 11, '<tr>'); + assertSpan(elem.endSourceSpan, 23, 28, '</tr>'); + } + { + var elem = doc.querySelector('td'); + assertSpan(elem.sourceSpan, 11, 15, '<td>'); + assertSpan(elem.endSourceSpan, 18, 23, '</td>'); + } + }); + + test('select optgroup option', () { + var text = '<select><optgroup><option>123</option></optgroup></select>'; + var doc = parse(text, generateSpans: true); + { + var elem = doc.querySelector('select'); + assertSpan(elem.sourceSpan, 0, 8, '<select>'); + assertSpan(elem.endSourceSpan, 49, 58, '</select>'); + } + { + var elem = doc.querySelector('optgroup'); + assertSpan(elem.sourceSpan, 8, 18, '<optgroup>'); + assertSpan(elem.endSourceSpan, 38, 49, '</optgroup>'); + } + { + var elem = doc.querySelector('option'); + assertSpan(elem.sourceSpan, 18, 26, '<option>'); + assertSpan(elem.endSourceSpan, 29, 38, '</option>'); + } + }); + }); +} \ No newline at end of file From d7e450643c2af9b5b8f088a4d8049bad47c5c35e Mon Sep 17 00:00:00 2001 From: Sigmund Cherem <sigmund@google.com> Date: Fri, 28 Aug 2015 13:15:11 -0700 Subject: [PATCH 060/212] Prepare version for release --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 2562a13f6..588c735a2 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html package. +#### Pub version 0.12.2 + * Added `Element.endSourceSpan`, containing the span of a closing tag. + #### Pub version 0.12.0+1 * Support `csslib` version `0.12.0`. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 7237df21f..15c83c79c 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.12.1+2 +version: 0.12.2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From fe436304944a33e225d00f05a42d692d61123789 Mon Sep 17 00:00:00 2001 From: Sigmund Cherem <sigmund@google.com> Date: Wed, 16 Dec 2015 17:34:24 -0800 Subject: [PATCH 061/212] re-publish package:html, but without the .packages file. Fixes dart-lang/html#25262 R=johnmccutchan@google.com Review URL: https://codereview.chromium.org//1528213003 . --- pkgs/html/.gitignore | 1 + pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkgs/html/.gitignore b/pkgs/html/.gitignore index e97917062..f20a0d087 100644 --- a/pkgs/html/.gitignore +++ b/pkgs/html/.gitignore @@ -2,6 +2,7 @@ .pub build/ packages +.packages # Or the files created by dart2js. *.dart.js diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 588c735a2..f4861d1fa 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html package. +#### Pub version 0.12.2+1 + * Exclude `.packages` file from the published package. + #### Pub version 0.12.2 * Added `Element.endSourceSpan`, containing the span of a closing tag. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 15c83c79c..64c8ea69f 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.12.2 +version: 0.12.2+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From 8269025a1716218077fdd9bcccaa68875e35df55 Mon Sep 17 00:00:00 2001 From: Bob Nystrom <robert@stuffwithstuff.com> Date: Thu, 21 Apr 2016 13:46:14 -0700 Subject: [PATCH 062/212] Expand the version constraint to allow using csslib 0.13.x. I've pushed out new versions of csslib that are strong mode clean. They technically have some breaking changes, so I bumped the version past 0.12.0, but in practice html works with them just fine. This allows that. R=jmesserly@google.com Review URL: https://codereview.chromium.org//1907013002 . --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index f4861d1fa..4dbea3924 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html package. +#### Pub version 0.12.2+2 + * Support `csslib` versions `0.13.x`. + #### Pub version 0.12.2+1 * Exclude `.packages` file from the published package. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 64c8ea69f..697d1c890 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html -version: 0.12.2+1 +version: 0.12.2+2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0 <0.13.0' + csslib: '>=0.10.0 <0.14.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From 1b44f03b11dbf3869e013855e1b6c3b8e4bd7864 Mon Sep 17 00:00:00 2001 From: Sigmund Cherem <sigmund@google.com> Date: Wed, 11 May 2016 16:16:23 -0700 Subject: [PATCH 063/212] Make package:html strong clean R=jmesserly@google.com Review URL: https://codereview.chromium.org//1971923002 . --- pkgs/html/.analysis_options | 2 + pkgs/html/CHANGELOG.md | 8 + pkgs/html/lib/dom.dart | 36 +-- pkgs/html/lib/parser.dart | 335 ++++++++++++++++-------- pkgs/html/lib/src/css_class_set.dart | 28 +- pkgs/html/lib/src/encoding_parser.dart | 30 ++- pkgs/html/lib/src/list_proxy.dart | 15 +- pkgs/html/lib/src/query_selector.dart | 5 +- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/utils.dart | 2 +- pkgs/html/pubspec.yaml | 4 +- pkgs/html/test/dom_test.dart | 108 ++++---- pkgs/html/test/parser_feature_test.dart | 10 +- pkgs/html/test/run_all.dart | 2 +- pkgs/html/test/support.dart | 9 +- 15 files changed, 369 insertions(+), 227 deletions(-) create mode 100644 pkgs/html/.analysis_options diff --git a/pkgs/html/.analysis_options b/pkgs/html/.analysis_options new file mode 100644 index 000000000..a10d4c5a0 --- /dev/null +++ b/pkgs/html/.analysis_options @@ -0,0 +1,2 @@ +analyzer: + strong-mode: true diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 4dbea3924..3320989f8 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,14 @@ This file contains highlights of what changes on each version of the html package. +## 0.13.0 + + * **BREAKING** Fix all [strong mode][] errors and warnings. + This involved adding more precise types on some public APIs, which is why it + may break users. + +[strong mode]: https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md + #### Pub version 0.12.2+2 * Support `csslib` versions `0.13.x`. diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 9e6475957..63182f634 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -742,16 +742,17 @@ class NodeList extends ListProxy<Node> { // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see // http://code.google.com/p/dart/issues/detail?id=5371 - void setRange(int start, int rangeLength, List<Node> from, + void setRange(int start, int rangeLength, Iterable<Node> from, [int startFrom = 0]) { - if (from is NodeList) { + List<Node> from_ = from as List<Node>; + if (from_ is NodeList) { // Note: this is presumed to make a copy - from = from.sublist(startFrom, startFrom + rangeLength); + from_ = from_.sublist(startFrom, startFrom + rangeLength); } // Note: see comment in [addAll]. We need to be careful about the order of // operations if [from] is also a NodeList. for (int i = rangeLength - 1; i >= 0; i--) { - this[start + i] = from[startFrom + i]; + this[start + i] = from_[startFrom + i]; } } @@ -765,14 +766,14 @@ class NodeList extends ListProxy<Node> { super.removeRange(start, rangeLength); } - void removeWhere(bool test(Element e)) { + void removeWhere(bool test(Node e)) { for (var node in where(test)) { node.parentNode = null; } super.removeWhere(test); } - void retainWhere(bool test(Element e)) { + void retainWhere(bool test(Node e)) { for (var node in where((n) => !test(n))) { node.parentNode = null; } @@ -786,11 +787,11 @@ class NodeList extends ListProxy<Node> { super.insertAll(index, list); } - _flattenDocFragments(Iterable<Node> collection) { + List<Node> _flattenDocFragments(Iterable<Node> collection) { // Note: this function serves two purposes: // * it flattens document fragments // * it creates a copy of [collections] when `collection is NodeList`. - var result = []; + var result = <Node>[]; for (var node in collection) { if (node is DocumentFragment) { result.addAll(node.nodes); @@ -860,7 +861,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> } } - bool contains(Element element) { + bool contains(Object element) { return element is Element && _childNodes.contains(element); } @@ -901,9 +902,10 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> return result; } - Iterable map(f(Element element)) => _filtered.map(f); + Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(Element element)) => _filtered.map(f); Iterable<Element> where(bool f(Element element)) => _filtered.where(f); - Iterable expand(Iterable f(Element element)) => _filtered.expand(f); + Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(Element element)) => + _filtered.expand(f); void insert(int index, Element value) { _childNodes.insert(index, value); @@ -935,8 +937,8 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> return _filtered.reduce(combine); } - dynamic fold(dynamic initialValue, - dynamic combine(dynamic previousValue, Element element)) { + dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, + dynamic/*=T*/ combine(var/*=T*/ previousValue, Element element)) { return _filtered.fold(initialValue, combine); } @@ -968,10 +970,14 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> List<Element> sublist(int start, [int end]) => _filtered.sublist(start, end); Iterable<Element> getRange(int start, int end) => _filtered.getRange(start, end); - int indexOf(Element element, [int start = 0]) => + // TODO(sigmund): this should be typed Element, but we currently run into a + // bug where ListMixin<E>.indexOf() expects Object as the argument. + int indexOf(element, [int start = 0]) => _filtered.indexOf(element, start); - int lastIndexOf(Element element, [int start = null]) { + // TODO(sigmund): this should be typed Element, but we currently run into a + // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. + int lastIndexOf(element, [int start = null]) { if (start == null) start = length - 1; return _filtered.lastIndexOf(element, start); } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index dc95941df..0575b3d66 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -210,7 +210,7 @@ class HtmlParser { try { mainLoop(); break; - } on ReparseException catch (e) { + } on ReparseException catch (_) { // Note: this happens if we start parsing but the character encoding // changes. So we should only need to restart very early in the parse. reset(); @@ -819,7 +819,8 @@ class BeforeHtmlPhase extends Phase { // helper methods void insertHtmlElement() { - tree.insertRoot(new StartTagToken("html", data: {})); + tree.insertRoot(new StartTagToken("html", + data: new LinkedHashMap<dynamic, String>())); parser.phase = parser._beforeHeadPhase; } @@ -875,7 +876,8 @@ class BeforeHeadPhase extends Phase { case 'html': return startTagHtml(token); case 'head': - return startTagHead(token); + startTagHead(token); + return null; default: return startTagOther(token); } @@ -889,12 +891,14 @@ class BeforeHeadPhase extends Phase { case "br": return endTagImplyHead(token); default: - return endTagOther(token); + endTagOther(token); + return null; } } bool processEOF() { - startTagHead(new StartTagToken("head", data: {})); + startTagHead(new StartTagToken("head", + data: new LinkedHashMap<dynamic, String>())); return true; } @@ -903,7 +907,8 @@ class BeforeHeadPhase extends Phase { } Token processCharacters(CharactersToken token) { - startTagHead(new StartTagToken("head", data: {})); + startTagHead(new StartTagToken("head", + data: new LinkedHashMap<dynamic, String>())); return token; } @@ -918,12 +923,14 @@ class BeforeHeadPhase extends Phase { } Token startTagOther(StartTagToken token) { - startTagHead(new StartTagToken("head", data: {})); + startTagHead(new StartTagToken("head", + data: new LinkedHashMap<dynamic, String>())); return token; } Token endTagImplyHead(EndTagToken token) { - startTagHead(new StartTagToken("head", data: {})); + startTagHead(new StartTagToken("head", + data: new LinkedHashMap<dynamic, String>())); return token; } @@ -941,23 +948,29 @@ class InHeadPhase extends Phase { case "html": return startTagHtml(token); case "title": - return startTagTitle(token); + startTagTitle(token); + return null; case "noscript": case "noframes": case "style": - return startTagNoScriptNoFramesStyle(token); + startTagNoScriptNoFramesStyle(token); + return null; case "script": - return startTagScript(token); + startTagScript(token); + return null; case "base": case "basefont": case "bgsound": case "command": case "link": - return startTagBaseLinkCommand(token); + startTagBaseLinkCommand(token); + return null; case "meta": - return startTagMeta(token); + startTagMeta(token); + return null; case "head": - return startTagHead(token); + startTagHead(token); + return null; default: return startTagOther(token); } @@ -966,13 +979,15 @@ class InHeadPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "head": - return endTagHead(token); + endTagHead(token); + return null; case "br": case "html": case "body": return endTagHtmlBodyBr(token); default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -1075,9 +1090,11 @@ class AfterHeadPhase extends Phase { case "html": return startTagHtml(token); case "body": - return startTagBody(token); + startTagBody(token); + return null; case "frameset": - return startTagFrameset(token); + startTagFrameset(token); + return null; case "base": case "basefont": case "bgsound": @@ -1087,9 +1104,11 @@ class AfterHeadPhase extends Phase { case "script": case "style": case "title": - return startTagFromHead(token); + startTagFromHead(token); + return null; case "head": - return startTagHead(token); + startTagHead(token); + return null; default: return startTagOther(token); } @@ -1102,7 +1121,8 @@ class AfterHeadPhase extends Phase { case "br": return endTagHtmlBodyBr(token); default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -1164,7 +1184,8 @@ class AfterHeadPhase extends Phase { } void anythingElse() { - tree.insertElement(new StartTagToken("body", data: {})); + tree.insertElement(new StartTagToken("body", + data: new LinkedHashMap<dynamic, String>())); parser.phase = parser._inBodyPhase; parser.framesetOK = true; } @@ -1195,9 +1216,11 @@ class InBodyPhase extends Phase { case "title": return startTagProcessInHead(token); case "body": - return startTagBody(token); + startTagBody(token); + return null; case "frameset": - return startTagFrameset(token); + startTagFrameset(token); + return null; case "address": case "article": case "aside": @@ -1221,7 +1244,8 @@ class InBodyPhase extends Phase { case "section": case "summary": case "ul": - return startTagCloseP(token); + startTagCloseP(token); + return null; // headingElements case "h1": case "h2": @@ -1229,20 +1253,26 @@ class InBodyPhase extends Phase { case "h4": case "h5": case "h6": - return startTagHeading(token); + startTagHeading(token); + return null; case "pre": case "listing": - return startTagPreListing(token); + startTagPreListing(token); + return null; case "form": - return startTagForm(token); + startTagForm(token); + return null; case "li": case "dd": case "dt": - return startTagListItem(token); + startTagListItem(token); + return null; case "plaintext": - return startTagPlaintext(token); + startTagPlaintext(token); + return null; case "a": - return startTagA(token); + startTagA(token); + return null; case "b": case "big": case "code": @@ -1255,58 +1285,77 @@ class InBodyPhase extends Phase { case "strong": case "tt": case "u": - return startTagFormatting(token); + startTagFormatting(token); + return null; case "nobr": - return startTagNobr(token); + startTagNobr(token); + return null; case "button": return startTagButton(token); case "applet": case "marquee": case "object": - return startTagAppletMarqueeObject(token); + startTagAppletMarqueeObject(token); + return null; case "xmp": - return startTagXmp(token); + startTagXmp(token); + return null; case "table": - return startTagTable(token); + startTagTable(token); + return null; case "area": case "br": case "embed": case "img": case "keygen": case "wbr": - return startTagVoidFormatting(token); + startTagVoidFormatting(token); + return null; case "param": case "source": case "track": - return startTagParamSource(token); + startTagParamSource(token); + return null; case "input": - return startTagInput(token); + startTagInput(token); + return null; case "hr": - return startTagHr(token); + startTagHr(token); + return null; case "image": - return startTagImage(token); + startTagImage(token); + return null; case "isindex": - return startTagIsIndex(token); + startTagIsIndex(token); + return null; case "textarea": - return startTagTextarea(token); + startTagTextarea(token); + return null; case "iframe": - return startTagIFrame(token); + startTagIFrame(token); + return null; case "noembed": case "noframes": case "noscript": - return startTagRawtext(token); + startTagRawtext(token); + return null; case "select": - return startTagSelect(token); + startTagSelect(token); + return null; case "rp": case "rt": - return startTagRpRt(token); + startTagRpRt(token); + return null; case "option": case "optgroup": - return startTagOpt(token); + startTagOpt(token); + return null; case "math": - return startTagMath(token); + startTagMath(token); + return null; case "svg": - return startTagSvg(token); + startTagSvg(token); + return null; case "caption": case "col": case "colgroup": @@ -1318,7 +1367,8 @@ class InBodyPhase extends Phase { case "th": case "thead": case "tr": - return startTagMisplaced(token); + startTagMisplaced(token); + return null; default: return startTagOther(token); } @@ -1327,7 +1377,8 @@ class InBodyPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "body": - return endTagBody(token); + endTagBody(token); + return null; case "html": return endTagHtml(token); case "address": @@ -1353,15 +1404,19 @@ class InBodyPhase extends Phase { case "section": case "summary": case "ul": - return endTagBlock(token); + endTagBlock(token); + return null; case "form": - return endTagForm(token); + endTagForm(token); + return null; case "p": - return endTagP(token); + endTagP(token); + return null; case "dd": case "dt": case "li": - return endTagListItem(token); + endTagListItem(token); + return null; // headingElements case "h1": case "h2": @@ -1369,7 +1424,8 @@ class InBodyPhase extends Phase { case "h4": case "h5": case "h6": - return endTagHeading(token); + endTagHeading(token); + return null; case "a": case "b": case "big": @@ -1384,15 +1440,19 @@ class InBodyPhase extends Phase { case "strong": case "tt": case "u": - return endTagFormatting(token); + endTagFormatting(token); + return null; case "applet": case "marquee": case "object": - return endTagAppletMarqueeObject(token); + endTagAppletMarqueeObject(token); + return null; case "br": - return endTagBr(token); + endTagBr(token); + return null; default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -1733,28 +1793,31 @@ class InBodyPhase extends Phase { if (tree.formPointer != null) { return; } - var formAttrs = {}; + var formAttrs = new LinkedHashMap<dynamic, String>(); var dataAction = token.data["action"]; if (dataAction != null) { formAttrs["action"] = dataAction; } processStartTag(new StartTagToken("form", data: formAttrs)); - processStartTag(new StartTagToken("hr", data: {})); - processStartTag(new StartTagToken("label", data: {})); + processStartTag(new StartTagToken("hr", + data: new LinkedHashMap<dynamic, String>())); + processStartTag(new StartTagToken("label", + data: new LinkedHashMap<dynamic, String>())); // XXX Localization ... var prompt = token.data["prompt"]; if (prompt == null) { prompt = "This is a searchable index. Enter search keywords: "; } processCharacters(new CharactersToken(prompt)); - var attributes = new LinkedHashMap.from(token.data); + var attributes = new LinkedHashMap<dynamic, String>.from(token.data); attributes.remove('action'); attributes.remove('prompt'); attributes["name"] = "isindex"; processStartTag(new StartTagToken( "input", data: attributes, selfClosing: token.selfClosing)); processEndTag(new EndTagToken("label")); - processStartTag(new StartTagToken("hr", data: {})); + processStartTag(new StartTagToken("hr", + data: new LinkedHashMap<dynamic, String>())); processEndTag(new EndTagToken("form")); } @@ -1857,7 +1920,8 @@ class InBodyPhase extends Phase { void endTagP(EndTagToken token) { if (!tree.elementInScope("p", variant: "button")) { - startTagCloseP(new StartTagToken("p", data: {})); + startTagCloseP(new StartTagToken("p", + data: new LinkedHashMap<dynamic, String>())); parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); endTagP(new EndTagToken("p")); } else { @@ -1994,7 +2058,7 @@ class InBodyPhase extends Phase { } /// The much-feared adoption agency algorithm. - endTagFormatting(EndTagToken token) { + void endTagFormatting(EndTagToken token) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency // TODO(jmesserly): the comments here don't match the numbered steps in the // updated spec. This needs a pass over it to verify that it still matches. @@ -2164,7 +2228,8 @@ class InBodyPhase extends Phase { "newName": "br element" }); tree.reconstructActiveFormattingElements(); - tree.insertElement(new StartTagToken("br", data: {})); + tree.insertElement(new StartTagToken("br", + data: new LinkedHashMap<dynamic, String>())); tree.openElements.removeLast(); } @@ -2199,8 +2264,11 @@ class TextPhase extends Phase { } processEndTag(EndTagToken token) { - if (token.name == 'script') return endTagScript(token); - return endTagOther(token); + if (token.name == 'script') { + endTagScript(token); + return null; + } + endTagOther(token); } Token processCharacters(CharactersToken token) { @@ -2240,15 +2308,18 @@ class InTablePhase extends Phase { case "html": return startTagHtml(token); case "caption": - return startTagCaption(token); + startTagCaption(token); + return null; case "colgroup": - return startTagColgroup(token); + startTagColgroup(token); + return null; case "col": return startTagCol(token); case "tbody": case "tfoot": case "thead": - return startTagRowGroup(token); + startTagRowGroup(token); + return null; case "td": case "th": case "tr": @@ -2259,18 +2330,22 @@ class InTablePhase extends Phase { case "script": return startTagStyleScript(token); case "input": - return startTagInput(token); + startTagInput(token); + return null; case "form": - return startTagForm(token); + startTagForm(token); + return null; default: - return startTagOther(token); + startTagOther(token); + return null; } } processEndTag(EndTagToken token) { switch (token.name) { case "table": - return endTagTable(token); + endTagTable(token); + return null; case "body": case "caption": case "col": @@ -2282,9 +2357,11 @@ class InTablePhase extends Phase { case "th": case "thead": case "tr": - return endTagIgnore(token); + endTagIgnore(token); + return null; default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -2350,7 +2427,8 @@ class InTablePhase extends Phase { } Token startTagCol(StartTagToken token) { - startTagColgroup(new StartTagToken("colgroup", data: {})); + startTagColgroup(new StartTagToken("colgroup", + data: new LinkedHashMap<dynamic, String>())); return token; } @@ -2361,7 +2439,8 @@ class InTablePhase extends Phase { } Token startTagImplyTbody(StartTagToken token) { - startTagRowGroup(new StartTagToken("tbody", data: {})); + startTagRowGroup(new StartTagToken("tbody", + data: new LinkedHashMap<dynamic, String>())); return token; } @@ -2542,7 +2621,8 @@ class InCaptionPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "caption": - return endTagCaption(token); + endTagCaption(token); + return null; case "table": return endTagTable(token); case "body": @@ -2555,7 +2635,8 @@ class InCaptionPhase extends Phase { case "th": case "thead": case "tr": - return endTagIgnore(token); + endTagIgnore(token); + return null; default: return endTagOther(token); } @@ -2641,7 +2722,8 @@ class InColumnGroupPhase extends Phase { case "html": return startTagHtml(token); case "col": - return startTagCol(token); + startTagCol(token); + return null; default: return startTagOther(token); } @@ -2650,9 +2732,11 @@ class InColumnGroupPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "colgroup": - return endTagColgroup(token); + endTagColgroup(token); + return null; case "col": - return endTagCol(token); + endTagCol(token); + return null; default: return endTagOther(token); } @@ -2722,7 +2806,8 @@ class InTableBodyPhase extends Phase { case "html": return startTagHtml(token); case "tr": - return startTagTr(token); + startTagTr(token); + return null; case "td": case "th": return startTagTableCell(token); @@ -2743,7 +2828,8 @@ class InTableBodyPhase extends Phase { case "tbody": case "tfoot": case "thead": - return endTagTableRowGroup(token); + endTagTableRowGroup(token); + return null; case "table": return endTagTable(token); case "body": @@ -2754,7 +2840,8 @@ class InTableBodyPhase extends Phase { case "td": case "th": case "tr": - return endTagIgnore(token); + endTagIgnore(token); + return null; default: return endTagOther(token); } @@ -2796,7 +2883,8 @@ class InTableBodyPhase extends Phase { Token startTagTableCell(StartTagToken token) { parser.parseError( token.span, "unexpected-cell-in-table-body", {"name": token.name}); - startTagTr(new StartTagToken("tr", data: {})); + startTagTr(new StartTagToken("tr", + data: new LinkedHashMap<dynamic, String>())); return token; } @@ -2854,7 +2942,8 @@ class InRowPhase extends Phase { return startTagHtml(token); case "td": case "th": - return startTagTableCell(token); + startTagTableCell(token); + return null; case "caption": case "col": case "colgroup": @@ -2871,7 +2960,8 @@ class InRowPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "tr": - return endTagTr(token); + endTagTr(token); + return null; case "table": return endTagTable(token); case "tbody": @@ -2885,7 +2975,8 @@ class InRowPhase extends Phase { case "html": case "td": case "th": - return endTagIgnore(token); + endTagIgnore(token); + return null; default: return endTagOther(token); } @@ -3009,13 +3100,15 @@ class InCellPhase extends Phase { switch (token.name) { case "td": case "th": - return endTagTableCell(token); + endTagTableCell(token); + return null; case "body": case "caption": case "col": case "colgroup": case "html": - return endTagIgnore(token); + endTagIgnore(token); + return null; case "table": case "tbody": case "tfoot": @@ -3109,11 +3202,14 @@ class InSelectPhase extends Phase { case "html": return startTagHtml(token); case "option": - return startTagOption(token); + startTagOption(token); + return null; case "optgroup": - return startTagOptgroup(token); + startTagOptgroup(token); + return null; case "select": - return startTagSelect(token); + startTagSelect(token); + return null; case "input": case "keygen": case "textarea": @@ -3128,13 +3224,17 @@ class InSelectPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "option": - return endTagOption(token); + endTagOption(token); + return null; case "optgroup": - return endTagOptgroup(token); + endTagOptgroup(token); + return null; case "select": - return endTagSelect(token); + endTagSelect(token); + return null; default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -3504,7 +3604,10 @@ class AfterBodyPhase extends Phase { } processEndTag(EndTagToken token) { - if (token.name == "html") return endTagHtml(token); + if (token.name == "html") { + endTagHtml(token); + return null; + } return endTagOther(token); } @@ -3566,9 +3669,11 @@ class InFramesetPhase extends Phase { case "html": return startTagHtml(token); case "frameset": - return startTagFrameset(token); + startTagFrameset(token); + return null; case "frame": - return startTagFrame(token); + startTagFrame(token); + return null; case "noframes": return startTagNoframes(token); default: @@ -3579,9 +3684,11 @@ class InFramesetPhase extends Phase { processEndTag(EndTagToken token) { switch (token.name) { case "frameset": - return endTagFrameset(token); + endTagFrameset(token); + return null; default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -3653,16 +3760,19 @@ class AfterFramesetPhase extends Phase { case "noframes": return startTagNoframes(token); default: - return startTagOther(token); + startTagOther(token); + return null; } } processEndTag(EndTagToken token) { switch (token.name) { case "html": - return endTagHtml(token); + endTagHtml(token); + return null; default: - return endTagOther(token); + endTagOther(token); + return null; } } @@ -3748,7 +3858,8 @@ class AfterAfterFramesetPhase extends Phase { case "noframes": return startTagNoFrames(token); default: - return startTagOther(token); + startTagOther(token); + return null; } } diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 2e131a538..c7927b82c 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -55,7 +55,7 @@ abstract class CssClassSet implements Set<String> { * This is the Dart equivalent of jQuery's * [hasClass](http://api.jquery.com/hasClass/). */ - bool contains(String value); + bool contains(Object value); /** * Add the class [value] to element. @@ -93,7 +93,7 @@ abstract class CssClassSet implements Set<String> { * This is the Dart equivalent of jQuery's * [removeClass](http://api.jquery.com/removeClass/). */ - void removeAll(Iterable<String> iterable); + void removeAll(Iterable<Object> iterable); /** * Toggles all classes specified in [iterable] on element. @@ -151,11 +151,11 @@ abstract class CssClassSetImpl implements CssClassSet { String join([String separator = ""]) => readClasses().join(separator); - Iterable map(f(String element)) => readClasses().map(f); + Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(String e)) => readClasses().map(f); Iterable<String> where(bool f(String element)) => readClasses().where(f); - Iterable expand(Iterable f(String element)) => readClasses().expand(f); + Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(String element)) => readClasses().expand(f); bool every(bool f(String element)) => readClasses().every(f); @@ -171,8 +171,8 @@ abstract class CssClassSetImpl implements CssClassSet { return readClasses().reduce(combine); } - dynamic fold(dynamic initialValue, - dynamic combine(dynamic previousValue, String element)) { + dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, + dynamic/*=T*/ combine(var/*=T*/ previousValue, String element)) { return readClasses().fold(initialValue, combine); } // interface Collection - END @@ -184,10 +184,10 @@ abstract class CssClassSetImpl implements CssClassSet { * This is the Dart equivalent of jQuery's * [hasClass](http://api.jquery.com/hasClass/). */ - bool contains(String value) => readClasses().contains(value); + bool contains(Object value) => readClasses().contains(value); /** Lookup from the Set interface. Not interesting for a String set. */ - String lookup(String value) => contains(value) ? value : null; + String lookup(Object value) => contains(value) ? value as String : null; /** * Add the class [value] to element. @@ -233,7 +233,7 @@ abstract class CssClassSetImpl implements CssClassSet { * This is the Dart equivalent of jQuery's * [removeClass](http://api.jquery.com/removeClass/). */ - void removeAll(Iterable<String> iterable) { + void removeAll(Iterable<Object> iterable) { modify((s) => s.removeAll(iterable)); } @@ -251,7 +251,7 @@ abstract class CssClassSetImpl implements CssClassSet { iterable.forEach((e) => toggle(e, shouldAdd)); } - void retainAll(Iterable<String> iterable) { + void retainAll(Iterable<Object> iterable) { modify((s) => s.retainAll(iterable)); } @@ -263,10 +263,10 @@ abstract class CssClassSetImpl implements CssClassSet { modify((s) => s.retainWhere(test)); } - bool containsAll(Iterable<String> collection) => + bool containsAll(Iterable<Object> collection) => readClasses().containsAll(collection); - Set<String> intersection(Set<String> other) => + Set<String> intersection(Set<Object> other) => readClasses().intersection(other); Set<String> union(Set<String> other) => readClasses().union(other); @@ -285,9 +285,9 @@ abstract class CssClassSetImpl implements CssClassSet { Iterable<String> skip(int n) => readClasses().skip(n); Iterable<String> skipWhile(bool test(String value)) => readClasses().skipWhile(test); - dynamic firstWhere(bool test(String value), {Object orElse()}) => + String firstWhere(bool test(String value), {String orElse()}) => readClasses().firstWhere(test, orElse: orElse); - dynamic lastWhere(bool test(String value), {Object orElse()}) => + String lastWhere(bool test(String value), {String orElse()}) => readClasses().lastWhere(test, orElse: orElse); String singleWhere(bool test(String value)) => readClasses().singleWhere(test); diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index fd64ff9b0..0b84989ad 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -121,6 +121,14 @@ class EncodingBytes { } } +typedef bool _MethodHandler(); + +class _DispatchEntry { + final String pattern; + final _MethodHandler handler; + _DispatchEntry(this.pattern, this.handler); +} + /// Mini parser for detecting character encoding from meta elements. class EncodingParser { final EncodingBytes data; @@ -133,19 +141,19 @@ class EncodingParser { String getEncoding() { final methodDispatch = [ - ["<!--", handleComment], - ["<meta", handleMeta], - ["</", handlePossibleEndTag], - ["<!", handleOther], - ["<?", handleOther], - ["<", handlePossibleStartTag] + new _DispatchEntry("<!--", handleComment), + new _DispatchEntry("<meta", handleMeta), + new _DispatchEntry("</", handlePossibleEndTag), + new _DispatchEntry("<!", handleOther), + new _DispatchEntry("<?", handleOther), + new _DispatchEntry("<", handlePossibleStartTag), ]; try { for (;;) { for (var dispatch in methodDispatch) { - if (data.matchBytes(dispatch[0])) { - var keepParsing = dispatch[1](); + if (data.matchBytes(dispatch.pattern)) { + var keepParsing = dispatch.handler(); if (keepParsing) break; // We found an encoding. Stop. @@ -154,7 +162,7 @@ class EncodingParser { } data.position += 1; } - } on StateError catch (e) { + } on StateError catch (_) { // Catch this here to match behavior of Python's StopIteration // TODO(jmesserly): refactor to not use exceptions } @@ -352,12 +360,12 @@ class ContentAttrParser { try { data.skipUntil(isWhitespace); return data.slice(oldPosition, data.position); - } on StateError catch (e) { + } on StateError catch (_) { //Return the whole remaining value return data.slice(oldPosition); } } - } on StateError catch (e) { + } on StateError catch (_) { return null; } } diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 99acdb673..5df1ed44f 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -20,11 +20,14 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { // TODO(jmesserly): This should be on List. // See http://code.google.com/p/dart/issues/detail?id=947 - bool remove(E item) { - int i = indexOf(item); - if (i == -1) return false; - removeAt(i); - return true; + bool remove(Object item) { + if (item is E) { + int i = indexOf(item); + if (i == -1) return false; + removeAt(i); + return true; + } + return false; } void insert(int index, E item) => _list.insert(index, item); @@ -81,7 +84,7 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { List<E> getRange(int start, int end) => _list.getRange(start, end); - void setRange(int start, int length, List<E> from, [int startFrom = 0]) { + void setRange(int start, int length, Iterable<E> from, [int startFrom = 0]) { _list.setRange(start, length, from, startFrom); } void removeRange(int start, int length) { diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index e586d1aa5..3aa45f296 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -3,6 +3,7 @@ library html.src.query; import 'package:csslib/parser.dart' as css; import 'package:csslib/parser.dart' show TokenKind; +import 'package:csslib/src/messages.dart' show Message; import 'package:csslib/visitor.dart'; // the CSSOM import 'package:html/dom.dart'; import 'package:html/src/constants.dart' show isWhitespaceCC; @@ -14,7 +15,7 @@ Element querySelector(Node node, String selector) => new SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); List<Element> querySelectorAll(Node node, String selector) { - var results = []; + var results = <Element>[]; new SelectorEvaluator().querySelectorAll( node, _parseSelectorList(selector), results); return results; @@ -22,7 +23,7 @@ List<Element> querySelectorAll(Node node, String selector) { // http://dev.w3.org/csswg/selectors-4/#grouping SelectorGroup _parseSelectorList(String selector) { - var errors = []; + var errors = <Message>[]; var group = css.parseSelectorGroup(selector, errors: errors); if (group == null || errors.isNotEmpty) { throw new FormatException("'$selector' is not a valid selector: $errors"); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 3273858fa..68cb6dcd1 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -12,7 +12,7 @@ import 'utils.dart'; // TODO(jmesserly): we could use a better data structure here like a trie, if // we had it implemented in Dart. Map<String, List<String>> entitiesByFirstChar = (() { - var result = {}; + var result = <String, List<String>>{}; for (var k in entities.keys) { result.putIfAbsent(k[0], () => []).add(k); } diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index fb58cf144..16837b03d 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -43,7 +43,7 @@ bool startsWithAny(String str, List<String> prefixes) { } // Like the python [:] operator. -List slice(List list, int start, [int end]) { +List/*<T>*/ slice/*<T>*/(List/*<T>*/ list, int start, [int end]) { if (end == null) end = list.length; if (end < 0) end += list.length; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 697d1c890..4a595c1a2 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html -version: 0.12.2+2 +version: 0.13.0 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: sdk: '>=1.2.0 <2.0.0' dependencies: - csslib: '>=0.10.0 <0.14.0' + csslib: '>=0.13.2 <0.14.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index d4e0809f2..404a4882b 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -26,8 +26,8 @@ main() { test('getElementById', () { var foo = doc.body.nodes[0]; var Foo = foo.nodes[2]; - expect(foo.id, 'foo'); - expect(Foo.id, 'Foo'); + expect((foo as Element).id, 'foo'); + expect((Foo as Element).id, 'Foo'); expect(doc.getElementById('foo'), foo); expect(doc.getElementById('Foo'), Foo); }); @@ -36,8 +36,8 @@ main() { var foo = doc.body.nodes[0]; var barBaz = foo.nodes[0]; var quxBaz = foo.nodes[1]; - expect(barBaz.className, ' bar baz'); - expect(quxBaz.className, 'qux baz '); + expect((barBaz as Element).className, ' bar baz'); + expect((quxBaz as Element).className, 'qux baz '); expect(doc.getElementsByClassName('baz'), [barBaz, quxBaz]); expect(doc.getElementsByClassName('bar '), [barBaz]); expect(doc.getElementsByClassName(' qux'), [quxBaz]); @@ -57,83 +57,83 @@ main() { test('add', () { var doc = parse('<body>'); doc.body.nodes.add(parseFragment('<x-foo>')); - expect(doc.body.nodes[0].localName, 'x-foo'); + expect((doc.body.nodes[0] as Element).localName, 'x-foo'); doc.body.nodes.add(parseFragment('<x-bar>')); - expect(doc.body.nodes[1].localName, 'x-bar'); + expect((doc.body.nodes[1] as Element).localName, 'x-bar'); }); test('addLast', () { var doc = parse('<body>'); doc.body.nodes.addLast(parseFragment('<x-foo>')); - expect(doc.body.nodes[0].localName, 'x-foo'); + expect((doc.body.nodes[0] as Element).localName, 'x-foo'); doc.body.nodes.addLast(parseFragment('<x-bar>')); - expect(doc.body.nodes[1].localName, 'x-bar'); + expect((doc.body.nodes[1] as Element).localName, 'x-bar'); }); test('addAll', () { var doc = parse('<body><x-a></x-a>'); doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'x-b'); - expect(doc.body.nodes[2].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'x-b'); + expect((doc.body.nodes[2] as Element).localName, 'x-c'); }); test('insert', () { var doc = parse('<body><x-a></x-a>'); doc.body.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>')); - expect(doc.body.nodes[0].localName, 'x-b'); - expect(doc.body.nodes[1].localName, 'x-c'); - expect(doc.body.nodes[2].localName, 'x-a'); + expect((doc.body.nodes[0] as Element).localName, 'x-b'); + expect((doc.body.nodes[1] as Element).localName, 'x-c'); + expect((doc.body.nodes[2] as Element).localName, 'x-a'); doc = parse('<body><x-a></x-a>'); doc.body.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>')); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'x-b'); - expect(doc.body.nodes[2].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'x-b'); + expect((doc.body.nodes[2] as Element).localName, 'x-c'); doc = parse('<body><x-a></x-a>'); doc.body.nodes.insert(0, parseFragment('<x-b></x-b>')); doc.body.nodes.insert(1, parseFragment('<x-c></x-c>')); - expect(doc.body.nodes[0].localName, 'x-b'); - expect(doc.body.nodes[1].localName, 'x-c'); - expect(doc.body.nodes[2].localName, 'x-a'); + expect((doc.body.nodes[0] as Element).localName, 'x-b'); + expect((doc.body.nodes[1] as Element).localName, 'x-c'); + expect((doc.body.nodes[2] as Element).localName, 'x-a'); }); test('insertAll', () { var doc = parse('<body><x-a></x-a>'); doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]); - expect(doc.body.nodes[0].localName, 'x-b'); - expect(doc.body.nodes[1].localName, 'x-c'); - expect(doc.body.nodes[2].localName, 'x-a'); + expect((doc.body.nodes[0] as Element).localName, 'x-b'); + expect((doc.body.nodes[1] as Element).localName, 'x-c'); + expect((doc.body.nodes[2] as Element).localName, 'x-a'); expect(doc.body.nodes.length, 3); doc = parse('<body><x-a></x-a>'); doc.body.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'x-b'); - expect(doc.body.nodes[2].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'x-b'); + expect((doc.body.nodes[2] as Element).localName, 'x-c'); doc = parse('<body><x-a></x-a>'); doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]); doc.body.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]); - expect(doc.body.nodes[0].localName, 'x-b'); - expect(doc.body.nodes[1].localName, 'x-c'); - expect(doc.body.nodes[2].localName, 'x-a'); + expect((doc.body.nodes[0] as Element).localName, 'x-b'); + expect((doc.body.nodes[1] as Element).localName, 'x-c'); + expect((doc.body.nodes[2] as Element).localName, 'x-a'); }); test('operator []=', () { var doc = parse('<body><x-a></x-a>'); doc.body.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>'); - expect(doc.body.nodes[0].localName, 'x-b'); - expect(doc.body.nodes[1].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-b'); + expect((doc.body.nodes[1] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 2); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>'); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); - expect(doc.body.nodes[3].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); + expect((doc.body.nodes[3] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 4); }); @@ -141,18 +141,18 @@ main() { var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes.setRange(1, 2, fragment.nodes, 0); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); expect(doc.body.nodes.length, 3); fragment = parseFragment('<y-b></y-b><y-c></y-c>'); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes.setRange(1, 1, [fragment], 0); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); - expect(doc.body.nodes[3].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); + expect((doc.body.nodes[3] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 4); }); @@ -160,19 +160,19 @@ main() { var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes.replaceRange(1, 2, fragment.nodes); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); - expect(doc.body.nodes[3].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); + expect((doc.body.nodes[3] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 4); fragment = parseFragment('<y-b></y-b><y-c></y-c>'); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes.replaceRange(1, 2, [fragment]); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); - expect(doc.body.nodes[3].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); + expect((doc.body.nodes[3] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 4); }); @@ -180,10 +180,10 @@ main() { var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes[1].replaceWith(fragment); - expect(doc.body.nodes[0].localName, 'x-a'); - expect(doc.body.nodes[1].localName, 'y-b'); - expect(doc.body.nodes[2].localName, 'y-c'); - expect(doc.body.nodes[3].localName, 'x-c'); + expect((doc.body.nodes[0] as Element).localName, 'x-a'); + expect((doc.body.nodes[1] as Element).localName, 'y-b'); + expect((doc.body.nodes[2] as Element).localName, 'y-c'); + expect((doc.body.nodes[3] as Element).localName, 'x-c'); expect(doc.body.nodes.length, 4); }); }); diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 54d68a945..6d3af0ca7 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -25,12 +25,12 @@ main() { test('namespace html elements on', () { var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse(); - expect(doc.nodes[0].namespaceUri, Namespaces.html); + expect((doc.nodes[0] as Element).namespaceUri, Namespaces.html); }); test('namespace html elements off', () { var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse(); - expect(doc.nodes[0].namespaceUri, null); + expect((doc.nodes[0] as Element).namespaceUri, null); }); test('parse error spans - full', () { @@ -290,7 +290,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(e.text, 'bar'); c.text = 'qux'; - expect(c.data, 'qux'); + expect((c as Comment).data, 'qux'); expect(c.text, 'qux'); expect(e.text, 'bar'); }); @@ -310,7 +310,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); group('Encoding pre-parser', () { - getEncoding(s) => new EncodingParser(s.codeUnits).getEncoding(); + getEncoding(String s) => new EncodingParser(s.codeUnits).getEncoding(); test('gets encoding from meta charset', () { expect(getEncoding('<meta charset="utf-16">'), 'utf-16'); @@ -473,4 +473,4 @@ _testElementSpans() { } }); }); -} \ No newline at end of file +} diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart index 14e6b34ff..d2bf9ceff 100644 --- a/pkgs/html/test/run_all.dart +++ b/pkgs/html/test/run_all.dart @@ -17,7 +17,7 @@ main(List<String> args) { var pattern = new RegExp(args.length > 0 ? args[0] : '.'); useCompactVMConfiguration(); - void addGroup(testFile, testMain) { + void addGroup(testFile, void testMain()) { if (pattern.hasMatch(testFile)) { group(testFile.replaceAll('_test.dart', ':'), testMain); } diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 1b4c0b49e..1bb255016 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -10,7 +10,7 @@ import 'package:html/dom_parsing.dart'; typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements); -Map _treeTypes; +Map<String, TreeBuilderFactory> _treeTypes; Map<String, TreeBuilderFactory> get treeTypes { if (_treeTypes == null) { // TODO(jmesserly): add DOM here once it's implemented @@ -133,13 +133,16 @@ class TestSerializer extends TreeVisitor { indent -= 2; } - visitDocument(node) { + visitDocument(node) => _visitDocumentOrFragment(node); + + _visitDocumentOrFragment(node) { indent += 1; for (var child in node.nodes) visit(child); indent -= 1; } - visitDocumentFragment(DocumentFragment node) => visitDocument(node); + visitDocumentFragment(DocumentFragment node) => + _visitDocumentOrFragment(node); visitElement(Element node) { _newline(); From 56c2644d41dcb7f567d2fe53a2387b29e3830499 Mon Sep 17 00:00:00 2001 From: William Hesse <whesse@google.com> Date: Thu, 18 Aug 2016 17:08:53 +0200 Subject: [PATCH 064/212] Update failing test and status file BUG=https://github.com/dart-lang/html/issues/37 R=eernst@google.com Review URL: https://codereview.chromium.org//2252383002 . --- pkgs/html/.status | 1 + pkgs/html/test/parser_feature_test.dart | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/html/.status b/pkgs/html/.status index 3bfc3528b..a42413806 100644 --- a/pkgs/html/.status +++ b/pkgs/html/.status @@ -26,3 +26,4 @@ test/selectors/*: Skip [ $runtime == vm ] test/browser/browser_test: Skip +test/selectors/level1_baseline_test: RuntimeError # Issue 37 \ No newline at end of file diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 6d3af0ca7..43a34266f 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -251,7 +251,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. 'ParserError on line 1, column 4: Unexpected non-space characters. ' 'Expected DOCTYPE.\n' 'foo\n' - ' ^'); + ' ^'); }); test('Element.text', () { From b93c2910224d690a68be9f0de4c3f78e72ec7a2e Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy <keertip@google.com> Date: Mon, 3 Oct 2016 11:08:16 -0700 Subject: [PATCH 065/212] Fix strong mode error 'Could not infer type parameter' BUG= R=kevmoo@google.com Review URL: https://codereview.chromium.org//2390773002 . --- pkgs/html/lib/src/treebuilder.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 83e679a7c..6be687e35 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -352,7 +352,7 @@ class TreeBuilder { // XXX - this is really inelegant Node lastTable = null; Node fosterParent = null; - var insertBefore = null; + Node insertBefore = null; for (var elm in openElements.reversed) { if (elm.localName == "table") { lastTable = elm; From b08974fe80f7130a8bd524c80a6e564a4d7ef423 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy <keertip@users.noreply.github.com> Date: Mon, 24 Oct 2016 07:08:11 -0700 Subject: [PATCH 066/212] Update Set.difference signature for 1.21.0-dev.2.0 (dart-lang/html#43) Update Set.difference signature for 1.21.0-dev.2.0 --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/lib/src/css_class_set.dart | 2 +- pkgs/html/pubspec.yaml | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 3320989f8..dbf745c2b 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,9 @@ This file contains highlights of what changes on each version of the html package. +## 0.13.1 + * Update Set.difference to take a Set<Object>. + ## 0.13.0 * **BREAKING** Fix all [strong mode][] errors and warnings. diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index c7927b82c..ddc1612d4 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -271,7 +271,7 @@ abstract class CssClassSetImpl implements CssClassSet { Set<String> union(Set<String> other) => readClasses().union(other); - Set<String> difference(Set<String> other) => readClasses().difference(other); + Set<String> difference(Set<Object> other) => readClasses().difference(other); String get first => readClasses().first; String get last => readClasses().last; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 4a595c1a2..cceb1e489 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,10 +1,10 @@ name: html -version: 0.13.0 +version: 0.13.1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: - sdk: '>=1.2.0 <2.0.0' + sdk: '>=1.21.0-dev.2.0 <2.0.0' dependencies: csslib: '>=0.13.2 <0.14.0' source_span: '>=1.0.0 <2.0.0' From bdd32d188a70baab2281c9f6b57271e438f710d7 Mon Sep 17 00:00:00 2001 From: keertip <keertip@google.com> Date: Thu, 8 Dec 2016 15:12:20 -0800 Subject: [PATCH 067/212] Strong mode fixes for package BUG= R=kevmoo@google.com Review URL: https://codereview.chromium.org//2560823004 . --- pkgs/html/lib/dom.dart | 5 ++--- pkgs/html/lib/src/encoding_parser.dart | 2 -- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 63182f634..bd3e2bdb5 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -809,7 +809,6 @@ class NodeList extends ListProxy<Node> { // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. class FilteredElementList extends IterableBase<Element> with ListMixin<Element> implements List<Element> { - final Node _node; final List<Node> _childNodes; /// Creates a collection of the elements that descend from a node. @@ -819,8 +818,8 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> /// var filteredElements = new FilteredElementList(query("#container")); /// // filteredElements is [a, b, c]. FilteredElementList(Node node) - : _childNodes = node.nodes, - _node = node; + : _childNodes = node.nodes; + // We can't memoize this, since it's possible that children will be messed // with externally to this class. diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 0b84989ad..9da260bed 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -200,7 +200,6 @@ class EncodingParser { } } } - return true; // unreachable } bool handlePossibleStartTag() => handlePossibleTag(false); @@ -322,7 +321,6 @@ class EncodingParser { attrValue.add(c); } } - return null; // unreachable } } From 6da20868bb85f92672640dde0ce91e03116c6e8f Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 31 May 2017 12:25:33 -0700 Subject: [PATCH 068/212] support latest csslib --- pkgs/html/CHANGELOG.md | 5 ++--- pkgs/html/pubspec.yaml | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index dbf745c2b..af731063e 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,7 +1,6 @@ -# changelog +## 0.13.2 -This file contains highlights of what changes on each version of the html -package. + * Support the latest release of `pkg/csslib`. ## 0.13.1 * Update Set.difference to take a Set<Object>. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index cceb1e489..5e9f0d520 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html -version: 0.13.1 +version: 0.13.2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: - sdk: '>=1.21.0-dev.2.0 <2.0.0' + sdk: '>=1.21.0 <2.0.0' dependencies: - csslib: '>=0.13.2 <0.14.0' + csslib: '>=0.13.2 <0.15.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' dev_dependencies: From 7515cadde5b3581353135da84487b09e618c5895 Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy <keertip@google.com> Date: Mon, 7 Aug 2017 09:51:01 -0700 Subject: [PATCH 069/212] Update generic comment syntax BUG= R=kevmoo@google.com Review-Url: https://codereview.chromium.org//2996603002 . --- pkgs/html/lib/dom.dart | 36 +++++++++++++--------------- pkgs/html/lib/src/css_class_set.dart | 10 ++++---- pkgs/html/lib/src/utils.dart | 5 ++-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index bd3e2bdb5..a50048130 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -8,16 +8,17 @@ library dom; // implement that. import 'dart:collection'; + import 'package:source_span/source_span.dart'; +import 'dom_parsing.dart'; +import 'parser.dart'; import 'src/constants.dart'; import 'src/css_class_set.dart'; import 'src/list_proxy.dart'; import 'src/query_selector.dart' as query; import 'src/token.dart'; import 'src/tokenizer.dart'; -import 'dom_parsing.dart'; -import 'parser.dart'; export 'src/css_class_set.dart' show CssClassSet; @@ -110,8 +111,8 @@ abstract class _ElementAndDocument implements _ParentNode { List<Element> getElementsByTagName(String localName) => querySelectorAll(localName); - List<Element> getElementsByClassName(String classNames) => querySelectorAll( - classNames.splitMapJoin(' ', + List<Element> getElementsByClassName(String classNames) => + querySelectorAll(classNames.splitMapJoin(' ', onNonMatch: (m) => m.isNotEmpty ? '.$m' : m, onMatch: (m) => '')); } @@ -292,8 +293,8 @@ abstract class Node { _attributeSpans[attr.name] = sourceSpan.file.span(offset + attr.start, offset + attr.end); if (attr.startValue != null) { - _attributeValueSpans[attr.name] = sourceSpan.file.span( - offset + attr.startValue, offset + attr.endValue); + _attributeValueSpans[attr.name] = sourceSpan.file + .span(offset + attr.startValue, offset + attr.endValue); } } } @@ -407,7 +408,9 @@ class Text extends Node { /// It will flatten back to a String on read. var _data; - Text(String data) : _data = data != null ? data : '', super._(); + Text(String data) + : _data = data != null ? data : '', + super._(); int get nodeType => Node.TEXT_NODE; @@ -476,7 +479,6 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // TODO(jmesserly): for our version we can do something smarter in the parser. // All we really need is to set the correct parse state. factory Element.html(String html) { - // TODO(jacobr): this method can be made more robust and performant. // 1) Cache the dummy parent elements required to use innerHTML rather than // creating them every call. @@ -807,7 +809,8 @@ class NodeList extends ListProxy<Node> { /// filtered so that only elements are in the collection. // TODO(jmesserly): this was copied from dart:html // TODO(jmesserly): "implements List<Element>" is a workaround for analyzer bug. -class FilteredElementList extends IterableBase<Element> with ListMixin<Element> +class FilteredElementList extends IterableBase<Element> + with ListMixin<Element> implements List<Element> { final List<Node> _childNodes; @@ -817,9 +820,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> /// /// var filteredElements = new FilteredElementList(query("#container")); /// // filteredElements is [a, b, c]. - FilteredElementList(Node node) - : _childNodes = node.nodes; - + FilteredElementList(Node node) : _childNodes = node.nodes; // We can't memoize this, since it's possible that children will be messed // with externally to this class. @@ -901,10 +902,9 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> return result; } - Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(Element element)) => _filtered.map(f); + Iterable<T> map<T>(T f(Element element)) => _filtered.map(f); Iterable<Element> where(bool f(Element element)) => _filtered.where(f); - Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(Element element)) => - _filtered.expand(f); + Iterable<T> expand<T>(Iterable<T> f(Element element)) => _filtered.expand(f); void insert(int index, Element value) { _childNodes.insert(index, value); @@ -936,8 +936,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> return _filtered.reduce(combine); } - dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, - dynamic/*=T*/ combine(var/*=T*/ previousValue, Element element)) { + T fold<T>(T initialValue, T combine(T previousValue, Element element)) { return _filtered.fold(initialValue, combine); } @@ -971,8 +970,7 @@ class FilteredElementList extends IterableBase<Element> with ListMixin<Element> _filtered.getRange(start, end); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.indexOf() expects Object as the argument. - int indexOf(element, [int start = 0]) => - _filtered.indexOf(element, start); + int indexOf(element, [int start = 0]) => _filtered.indexOf(element, start); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index ddc1612d4..40575c2bb 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -6,6 +6,7 @@ library html.dom.src; import 'dart:collection'; + import 'package:html/dom.dart'; class ElementCssClassSet extends CssClassSetImpl { @@ -33,7 +34,6 @@ class ElementCssClassSet extends CssClassSetImpl { /** A Set that stores the CSS class names for an element. */ abstract class CssClassSet implements Set<String> { - /** * Adds the class [value] to the element if it is not on it, removes it if it * is. @@ -151,11 +151,12 @@ abstract class CssClassSetImpl implements CssClassSet { String join([String separator = ""]) => readClasses().join(separator); - Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(String e)) => readClasses().map(f); + Iterable<T> map<T>(T f(String e)) => readClasses().map(f); Iterable<String> where(bool f(String element)) => readClasses().where(f); - Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(String element)) => readClasses().expand(f); + Iterable<T> expand<T>(Iterable<T> f(String element)) => + readClasses().expand(f); bool every(bool f(String element)) => readClasses().every(f); @@ -171,8 +172,7 @@ abstract class CssClassSetImpl implements CssClassSet { return readClasses().reduce(combine); } - dynamic/*=T*/ fold/*<T>*/(var/*=T*/ initialValue, - dynamic/*=T*/ combine(var/*=T*/ previousValue, String element)) { + T fold<T>(T initialValue, T combine(T previousValue, String element)) { return readClasses().fold(initialValue, combine); } // interface Collection - END diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 16837b03d..909b89962 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -43,7 +43,7 @@ bool startsWithAny(String str, List<String> prefixes) { } // Like the python [:] operator. -List/*<T>*/ slice/*<T>*/(List/*<T>*/ list, int start, [int end]) { +List<T> slice<T>(List<T> list, int start, [int end]) { if (end == null) end = list.length; if (end < 0) end += list.length; @@ -79,8 +79,7 @@ String formatStr(String format, Map data) { data.forEach((key, value) { var result = new StringBuffer(); var search = '%($key)'; - int last = 0, - match; + int last = 0, match; while ((match = format.indexOf(search, last)) >= 0) { result.write(format.substring(last, match)); match += search.length; From 41de56183c2d82fa05790aeafa2b3a2332ccaf4a Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 2 Aug 2017 09:21:47 -0700 Subject: [PATCH 070/212] rename analysis_options --- pkgs/html/{.analysis_options => analysis_options.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/html/{.analysis_options => analysis_options.yaml} (100%) diff --git a/pkgs/html/.analysis_options b/pkgs/html/analysis_options.yaml similarity index 100% rename from pkgs/html/.analysis_options rename to pkgs/html/analysis_options.yaml From 03fb0a720184acc10bf717317a09625b2e8284f6 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 2 Aug 2017 09:23:49 -0700 Subject: [PATCH 071/212] dartfmt --- pkgs/html/lib/parser.dart | 340 +++++++++++------------ pkgs/html/lib/src/char_encodings.dart | 13 +- pkgs/html/lib/src/constants.dart | 20 +- pkgs/html/lib/src/encoding_parser.dart | 12 +- pkgs/html/lib/src/inputstream.dart | 7 +- pkgs/html/lib/src/list_proxy.dart | 8 +- pkgs/html/lib/src/query_selector.dart | 10 +- pkgs/html/lib/src/token.dart | 7 +- pkgs/html/lib/src/tokenizer.dart | 85 +++--- pkgs/html/lib/src/treebuilder.dart | 12 +- pkgs/html/test/parser_feature_test.dart | 7 +- pkgs/html/test/parser_test.dart | 19 +- pkgs/html/test/selectors/level1_lib.dart | 4 +- 13 files changed, 280 insertions(+), 264 deletions(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 0575b3d66..546061fe5 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -55,8 +55,11 @@ Document parse(input, /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. -DocumentFragment parseFragment(input, {String container: "div", String encoding, - bool generateSpans: false, String sourceUrl}) { +DocumentFragment parseFragment(input, + {String container: "div", + String encoding, + bool generateSpans: false, + String sourceUrl}) { var p = new HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parseFragment(container); @@ -138,9 +141,14 @@ class HtmlParser { /// automatic conversion of element and attribute names to lower case. Note /// that standard way to parse HTML is to lowercase, which is what the browser /// DOM will do if you request [Node.outerHTML], for example. - HtmlParser(input, {String encoding, bool parseMeta: true, - bool lowercaseElementName: true, bool lowercaseAttrName: true, - this.strict: false, bool generateSpans: false, String sourceUrl, + HtmlParser(input, + {String encoding, + bool parseMeta: true, + bool lowercaseElementName: true, + bool lowercaseAttrName: true, + this.strict: false, + bool generateSpans: false, + String sourceUrl, TreeBuilder tree}) : generateSpans = generateSpans, tree = tree != null ? tree : new TreeBuilder(true), @@ -345,9 +353,8 @@ class HtmlParser { if (token is StartTagToken) { if (token.selfClosing && !token.selfClosingAcknowledged) { - parseError(token.span, "non-void-element-with-trailing-solidus", { - "name": token.name - }); + parseError(token.span, "non-void-element-with-trailing-solidus", + {"name": token.name}); } } } @@ -696,86 +703,88 @@ class InitialPhase extends Phase { publicId = asciiUpper2Lower(publicId); } - if (!correct || token.name != "html" || startsWithAny(publicId, const [ - "+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", - "-//o'reilly and associates//dtd html 2.0//", - "-//o'reilly and associates//dtd html extended 1.0//", - "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//" - ]) || + if (!correct || + token.name != "html" || + startsWithAny(publicId, const [ + "+//silmaril//dtd html pro v0r11 19970101//", + "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", + "-//as//dtd html 3.0 aswedit + extensions//", + "-//ietf//dtd html 2.0 level 1//", + "-//ietf//dtd html 2.0 level 2//", + "-//ietf//dtd html 2.0 strict level 1//", + "-//ietf//dtd html 2.0 strict level 2//", + "-//ietf//dtd html 2.0 strict//", + "-//ietf//dtd html 2.0//", + "-//ietf//dtd html 2.1e//", + "-//ietf//dtd html 3.0//", + "-//ietf//dtd html 3.2 final//", + "-//ietf//dtd html 3.2//", + "-//ietf//dtd html 3//", + "-//ietf//dtd html level 0//", + "-//ietf//dtd html level 1//", + "-//ietf//dtd html level 2//", + "-//ietf//dtd html level 3//", + "-//ietf//dtd html strict level 0//", + "-//ietf//dtd html strict level 1//", + "-//ietf//dtd html strict level 2//", + "-//ietf//dtd html strict level 3//", + "-//ietf//dtd html strict//", + "-//ietf//dtd html//", + "-//metrius//dtd metrius presentational//", + "-//microsoft//dtd internet explorer 2.0 html strict//", + "-//microsoft//dtd internet explorer 2.0 html//", + "-//microsoft//dtd internet explorer 2.0 tables//", + "-//microsoft//dtd internet explorer 3.0 html strict//", + "-//microsoft//dtd internet explorer 3.0 html//", + "-//microsoft//dtd internet explorer 3.0 tables//", + "-//netscape comm. corp.//dtd html//", + "-//netscape comm. corp.//dtd strict html//", + "-//o'reilly and associates//dtd html 2.0//", + "-//o'reilly and associates//dtd html extended 1.0//", + "-//o'reilly and associates//dtd html extended relaxed 1.0//", + "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", + "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", + "-//spyglass//dtd html 2.0 extended//", + "-//sq//dtd html 2.0 hotmetal + extensions//", + "-//sun microsystems corp.//dtd hotjava html//", + "-//sun microsystems corp.//dtd hotjava strict html//", + "-//w3c//dtd html 3 1995-03-24//", + "-//w3c//dtd html 3.2 draft//", + "-//w3c//dtd html 3.2 final//", + "-//w3c//dtd html 3.2//", + "-//w3c//dtd html 3.2s draft//", + "-//w3c//dtd html 4.0 frameset//", + "-//w3c//dtd html 4.0 transitional//", + "-//w3c//dtd html experimental 19960712//", + "-//w3c//dtd html experimental 970421//", + "-//w3c//dtd w3 html//", + "-//w3o//dtd w3 html 3.0//", + "-//webtechs//dtd mozilla html 2.0//", + "-//webtechs//dtd mozilla html//" + ]) || const [ - "-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html" - ].contains(publicId) || + "-//w3o//dtd w3 html strict 3.0//en//", + "-/w3c/dtd html 4.0 transitional/en", + "html" + ].contains(publicId) || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//" - ]) && + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]) && systemId == null || systemId != null && systemId.toLowerCase() == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") { parser.compatMode = "quirks"; } else if (startsWithAny(publicId, const [ - "-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//" - ]) || + "-//w3c//dtd xhtml 1.0 frameset//", + "-//w3c//dtd xhtml 1.0 transitional//" + ]) || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//" - ]) && - systemId != null) { + "-//w3c//dtd html 4.01 frameset//", + "-//w3c//dtd html 4.01 transitional//" + ]) && + systemId != null) { parser.compatMode = "limited quirks"; } parser.phase = parser._beforeHtmlPhase; @@ -819,8 +828,8 @@ class BeforeHtmlPhase extends Phase { // helper methods void insertHtmlElement() { - tree.insertRoot(new StartTagToken("html", - data: new LinkedHashMap<dynamic, String>())); + tree.insertRoot( + new StartTagToken("html", data: new LinkedHashMap<dynamic, String>())); parser.phase = parser._beforeHeadPhase; } @@ -897,8 +906,8 @@ class BeforeHeadPhase extends Phase { } bool processEOF() { - startTagHead(new StartTagToken("head", - data: new LinkedHashMap<dynamic, String>())); + startTagHead( + new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); return true; } @@ -907,8 +916,8 @@ class BeforeHeadPhase extends Phase { } Token processCharacters(CharactersToken token) { - startTagHead(new StartTagToken("head", - data: new LinkedHashMap<dynamic, String>())); + startTagHead( + new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); return token; } @@ -923,14 +932,14 @@ class BeforeHeadPhase extends Phase { } Token startTagOther(StartTagToken token) { - startTagHead(new StartTagToken("head", - data: new LinkedHashMap<dynamic, String>())); + startTagHead( + new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); return token; } Token endTagImplyHead(EndTagToken token) { - startTagHead(new StartTagToken("head", - data: new LinkedHashMap<dynamic, String>())); + startTagHead( + new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); return token; } @@ -1152,9 +1161,8 @@ class AfterHeadPhase extends Phase { } void startTagFromHead(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", { - "name": token.name - }); + parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", + {"name": token.name}); tree.openElements.add(tree.headPointer); parser._inHeadPhase.processStartTag(token); for (var node in tree.openElements.reversed) { @@ -1184,8 +1192,8 @@ class AfterHeadPhase extends Phase { } void anythingElse() { - tree.insertElement(new StartTagToken("body", - data: new LinkedHashMap<dynamic, String>())); + tree.insertElement( + new StartTagToken("body", data: new LinkedHashMap<dynamic, String>())); parser.phase = parser._inBodyPhase; parser.framesetOK = true; } @@ -1661,8 +1669,8 @@ class InBodyPhase extends Phase { endTagP(new EndTagToken("p")); } if (headingElements.contains(tree.openElements.last.localName)) { - parser.parseError( - token.span, "unexpected-start-tag", {"name": token.name}); + parser + .parseError(token.span, "unexpected-start-tag", {"name": token.name}); tree.openElements.removeLast(); } tree.insertElement(token); @@ -1671,10 +1679,8 @@ class InBodyPhase extends Phase { void startTagA(StartTagToken token) { var afeAElement = tree.elementInActiveFormattingElements("a"); if (afeAElement != null) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { - "startName": "a", - "endName": "a" - }); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", + {"startName": "a", "endName": "a"}); endTagFormatting(new EndTagToken("a")); tree.openElements.remove(afeAElement); tree.activeFormattingElements.remove(afeAElement); @@ -1691,10 +1697,8 @@ class InBodyPhase extends Phase { void startTagNobr(StartTagToken token) { tree.reconstructActiveFormattingElements(); if (tree.elementInScope("nobr")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { - "startName": "nobr", - "endName": "nobr" - }); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", + {"startName": "nobr", "endName": "nobr"}); processEndTag(new EndTagToken("nobr")); // XXX Need tests that trigger the following tree.reconstructActiveFormattingElements(); @@ -1704,10 +1708,8 @@ class InBodyPhase extends Phase { Token startTagButton(StartTagToken token) { if (tree.elementInScope("button")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { - "startName": "button", - "endName": "button" - }); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", + {"startName": "button", "endName": "button"}); processEndTag(new EndTagToken("button")); return token; } else { @@ -1780,10 +1782,8 @@ class InBodyPhase extends Phase { void startTagImage(StartTagToken token) { // No really... - parser.parseError(token.span, "unexpected-start-tag-treated-as", { - "originalName": "image", - "newName": "img" - }); + parser.parseError(token.span, "unexpected-start-tag-treated-as", + {"originalName": "image", "newName": "img"}); processStartTag(new StartTagToken("img", data: token.data, selfClosing: token.selfClosing)); } @@ -1799,10 +1799,10 @@ class InBodyPhase extends Phase { formAttrs["action"] = dataAction; } processStartTag(new StartTagToken("form", data: formAttrs)); - processStartTag(new StartTagToken("hr", - data: new LinkedHashMap<dynamic, String>())); - processStartTag(new StartTagToken("label", - data: new LinkedHashMap<dynamic, String>())); + processStartTag( + new StartTagToken("hr", data: new LinkedHashMap<dynamic, String>())); + processStartTag( + new StartTagToken("label", data: new LinkedHashMap<dynamic, String>())); // XXX Localization ... var prompt = token.data["prompt"]; if (prompt == null) { @@ -1813,11 +1813,11 @@ class InBodyPhase extends Phase { attributes.remove('action'); attributes.remove('prompt'); attributes["name"] = "isindex"; - processStartTag(new StartTagToken( - "input", data: attributes, selfClosing: token.selfClosing)); + processStartTag(new StartTagToken("input", + data: attributes, selfClosing: token.selfClosing)); processEndTag(new EndTagToken("label")); - processStartTag(new StartTagToken("hr", - data: new LinkedHashMap<dynamic, String>())); + processStartTag( + new StartTagToken("hr", data: new LinkedHashMap<dynamic, String>())); processEndTag(new EndTagToken("form")); } @@ -1920,8 +1920,8 @@ class InBodyPhase extends Phase { void endTagP(EndTagToken token) { if (!tree.elementInScope("p", variant: "button")) { - startTagCloseP(new StartTagToken("p", - data: new LinkedHashMap<dynamic, String>())); + startTagCloseP( + new StartTagToken("p", data: new LinkedHashMap<dynamic, String>())); parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); endTagP(new EndTagToken("p")); } else { @@ -1961,10 +1961,8 @@ class InBodyPhase extends Phase { continue; } // Not sure this is the correct name for the parse error - parser.parseError(token.span, "expected-one-end-tag-but-got-another", { - "gotName": "body", - "expectedName": node.localName - }); + parser.parseError(token.span, "expected-one-end-tag-but-got-another", + {"gotName": "body", "expectedName": node.localName}); break; } } @@ -2025,8 +2023,8 @@ class InBodyPhase extends Phase { } else { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { - parser.parseError( - token.span, "end-tag-too-early", {"name": token.name}); + parser + .parseError(token.span, "end-tag-too-early", {"name": token.name}); } popOpenElementsUntil(token); } @@ -2175,13 +2173,8 @@ class InBodyPhase extends Phase { lastNode.parentNode.nodes.remove(lastNode); } - if (const [ - "table", - "tbody", - "tfoot", - "thead", - "tr" - ].contains(commonAncestor.localName)) { + if (const ["table", "tbody", "tfoot", "thead", "tr"] + .contains(commonAncestor.localName)) { var nodePos = tree.getTableMisnestedNodePosition(); nodePos[0].insertBefore(lastNode, nodePos[1]); } else { @@ -2199,13 +2192,13 @@ class InBodyPhase extends Phase { // Step 11 tree.activeFormattingElements.remove(formattingElement); - tree.activeFormattingElements.insert( - min(bookmark, tree.activeFormattingElements.length), clone); + tree.activeFormattingElements + .insert(min(bookmark, tree.activeFormattingElements.length), clone); // Step 12 tree.openElements.remove(formattingElement); - tree.openElements.insert( - tree.openElements.indexOf(furthestBlock) + 1, clone); + tree.openElements + .insert(tree.openElements.indexOf(furthestBlock) + 1, clone); } } @@ -2223,13 +2216,11 @@ class InBodyPhase extends Phase { } void endTagBr(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-treated-as", { - "originalName": "br", - "newName": "br element" - }); + parser.parseError(token.span, "unexpected-end-tag-treated-as", + {"originalName": "br", "newName": "br element"}); tree.reconstructActiveFormattingElements(); - tree.insertElement(new StartTagToken("br", - data: new LinkedHashMap<dynamic, String>())); + tree.insertElement( + new StartTagToken("br", data: new LinkedHashMap<dynamic, String>())); tree.openElements.removeLast(); } @@ -2439,16 +2430,14 @@ class InTablePhase extends Phase { } Token startTagImplyTbody(StartTagToken token) { - startTagRowGroup(new StartTagToken("tbody", - data: new LinkedHashMap<dynamic, String>())); + startTagRowGroup( + new StartTagToken("tbody", data: new LinkedHashMap<dynamic, String>())); return token; } Token startTagTable(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", { - "startName": "table", - "endName": "table" - }); + parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", + {"startName": "table", "endName": "table"}); parser.phase.processEndTag(new EndTagToken("table")); if (!parser.innerHTMLMode) { return token; @@ -2481,9 +2470,8 @@ class InTablePhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", { - "name": token.name - }); + parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", + {"name": token.name}); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processStartTag(token); @@ -2495,10 +2483,8 @@ class InTablePhase extends Phase { tree.generateImpliedEndTags(); var last = tree.openElements.last; if (last.localName != "table") { - parser.parseError(token.span, "end-tag-too-early-named", { - "gotName": "table", - "expectedName": last.localName - }); + parser.parseError(token.span, "end-tag-too-early-named", + {"gotName": "table", "expectedName": last.localName}); } while (tree.openElements.last.localName != "table") { tree.openElements.removeLast(); @@ -2518,9 +2504,8 @@ class InTablePhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-implies-table-voodoo", { - "name": token.name - }); + parser.parseError(token.span, "unexpected-end-tag-implies-table-voodoo", + {"name": token.name}); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processEndTag(token); @@ -2883,8 +2868,8 @@ class InTableBodyPhase extends Phase { Token startTagTableCell(StartTagToken token) { parser.parseError( token.span, "unexpected-cell-in-table-body", {"name": token.name}); - startTagTr(new StartTagToken("tr", - data: new LinkedHashMap<dynamic, String>())); + startTagTr( + new StartTagToken("tr", data: new LinkedHashMap<dynamic, String>())); return token; } @@ -2988,10 +2973,10 @@ class InRowPhase extends Phase { var last = tree.openElements.last; if (last.localName == "tr" || last.localName == "html") break; - parser.parseError(last.sourceSpan, - "unexpected-implied-end-tag-in-table-row", { - "name": tree.openElements.last.localName - }); + parser.parseError( + last.sourceSpan, + "unexpected-implied-end-tag-in-table-row", + {"name": tree.openElements.last.localName}); tree.openElements.removeLast(); } } @@ -3391,10 +3376,10 @@ class InSelectInTablePhase extends Phase { } Token startTagTable(StartTagToken token) { - parser.parseError(token.span, - "unexpected-table-element-start-tag-in-select-in-table", { - "name": token.name - }); + parser.parseError( + token.span, + "unexpected-table-element-start-tag-in-select-in-table", + {"name": token.name}); endTagOther(new EndTagToken("select")); return token; } @@ -3404,10 +3389,10 @@ class InSelectInTablePhase extends Phase { } Token endTagTable(EndTagToken token) { - parser.parseError(token.span, - "unexpected-table-element-end-tag-in-select-in-table", { - "name": token.name - }); + parser.parseError( + token.span, + "unexpected-table-element-end-tag-in-select-in-table", + {"name": token.name}); if (tree.elementInScope(token.name, variant: "table")) { endTagOther(new EndTagToken("select")); return token; @@ -3789,9 +3774,8 @@ class AfterFramesetPhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-after-frameset", { - "name": token.name - }); + parser.parseError(token.span, "unexpected-start-tag-after-frameset", + {"name": token.name}); } void endTagHtml(EndTagToken token) { diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 5ddf72796..56680bd28 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -21,7 +21,8 @@ bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { /// Decodes the [bytes] with the provided [encoding] and returns an iterable for /// the codepoints. Supports the major unicode encodings as well as ascii and /// and windows-1252 encodings. -Iterable<int> decodeBytes(String encoding, List<int> bytes, [int offset = 0, +Iterable<int> decodeBytes(String encoding, List<int> bytes, + [int offset = 0, int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { if (length == null) length = bytes.length; @@ -99,7 +100,8 @@ List<int> toCodepoints(String input) { /// needed. Set the [replacementCharacter] to null to throw an [ArgumentError] /// rather than replace the bad value. IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, - [int offset = 0, int length, + [int offset = 0, + int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { return new IterableWindows1252Decoder( bytes, offset, length, replacementCodepoint); @@ -114,7 +116,8 @@ class IterableWindows1252Decoder extends IterableBase<int> { final int length; final int replacementCodepoint; - IterableWindows1252Decoder(List<int> this.bytes, [int this.offset = 0, + IterableWindows1252Decoder(List<int> this.bytes, + [int this.offset = 0, int this.length = null, int this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]); @@ -134,7 +137,9 @@ class Windows1252Decoder implements Iterator<int> { int _offset; final int _length; - Windows1252Decoder(List<int> bytes, [int offset = 0, int length, + Windows1252Decoder(List<int> bytes, + [int offset = 0, + int length, this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) : _bytes = bytes, _offset = offset - 1, diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index e85e43a31..9f4878f4c 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -514,17 +514,27 @@ const rcdataElements = const [ ]; const Map<String, List<String>> booleanAttributes = const { - "": const ["irrelevant",], - "style": const ["scoped",], - "img": const ["ismap",], + "": const [ + "irrelevant", + ], + "style": const [ + "scoped", + ], + "img": const [ + "ismap", + ], "audio": const ["autoplay", "controls"], "video": const ["autoplay", "controls"], "script": const ["defer", "async"], - "details": const ["open",], + "details": const [ + "open", + ], "datagrid": const ["multiple", "disabled"], "command": const ["hidden", "disabled", "checked", "default"], "hr": const ["noshade"], - "men": const ["autosubmit",], + "men": const [ + "autosubmit", + ], "fieldset": const ["disabled", "readonly"], "option": const ["disabled", "readonly", "selected"], "optgroup": const ["disabled", "readonly"], diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 9da260bed..21d6783b8 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -141,12 +141,12 @@ class EncodingParser { String getEncoding() { final methodDispatch = [ - new _DispatchEntry("<!--", handleComment), - new _DispatchEntry("<meta", handleMeta), - new _DispatchEntry("</", handlePossibleEndTag), - new _DispatchEntry("<!", handleOther), - new _DispatchEntry("<?", handleOther), - new _DispatchEntry("<", handlePossibleStartTag), + new _DispatchEntry("<!--", handleComment), + new _DispatchEntry("<meta", handleMeta), + new _DispatchEntry("</", handlePossibleEndTag), + new _DispatchEntry("<!", handleOther), + new _DispatchEntry("<?", handleOther), + new _DispatchEntry("<", handlePossibleStartTag), ]; try { diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index cb40bc91a..849ed936e 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -68,8 +68,11 @@ class HtmlInputStream { /// element) /// /// [parseMeta] - Look for a <meta> element containing encoding information - HtmlInputStream(source, [String encoding, bool parseMeta = true, - this.generateSpans = false, this.sourceUrl]) + HtmlInputStream(source, + [String encoding, + bool parseMeta = true, + this.generateSpans = false, + this.sourceUrl]) : charEncodingName = codecName(encoding) { if (source is String) { _rawChars = toCodepoints(source); diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 5df1ed44f..7c6e612ab 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -9,7 +9,6 @@ import 'dart:math' show Random; // TOOD(jmesserly): this needs to be removed, but fixing NodeList is tricky. class ListProxy<E> extends IterableBase<E> implements List<E> { - /// The inner [List<T>] with the actual storage. final List<E> _list; @@ -48,9 +47,11 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { operator []=(int index, E value) { _list[index] = value; } + set length(int value) { _list.length = value; } + void add(E value) { _list.add(value); } @@ -58,12 +59,15 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void addLast(E value) { add(value); } + void addAll(Iterable<E> collection) { _list.addAll(collection); } + void sort([int compare(E a, E b)]) { _list.sort(compare); } + void shuffle([Random random]) { _list.shuffle(random); } @@ -87,9 +91,11 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { void setRange(int start, int length, Iterable<E> from, [int startFrom = 0]) { _list.setRange(start, length, from, startFrom); } + void removeRange(int start, int length) { _list.removeRange(start, length); } + void insertAll(int index, Iterable<E> iterable) { _list.insertAll(index, iterable); } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 3aa45f296..5c438dbda 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -16,8 +16,8 @@ Element querySelector(Node node, String selector) => List<Element> querySelectorAll(Node node, String selector) { var results = <Element>[]; - new SelectorEvaluator().querySelectorAll( - node, _parseSelectorList(selector), results); + new SelectorEvaluator() + .querySelectorAll(node, _parseSelectorList(selector), results); return results; } @@ -124,9 +124,9 @@ class SelectorEvaluator extends Visitor { return result; } - _unimplemented(SimpleSelector selector) => new UnimplementedError( - "'$selector' selector of type " - "${selector.runtimeType} is not implemented"); + _unimplemented(SimpleSelector selector) => + new UnimplementedError("'$selector' selector of type " + "${selector.runtimeType} is not implemented"); _unsupported(selector) => new FormatException("'$selector' is not a valid selector"); diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 9a2843c5f..877a6a3e8 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -32,8 +32,11 @@ class StartTagToken extends TagToken { /// The namespace. This is filled in later during tree building. String namespace; - StartTagToken(String name, {this.data, bool selfClosing: false, - this.selfClosingAcknowledged: false, this.namespace}) + StartTagToken(String name, + {this.data, + bool selfClosing: false, + this.selfClosingAcknowledged: false, + this.namespace}) : super(name, selfClosing); int get kind => TokenKind.startTag; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 68cb6dcd1..21505df70 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -65,11 +65,16 @@ class HtmlTokenizer implements Iterator<Token> { List<TagAttribute> _attributes; Set<String> _attributeNames; - HtmlTokenizer(doc, {String encoding, bool parseMeta: true, - this.lowercaseElementName: true, this.lowercaseAttrName: true, - bool generateSpans: false, String sourceUrl, this.attributeSpans: false}) + HtmlTokenizer(doc, + {String encoding, + bool parseMeta: true, + this.lowercaseElementName: true, + this.lowercaseAttrName: true, + bool generateSpans: false, + String sourceUrl, + this.attributeSpans: false}) : stream = new HtmlInputStream( - doc, encoding, parseMeta, generateSpans, sourceUrl), + doc, encoding, parseMeta, generateSpans, sourceUrl), tokenQueue = new Queue(), generateSpans = generateSpans { reset(); @@ -200,42 +205,42 @@ class HtmlTokenizer implements Iterator<Token> { (0x007F <= charAsInt && charAsInt <= 0x009F) || (0xFDD0 <= charAsInt && charAsInt <= 0xFDEF) || const [ - 0x000B, - 0xFFFE, - 0xFFFF, - 0x1FFFE, - 0x1FFFF, - 0x2FFFE, - 0x2FFFF, - 0x3FFFE, - 0x3FFFF, - 0x4FFFE, - 0x4FFFF, - 0x5FFFE, - 0x5FFFF, - 0x6FFFE, - 0x6FFFF, - 0x7FFFE, - 0x7FFFF, - 0x8FFFE, - 0x8FFFF, - 0x9FFFE, - 0x9FFFF, - 0xAFFFE, - 0xAFFFF, - 0xBFFFE, - 0xBFFFF, - 0xCFFFE, - 0xCFFFF, - 0xDFFFE, - 0xDFFFF, - 0xEFFFE, - 0xEFFFF, - 0xFFFFE, - 0xFFFFF, - 0x10FFFE, - 0x10FFFF - ].contains(charAsInt)) { + 0x000B, + 0xFFFE, + 0xFFFF, + 0x1FFFE, + 0x1FFFF, + 0x2FFFE, + 0x2FFFF, + 0x3FFFE, + 0x3FFFF, + 0x4FFFE, + 0x4FFFF, + 0x5FFFE, + 0x5FFFF, + 0x6FFFE, + 0x6FFFF, + 0x7FFFE, + 0x7FFFF, + 0x8FFFE, + 0x8FFFF, + 0x9FFFE, + 0x9FFFF, + 0xAFFFE, + 0xAFFFF, + 0xBFFFE, + 0xBFFFF, + 0xCFFFE, + 0xCFFFF, + 0xDFFFE, + 0xDFFFF, + 0xEFFFE, + 0xEFFFF, + 0xFFFFE, + 0xFFFFF, + 0x10FFFE, + 0x10FFFF + ].contains(charAsInt)) { _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 6be687e35..ac71e48dc 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -378,16 +378,8 @@ class TreeBuilder { var name = openElements.last.localName; // XXX td, th and tr are not actually needed if (name != exclude && - const [ - "dd", - "dt", - "li", - "option", - "optgroup", - "p", - "rp", - "rt" - ].contains(name)) { + const ["dd", "dt", "li", "option", "optgroup", "p", "rp", "rt"] + .contains(name)) { openElements.removeLast(); // XXX This is not entirely what the specification says. We should // investigate it more closely. diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 43a34266f..d185a140a 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -234,7 +234,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); expect(keys[0].name, 'type'); - expect(n.outerHtml, '<desc xlink:type="simple" ' + expect( + n.outerHtml, + '<desc xlink:type="simple" ' 'xlink:href="http://example.com/logo.png" xlink:show="new"></desc>'); }); }); @@ -247,7 +249,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars'); expect(parser.errors[0].message, 'Unexpected non-space characters. Expected DOCTYPE.'); - expect(parser.errors[0].toString(), + expect( + parser.errors[0].toString(), 'ParserError on line 1, column 4: Unexpected non-space characters. ' 'Expected DOCTYPE.\n' 'foo\n' diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 6f810860b..516a0f4ee 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -30,10 +30,14 @@ String namespaceHtml(String expected) { return lines.join("\n"); } -void runParserTest(String groupName, String innerHTML, String input, - String expected, List errors, TreeBuilderFactory treeCtor, +void runParserTest( + String groupName, + String innerHTML, + String input, + String expected, + List errors, + TreeBuilderFactory treeCtor, bool namespaceHTMLElements) { - // XXX - move this out into the setup function // concatenate all consecutive character tokens into a single token var builder = treeCtor(namespaceHTMLElements); @@ -53,14 +57,15 @@ void runParserTest(String groupName, String innerHTML, String input, } expect(output, equals(expected), - reason: "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); + reason: + "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); if (checkParseErrors) { expect(parser.errors.length, equals(errors.length), reason: "\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n" - "${errors.join('\n')}\n\n" - "Actual errors (${parser.errors.length}):\n" - "${parser.errors.map((e) => '$e').join('\n')}"); + "${errors.join('\n')}\n\n" + "Actual errors (${parser.errors.length}):\n" + "${parser.errors.map((e) => '$e').join('\n')}"); } } diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 3191353f6..34b7c757d 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -155,8 +155,8 @@ runSpecialSelectorTests(type, root) { var elm = root.querySelector('undefined'); assert_not_equals(elm, 'undefined', "This should find an element."); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assert_equals(elm.localName.toUpperCase(), - "UNDEFINED", "The tag name should be 'UNDEFINED'."); + assert_equals(elm.localName.toUpperCase(), "UNDEFINED", + "The tag name should be 'UNDEFINED'."); }, type + ".querySelector undefined"); test(() { From aec420579febe3e42ed2e40c688a24849b53defe Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 2 Aug 2017 09:52:18 -0700 Subject: [PATCH 072/212] start migration to pkg/test --- pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/dom_test.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 2 +- pkgs/html/test/parser_test.dart | 2 +- pkgs/html/test/run_all.dart | 4 +--- pkgs/html/test/selectors/level1_baseline_test.dart | 6 ++++-- pkgs/html/test/selectors/level1_lib.dart | 2 +- pkgs/html/test/support.dart | 9 ++++++--- pkgs/html/test/tokenizer_test.dart | 2 +- 9 files changed, 17 insertions(+), 14 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 5e9f0d520..265a98325 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -11,4 +11,4 @@ dependencies: utf: '>=0.9.0 <0.10.0' dev_dependencies: path: '>=0.9.0 <2.0.0' - unittest: '>=0.10.0 <0.12.0' + test: '^0.12.0' diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 404a4882b..671d0b107 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -1,7 +1,7 @@ /// Additional feature tests that aren't based on test data. library dom_test; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index d185a140a..e5c1d8ca8 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -1,7 +1,7 @@ /// Additional feature tests that aren't based on test data. library parser_feature_test; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:html/src/constants.dart'; diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 516a0f4ee..20c26ebb1 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -3,7 +3,7 @@ library parser_test; import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as pathos; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:html/parser_console.dart' as parser_console; diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart index d2bf9ceff..b050609fd 100644 --- a/pkgs/html/test/run_all.dart +++ b/pkgs/html/test/run_all.dart @@ -5,8 +5,7 @@ library test.run_all; -import 'package:unittest/compact_vm_config.dart'; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'dom_test.dart' as dom_test; import 'parser_feature_test.dart' as parser_feature_test; @@ -15,7 +14,6 @@ import 'tokenizer_test.dart' as tokenizer_test; main(List<String> args) { var pattern = new RegExp(args.length > 0 ? args[0] : '.'); - useCompactVMConfiguration(); void addGroup(testFile, void testMain()) { if (pattern.hasMatch(testFile)) { diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index e052843d0..bef290c7e 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -8,12 +8,14 @@ library html.test.selectors.level1_baseline_test; import 'dart:io'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; -import 'package:unittest/unittest.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; import 'level1_lib.dart' hide test; import 'selectors.dart'; +import '../support.dart'; Document getTestContentDocument() { - var testPath = Platform.script.resolve('level1-content.html').toFilePath(); + var testPath = p.join(testDir, 'selectors', 'level1-content.html'); return parse(new File(testPath).readAsStringSync()); } diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 34b7c757d..0bf08f628 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -10,7 +10,7 @@ library html.test.selectors.level1_lib; import 'package:html/dom.dart'; -import 'package:unittest/unittest.dart' as unittest; +import 'package:test/test.dart' as unittest; Document doc; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 1bb255016..f467faa0b 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -3,7 +3,8 @@ library support; import 'dart:io'; import 'dart:collection'; -import 'package:path/path.dart' as path; + +import 'package:path/path.dart' as p; import 'package:html/src/treebuilder.dart'; import 'package:html/dom.dart'; import 'package:html/dom_parsing.dart'; @@ -19,10 +20,12 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDataDir = Platform.script.resolve('data').toFilePath(); +final testDir = p.join(p.dirname(p.fromUri(Platform.packageConfig)), 'test'); + +final testDataDir = p.join(testDir, 'data'); Iterable<String> getDataFiles(String subdirectory) { - var dir = new Directory(path.join(testDataDir, subdirectory)); + var dir = new Directory(p.join(testDataDir, subdirectory)); return dir.listSync().where((f) => f is File).map((f) => f.path); } diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index bdac1fd31..a8543ff2c 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -5,7 +5,7 @@ import 'dart:convert'; import 'dart:io'; import 'dart:mirrors'; import 'package:path/path.dart' as pathos; -import 'package:unittest/unittest.dart'; +import 'package:test/test.dart'; import 'package:html/src/char_encodings.dart'; import 'package:html/src/token.dart'; import 'package:html/src/tokenizer.dart'; From 8349fbaa5fcc4a5282fb3ddf6fe274bb2568a41e Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Thu, 12 Oct 2017 15:17:06 -0700 Subject: [PATCH 073/212] sort directives and other lints --- pkgs/html/lib/dom.dart | 6 +++--- pkgs/html/lib/dom_parsing.dart | 4 ++-- pkgs/html/lib/parser.dart | 12 ++++++------ pkgs/html/lib/src/char_encodings.dart | 8 ++++---- pkgs/html/lib/src/css_class_set.dart | 2 +- pkgs/html/lib/src/inputstream.dart | 2 +- pkgs/html/lib/src/query_selector.dart | 2 +- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/treebuilder.dart | 6 +++--- pkgs/html/test/selectors/level1_baseline_test.dart | 3 ++- pkgs/html/test/support.dart | 4 ++-- 11 files changed, 26 insertions(+), 25 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index a50048130..cd2b9fb56 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -267,7 +267,7 @@ abstract class Node { nodes.clear(); } - bool hasChildNodes() => !nodes.isEmpty; + bool hasChildNodes() => nodes.isNotEmpty; bool contains(Node node) => nodes.contains(node); @@ -838,7 +838,7 @@ class FilteredElementList extends IterableBase<Element> this[index].replaceWith(value); } - void set length(int newLength) { + set length(int newLength) { final len = this.length; if (newLength >= len) { return; @@ -974,7 +974,7 @@ class FilteredElementList extends IterableBase<Element> // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. - int lastIndexOf(element, [int start = null]) { + int lastIndexOf(element, [int start]) { if (start == null) start = length - 1; return _filtered.lastIndexOf(element, start); } diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 5575dcd2f..56518c257 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -128,10 +128,10 @@ class CodeMarkupVisitor extends TreeVisitor { String htmlSerializeEscape(String text, {bool attributeMode: false}) { // TODO(jmesserly): is it faster to build up a list of codepoints? // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. - StringBuffer result = null; + StringBuffer result; for (int i = 0; i < text.length; i++) { var ch = text[i]; - String replace = null; + String replace; switch (ch) { case '&': replace = '&amp;'; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 546061fe5..e1c60997d 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -17,13 +17,13 @@ import 'dart:collection'; import 'dart:math'; import 'package:source_span/source_span.dart'; -import 'src/treebuilder.dart'; +import 'dom.dart'; import 'src/constants.dart'; import 'src/encoding_parser.dart'; import 'src/token.dart'; import 'src/tokenizer.dart'; +import 'src/treebuilder.dart'; import 'src/utils.dart'; -import 'dom.dart'; /// Parse the [input] html5 document into a tree. The [input] can be /// a [String], [List<int>] of bytes or an [HtmlTokenizer]. @@ -2092,7 +2092,7 @@ class InBodyPhase extends Phase { // Step 2 // Start of the adoption agency algorithm proper var afeIndex = tree.openElements.indexOf(formattingElement); - Node furthestBlock = null; + Node furthestBlock; for (Node element in slice(tree.openElements, afeIndex)) { if (specialElements.contains(getElementNameTuple(element))) { furthestBlock = element; @@ -2517,7 +2517,7 @@ class InTableTextPhase extends Phase { Phase originalPhase; List<StringToken> characterTokens; - InTableTextPhase(parser) + InTableTextPhase(HtmlParser parser) : characterTokens = <StringToken>[], super(parser); @@ -2526,7 +2526,7 @@ class InTableTextPhase extends Phase { // TODO(sigmund,jmesserly): remove '' (dartbug.com/8480) var data = characterTokens.map((t) => t.data).join(''); - var span = null; + FileSpan span; if (parser.generateSpans) { span = characterTokens[0].span.expand(characterTokens.last.span); @@ -3551,7 +3551,7 @@ class InForeignContentPhase extends Phase { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } - var newToken = null; + var newToken; while (true) { if (asciiUpper2Lower(node.localName) == token.name) { //XXX this isn't in the spec but it seems necessary diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 56680bd28..bf1fa470e 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -116,10 +116,10 @@ class IterableWindows1252Decoder extends IterableBase<int> { final int length; final int replacementCodepoint; - IterableWindows1252Decoder(List<int> this.bytes, - [int this.offset = 0, - int this.length = null, - int this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]); + IterableWindows1252Decoder(this.bytes, + [this.offset = 0, + this.length, + this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]); Windows1252Decoder get iterator => new Windows1252Decoder(bytes, offset, length, replacementCodepoint); diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 40575c2bb..e1fc3f13e 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -20,7 +20,7 @@ class ElementCssClassSet extends CssClassSetImpl { for (String name in classname.split(' ')) { String trimmed = name.trim(); - if (!trimmed.isEmpty) { + if (trimmed.isNotEmpty) { s.add(trimmed); } } diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index 849ed936e..d68327796 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -5,8 +5,8 @@ import 'package:utf/utf.dart'; import 'package:source_span/source_span.dart'; import 'char_encodings.dart'; import 'constants.dart'; -import 'utils.dart'; import 'encoding_parser.dart'; +import 'utils.dart'; /// Hooks to call into dart:io without directly referencing it. class ConsoleSupport { diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 5c438dbda..38045d474 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -67,7 +67,7 @@ class SelectorEvaluator extends Visitor { var result = true; // Note: evaluate selectors right-to-left as it's more efficient. - int combinator = null; + int combinator; for (var s in selector.simpleSelectorSequences.reversed) { if (combinator == null) { result = s.simpleSelector.visit(this); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 21505df70..db9ab6330 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -310,7 +310,7 @@ class HtmlTokenizer implements Iterator<Token> { // At this point we have a string that starts with some characters // that may match an entity - String entityName = null; + String entityName; // Try to find the longest entity the string will match to take care // of &noti for instance. diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index ac71e48dc..db9165121 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -350,9 +350,9 @@ class TreeBuilder { // The foster parent element is the one which comes before the most // recently opened table element // XXX - this is really inelegant - Node lastTable = null; - Node fosterParent = null; - Node insertBefore = null; + Node lastTable; + Node fosterParent; + Node insertBefore; for (var elm in openElements.reversed) { if (elm.localName == "table") { lastTable = elm; diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index bef290c7e..9bac00d4e 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -10,9 +10,10 @@ import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:path/path.dart' as p; import 'package:test/test.dart'; + +import '../support.dart'; import 'level1_lib.dart' hide test; import 'selectors.dart'; -import '../support.dart'; Document getTestContentDocument() { var testPath = p.join(testDir, 'selectors', 'level1-content.html'); diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index f467faa0b..2af8b7c3f 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -1,8 +1,8 @@ /// Support code for the tests in this directory. library support; -import 'dart:io'; import 'dart:collection'; +import 'dart:io'; import 'package:path/path.dart' as p; import 'package:html/src/treebuilder.dart'; @@ -45,7 +45,7 @@ class TestData extends IterableBase<Map> { List<Map> _getData() { var data = <String, String>{}; - var key = null; + String key; var result = <Map>[]; var lines = _text.split('\n'); // Remove trailing newline to match Python From bc291f6e1becee11866322f472e940623a1acf79 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Thu, 12 Oct 2017 15:26:45 -0700 Subject: [PATCH 074/212] finish test cleanup --- pkgs/html/test/run.sh | 22 --------------- pkgs/html/test/run_all.dart | 28 ------------------- .../test/selectors/level1_baseline_test.dart | 3 ++ 3 files changed, 3 insertions(+), 50 deletions(-) delete mode 100755 pkgs/html/test/run.sh delete mode 100644 pkgs/html/test/run_all.dart diff --git a/pkgs/html/test/run.sh b/pkgs/html/test/run.sh deleted file mode 100755 index c060bd754..000000000 --- a/pkgs/html/test/run.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/bin/bash -# Copyright (c) 2012, the Dart project authors. Please see the LICENSE file -# for details. All rights reserved. Use of this source code is governed by a -# MIT-style license that can be found in the LICENSE file. - -# bail on error -set -e - -# TODO(sigmund): replace with a real test runner -DIR=$( cd $( dirname "${BASH_SOURCE[0]}" ) && pwd ) - -# Note: dart_analyzer needs to be run from the root directory for proper path -# canonicalization. -pushd $DIR/.. -# TODO(jmesserly): switch to new analyzer. Note: it's missing a lot of the -# tests for implemented members; we should get that fixed before switching. -echo Analyzing library for warnings or type errors -dartanalyzer --fatal-warnings lib/*.dart || \ - echo "ignore analyzer errors" -popd - -dart --checked test/run_all.dart $@ diff --git a/pkgs/html/test/run_all.dart b/pkgs/html/test/run_all.dart deleted file mode 100644 index b050609fd..000000000 --- a/pkgs/html/test/run_all.dart +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env dart -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library test.run_all; - -import 'package:test/test.dart'; - -import 'dom_test.dart' as dom_test; -import 'parser_feature_test.dart' as parser_feature_test; -import 'parser_test.dart' as parser_test; -import 'tokenizer_test.dart' as tokenizer_test; - -main(List<String> args) { - var pattern = new RegExp(args.length > 0 ? args[0] : '.'); - - void addGroup(testFile, void testMain()) { - if (pattern.hasMatch(testFile)) { - group(testFile.replaceAll('_test.dart', ':'), testMain); - } - } - - addGroup('dom_test.dart', dom_test.main); - addGroup('parser_feature_test.dart', parser_feature_test.main); - addGroup('parser_test.dart', parser_test.main); - addGroup('tokenizer_test.dart', tokenizer_test.main); -} diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 9bac00d4e..52ecd3e2c 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -3,6 +3,9 @@ /// /// Note, unlike the original we don't operate in-browser on a DOM loaded into /// an iframe, but instead operate over a parsed DOM. + +@Skip() + library html.test.selectors.level1_baseline_test; import 'dart:io'; From f13da583a99218ff89afcb70e768641bb6148558 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 11:47:52 -0800 Subject: [PATCH 075/212] Use SetBase for CssClassSet --- pkgs/html/lib/src/css_class_set.dart | 111 ++------------------------- pkgs/html/pubspec.yaml | 2 +- 2 files changed, 7 insertions(+), 106 deletions(-) diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index e1fc3f13e..eca2400b4 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -9,7 +9,7 @@ import 'dart:collection'; import 'package:html/dom.dart'; -class ElementCssClassSet extends CssClassSetImpl { +class ElementCssClassSet extends _CssClassSetImpl { final Element _element; ElementCssClassSet(this._element); @@ -108,7 +108,7 @@ abstract class CssClassSet implements Set<String> { void toggleAll(Iterable<String> iterable, [bool shouldAdd]); } -abstract class CssClassSetImpl implements CssClassSet { +abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { String toString() { return readClasses().join(' '); } @@ -140,43 +140,10 @@ abstract class CssClassSetImpl implements CssClassSet { */ bool get frozen => false; - // interface Iterable - BEGIN Iterator<String> get iterator => readClasses().iterator; - // interface Iterable - END - - // interface Collection - BEGIN - void forEach(void f(String element)) { - readClasses().forEach(f); - } - - String join([String separator = ""]) => readClasses().join(separator); - - Iterable<T> map<T>(T f(String e)) => readClasses().map(f); - - Iterable<String> where(bool f(String element)) => readClasses().where(f); - - Iterable<T> expand<T>(Iterable<T> f(String element)) => - readClasses().expand(f); - - bool every(bool f(String element)) => readClasses().every(f); - - bool any(bool f(String element)) => readClasses().any(f); - - bool get isEmpty => readClasses().isEmpty; - - bool get isNotEmpty => readClasses().isNotEmpty; int get length => readClasses().length; - String reduce(String combine(String value, String element)) { - return readClasses().reduce(combine); - } - - T fold<T>(T initialValue, T combine(T previousValue, String element)) { - return readClasses().fold(initialValue, combine); - } - // interface Collection - END - // interface Set - BEGIN /** * Determine if this element contains the class [value]. @@ -189,6 +156,8 @@ abstract class CssClassSetImpl implements CssClassSet { /** Lookup from the Set interface. Not interesting for a String set. */ String lookup(Object value) => contains(value) ? value as String : null; + Set<String> toSet() => readClasses().toSet(); + /** * Add the class [value] to element. * @@ -198,7 +167,7 @@ abstract class CssClassSetImpl implements CssClassSet { bool add(String value) { // TODO - figure out if we need to do any validation here // or if the browser natively does enough. - return modify((s) => s.add(value)); + return _modify((s) => s.add(value)); } /** @@ -216,27 +185,6 @@ abstract class CssClassSetImpl implements CssClassSet { return result; } - /** - * Add all classes specified in [iterable] to element. - * - * This is the Dart equivalent of jQuery's - * [addClass](http://api.jquery.com/addClass/). - */ - void addAll(Iterable<String> iterable) { - // TODO - see comment above about validation. - modify((s) => s.addAll(iterable)); - } - - /** - * Remove all classes specified in [iterable] from element. - * - * This is the Dart equivalent of jQuery's - * [removeClass](http://api.jquery.com/removeClass/). - */ - void removeAll(Iterable<Object> iterable) { - modify((s) => s.removeAll(iterable)); - } - /** * Toggles all classes specified in [iterable] on element. * @@ -251,53 +199,6 @@ abstract class CssClassSetImpl implements CssClassSet { iterable.forEach((e) => toggle(e, shouldAdd)); } - void retainAll(Iterable<Object> iterable) { - modify((s) => s.retainAll(iterable)); - } - - void removeWhere(bool test(String name)) { - modify((s) => s.removeWhere(test)); - } - - void retainWhere(bool test(String name)) { - modify((s) => s.retainWhere(test)); - } - - bool containsAll(Iterable<Object> collection) => - readClasses().containsAll(collection); - - Set<String> intersection(Set<Object> other) => - readClasses().intersection(other); - - Set<String> union(Set<String> other) => readClasses().union(other); - - Set<String> difference(Set<Object> other) => readClasses().difference(other); - - String get first => readClasses().first; - String get last => readClasses().last; - String get single => readClasses().single; - List<String> toList({bool growable: true}) => - readClasses().toList(growable: growable); - Set<String> toSet() => readClasses().toSet(); - Iterable<String> take(int n) => readClasses().take(n); - Iterable<String> takeWhile(bool test(String value)) => - readClasses().takeWhile(test); - Iterable<String> skip(int n) => readClasses().skip(n); - Iterable<String> skipWhile(bool test(String value)) => - readClasses().skipWhile(test); - String firstWhere(bool test(String value), {String orElse()}) => - readClasses().firstWhere(test, orElse: orElse); - String lastWhere(bool test(String value), {String orElse()}) => - readClasses().lastWhere(test, orElse: orElse); - String singleWhere(bool test(String value)) => - readClasses().singleWhere(test); - String elementAt(int index) => readClasses().elementAt(index); - - void clear() { - modify((s) => s.clear()); - } - // interface Set - END - /** * Helper method used to modify the set of css classes on this element. * @@ -307,7 +208,7 @@ abstract class CssClassSetImpl implements CssClassSet { * After f returns, the modified set is written to the * className property of this element. */ - modify(f(Set<String> s)) { + bool _modify(bool f(Set<String> s)) { Set<String> s = readClasses(); var ret = f(s); writeClasses(s); diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 265a98325..09bf52ee3 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.2 +version: 0.13.3-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From 54b4201aca0c23d83f50b6713b906fbcd99ca655 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 12:05:48 -0800 Subject: [PATCH 076/212] List proxy --- pkgs/html/lib/dom.dart | 2 - pkgs/html/lib/src/list_proxy.dart | 83 ++---------------------------- pkgs/html/lib/src/treebuilder.dart | 1 - 3 files changed, 5 insertions(+), 81 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index cd2b9fb56..132aa5500 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -682,8 +682,6 @@ class NodeList extends ListProxy<Node> { NodeList._(); - Node get first => this[0]; - Node _setParent(Node node) { // Note: we need to remove the node from its previous parent node, if any, // before updating its parent pointer to point at our parent. diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 7c6e612ab..b2fe5129f 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -1,49 +1,22 @@ -// TODO(jmesserly): remove this once we have a subclassable growable list -// in our libraries. - /// A [List] proxy that you can subclass. library list_proxy; import 'dart:collection'; -import 'dart:math' show Random; -// TOOD(jmesserly): this needs to be removed, but fixing NodeList is tricky. -class ListProxy<E> extends IterableBase<E> implements List<E> { +abstract class ListProxy<E> extends ListBase<E> { /// The inner [List<T>] with the actual storage. - final List<E> _list; - - /// Creates a list proxy. - /// You can optionally specify the list to use for [storage] of the items, - /// otherwise this will create a [List<E>]. - ListProxy([List<E> storage]) : _list = storage != null ? storage : <E>[]; + final List<E> _list = <E>[]; - // TODO(jmesserly): This should be on List. - // See http://code.google.com/p/dart/issues/detail?id=947 - bool remove(Object item) { - if (item is E) { - int i = indexOf(item); - if (i == -1) return false; - removeAt(i); - return true; - } - return false; - } + bool remove(Object item) => _list.remove(item); - void insert(int index, E item) => _list.insert(index, item); - - // Override from Iterable to fix performance - // Length and last become O(1) instead of O(N) - // The others are just different constant factor. int get length => _list.length; - E get last => _list.last; - E get first => _list.first; - E get single => _list.single; // From Iterable Iterator<E> get iterator => _list.iterator; // From List E operator [](int index) => _list[index]; + operator []=(int index, E value) { _list[index] = value; } @@ -56,59 +29,13 @@ class ListProxy<E> extends IterableBase<E> implements List<E> { _list.add(value); } - void addLast(E value) { - add(value); - } + void insert(int index, E item) => _list.insert(index, item); void addAll(Iterable<E> collection) { _list.addAll(collection); } - void sort([int compare(E a, E b)]) { - _list.sort(compare); - } - - void shuffle([Random random]) { - _list.shuffle(random); - } - - int indexOf(E element, [int start = 0]) => _list.indexOf(element, start); - int lastIndexOf(E element, [int start]) => _list.lastIndexOf(element, start); - void clear() { - _list.clear(); - } - - E removeAt(int index) => _list.removeAt(index); - E removeLast() => _list.removeLast(); - - void removeWhere(bool test(E element)) => _list.removeWhere(test); - void retainWhere(bool test(E element)) => _list.retainWhere(test); - - List<E> sublist(int start, [int end]) => _list.sublist(start, end); - - List<E> getRange(int start, int end) => _list.getRange(start, end); - - void setRange(int start, int length, Iterable<E> from, [int startFrom = 0]) { - _list.setRange(start, length, from, startFrom); - } - - void removeRange(int start, int length) { - _list.removeRange(start, length); - } - void insertAll(int index, Iterable<E> iterable) { _list.insertAll(index, iterable); } - - Iterable<E> get reversed => _list.reversed; - - Map<int, E> asMap() => _list.asMap(); - - void replaceRange(int start, int end, Iterable<E> newContents) => - _list.replaceRange(start, end, newContents); - - void setAll(int index, Iterable<E> iterable) => _list.setAll(index, iterable); - - void fillRange(int start, int end, [E fillValue]) => - _list.fillRange(start, end, fillValue); } diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index db9165121..69e181751 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -18,7 +18,6 @@ const Node Marker = null; // TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt // didn't work. class ActiveFormattingElements extends ListProxy<Element> { - ActiveFormattingElements() : super(); // Override the "add" method. // TODO(jmesserly): I'd rather not override this; can we do this in the From 734c4d26aa7f97d93595525f5633a67e06a33e91 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 12:12:57 -0800 Subject: [PATCH 077/212] Remove old CI files --- pkgs/html/.status | 29 ----------------------------- pkgs/html/.test_config | 3 +++ pkgs/html/codereview.settings | 3 --- 3 files changed, 3 insertions(+), 32 deletions(-) delete mode 100644 pkgs/html/.status create mode 100644 pkgs/html/.test_config delete mode 100644 pkgs/html/codereview.settings diff --git a/pkgs/html/.status b/pkgs/html/.status deleted file mode 100644 index a42413806..000000000 --- a/pkgs/html/.status +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file -# for details. All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -# Don't run any test-like files that show up in packages directories. It -# shouldn't be necessary to run "pub install" in these packages, but if you do -# it shouldn't break the tests. -*/packages/*/*: Skip -*/*/packages/*/*: Skip -*/*/*/packages/*/*: Skip -*/*/*/*/packages/*/*: Skip -*/*/*/*/*/packages/*/*: Skip - -build/*: Skip # nothing requires pub-build - -[ $runtime == vm && $mode == debug] -test/tokenizer_test: Skip # Times out - -[ $runtime == vm && ( $arch == simarm || $arch == simmips ) ] -test/tokenizer_test: Pass, Slow - -[ $browser ] -test/parser_test: Skip -test/tokenizer_test: Skip -test/selectors/*: Skip - -[ $runtime == vm ] -test/browser/browser_test: Skip -test/selectors/level1_baseline_test: RuntimeError # Issue 37 \ No newline at end of file diff --git a/pkgs/html/.test_config b/pkgs/html/.test_config new file mode 100644 index 000000000..412fc5c5c --- /dev/null +++ b/pkgs/html/.test_config @@ -0,0 +1,3 @@ +{ + "test_package": true +} \ No newline at end of file diff --git a/pkgs/html/codereview.settings b/pkgs/html/codereview.settings deleted file mode 100644 index caca72f48..000000000 --- a/pkgs/html/codereview.settings +++ /dev/null @@ -1,3 +0,0 @@ -CODE_REVIEW_SERVER: http://codereview.chromium.org/ -VIEW_VC: https://github.com/dart-lang/html/commit/ -CC_LIST: reviews@dartlang.org From 9131cd29a97e797acf31f5636b8aae547ad73b00 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 13:10:40 -0800 Subject: [PATCH 078/212] Add Travis-CI support --- pkgs/html/.travis.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 pkgs/html/.travis.yml diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml new file mode 100644 index 000000000..ae4290c2e --- /dev/null +++ b/pkgs/html/.travis.yml @@ -0,0 +1,21 @@ +language: dart +dart: + - dev + - stable + +dart_task: + - test + - dartanalyzer + +matrix: + include: + - dart: dev + dart_task: dartfmt + +# Only building master means that we don't run two builds for each pull request. +branches: + only: [master] + +cache: + directories: + - $HOME/.pub-cache From fd343f20333f5c02a5cd6efcf26f074d55aad998 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 13:30:11 -0800 Subject: [PATCH 079/212] enable many lints --- pkgs/html/analysis_options.yaml | 49 ++++++++++++++++++++++++ pkgs/html/lib/dom.dart | 8 ++-- pkgs/html/lib/dom_parsing.dart | 4 +- pkgs/html/lib/parser.dart | 20 +++++----- pkgs/html/lib/src/encoding_parser.dart | 2 +- pkgs/html/lib/src/tokenizer.dart | 16 ++++---- pkgs/html/lib/src/treebuilder.dart | 9 ++--- pkgs/html/test/selectors/level1_lib.dart | 2 +- pkgs/html/test/support.dart | 6 +-- pkgs/html/test/tokenizer_test.dart | 6 +-- 10 files changed, 85 insertions(+), 37 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index a10d4c5a0..da175164b 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,2 +1,51 @@ analyzer: strong-mode: true + errors: + unused_import: error + unused_local_variable: error + dead_code: error + override_on_non_overriding_method: error +linter: + rules: + # Errors + - avoid_empty_else + - await_only_futures + #- comment_references + - control_flow_in_finally + - empty_statements + - hash_and_equals + - iterable_contains_unrelated_type + - no_duplicate_case_values + - test_types_in_equals + - throw_in_finally + - unawaited_futures + - unnecessary_statements + - unrelated_type_equality_checks + - valid_regexps + + # Style + #- annotate_overrides + #- avoid_function_literals_in_foreach_calls + - avoid_init_to_null + - avoid_return_types_on_setters + - avoid_returning_null + - avoid_unused_constructor_parameters + - camel_case_types + - directives_ordering + - empty_catches + - empty_constructor_bodies + - library_names + - library_prefixes + #- non_constant_identifier_names + #- prefer_conditional_assignment + - prefer_final_fields + - prefer_is_empty + - prefer_is_not_empty + #- prefer_typing_uninitialized_variables + - recursive_getters + #- slash_for_doc_comments + - type_init_formals + #- unnecessary_brace_in_string_interps + - unnecessary_getters_setters + - unnecessary_lambdas + - unnecessary_null_aware_assignments diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 132aa5500..fb0d45865 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -257,7 +257,7 @@ abstract class Node { // TODO(jmesserly): should this be a property or remove? /// Return true if the node has children or text. - bool hasContent() => nodes.length > 0; + bool hasContent() => nodes.isNotEmpty; /// Move all the children of the current node to [newParent]. /// This is needed so that trees that don't store text as nodes move the @@ -406,7 +406,7 @@ class Text extends Node { /// The text node's data, stored as either a String or StringBuffer. /// We support storing a StringBuffer here to support fast [appendData]. /// It will flatten back to a String on read. - var _data; + dynamic _data; Text(String data) : _data = data != null ? data : '', @@ -565,7 +565,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { str.write(_getSerializationPrefix(namespaceUri)); str.write(localName); - if (attributes.length > 0) { + if (attributes.isNotEmpty) { attributes.forEach((key, v) { // Note: AttributeName.toString handles serialization of attribute // namespace, if needed. @@ -579,7 +579,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { str.write('>'); - if (nodes.length > 0) { + if (nodes.isNotEmpty) { if (localName == 'pre' || localName == 'textarea' || localName == 'listing') { diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 56518c257..3435a8128 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -85,14 +85,14 @@ class CodeMarkupVisitor extends TreeVisitor { visitElement(Element node) { final tag = node.localName; _str.write('&lt;<code class="markup element-name">$tag</code>'); - if (node.attributes.length > 0) { + if (node.attributes.isNotEmpty) { node.attributes.forEach((key, v) { v = htmlSerializeEscape(v, attributeMode: true); _str.write(' <code class="markup attribute-name">$key</code>' '=<code class="markup attribute-value">"$v"</code>'); }); } - if (node.nodes.length > 0) { + if (node.nodes.isNotEmpty) { _str.write(">"); visitChildren(node); } else if (isVoidElement(tag)) { diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index e1c60997d..75a5c6228 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -276,7 +276,7 @@ class HtmlParser { } bool inForeignContent(Token token, int type) { - if (tree.openElements.length == 0) return false; + if (tree.openElements.isEmpty) return false; var node = tree.openElements.last; if (node.namespaceUri == tree.defaultNamespace) return false; @@ -1235,7 +1235,6 @@ class InBodyPhase extends Phase { case "blockquote": case "center": case "details": - case "details": case "dir": case "div": case "dl": @@ -1343,7 +1342,6 @@ class InBodyPhase extends Phase { startTagIFrame(token); return null; case "noembed": - case "noframes": case "noscript": startTagRawtext(token); return null; @@ -1538,7 +1536,7 @@ class InBodyPhase extends Phase { data = data.substring(1); } } - if (data.length > 0) { + if (data.isNotEmpty) { tree.reconstructActiveFormattingElements(); tree.insertText(data, token.span); } @@ -2012,7 +2010,7 @@ class InBodyPhase extends Phase { } void endTagListItem(EndTagToken token) { - var variant; + String variant; if (token.name == "li") { variant = "list"; } else { @@ -2232,7 +2230,9 @@ class InBodyPhase extends Phase { parser.parseError( token.span, "unexpected-end-tag", {"name": token.name}); } - while (tree.openElements.removeLast() != node); + while (tree.openElements.removeLast() != node) { + // noop + } node.endSourceSpan = token.span; break; } else { @@ -2522,7 +2522,7 @@ class InTableTextPhase extends Phase { super(parser); void flushCharacters() { - if (characterTokens.length == 0) return; + if (characterTokens.isEmpty) return; // TODO(sigmund,jmesserly): remove '' (dartbug.com/8480) var data = characterTokens.map((t) => t.data).join(''); @@ -2534,7 +2534,7 @@ class InTableTextPhase extends Phase { if (!allWhitespace(data)) { parser._inTablePhase.insertText(new CharactersToken(data)..span = span); - } else if (data.length > 0) { + } else if (data.isNotEmpty) { tree.insertText(data, span); } characterTokens = <StringToken>[]; @@ -3551,7 +3551,7 @@ class InForeignContentPhase extends Phase { parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); } - var newToken; + Token newToken; while (true) { if (asciiUpper2Lower(node.localName) == token.name) { //XXX this isn't in the spec but it seems necessary @@ -3561,7 +3561,7 @@ class InForeignContentPhase extends Phase { parser.phase = inTableText.originalPhase; } while (tree.openElements.removeLast() != node) { - assert(tree.openElements.length > 0); + assert(tree.openElements.isNotEmpty); } newToken = null; break; diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 21d6783b8..d97e4cc1b 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -254,7 +254,7 @@ class EncodingParser { while (true) { if (c == null) { return null; - } else if (c == "=" && attrName.length > 0) { + } else if (c == "=" && attrName.isNotEmpty) { break; } else if (isWhitespace(c)) { // Step 6! diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index db9ab6330..30092a29e 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -125,16 +125,16 @@ class HtmlTokenizer implements Iterator<Token> { bool moveNext() { // Start processing. When EOF is reached state will return false; // instead of true and the loop will terminate. - while (stream.errors.length == 0 && tokenQueue.length == 0) { + while (stream.errors.isEmpty && tokenQueue.isEmpty) { if (!state()) { _current = null; return false; } } - if (stream.errors.length > 0) { + if (stream.errors.isNotEmpty) { _current = new ParseErrorToken(stream.errors.removeFirst()); } else { - assert(tokenQueue.length > 0); + assert(tokenQueue.isNotEmpty); _current = tokenQueue.removeFirst(); } return true; @@ -302,7 +302,7 @@ class HtmlTokenizer implements Iterator<Token> { filteredEntityList = filteredEntityList.where((e) => e.startsWith(name)).toList(); - if (filteredEntityList.length == 0) { + if (filteredEntityList.isEmpty) { break; } charStack.add(stream.char()); @@ -349,7 +349,7 @@ class HtmlTokenizer implements Iterator<Token> { if (fromAttribute) { _attributeValue.write(output); } else { - var token; + Token token; if (isWhitespace(output)) { token = new SpaceCharactersToken(output); } else { @@ -1316,7 +1316,7 @@ class HtmlTokenizer implements Iterator<Token> { } } else if (charStack.last == "[" && parser != null && - parser.tree.openElements.length > 0 && + parser.tree.openElements.isNotEmpty && parser.tree.openElements.last.namespaceUri != parser.tree.defaultNamespace) { var matched = true; @@ -1335,7 +1335,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(new ParseErrorToken("expected-dashes-or-doctype")); - while (charStack.length > 0) { + while (charStack.isNotEmpty) { stream.unget(charStack.removeLast()); } state = bogusCommentState; @@ -1904,7 +1904,7 @@ class HtmlTokenizer implements Iterator<Token> { } } - if (data.length > 0) { + if (data.isNotEmpty) { _addToken(new CharactersToken(data.join())); } state = dataState; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 69e181751..12cdbbb20 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -18,7 +18,6 @@ const Node Marker = null; // TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt // didn't work. class ActiveFormattingElements extends ListProxy<Element> { - // Override the "add" method. // TODO(jmesserly): I'd rather not override this; can we do this in the // calling code instead? @@ -45,7 +44,7 @@ class ActiveFormattingElements extends ListProxy<Element> { // TODO(jmesserly): this should exist in corelib... bool _mapEquals(Map a, Map b) { if (a.length != b.length) return false; - if (a.length == 0) return true; + if (a.isEmpty) return true; for (var keyA in a.keys) { var valB = b[keyA]; @@ -158,7 +157,7 @@ class TreeBuilder { // code. It should still do the same though. // Step 1: stop the algorithm when there's nothing to do. - if (activeFormattingElements.length == 0) { + if (activeFormattingElements.isEmpty) { return; } @@ -209,7 +208,7 @@ class TreeBuilder { void clearActiveFormattingElements() { var entry = activeFormattingElements.removeLast(); - while (activeFormattingElements.length > 0 && entry != Marker) { + while (activeFormattingElements.isNotEmpty && entry != Marker) { entry = activeFormattingElements.removeLast(); } } @@ -321,7 +320,7 @@ class TreeBuilder { [Element refNode]) { var nodes = parent.nodes; if (refNode == null) { - if (nodes.length > 0 && nodes.last is Text) { + if (nodes.isNotEmpty && nodes.last is Text) { Text last = nodes.last; last.appendData(data); diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 0bf08f628..3c3df2056 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -232,7 +232,7 @@ runValidSelectorTest(type, root, selectors, testType, docType) { test(() { found = root.querySelector(q); - if (e.length > 0) { + if (e.isNotEmpty) { assert_not_equals(found, null, "The method should return a match."); assert_equals(found.attributes["id"], e[0], "The method should return the first match."); diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 2af8b7c3f..022da355d 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -55,7 +55,7 @@ class TestData extends IterableBase<Map> { for (var line in lines) { var heading = sectionHeading(line); if (heading != null) { - if (data.length > 0 && heading == newTestHeading) { + if (data.isNotEmpty && heading == newTestHeading) { // Remove trailing newline data[key] = data[key].substring(0, data[key].length - 1); result.add(normaliseOutput(data)); @@ -68,7 +68,7 @@ class TestData extends IterableBase<Map> { } } - if (data.length > 0) { + if (data.isNotEmpty) { result.add(normaliseOutput(data)); } return result; @@ -150,7 +150,7 @@ class TestSerializer extends TreeVisitor { visitElement(Element node) { _newline(); _str.write(node); - if (node.attributes.length > 0) { + if (node.attributes.isNotEmpty) { indent += 2; var keys = new List.from(node.attributes.keys); keys.sort((x, y) => x.compareTo(y)); diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index a8543ff2c..c268f9fb0 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -14,10 +14,10 @@ import 'support.dart'; class TokenizerTestParser { String _state; - var _lastStartTag; + String _lastStartTag; List outputTokens; - TokenizerTestParser(String initialState, [lastStartTag]) + TokenizerTestParser(String initialState, [String lastStartTag]) : _state = initialState, _lastStartTag = lastStartTag; @@ -105,7 +105,7 @@ List concatenateCharacterTokens(List tokens) { var outputTokens = []; for (var token in tokens) { if (token.indexOf("ParseError") == -1 && token[0] == "Character") { - if (outputTokens.length > 0 && + if (outputTokens.isNotEmpty && outputTokens.last.indexOf("ParseError") == -1 && outputTokens.last[0] == "Character") { outputTokens.last[1] = '${outputTokens.last[1]}${token[1]}'; From 8328873fcf72441b2582621e9cb2f0e39ca9cc38 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 13:38:57 -0800 Subject: [PATCH 080/212] Test on browsers - and exclude tests that require the vm --- pkgs/html/.travis.yml | 3 ++- pkgs/html/test/parser_test.dart | 1 + pkgs/html/test/tokenizer_test.dart | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index ae4290c2e..5b7ab8402 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -4,7 +4,8 @@ dart: - stable dart_task: - - test + - test: -p vm + - test: -p chrome,firefox - dartanalyzer matrix: diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 20c26ebb1..69a52a519 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -1,3 +1,4 @@ +@TestOn('vm') library parser_test; import 'dart:convert'; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index c268f9fb0..dba4eced7 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -1,3 +1,4 @@ +@TestOn('vm') library tokenizer_test; // Note: mirrors used to match the getattr usage in the original test From 7f904d5c3cc684b77b65821a58dc1b3012c09632 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 13:45:48 -0800 Subject: [PATCH 081/212] Implement RemoveAt and RemoveRange on ListProxy Fixes problems when running on Dart 1.24 --- pkgs/html/lib/src/list_proxy.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index b2fe5129f..63aeea6ef 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -38,4 +38,10 @@ abstract class ListProxy<E> extends ListBase<E> { void insertAll(int index, Iterable<E> iterable) { _list.insertAll(index, iterable); } + + E removeAt(int index) => _list.removeAt(index); + + void removeRange(int start, int length) { + _list.removeRange(start, length); + } } From b97c3c53eba2e7a37ade7913ea6935437488ac2a Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 20 Dec 2017 14:17:11 -0800 Subject: [PATCH 082/212] Fix and enable level1_baseline_test - with some skips --- .../test/selectors/level1_baseline_test.dart | 5 +- pkgs/html/test/selectors/level1_lib.dart | 125 ++++++++++-------- 2 files changed, 71 insertions(+), 59 deletions(-) diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 52ecd3e2c..9066842c2 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -4,8 +4,7 @@ /// Note, unlike the original we don't operate in-browser on a DOM loaded into /// an iframe, but instead operate over a parsed DOM. -@Skip() - +@TestOn('vm') library html.test.selectors.level1_baseline_test; import 'dart:io'; @@ -15,7 +14,7 @@ import 'package:path/path.dart' as p; import 'package:test/test.dart'; import '../support.dart'; -import 'level1_lib.dart' hide test; +import 'level1_lib.dart'; import 'selectors.dart'; Document getTestContentDocument() { diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 3c3df2056..4ffa9a8ed 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -2,7 +2,7 @@ /// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> /// /// Note: tried to make minimal changes possible here. Hence some oddities such -/// as [test] arguments having a different order, long lines, etc. +/// as [runTest] arguments having a different order, long lines, etc. /// /// As usual with ports: being faithful to the original style is more important /// than other style goals, as it reduces friction to integrating changes @@ -71,21 +71,21 @@ setupSpecialElements(parent) { * Check that the querySelector and querySelectorAll methods exist on the given Node */ interfaceCheck(type, obj) { - test(() { + runTest(() { var q = obj.querySelector is Function; - assert_true(q, type + " supports querySelector."); + assertTrue(q, type + " supports querySelector."); }, type + " supports querySelector"); - test(() { + runTest(() { var qa = obj.querySelectorAll is Function; - assert_true(qa, type + " supports querySelectorAll."); + assertTrue(qa, type + " supports querySelectorAll."); }, type + " supports querySelectorAll"); - test(() { + runTest(() { var list = obj.querySelectorAll("div"); // TODO(jmesserly): testing List<Element> for now. It should return an // ElementList which has extra properties. Needed for dart:html compat. - assert_true(list is List<Element>, + assertTrue(list is List<Element>, "The result should be an instance of a NodeList"); }, type + ".querySelectorAll returns NodeList instance"); } @@ -97,20 +97,20 @@ interfaceCheck(type, obj) { verifyStaticList(type, root) { var pre, post, preLength; - test(() { + runTest(() { pre = root.querySelectorAll("div"); preLength = pre.length; var div = doc.createElement("div"); (root is Document ? root.body : root).append(div); - assert_equals( + assertEquals( pre.length, preLength, "The length of the NodeList should not change."); }, type + ": static NodeList"); - test(() { + runTest(() { post = root.querySelectorAll("div"); - assert_equals(post.length, preLength + 1, + assertEquals(post.length, preLength + 1, "The length of the new NodeList should be 1 more than the previous list."); }, type + ": new NodeList"); } @@ -122,57 +122,57 @@ verifyStaticList(type, root) { runSpecialSelectorTests(type, root) { // Dart note: changed these tests because we don't have auto conversion to // String like JavaScript does. - test(() { + runTest(() { // 1 - assert_equals(root.querySelectorAll('null').length, 1, + assertEquals(root.querySelectorAll('null').length, 1, "This should find one element with the tag name 'NULL'."); }, type + ".querySelectorAll null"); - test(() { + runTest(() { // 2 - assert_equals(root.querySelectorAll('undefined').length, 1, + assertEquals(root.querySelectorAll('undefined').length, 1, "This should find one element with the tag name 'UNDEFINED'."); }, type + ".querySelectorAll undefined"); - test(() { + runTest(() { // 3 - assert_throws((e) => e is NoSuchMethodError, () { + assertThrows((e) => e is NoSuchMethodError, () { root.querySelectorAll(); }, "This should throw a TypeError."); }, type + ".querySelectorAll no parameter"); - test(() { + runTest(() { // 4 var elm = root.querySelector('null'); - assert_not_equals(elm, null, "This should find an element."); + assertNotEquals(elm, null, "This should find an element."); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assert_equals( + assertEquals( elm.localName.toUpperCase(), "NULL", "The tag name should be 'NULL'."); }, type + ".querySelector null"); - test(() { + runTest(() { // 5 var elm = root.querySelector('undefined'); - assert_not_equals(elm, 'undefined', "This should find an element."); + assertNotEquals(elm, 'undefined', "This should find an element."); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assert_equals(elm.localName.toUpperCase(), "UNDEFINED", + assertEquals(elm.localName.toUpperCase(), "UNDEFINED", "The tag name should be 'UNDEFINED'."); }, type + ".querySelector undefined"); - test(() { + runTest(() { // 6 - assert_throws((e) => e is NoSuchMethodError, () { + assertThrows((e) => e is NoSuchMethodError, () { root.querySelector(); }, "This should throw a TypeError."); }, type + ".querySelector no parameter"); - test(() { + runTest(() { // 7 var result = root.querySelectorAll("*"); var i = 0; traverse(root, (elem) { if (!identical(elem, root)) { - assert_equals( + assertEquals( elem, result[i], "The result in index $i should be in tree order."); i++; } @@ -180,11 +180,22 @@ runSpecialSelectorTests(type, root) { }, type + ".querySelectorAll tree order"); } +/// Tests containing this string fail for an unknown reason +final _failureName = 'matching custom data-* attribute with'; + +String _getSkip(String name) { + if (name.contains(_failureName)) { + return 'Tests related to `$_failureName` fail for an unknown reason.'; + } + return null; +} + /* * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() * Only run these tests when results are expected. Don't run for syntax error tests. */ -runValidSelectorTest(type, root, selectors, testType, docType) { +runValidSelectorTest(String type, root, List<Map<String, dynamic>> selectors, + testType, docType) { var nodeType = ""; switch (root.nodeType) { case Node.DOCUMENT_NODE: @@ -203,6 +214,7 @@ runValidSelectorTest(type, root, selectors, testType, docType) { for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; var n = s["name"]; + var skip = _getSkip(n); var q = s["selector"]; var e = s["expect"]; @@ -213,37 +225,37 @@ runValidSelectorTest(type, root, selectors, testType, docType) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) var foundall, found; - test(() { + runTest(() { foundall = root.querySelectorAll(q); - assert_not_equals(foundall, null, "The method should not return null."); - assert_equals(foundall.length, e.length, + assertNotEquals(foundall, null, "The method should not return null."); + assertEquals(foundall.length, e.length, "The method should return the expected number of matches."); for (var i = 0; i < e.length; i++) { - assert_not_equals( + assertNotEquals( foundall[i], null, "The item in index $i should not be null."); - assert_equals(foundall[i].attributes["id"], e[i], + assertEquals(foundall[i].attributes["id"], e[i], "The item in index $i should have the expected ID."); - assert_false(foundall[i].attributes.containsKey("data-clone"), + assertFalse(foundall[i].attributes.containsKey("data-clone"), "This should not be a cloned element."); } - }, type + ".querySelectorAll: " + n + ": " + q); + }, type + ".querySelectorAll: " + n + ": " + q, skip: skip); - test(() { + runTest(() { found = root.querySelector(q); if (e.isNotEmpty) { - assert_not_equals(found, null, "The method should return a match."); - assert_equals(found.attributes["id"], e[0], + assertNotEquals(found, null, "The method should return a match."); + assertEquals(found.attributes["id"], e[0], "The method should return the first match."); - assert_equals(found, foundall[0], + assertEquals(found, foundall[0], "The result should match the first item from querySelectorAll."); - assert_false(found.attributes.containsKey("data-clone"), + assertFalse(found.attributes.containsKey("data-clone"), "This should not be annotated as a cloned element."); } else { - assert_equals(found, null, "The method should not match anything."); + assertEquals(found, null, "The method should not match anything."); } - }, type + ".querySelector: " + n + ": " + q); + }, type + ".querySelector: " + n + ": " + q, skip: skip); } else { //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) } @@ -254,28 +266,28 @@ runValidSelectorTest(type, root, selectors, testType, docType) { * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() * Only run these tests when errors are expected. Don't run for valid selector tests. */ -runInvalidSelectorTest(type, root, selectors) { +runInvalidSelectorTest(String type, root, List selectors) { for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; var n = s["name"]; var q = s["selector"]; // Dart note: FormatException seems a reasonable mapping of SyntaxError - test(() { - assert_throws((e) => e is FormatException, () { + runTest(() { + assertThrows((e) => e is FormatException, () { root.querySelector(q); }); }, type + ".querySelector: " + n + ": " + q); - test(() { - assert_throws((e) => e is FormatException, () { + runTest(() { + assertThrows((e) => e is FormatException, () { root.querySelectorAll(q); }); }, type + ".querySelectorAll: " + n + ": " + q); } } -traverse(Node elem, fn) { +traverse(Node elem, void fn(Node elem)) { if (elem.nodeType == Node.ELEMENT_NODE) { fn(elem); } @@ -286,18 +298,19 @@ traverse(Node elem, fn) { } } -test(Function body, String name) => unittest.test(name, body); +runTest(Function body, String name, {String skip}) => + unittest.test(name, body, skip: skip); -assert_true(value, String reason) => - unittest.expect(value, true, reason: reason); +assertTrue(bool value, String reason) => + unittest.expect(value, unittest.isTrue, reason: reason); -assert_false(value, String reason) => - unittest.expect(value, false, reason: reason); +assertFalse(bool value, String reason) => + unittest.expect(value, unittest.isFalse, reason: reason); -assert_equals(x, y, reason) => unittest.expect(x, y, reason: reason); +assertEquals(x, y, String reason) => unittest.expect(x, y, reason: reason); -assert_not_equals(x, y, reason) => +assertNotEquals(x, y, String reason) => unittest.expect(x, unittest.isNot(y), reason: reason); -assert_throws(exception, body, [reason]) => +assertThrows(exception, body(), [String reason]) => unittest.expect(body, unittest.throwsA(exception), reason: reason); From 6c4918e3b85af66d2f712a1195a75f6cccc640b6 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Thu, 21 Dec 2017 16:34:49 -0800 Subject: [PATCH 083/212] prepare for release (dart-lang/html#61) --- pkgs/html/CHANGELOG.md | 5 +++++ pkgs/html/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index af731063e..50deb7fb7 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.13.2+1 + +* Changed the implementation of `Set` and `List` classes to use base classes + from `dart:collection`. + ## 0.13.2 * Support the latest release of `pkg/csslib`. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 09bf52ee3..acbe3f60d 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.3-dev +version: 0.13.2+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From d07a21f15245e01c16ca5305e18cc353db23d44c Mon Sep 17 00:00:00 2001 From: Daniel Davidson <dbdavidson@yahoo.com> Date: Sat, 6 Jan 2018 00:05:10 -0600 Subject: [PATCH 084/212] fixed slice to use end index rather than length (dart-lang/html#62) --- pkgs/html/lib/src/encoding_parser.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index d97e4cc1b..ef5e7088e 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -117,7 +117,7 @@ class EncodingBytes { String slice(int start, [int end]) { if (end == null) end = length; if (end < 0) end += length; - return _bytes.substring(start, end - start); + return _bytes.substring(start, end); } } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index e5c1d8ca8..de8843b15 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -335,6 +335,13 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('ignores whitespace', () { expect(getEncoding(' <meta charset="utf-16">'), 'utf-16'); }); + + test('parses content attr', () { + expect( + getEncoding( + '<meta http-equiv="content-type" content="text/html; charset=UTF-8">'), + null); + }); }); } From 16a7c513e3e9d73b096364c3aa888b54a336017c Mon Sep 17 00:00:00 2001 From: Keerti Parthasarathy <keertip@users.noreply.github.com> Date: Mon, 8 Jan 2018 16:05:57 -0800 Subject: [PATCH 085/212] Update signatures for implementation of Iterable.singleWhere (dart-lang/html#63) * Update signatures for implementation of Iterable.singleWhere * Add an check if orElse is passed in --- pkgs/html/CHANGELOG.md | 5 +++++ pkgs/html/lib/dom.dart | 3 ++- pkgs/html/pubspec.yaml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 50deb7fb7..029212352 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.13.2+2 + +* Update signature for implementations of `Iterable.singleWhere` to include + optional argument. + ## 0.13.2+1 * Changed the implementation of `Set` and `List` classes to use base classes diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index fb0d45865..df9655e17 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -951,7 +951,8 @@ class FilteredElementList extends IterableBase<Element> return _filtered.lastWhere(test, orElse: orElse); } - Element singleWhere(bool test(Element value)) { + Element singleWhere(bool test(Element value), {Element orElse()}) { + if (orElse != null) throw new UnimplementedError('orElse'); return _filtered.singleWhere(test); } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index acbe3f60d..59f1650b2 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.2+1 +version: 0.13.2+2 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From 29c8475821f5a479d131cf3b08e2d3b3ba2497e7 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 19 Jan 2018 19:24:21 -0800 Subject: [PATCH 086/212] Remove tests expecting >64-bit ints (dart-lang/html#65) Fixes https://github.com/dart-lang/html/issues/64 --- pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/data/tokenizer/test4.test | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 59f1650b2..09bf52ee3 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.2+2 +version: 0.13.3-dev author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html diff --git a/pkgs/html/test/data/tokenizer/test4.test b/pkgs/html/test/data/tokenizer/test4.test index 80f859e21..c0f3b2b8c 100644 --- a/pkgs/html/test/data/tokenizer/test4.test +++ b/pkgs/html/test/data/tokenizer/test4.test @@ -152,14 +152,6 @@ "input":"&#4294967361;", "output":["ParseError", ["Character", "\uFFFD"]]}, -{"description":"65-bit hex numeric entity", -"input":"&#x10000000000000041;", -"output":["ParseError", ["Character", "\uFFFD"]]}, - -{"description":"65-bit decimal numeric entity", -"input":"&#18446744073709551681;", -"output":["ParseError", ["Character", "\uFFFD"]]}, - {"description":"Surrogate code point edge cases", "input":"&#xD7FF;&#xD800;&#xD801;&#xDFFE;&#xDFFF;&#xE000;", "output":[["Character", "\uD7FF"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD"], "ParseError", ["Character", "\uFFFD\uE000"]]}, From 5dd246ea2333ee0085dc1845a671ab445f3a73b4 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Fri, 9 Mar 2018 15:46:05 -0800 Subject: [PATCH 087/212] fix an issue when run with --preview-dart-2 --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/lib/dom.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 029212352..bc2e054ce 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -2,7 +2,7 @@ * Update signature for implementations of `Iterable.singleWhere` to include optional argument. - + ## 0.13.2+1 * Changed the implementation of `Set` and `List` classes to use base classes diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index df9655e17..8a8f74dfc 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -969,11 +969,11 @@ class FilteredElementList extends IterableBase<Element> _filtered.getRange(start, end); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.indexOf() expects Object as the argument. - int indexOf(element, [int start = 0]) => _filtered.indexOf(element, start); + int indexOf(Object element, [int start = 0]) => _filtered.indexOf(element, start); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. - int lastIndexOf(element, [int start]) { + int lastIndexOf(Object element, [int start]) { if (start == null) start = length - 1; return _filtered.lastIndexOf(element, start); } From f9b9caec78834851c8da26f0f0e8a0863f142ce7 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Fri, 9 Mar 2018 15:55:15 -0800 Subject: [PATCH 088/212] dartfmt --- pkgs/html/lib/dom.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 8a8f74dfc..2e57f6476 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -969,7 +969,8 @@ class FilteredElementList extends IterableBase<Element> _filtered.getRange(start, end); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.indexOf() expects Object as the argument. - int indexOf(Object element, [int start = 0]) => _filtered.indexOf(element, start); + int indexOf(Object element, [int start = 0]) => + _filtered.indexOf(element, start); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. From bc6deef336d4914da8e127f4506f9ccb0efe1842 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Fri, 9 Mar 2018 16:01:40 -0800 Subject: [PATCH 089/212] update the changelog --- pkgs/html/.gitignore | 1 + pkgs/html/CHANGELOG.md | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/pkgs/html/.gitignore b/pkgs/html/.gitignore index f20a0d087..3ab3a4493 100644 --- a/pkgs/html/.gitignore +++ b/pkgs/html/.gitignore @@ -1,5 +1,6 @@ # Don’t commit the following directories created by pub. .pub +.dart_tool/ build/ packages .packages diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index bc2e054ce..25215a12b 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,12 +1,17 @@ +## 0.13.3 + + * Update the signatures of `FilteredElementList.indexOf` and + `FilteredElementList.lastIndexOf` to include type annotations. + ## 0.13.2+2 -* Update signature for implementations of `Iterable.singleWhere` to include - optional argument. + * Update signature for implementations of `Iterable.singleWhere` to include + optional argument. ## 0.13.2+1 -* Changed the implementation of `Set` and `List` classes to use base classes - from `dart:collection`. + * Changed the implementation of `Set` and `List` classes to use base classes + from `dart:collection`. ## 0.13.2 From 88e69657bdfa0b3389f8c56afe754b362219501a Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Fri, 9 Mar 2018 16:43:27 -0800 Subject: [PATCH 090/212] bump the version for publish --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 09bf52ee3..f962aeb60 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.3-dev +version: 0.13.3 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html From 38a1036c285c195b28005a7fbcacba1f6e92a64b Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" <lrn@google.com> Date: Wed, 30 May 2018 17:58:32 +0200 Subject: [PATCH 091/212] Remove upper case constants (dart-lang/html#72) * Remove usage of upper-case constants. * update SDK constraint * remove stable from Travis config --- pkgs/html/.travis.yml | 2 -- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/pubspec.yaml | 4 ++-- pkgs/html/test/parser_test.dart | 4 ++-- pkgs/html/test/tokenizer_test.dart | 6 +++--- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 5b7ab8402..275041442 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -1,8 +1,6 @@ language: dart dart: - dev - - stable - dart_task: - test: -p vm - test: -p chrome,firefox diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 25215a12b..0b295acb2 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.13.3+1 + + * Updated SDK version to 2.0.0-dev.17.0 + ## 0.13.3 * Update the signatures of `FilteredElementList.indexOf` and diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index f962aeb60..162c2da86 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,10 +1,10 @@ name: html -version: 0.13.3 +version: 0.13.3+1 author: Dart Team <misc@dartlang.org> description: A library for working with HTML documents. Previously known as html5lib. homepage: https://github.com/dart-lang/html environment: - sdk: '>=1.21.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <2.0.0' dependencies: csslib: '>=0.13.2 <0.15.0' source_span: '>=1.0.0 <2.0.0' diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 69a52a519..f09ae225d 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -112,11 +112,11 @@ void main() { /// Extract the name for the test based on the test input data. _nameFor(String input) { - // Using JSON.decode to unescape other unicode characters + // Using jsonDecode to unescape other unicode characters var escapeQuote = input .replaceAll(new RegExp('\\\\.'), '_') .replaceAll(new RegExp('\u0000'), '_') .replaceAll('"', '\\"') .replaceAll(new RegExp('[\n\r\t]'), '_'); - return JSON.decode('"$escapeQuote"'); + return jsonDecode('"$escapeQuote"'); } diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index dba4eced7..7432cda61 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -204,10 +204,10 @@ void runTokenizerTest(Map testInfo) { } Map unescape(Map testInfo) { - // TODO(sigmundch,jmesserly): we currently use JSON.decode to unescape the + // TODO(sigmundch,jmesserly): we currently use jsonDecode to unescape the // unicode characters in the string, we should use a decoding that works with // any control characters. - decode(inp) => inp == '\u0000' ? inp : JSON.decode('"$inp"'); + decode(inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); testInfo["input"] = decode(testInfo["input"]); for (var token in testInfo["output"]) { @@ -244,7 +244,7 @@ void main() { if (!path.endsWith('.test')) continue; var text = new File(path).readAsStringSync(); - var tests = JSON.decode(text); + var tests = jsonDecode(text); var testName = pathos.basenameWithoutExtension(path); var testList = tests['tests']; if (testList == null) continue; From 97ff40707781d76967a29469c48ef8c3ebd869f9 Mon Sep 17 00:00:00 2001 From: Patrice Chalin <chalin@users.noreply.github.com> Date: Thu, 19 Jul 2018 17:25:46 -0400 Subject: [PATCH 092/212] chore: set max SDK version to <3.0.0 (dart-lang/html#76) --- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/analysis_options.yaml | 1 - pkgs/html/pubspec.yaml | 14 +++++++++----- pkgs/html/test/parser_feature_test.dart | 4 ++-- pkgs/html/test/parser_test.dart | 4 ++-- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 0b295acb2..8b23c18c1 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.13.3+2 + +* Set max SDK version to `<3.0.0`, and adjust other dependencies. + ## 0.13.3+1 * Updated SDK version to 2.0.0-dev.17.0 diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index da175164b..2ba6e217f 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,5 +1,4 @@ analyzer: - strong-mode: true errors: unused_import: error unused_local_variable: error diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 162c2da86..0aa377c90 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,14 +1,18 @@ name: html -version: 0.13.3+1 -author: Dart Team <misc@dartlang.org> +version: 0.13.3+2 + description: A library for working with HTML documents. Previously known as html5lib. +author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/html + environment: - sdk: '>=2.0.0-dev.17.0 <2.0.0' + sdk: '>=2.0.0-dev.17.0 <3.0.0' + dependencies: csslib: '>=0.13.2 <0.15.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' + dev_dependencies: - path: '>=0.9.0 <2.0.0' - test: '^0.12.0' + path: ^1.6.2 + test: ^1.3.0 diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index de8843b15..45c704c02 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -85,7 +85,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. var html = '<body><div>$textContent</div>'; var doc = parse(html, generateSpans: true); Text text = doc.body.nodes[0].nodes[0]; - expect(text, new isInstanceOf<Text>()); + expect(text, new TypeMatcher<Text>()); expect(text.data, textContent); expect(text.sourceSpan.start.offset, html.indexOf(textContent)); expect(text.sourceSpan.length, textContent.length); @@ -229,7 +229,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. '''); var n = doc.querySelector('desc'); var keys = n.attributes.keys.toList(); - expect(keys[0], new isInstanceOf<AttributeName>()); + expect(keys[0], new TypeMatcher<AttributeName>()); expect(keys[0].prefix, 'xlink'); expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); expect(keys[0].name, 'type'); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index f09ae225d..c0a96cbff 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -74,9 +74,9 @@ void main() { test('dart:io', () { // ensure IO support is unregistered expect(inputstream.consoleSupport, - new isInstanceOf<inputstream.ConsoleSupport>()); + new TypeMatcher<inputstream.ConsoleSupport>()); var file = new File('$testDataDir/parser_feature/raw_file.html').openSync(); - expect(() => parse(file), throwsA(new isInstanceOf<ArgumentError>())); + expect(() => parse(file), throwsA(new TypeMatcher<ArgumentError>())); parser_console.useConsole(); expect(parse(file).body.innerHtml.trim(), 'Hello world!'); }); From c1f8846f1c0cf3af4ddc6d56562cfbebb1b51bc0 Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Fri, 10 Aug 2018 09:43:16 -0700 Subject: [PATCH 093/212] Fix missing_return in two spots --- pkgs/html/lib/parser.dart | 70 ++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 75a5c6228..2c2c039bb 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -880,7 +880,7 @@ class BeforeHtmlPhase extends Phase { class BeforeHeadPhase extends Phase { BeforeHeadPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -892,7 +892,7 @@ class BeforeHeadPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "head": case "body": @@ -952,7 +952,7 @@ class BeforeHeadPhase extends Phase { class InHeadPhase extends Phase { InHeadPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -985,7 +985,7 @@ class InHeadPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "head": endTagHead(token); @@ -1094,7 +1094,7 @@ class InHeadPhase extends Phase { class AfterHeadPhase extends Phase { AfterHeadPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -1123,7 +1123,7 @@ class AfterHeadPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "body": case "html": @@ -1208,7 +1208,7 @@ class InBodyPhase extends Phase { // the really-really-really-very crazy mode InBodyPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -1380,7 +1380,7 @@ class InBodyPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "body": endTagBody(token); @@ -2250,16 +2250,18 @@ class TextPhase extends Phase { TextPhase(parser) : super(parser); // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name - processStartTag(StartTagToken token) { + // ignore: missing_return + Token processStartTag(StartTagToken token) { assert(false); } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { if (token.name == 'script') { endTagScript(token); return null; } endTagOther(token); + return null; } Token processCharacters(CharactersToken token) { @@ -2294,7 +2296,7 @@ class InTablePhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table InTablePhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -2332,7 +2334,7 @@ class InTablePhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "table": endTagTable(token); @@ -2584,7 +2586,7 @@ class InCaptionPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-caption InCaptionPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -2603,7 +2605,7 @@ class InCaptionPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "caption": endTagCaption(token); @@ -2702,7 +2704,7 @@ class InColumnGroupPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-column InColumnGroupPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -2714,7 +2716,7 @@ class InColumnGroupPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "colgroup": endTagColgroup(token); @@ -2786,7 +2788,7 @@ class InTableBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table0 InTableBodyPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -2808,7 +2810,7 @@ class InTableBodyPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "tbody": case "tfoot": @@ -2921,7 +2923,7 @@ class InRowPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-row InRowPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -2942,7 +2944,7 @@ class InRowPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "tr": endTagTr(token); @@ -3062,7 +3064,7 @@ class InCellPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-cell InCellPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -3081,7 +3083,7 @@ class InCellPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "td": case "th": @@ -3182,7 +3184,7 @@ class InCellPhase extends Phase { class InSelectPhase extends Phase { InSelectPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -3206,7 +3208,7 @@ class InSelectPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "option": endTagOption(token); @@ -3334,7 +3336,7 @@ class InSelectPhase extends Phase { class InSelectInTablePhase extends Phase { InSelectInTablePhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "caption": case "table": @@ -3350,7 +3352,7 @@ class InSelectInTablePhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "caption": case "table": @@ -3583,12 +3585,12 @@ class InForeignContentPhase extends Phase { class AfterBodyPhase extends Phase { AfterBodyPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { if (token.name == "html") return startTagHtml(token); return startTagOther(token); } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { if (token.name == "html") { endTagHtml(token); return null; @@ -3649,7 +3651,7 @@ class InFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-frameset InFramesetPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -3666,7 +3668,7 @@ class InFramesetPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "frameset": endTagFrameset(token); @@ -3738,7 +3740,7 @@ class AfterFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///after3 AfterFramesetPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); @@ -3750,7 +3752,7 @@ class AfterFramesetPhase extends Phase { } } - processEndTag(EndTagToken token) { + Token processEndTag(EndTagToken token) { switch (token.name) { case "html": endTagHtml(token); @@ -3791,7 +3793,7 @@ class AfterFramesetPhase extends Phase { class AfterAfterBodyPhase extends Phase { AfterAfterBodyPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { if (token.name == 'html') return startTagHtml(token); return startTagOther(token); } @@ -3835,7 +3837,7 @@ class AfterAfterBodyPhase extends Phase { class AfterAfterFramesetPhase extends Phase { AfterAfterFramesetPhase(parser) : super(parser); - processStartTag(StartTagToken token) { + Token processStartTag(StartTagToken token) { switch (token.name) { case "html": return startTagHtml(token); From 2b41d6d6739d60101a1eb238c27314d3cf80cb5c Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Fri, 10 Aug 2018 09:46:44 -0700 Subject: [PATCH 094/212] Bump --- pkgs/html/CHANGELOG.md | 5 +++++ pkgs/html/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 8b23c18c1..ee47f53cf 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.13.3+3 + +* Fix missing_return analyzer errors in `processStartTag` and `processEndTag` + methods. + ## 0.13.3+2 * Set max SDK version to `<3.0.0`, and adjust other dependencies. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 0aa377c90..7aeb9ba8e 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.3+2 +version: 0.13.3+3 description: A library for working with HTML documents. Previously known as html5lib. author: Dart Team <misc@dartlang.org> From a0f0e97d3dff7d1129e55b007822214cf52f5669 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Mon, 29 Oct 2018 17:22:21 -0700 Subject: [PATCH 095/212] Enable and fix a number of lints (dart-lang/html#82) --- pkgs/html/.travis.yml | 2 +- pkgs/html/CHANGELOG.md | 4 + pkgs/html/analysis_options.yaml | 63 ++- pkgs/html/lib/dom.dart | 118 ++-- pkgs/html/lib/dom_parsing.dart | 10 +- pkgs/html/lib/parser.dart | 266 +++++---- pkgs/html/lib/parser_console.dart | 4 +- pkgs/html/lib/src/char_encodings.dart | 10 +- pkgs/html/lib/src/constants.dart | 310 +++++----- pkgs/html/lib/src/css_class_set.dart | 204 +++---- pkgs/html/lib/src/encoding_parser.dart | 30 +- pkgs/html/lib/src/inputstream.dart | 26 +- pkgs/html/lib/src/query_selector.dart | 15 +- pkgs/html/lib/src/token.dart | 10 +- pkgs/html/lib/src/tokenizer.dart | 532 +++++++++--------- pkgs/html/lib/src/treebuilder.dart | 36 +- pkgs/html/lib/src/utils.dart | 11 +- pkgs/html/pubspec.yaml | 7 +- pkgs/html/test/dom_test.dart | 14 +- pkgs/html/test/parser_feature_test.dart | 18 +- pkgs/html/test/parser_test.dart | 18 +- .../test/selectors/level1_baseline_test.dart | 4 +- pkgs/html/test/selectors/level1_lib.dart | 2 +- pkgs/html/test/selectors/selectors.dart | 408 +++++++------- pkgs/html/test/support.dart | 16 +- pkgs/html/test/tokenizer_test.dart | 16 +- 26 files changed, 1060 insertions(+), 1094 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 275041442..714aa8610 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -4,7 +4,7 @@ dart: dart_task: - test: -p vm - test: -p chrome,firefox - - dartanalyzer + - dartanalyzer: --fatal-warnings --fatal-infos . matrix: include: diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index ee47f53cf..321fd3ea4 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.13.4 + +* Require Dart 2.0 stable. + ## 0.13.3+3 * Fix missing_return analyzer errors in `processStartTag` and `processEndTag` diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 2ba6e217f..91416258e 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,50 +1,65 @@ +include: package:pedantic/analysis_options.yaml analyzer: errors: + unused_element: error unused_import: error unused_local_variable: error dead_code: error - override_on_non_overriding_method: error linter: rules: - # Errors - - avoid_empty_else - - await_only_futures - #- comment_references - - control_flow_in_finally - - empty_statements - - hash_and_equals - - iterable_contains_unrelated_type - - no_duplicate_case_values - - test_types_in_equals - - throw_in_finally - - unawaited_futures - - unnecessary_statements - - unrelated_type_equality_checks - - valid_regexps - - # Style #- annotate_overrides #- avoid_function_literals_in_foreach_calls - avoid_init_to_null - - avoid_return_types_on_setters + - avoid_null_checks_in_equality_operators + - avoid_relative_lib_imports - avoid_returning_null - avoid_unused_constructor_parameters + - await_only_futures - camel_case_types + - cancel_subscriptions + #- comment_references + # See https://github.com/dart-lang/logging/issues/43 + #- constant_identifier_names + - control_flow_in_finally - directives_ordering - empty_catches - empty_constructor_bodies + - empty_statements + - hash_and_equals + - implementation_imports + #- invariant_booleans + - iterable_contains_unrelated_type - library_names - library_prefixes - #- non_constant_identifier_names + - list_remove_unrelated_type + - no_adjacent_strings_in_list + - non_constant_identifier_names + #- omit_local_variable_types + - only_throw_errors + - overridden_fields + - package_api_docs + - package_names + - package_prefixed_library_names + - prefer_adjacent_string_concatenation + #- prefer_collection_literals #- prefer_conditional_assignment + - prefer_const_constructors - prefer_final_fields - - prefer_is_empty - - prefer_is_not_empty + - prefer_initializing_formals + #- prefer_interpolation_to_compose_strings + #- prefer_single_quotes #- prefer_typing_uninitialized_variables - - recursive_getters - #- slash_for_doc_comments + - slash_for_doc_comments + - test_types_in_equals + - super_goes_last + - test_types_in_equals + - throw_in_finally - type_init_formals #- unnecessary_brace_in_string_interps + - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas + - unnecessary_new - unnecessary_null_aware_assignments + - unnecessary_statements + - unnecessary_this diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 2e57f6476..1a6e7ed45 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -145,11 +145,11 @@ abstract class Node { /// /// Note that attribute order needs to be stable for serialization, so we use /// a LinkedHashMap. Each key is a [String] or [AttributeName]. - LinkedHashMap<dynamic, String> attributes = new LinkedHashMap(); + LinkedHashMap<dynamic, String> attributes = LinkedHashMap(); /// A list of child nodes of the current node. This must /// include all elements but not necessarily other node types. - final NodeList nodes = new NodeList._(); + final NodeList nodes = NodeList._(); List<Element> _elements; @@ -186,7 +186,7 @@ abstract class Node { List<Element> get children { if (_elements == null) { - _elements = new FilteredElementList(this); + _elements = FilteredElementList(this); } return _elements; } @@ -201,13 +201,13 @@ abstract class Node { // http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface String get _outerHtml { - var str = new StringBuffer(); + var str = StringBuffer(); _addOuterHtml(str); return str.toString(); } String get _innerHtml { - var str = new StringBuffer(); + var str = StringBuffer(); _addInnerHtml(str); return str.toString(); } @@ -249,7 +249,7 @@ abstract class Node { /// Replaces this node with another node. Node replaceWith(Node otherNode) { if (parentNode == null) { - throw new UnsupportedError('Node must have a parent to replace it.'); + throw UnsupportedError('Node must have a parent to replace it.'); } parentNode.nodes[parentNode.nodes.indexOf(this)] = otherNode; return this; @@ -275,12 +275,12 @@ abstract class Node { void _ensureAttributeSpans() { if (_attributeSpans != null) return; - _attributeSpans = new LinkedHashMap<dynamic, FileSpan>(); - _attributeValueSpans = new LinkedHashMap<dynamic, FileSpan>(); + _attributeSpans = LinkedHashMap<dynamic, FileSpan>(); + _attributeValueSpans = LinkedHashMap<dynamic, FileSpan>(); if (sourceSpan == null) return; - var tokenizer = new HtmlTokenizer(sourceSpan.text, + var tokenizer = HtmlTokenizer(sourceSpan.text, generateSpans: true, attributeSpans: true); tokenizer.moveNext(); @@ -333,18 +333,18 @@ class Document extends Node void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); - Document clone(bool deep) => _clone(new Document(), deep); + Document clone(bool deep) => _clone(Document(), deep); - Element createElement(String tag) => new Element.tag(tag); + Element createElement(String tag) => Element.tag(tag); // TODO(jmesserly): this is only a partial implementation of: // http://dom.spec.whatwg.org/#dom-document-createelementns Element createElementNS(String namespaceUri, String tag) { if (namespaceUri == '') namespaceUri = null; - return new Element._(tag, namespaceUri); + return Element._(tag, namespaceUri); } - DocumentFragment createDocumentFragment() => new DocumentFragment(); + DocumentFragment createDocumentFragment() => DocumentFragment(); } class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { @@ -363,7 +363,7 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { String toString() => "#document-fragment"; - DocumentFragment clone(bool deep) => _clone(new DocumentFragment(), deep); + DocumentFragment clone(bool deep) => _clone(DocumentFragment(), deep); void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); @@ -376,10 +376,7 @@ class DocumentType extends Node { final String publicId; final String systemId; - DocumentType(String name, this.publicId, this.systemId) - // Note: once Node.tagName is removed, don't pass "name" to super - : name = name, - super._(); + DocumentType(this.name, this.publicId, this.systemId) : super._(); int get nodeType => Node.DOCUMENT_TYPE_NODE; @@ -399,7 +396,7 @@ class DocumentType extends Node { str.write(toString()); } - DocumentType clone(bool deep) => new DocumentType(name, publicId, systemId); + DocumentType clone(bool deep) => DocumentType(name, publicId, systemId); } class Text extends Node { @@ -423,10 +420,10 @@ class Text extends Node { void _addOuterHtml(StringBuffer str) => writeTextNodeAsHtml(str, this); - Text clone(bool deep) => new Text(data); + Text clone(bool deep) => Text(data); void appendData(String data) { - if (_data is! StringBuffer) _data = new StringBuffer(_data); + if (_data is! StringBuffer) _data = StringBuffer(_data); StringBuffer sb = _data; sb.write(data); } @@ -457,9 +454,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { : namespaceUri = Namespaces.html, super._(); - static final _START_TAG_REGEXP = new RegExp('<(\\w+)'); + static final _startTagRegexp = RegExp('<(\\w+)'); - static final _CUSTOM_PARENT_TAG_MAP = const { + static final _customParentTagMap = const { 'body': 'html', 'head': 'html', 'caption': 'table', @@ -487,11 +484,11 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // 4) Detatch the created element from its dummy parent. String parentTag = 'div'; String tag; - final match = _START_TAG_REGEXP.firstMatch(html); + final match = _startTagRegexp.firstMatch(html); if (match != null) { tag = match.group(1).toLowerCase(); - if (_CUSTOM_PARENT_TAG_MAP.containsKey(tag)) { - parentTag = _CUSTOM_PARENT_TAG_MAP[tag]; + if (_customParentTagMap.containsKey(tag)) { + parentTag = _customParentTagMap[tag]; } } @@ -503,7 +500,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // You'll always get a head and a body when starting from html. element = fragment.children[tag == 'head' ? 0 : 1]; } else { - throw new ArgumentError('HTML had ${fragment.children.length} ' + throw ArgumentError('HTML had ${fragment.children.length} ' 'top level elements but 1 expected'); } element.remove(); @@ -613,8 +610,8 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } Element clone(bool deep) { - var result = new Element._(localName, namespaceUri) - ..attributes = new LinkedHashMap.from(attributes); + var result = Element._(localName, namespaceUri) + ..attributes = LinkedHashMap.from(attributes); return _clone(result, deep); } @@ -638,17 +635,15 @@ class Element extends Node with _ParentNode, _ElementAndDocument { attributes['class'] = '$value'; } - /** - * The set of CSS classes applied to this element. - * - * This set makes it easy to add, remove or toggle the classes applied to - * this element. - * - * element.classes.add('selected'); - * element.classes.toggle('isOnline'); - * element.classes.remove('selected'); - */ - CssClassSet get classes => new ElementCssClassSet(this); + /// The set of CSS classes applied to this element. + /// + /// This set makes it easy to add, remove or toggle the classes applied to + /// this element. + /// + /// element.classes.add('selected'); + /// element.classes.toggle('isOnline'); + /// element.classes.remove('selected'); + CssClassSet get classes => ElementCssClassSet(this); } class Comment extends Node { @@ -664,11 +659,11 @@ class Comment extends Node { str.write("<!--$data-->"); } - Comment clone(bool deep) => new Comment(data); + Comment clone(bool deep) => Comment(data); String get text => data; set text(String value) { - this.data = value; + data = value; } } @@ -744,15 +739,15 @@ class NodeList extends ListProxy<Node> { // http://code.google.com/p/dart/issues/detail?id=5371 void setRange(int start, int rangeLength, Iterable<Node> from, [int startFrom = 0]) { - List<Node> from_ = from as List<Node>; - if (from_ is NodeList) { + List<Node> fromVar = from as List<Node>; + if (fromVar is NodeList) { // Note: this is presumed to make a copy - from_ = from_.sublist(startFrom, startFrom + rangeLength); + fromVar = fromVar.sublist(startFrom, startFrom + rangeLength); } // Note: see comment in [addAll]. We need to be careful about the order of // operations if [from] is also a NodeList. for (int i = rangeLength - 1; i >= 0; i--) { - this[start + i] = from_[startFrom + i]; + this[start + i] = fromVar[startFrom + i]; } } @@ -826,7 +821,7 @@ class FilteredElementList extends IterableBase<Element> // TODO(nweiz): we don't always need to create a new list. For example // forEach, every, any, ... could directly work on the _childNodes. List<Element> get _filtered => - new List<Element>.from(_childNodes.where((n) => n is Element)); + List<Element>.from(_childNodes.where((n) => n is Element)); void forEach(void f(Element element)) { _filtered.forEach(f); @@ -837,11 +832,11 @@ class FilteredElementList extends IterableBase<Element> } set length(int newLength) { - final len = this.length; + final len = length; if (newLength >= len) { return; } else if (newLength < 0) { - throw new ArgumentError("Invalid list length"); + throw ArgumentError("Invalid list length"); } removeRange(newLength, len); @@ -866,20 +861,20 @@ class FilteredElementList extends IterableBase<Element> Iterable<Element> get reversed => _filtered.reversed; void sort([int compare(Element a, Element b)]) { - throw new UnsupportedError('TODO(jacobr): should we impl?'); + throw UnsupportedError('TODO(jacobr): should we impl?'); } void setRange(int start, int end, Iterable<Element> iterable, [int skipCount = 0]) { - throw new UnimplementedError(); + throw UnimplementedError(); } void fillRange(int start, int end, [Element fillValue]) { - throw new UnimplementedError(); + throw UnimplementedError(); } void replaceRange(int start, int end, Iterable<Element> iterable) { - throw new UnimplementedError(); + throw UnimplementedError(); } void removeRange(int start, int end) { @@ -893,7 +888,7 @@ class FilteredElementList extends IterableBase<Element> } Element removeLast() { - final result = this.last; + final result = last; if (result != null) { result.remove(); } @@ -940,9 +935,9 @@ class FilteredElementList extends IterableBase<Element> bool every(bool f(Element element)) => _filtered.every(f); bool any(bool f(Element element)) => _filtered.any(f); - List<Element> toList({bool growable: true}) => - new List<Element>.from(this, growable: growable); - Set<Element> toSet() => new Set<Element>.from(this); + List<Element> toList({bool growable = true}) => + List<Element>.from(this, growable: growable); + Set<Element> toSet() => Set<Element>.from(this); Element firstWhere(bool test(Element value), {Element orElse()}) { return _filtered.firstWhere(test, orElse: orElse); } @@ -952,7 +947,7 @@ class FilteredElementList extends IterableBase<Element> } Element singleWhere(bool test(Element value), {Element orElse()}) { - if (orElse != null) throw new UnimplementedError('orElse'); + if (orElse != null) throw UnimplementedError('orElse'); return _filtered.singleWhere(test); } @@ -988,16 +983,15 @@ class FilteredElementList extends IterableBase<Element> // http://dom.spec.whatwg.org/#dom-node-textcontent // For Element and DocumentFragment -String _getText(Node node) => - (new _ConcatTextVisitor()..visit(node)).toString(); +String _getText(Node node) => (_ConcatTextVisitor()..visit(node)).toString(); void _setText(Node node, String value) { node.nodes.clear(); - node.append(new Text(value)); + node.append(Text(value)); } class _ConcatTextVisitor extends TreeVisitor { - final _str = new StringBuffer(); + final _str = StringBuffer(); String toString() => _str.toString(); diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 3435a8128..4fc370707 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -22,7 +22,7 @@ class TreeVisitor { case Node.DOCUMENT_TYPE_NODE: return visitDocumentType(node); default: - throw new UnsupportedError('DOM node type ${node.nodeType}'); + throw UnsupportedError('DOM node type ${node.nodeType}'); } } @@ -54,7 +54,7 @@ class TreeVisitor { /// displaying the HTML's source code with CSS colors for different parts of the /// markup. See also [CodeMarkupVisitor]. String htmlToCodeMarkup(Node node) { - return (new CodeMarkupVisitor()..visit(node)).toString(); + return (CodeMarkupVisitor()..visit(node)).toString(); } /// Converts the DOM tree into an HTML string with code markup suitable for @@ -63,7 +63,7 @@ String htmlToCodeMarkup(Node node) { class CodeMarkupVisitor extends TreeVisitor { final StringBuffer _str; - CodeMarkupVisitor() : _str = new StringBuffer(); + CodeMarkupVisitor() : _str = StringBuffer(); String toString() => _str.toString(); @@ -125,7 +125,7 @@ class CodeMarkupVisitor extends TreeVisitor { /// /// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments /// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString -String htmlSerializeEscape(String text, {bool attributeMode: false}) { +String htmlSerializeEscape(String text, {bool attributeMode = false}) { // TODO(jmesserly): is it faster to build up a list of codepoints? // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. StringBuffer result; @@ -150,7 +150,7 @@ String htmlSerializeEscape(String text, {bool attributeMode: false}) { break; } if (replace != null) { - if (result == null) result = new StringBuffer(text.substring(0, i)); + if (result == null) result = StringBuffer(text.substring(0, i)); result.write(replace); } else if (result != null) { result.write(ch); diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 2c2c039bb..3f3217871 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -37,8 +37,8 @@ import 'src/utils.dart'; /// can additionally pass [sourceUrl] to indicate where the [input] was /// extracted from. Document parse(input, - {String encoding, bool generateSpans: false, String sourceUrl}) { - var p = new HtmlParser(input, + {String encoding, bool generateSpans = false, String sourceUrl}) { + var p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parse(); } @@ -56,11 +56,11 @@ Document parse(input, /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. DocumentFragment parseFragment(input, - {String container: "div", + {String container = "div", String encoding, - bool generateSpans: false, + bool generateSpans = false, String sourceUrl}) { - var p = new HtmlParser(input, + var p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parseFragment(container); } @@ -143,18 +143,17 @@ class HtmlParser { /// DOM will do if you request [Node.outerHTML], for example. HtmlParser(input, {String encoding, - bool parseMeta: true, - bool lowercaseElementName: true, - bool lowercaseAttrName: true, - this.strict: false, - bool generateSpans: false, + bool parseMeta = true, + bool lowercaseElementName = true, + bool lowercaseAttrName = true, + this.strict = false, + this.generateSpans = false, String sourceUrl, TreeBuilder tree}) - : generateSpans = generateSpans, - tree = tree != null ? tree : new TreeBuilder(true), + : tree = tree != null ? tree : TreeBuilder(true), tokenizer = (input is HtmlTokenizer ? input - : new HtmlTokenizer(input, + : HtmlTokenizer(input, encoding: encoding, parseMeta: parseMeta, lowercaseElementName: lowercaseElementName, @@ -162,33 +161,33 @@ class HtmlParser { generateSpans: generateSpans, sourceUrl: sourceUrl)) { tokenizer.parser = this; - _initialPhase = new InitialPhase(this); - _beforeHtmlPhase = new BeforeHtmlPhase(this); - _beforeHeadPhase = new BeforeHeadPhase(this); - _inHeadPhase = new InHeadPhase(this); + _initialPhase = InitialPhase(this); + _beforeHtmlPhase = BeforeHtmlPhase(this); + _beforeHeadPhase = BeforeHeadPhase(this); + _inHeadPhase = InHeadPhase(this); // TODO(jmesserly): html5lib did not implement the no script parsing mode // More information here: // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#scripting-flag // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inheadnoscript // "inHeadNoscript": new InHeadNoScriptPhase(this); - _afterHeadPhase = new AfterHeadPhase(this); - _inBodyPhase = new InBodyPhase(this); - _textPhase = new TextPhase(this); - _inTablePhase = new InTablePhase(this); - _inTableTextPhase = new InTableTextPhase(this); - _inCaptionPhase = new InCaptionPhase(this); - _inColumnGroupPhase = new InColumnGroupPhase(this); - _inTableBodyPhase = new InTableBodyPhase(this); - _inRowPhase = new InRowPhase(this); - _inCellPhase = new InCellPhase(this); - _inSelectPhase = new InSelectPhase(this); - _inSelectInTablePhase = new InSelectInTablePhase(this); - _inForeignContentPhase = new InForeignContentPhase(this); - _afterBodyPhase = new AfterBodyPhase(this); - _inFramesetPhase = new InFramesetPhase(this); - _afterFramesetPhase = new AfterFramesetPhase(this); - _afterAfterBodyPhase = new AfterAfterBodyPhase(this); - _afterAfterFramesetPhase = new AfterAfterFramesetPhase(this); + _afterHeadPhase = AfterHeadPhase(this); + _inBodyPhase = InBodyPhase(this); + _textPhase = TextPhase(this); + _inTablePhase = InTablePhase(this); + _inTableTextPhase = InTableTextPhase(this); + _inCaptionPhase = InCaptionPhase(this); + _inColumnGroupPhase = InColumnGroupPhase(this); + _inTableBodyPhase = InTableBodyPhase(this); + _inRowPhase = InRowPhase(this); + _inCellPhase = InCellPhase(this); + _inSelectPhase = InSelectPhase(this); + _inSelectInTablePhase = InSelectInTablePhase(this); + _inForeignContentPhase = InForeignContentPhase(this); + _afterBodyPhase = AfterBodyPhase(this); + _inFramesetPhase = InFramesetPhase(this); + _afterFramesetPhase = AfterFramesetPhase(this); + _afterAfterBodyPhase = AfterAfterBodyPhase(this); + _afterAfterFramesetPhase = AfterAfterFramesetPhase(this); } bool get innerHTMLMode => innerHTML != null; @@ -205,7 +204,7 @@ class HtmlParser { /// Pass a [container] to change the type of the containing element. /// After parsing, [errors] will be populated with parse errors, if any. DocumentFragment parseFragment([String container = "div"]) { - if (container == null) throw new ArgumentError('container'); + if (container == null) throw ArgumentError('container'); innerHTML = container.toLowerCase(); _parse(); return tree.getFragment(); @@ -266,13 +265,13 @@ class HtmlParser { return enc == "text/html" || enc == "application/xhtml+xml"; } else { return htmlIntegrationPointElements - .contains(new Pair(element.namespaceUri, element.localName)); + .contains(Pair(element.namespaceUri, element.localName)); } } bool isMathMLTextIntegrationPoint(Element element) { return mathmlTextIntegrationPointElements - .contains(new Pair(element.namespaceUri, element.localName)); + .contains(Pair(element.namespaceUri, element.localName)); } bool inForeignContent(Token token, int type) { @@ -323,29 +322,29 @@ class HtmlParser { parseError(error.span, error.data, error.messageParams); newToken = null; } else { - Phase phase_ = phase; + Phase localPhase = phase; if (inForeignContent(token, type)) { - phase_ = _inForeignContentPhase; + localPhase = _inForeignContentPhase; } switch (type) { case TokenKind.characters: - newToken = phase_.processCharacters(newToken); + newToken = localPhase.processCharacters(newToken); break; case TokenKind.spaceCharacters: - newToken = phase_.processSpaceCharacters(newToken); + newToken = localPhase.processSpaceCharacters(newToken); break; case TokenKind.startTag: - newToken = phase_.processStartTag(newToken); + newToken = localPhase.processStartTag(newToken); break; case TokenKind.endTag: - newToken = phase_.processEndTag(newToken); + newToken = localPhase.processEndTag(newToken); break; case TokenKind.comment: - newToken = phase_.processComment(newToken); + newToken = localPhase.processComment(newToken); break; case TokenKind.doctype: - newToken = phase_.processDoctype(newToken); + newToken = localPhase.processDoctype(newToken); break; } } @@ -385,7 +384,7 @@ class HtmlParser { span = _lastSpan; } - var err = new ParseError(errorcode, span, datavars); + var err = ParseError(errorcode, span, datavars); errors.add(err); if (strict) throw err; } @@ -474,20 +473,18 @@ class HtmlParser { // TODO(jmesserly): I don't like mixing non-string objects with strings in // the Node.attributes Map. Is there another solution? final replacements = const { - "xlink:actuate": - const AttributeName("xlink", "actuate", Namespaces.xlink), - "xlink:arcrole": - const AttributeName("xlink", "arcrole", Namespaces.xlink), - "xlink:href": const AttributeName("xlink", "href", Namespaces.xlink), - "xlink:role": const AttributeName("xlink", "role", Namespaces.xlink), - "xlink:show": const AttributeName("xlink", "show", Namespaces.xlink), - "xlink:title": const AttributeName("xlink", "title", Namespaces.xlink), - "xlink:type": const AttributeName("xlink", "type", Namespaces.xlink), - "xml:base": const AttributeName("xml", "base", Namespaces.xml), - "xml:lang": const AttributeName("xml", "lang", Namespaces.xml), - "xml:space": const AttributeName("xml", "space", Namespaces.xml), - "xmlns": const AttributeName(null, "xmlns", Namespaces.xmlns), - "xmlns:xlink": const AttributeName("xmlns", "xlink", Namespaces.xmlns) + "xlink:actuate": AttributeName("xlink", "actuate", Namespaces.xlink), + "xlink:arcrole": AttributeName("xlink", "arcrole", Namespaces.xlink), + "xlink:href": AttributeName("xlink", "href", Namespaces.xlink), + "xlink:role": AttributeName("xlink", "role", Namespaces.xlink), + "xlink:show": AttributeName("xlink", "show", Namespaces.xlink), + "xlink:title": AttributeName("xlink", "title", Namespaces.xlink), + "xlink:type": AttributeName("xlink", "type", Namespaces.xlink), + "xml:base": AttributeName("xml", "base", Namespaces.xml), + "xml:lang": AttributeName("xml", "lang", Namespaces.xml), + "xml:space": AttributeName("xml", "space", Namespaces.xml), + "xmlns": AttributeName(null, "xmlns", Namespaces.xmlns), + "xmlns:xlink": AttributeName("xmlns", "xlink", Namespaces.xmlns) }; for (var originalName in token.data.keys.toList()) { @@ -604,12 +601,10 @@ class Phase { final TreeBuilder tree; - Phase(HtmlParser parser) - : parser = parser, - tree = parser.tree; + Phase(this.parser) : tree = parser.tree; bool processEOF() { - throw new UnimplementedError(); + throw UnimplementedError(); } Token processComment(CommentToken token) { @@ -635,7 +630,7 @@ class Phase { } Token processStartTag(StartTagToken token) { - throw new UnimplementedError(); + throw UnimplementedError(); } Token startTagHtml(StartTagToken token) { @@ -653,7 +648,7 @@ class Phase { } Token processEndTag(EndTagToken token) { - throw new UnimplementedError(); + throw UnimplementedError(); } /// Helper method for popping openElements. @@ -829,7 +824,7 @@ class BeforeHtmlPhase extends Phase { // helper methods void insertHtmlElement() { tree.insertRoot( - new StartTagToken("html", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("html", data: LinkedHashMap<dynamic, String>())); parser.phase = parser._beforeHeadPhase; } @@ -906,8 +901,7 @@ class BeforeHeadPhase extends Phase { } bool processEOF() { - startTagHead( - new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); return true; } @@ -916,8 +910,7 @@ class BeforeHeadPhase extends Phase { } Token processCharacters(CharactersToken token) { - startTagHead( - new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); return token; } @@ -932,14 +925,12 @@ class BeforeHeadPhase extends Phase { } Token startTagOther(StartTagToken token) { - startTagHead( - new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); return token; } Token endTagImplyHead(EndTagToken token) { - startTagHead( - new StartTagToken("head", data: new LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); return token; } @@ -1037,8 +1028,8 @@ class InHeadPhase extends Phase { if (charset != null) { parser.tokenizer.stream.changeEncoding(charset); } else if (content != null) { - var data = new EncodingBytes(content); - var codec = new ContentAttrParser(data).parse(); + var data = EncodingBytes(content); + var codec = ContentAttrParser(data).parse(); parser.tokenizer.stream.changeEncoding(codec); } } @@ -1082,7 +1073,7 @@ class InHeadPhase extends Phase { } void anythingElse() { - endTagHead(new EndTagToken("head")); + endTagHead(EndTagToken("head")); } } @@ -1193,7 +1184,7 @@ class AfterHeadPhase extends Phase { void anythingElse() { tree.insertElement( - new StartTagToken("body", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("body", data: LinkedHashMap<dynamic, String>())); parser.phase = parser._inBodyPhase; parser.framesetOK = true; } @@ -1601,14 +1592,14 @@ class InBodyPhase extends Phase { void startTagCloseP(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.insertElement(token); } void startTagPreListing(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.insertElement(token); parser.framesetOK = false; @@ -1620,7 +1611,7 @@ class InBodyPhase extends Phase { parser.parseError(token.span, "unexpected-start-tag", {"name": "form"}); } else { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.insertElement(token); tree.formPointer = tree.openElements.last; @@ -1631,14 +1622,14 @@ class InBodyPhase extends Phase { parser.framesetOK = false; final stopNamesMap = const { - "li": const ["li"], - "dt": const ["dt", "dd"], - "dd": const ["dt", "dd"] + "li": ["li"], + "dt": ["dt", "dd"], + "dd": ["dt", "dd"] }; var stopNames = stopNamesMap[token.name]; for (var node in tree.openElements.reversed) { if (stopNames.contains(node.localName)) { - parser.phase.processEndTag(new EndTagToken(node.localName)); + parser.phase.processEndTag(EndTagToken(node.localName)); break; } if (specialElements.contains(getElementNameTuple(node)) && @@ -1648,7 +1639,7 @@ class InBodyPhase extends Phase { } if (tree.elementInScope("p", variant: "button")) { - parser.phase.processEndTag(new EndTagToken("p")); + parser.phase.processEndTag(EndTagToken("p")); } tree.insertElement(token); @@ -1656,7 +1647,7 @@ class InBodyPhase extends Phase { void startTagPlaintext(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.insertElement(token); parser.tokenizer.state = parser.tokenizer.plaintextState; @@ -1664,7 +1655,7 @@ class InBodyPhase extends Phase { void startTagHeading(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } if (headingElements.contains(tree.openElements.last.localName)) { parser @@ -1679,7 +1670,7 @@ class InBodyPhase extends Phase { if (afeAElement != null) { parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", {"startName": "a", "endName": "a"}); - endTagFormatting(new EndTagToken("a")); + endTagFormatting(EndTagToken("a")); tree.openElements.remove(afeAElement); tree.activeFormattingElements.remove(afeAElement); } @@ -1697,7 +1688,7 @@ class InBodyPhase extends Phase { if (tree.elementInScope("nobr")) { parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", {"startName": "nobr", "endName": "nobr"}); - processEndTag(new EndTagToken("nobr")); + processEndTag(EndTagToken("nobr")); // XXX Need tests that trigger the following tree.reconstructActiveFormattingElements(); } @@ -1708,7 +1699,7 @@ class InBodyPhase extends Phase { if (tree.elementInScope("button")) { parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", {"startName": "button", "endName": "button"}); - processEndTag(new EndTagToken("button")); + processEndTag(EndTagToken("button")); return token; } else { tree.reconstructActiveFormattingElements(); @@ -1727,7 +1718,7 @@ class InBodyPhase extends Phase { void startTagXmp(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.reconstructActiveFormattingElements(); parser.framesetOK = false; @@ -1737,7 +1728,7 @@ class InBodyPhase extends Phase { void startTagTable(StartTagToken token) { if (parser.compatMode != "quirks") { if (tree.elementInScope("p", variant: "button")) { - processEndTag(new EndTagToken("p")); + processEndTag(EndTagToken("p")); } } tree.insertElement(token); @@ -1770,7 +1761,7 @@ class InBodyPhase extends Phase { void startTagHr(StartTagToken token) { if (tree.elementInScope("p", variant: "button")) { - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } tree.insertElement(token); tree.openElements.removeLast(); @@ -1782,8 +1773,8 @@ class InBodyPhase extends Phase { // No really... parser.parseError(token.span, "unexpected-start-tag-treated-as", {"originalName": "image", "newName": "img"}); - processStartTag(new StartTagToken("img", - data: token.data, selfClosing: token.selfClosing)); + processStartTag( + StartTagToken("img", data: token.data, selfClosing: token.selfClosing)); } void startTagIsIndex(StartTagToken token) { @@ -1791,32 +1782,32 @@ class InBodyPhase extends Phase { if (tree.formPointer != null) { return; } - var formAttrs = new LinkedHashMap<dynamic, String>(); + var formAttrs = LinkedHashMap<dynamic, String>(); var dataAction = token.data["action"]; if (dataAction != null) { formAttrs["action"] = dataAction; } - processStartTag(new StartTagToken("form", data: formAttrs)); + processStartTag(StartTagToken("form", data: formAttrs)); processStartTag( - new StartTagToken("hr", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("hr", data: LinkedHashMap<dynamic, String>())); processStartTag( - new StartTagToken("label", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("label", data: LinkedHashMap<dynamic, String>())); // XXX Localization ... var prompt = token.data["prompt"]; if (prompt == null) { prompt = "This is a searchable index. Enter search keywords: "; } - processCharacters(new CharactersToken(prompt)); - var attributes = new LinkedHashMap<dynamic, String>.from(token.data); + processCharacters(CharactersToken(prompt)); + var attributes = LinkedHashMap<dynamic, String>.from(token.data); attributes.remove('action'); attributes.remove('prompt'); attributes["name"] = "isindex"; - processStartTag(new StartTagToken("input", + processStartTag(StartTagToken("input", data: attributes, selfClosing: token.selfClosing)); - processEndTag(new EndTagToken("label")); + processEndTag(EndTagToken("label")); processStartTag( - new StartTagToken("hr", data: new LinkedHashMap<dynamic, String>())); - processEndTag(new EndTagToken("form")); + StartTagToken("hr", data: LinkedHashMap<dynamic, String>())); + processEndTag(EndTagToken("form")); } void startTagTextarea(StartTagToken token) { @@ -1838,7 +1829,7 @@ class InBodyPhase extends Phase { void startTagOpt(StartTagToken token) { if (tree.openElements.last.localName == "option") { - parser.phase.processEndTag(new EndTagToken("option")); + parser.phase.processEndTag(EndTagToken("option")); } tree.reconstructActiveFormattingElements(); parser.tree.insertElement(token); @@ -1919,9 +1910,9 @@ class InBodyPhase extends Phase { void endTagP(EndTagToken token) { if (!tree.elementInScope("p", variant: "button")) { startTagCloseP( - new StartTagToken("p", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("p", data: LinkedHashMap<dynamic, String>())); parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); - endTagP(new EndTagToken("p")); + endTagP(EndTagToken("p")); } else { tree.generateImpliedEndTags("p"); if (tree.openElements.last.localName != "p") { @@ -1970,7 +1961,7 @@ class InBodyPhase extends Phase { Token endTagHtml(EndTagToken token) { //We repeat the test for the body end tag token being ignored here if (tree.elementInScope("body")) { - endTagBody(new EndTagToken("body")); + endTagBody(EndTagToken("body")); return token; } return null; @@ -2218,7 +2209,7 @@ class InBodyPhase extends Phase { {"originalName": "br", "newName": "br element"}); tree.reconstructActiveFormattingElements(); tree.insertElement( - new StartTagToken("br", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("br", data: LinkedHashMap<dynamic, String>())); tree.openElements.removeLast(); } @@ -2420,8 +2411,8 @@ class InTablePhase extends Phase { } Token startTagCol(StartTagToken token) { - startTagColgroup(new StartTagToken("colgroup", - data: new LinkedHashMap<dynamic, String>())); + startTagColgroup( + StartTagToken("colgroup", data: LinkedHashMap<dynamic, String>())); return token; } @@ -2433,14 +2424,14 @@ class InTablePhase extends Phase { Token startTagImplyTbody(StartTagToken token) { startTagRowGroup( - new StartTagToken("tbody", data: new LinkedHashMap<dynamic, String>())); + StartTagToken("tbody", data: LinkedHashMap<dynamic, String>())); return token; } Token startTagTable(StartTagToken token) { parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", {"startName": "table", "endName": "table"}); - parser.phase.processEndTag(new EndTagToken("table")); + parser.phase.processEndTag(EndTagToken("table")); if (!parser.innerHTMLMode) { return token; } @@ -2535,7 +2526,7 @@ class InTableTextPhase extends Phase { } if (!allWhitespace(data)) { - parser._inTablePhase.insertText(new CharactersToken(data)..span = span); + parser._inTablePhase.insertText(CharactersToken(data)..span = span); } else if (data.isNotEmpty) { tree.insertText(data, span); } @@ -2646,7 +2637,7 @@ class InCaptionPhase extends Phase { parser.parseError(token.span, "undefined-error"); //XXX Have to duplicate logic here to find out if the tag is ignored var ignoreEndTag = ignoreEndTagCaption(); - parser.phase.processEndTag(new EndTagToken("caption")); + parser.phase.processEndTag(EndTagToken("caption")); if (!ignoreEndTag) { return token; } @@ -2684,7 +2675,7 @@ class InCaptionPhase extends Phase { Token endTagTable(EndTagToken token) { parser.parseError(token.span, "undefined-error"); var ignoreEndTag = ignoreEndTagCaption(); - parser.phase.processEndTag(new EndTagToken("caption")); + parser.phase.processEndTag(EndTagToken("caption")); if (!ignoreEndTag) { return token; } @@ -2739,14 +2730,14 @@ class InColumnGroupPhase extends Phase { assert(parser.innerHTMLMode); return false; } else { - endTagColgroup(new EndTagToken("colgroup")); + endTagColgroup(EndTagToken("colgroup")); return true; } } Token processCharacters(CharactersToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(new EndTagToken("colgroup")); + endTagColgroup(EndTagToken("colgroup")); return ignoreEndTag ? null : token; } @@ -2757,7 +2748,7 @@ class InColumnGroupPhase extends Phase { Token startTagOther(StartTagToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(new EndTagToken("colgroup")); + endTagColgroup(EndTagToken("colgroup")); return ignoreEndTag ? null : token; } @@ -2779,7 +2770,7 @@ class InColumnGroupPhase extends Phase { Token endTagOther(EndTagToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(new EndTagToken("colgroup")); + endTagColgroup(EndTagToken("colgroup")); return ignoreEndTag ? null : token; } } @@ -2870,8 +2861,7 @@ class InTableBodyPhase extends Phase { Token startTagTableCell(StartTagToken token) { parser.parseError( token.span, "unexpected-cell-in-table-body", {"name": token.name}); - startTagTr( - new StartTagToken("tr", data: new LinkedHashMap<dynamic, String>())); + startTagTr(StartTagToken("tr", data: LinkedHashMap<dynamic, String>())); return token; } @@ -2899,7 +2889,7 @@ class InTableBodyPhase extends Phase { tree.elementInScope("thead", variant: "table") || tree.elementInScope("tfoot", variant: "table")) { clearStackToTableBodyContext(); - endTagTableRowGroup(new EndTagToken(tree.openElements.last.localName)); + endTagTableRowGroup(EndTagToken(tree.openElements.last.localName)); return token; } else { // innerHTML case @@ -3010,7 +3000,7 @@ class InRowPhase extends Phase { Token startTagTableOther(StartTagToken token) { bool ignoreEndTag = ignoreEndTagTr(); - endTagTr(new EndTagToken("tr")); + endTagTr(EndTagToken("tr")); // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; } @@ -3034,7 +3024,7 @@ class InRowPhase extends Phase { Token endTagTable(EndTagToken token) { var ignoreEndTag = ignoreEndTagTr(); - endTagTr(new EndTagToken("tr")); + endTagTr(EndTagToken("tr")); // Reprocess the current tag if the tr end tag was not ignored // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; @@ -3042,7 +3032,7 @@ class InRowPhase extends Phase { Token endTagTableRowGroup(EndTagToken token) { if (tree.elementInScope(token.name, variant: "table")) { - endTagTr(new EndTagToken("tr")); + endTagTr(EndTagToken("tr")); return token; } else { parser.parseError(token.span, "undefined-error"); @@ -3110,9 +3100,9 @@ class InCellPhase extends Phase { // helper void closeCell() { if (tree.elementInScope("td", variant: "table")) { - endTagTableCell(new EndTagToken("td")); + endTagTableCell(EndTagToken("td")); } else if (tree.elementInScope("th", variant: "table")) { - endTagTableCell(new EndTagToken("th")); + endTagTableCell(EndTagToken("th")); } } @@ -3264,13 +3254,13 @@ class InSelectPhase extends Phase { void startTagSelect(StartTagToken token) { parser.parseError(token.span, "unexpected-select-in-select"); - endTagSelect(new EndTagToken("select")); + endTagSelect(EndTagToken("select")); } Token startTagInput(StartTagToken token) { parser.parseError(token.span, "unexpected-input-in-select"); if (tree.elementInScope("select", variant: "select")) { - endTagSelect(new EndTagToken("select")); + endTagSelect(EndTagToken("select")); return token; } else { assert(parser.innerHTMLMode); @@ -3382,7 +3372,7 @@ class InSelectInTablePhase extends Phase { token.span, "unexpected-table-element-start-tag-in-select-in-table", {"name": token.name}); - endTagOther(new EndTagToken("select")); + endTagOther(EndTagToken("select")); return token; } @@ -3396,7 +3386,7 @@ class InSelectInTablePhase extends Phase { "unexpected-table-element-end-tag-in-select-in-table", {"name": token.name}); if (tree.elementInScope(token.name, variant: "table")) { - endTagOther(new EndTagToken("select")); + endTagOther(EndTagToken("select")); return token; } return null; @@ -3409,7 +3399,7 @@ class InSelectInTablePhase extends Phase { class InForeignContentPhase extends Phase { // TODO(jmesserly): this is sorted so we could binary search. - static const breakoutElements = const [ + static const breakoutElements = [ 'b', 'big', 'blockquote', @@ -3915,5 +3905,5 @@ class ParseError implements SourceSpanException { Pair<String, String> getElementNameTuple(Element e) { var ns = e.namespaceUri; if (ns == null) ns = Namespaces.html; - return new Pair(ns, e.localName); + return Pair(ns, e.localName); } diff --git a/pkgs/html/lib/parser_console.dart b/pkgs/html/lib/parser_console.dart index 515f891c4..28dee1417 100644 --- a/pkgs/html/lib/parser_console.dart +++ b/pkgs/html/lib/parser_console.dart @@ -11,7 +11,7 @@ import 'src/inputstream.dart' as inputstream; /// this means it will be able to handle `dart:io` and [RandomAccessFile]s as /// input to the various [parse] methods. void useConsole() { - inputstream.consoleSupport = new _ConsoleSupport(); + inputstream.consoleSupport = _ConsoleSupport(); } class _ConsoleSupport extends inputstream.ConsoleSupport { @@ -25,7 +25,7 @@ class _ConsoleSupport extends inputstream.ConsoleSupport { /// Synchronously reads all bytes from the [file]. List<int> readAllBytesFromFile(RandomAccessFile file) { int length = file.lengthSync(); - var bytes = new List<int>(length); + var bytes = List<int>(length); int bytesRead = 0; while (bytesRead < length) { diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index bf1fa470e..ba10a4a39 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -36,7 +36,7 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes, // TODO(jmesserly): ideally this would be DecoderException, like the // one thrown in runtime/bin/string_stream.dart, but we don't want to // depend on dart:io. - throw new FormatException("Illegal ASCII character $byte"); + throw FormatException("Illegal ASCII character $byte"); } } return bytes; @@ -69,7 +69,7 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes, return decodeUtf32leAsIterable(bytes, offset, length, true, replace); default: - throw new ArgumentError('Encoding $encoding not supported'); + throw ArgumentError('Encoding $encoding not supported'); } } @@ -103,7 +103,7 @@ IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, [int offset = 0, int length, int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { - return new IterableWindows1252Decoder( + return IterableWindows1252Decoder( bytes, offset, length, replacementCodepoint); } @@ -122,7 +122,7 @@ class IterableWindows1252Decoder extends IterableBase<int> { this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]); Windows1252Decoder get iterator => - new Windows1252Decoder(bytes, offset, length, replacementCodepoint); + Windows1252Decoder(bytes, offset, length, replacementCodepoint); } /// Provides an iterator of Unicode codepoints from windows-1252 encoded bytes. @@ -218,7 +218,7 @@ class Windows1252Decoder implements Iterator<int> { case 0x90: case 0x9D: if (replacementCodepoint == null) { - throw new ArgumentError( + throw ArgumentError( "Invalid windows-1252 code point $char at $_offset"); } return replacementCodepoint; diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 9f4878f4c..fc0c6a1a3 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -6,7 +6,7 @@ import 'utils.dart'; // lookup than linear search "contains". In the Python code they were // frozensets. -final String EOF = null; +final String eof = null; class ReparseException implements Exception { final String message; @@ -19,7 +19,7 @@ class ReparseException implements Exception { /// These are error messages emitted by [HtmlParser]. The values use Python /// style string formatting, as implemented by [formatStr]. That function only /// supports the subset of format functionality used here. -const Map<String, String> errorMessages = const { +const Map<String, String> errorMessages = { "null-character": "Null character in input stream, replaced with U+FFFD.", "invalid-codepoint": "Invalid codepoint in stream.", "incorrectly-placed-solidus": "Solidus (/) incorrectly placed in tag.", @@ -264,139 +264,139 @@ class Namespaces { } } -const List scopingElements = const [ - const Pair(Namespaces.html, "applet"), - const Pair(Namespaces.html, "caption"), - const Pair(Namespaces.html, "html"), - const Pair(Namespaces.html, "marquee"), - const Pair(Namespaces.html, "object"), - const Pair(Namespaces.html, "table"), - const Pair(Namespaces.html, "td"), - const Pair(Namespaces.html, "th"), - const Pair(Namespaces.mathml, "mi"), - const Pair(Namespaces.mathml, "mo"), - const Pair(Namespaces.mathml, "mn"), - const Pair(Namespaces.mathml, "ms"), - const Pair(Namespaces.mathml, "mtext"), - const Pair(Namespaces.mathml, "annotation-xml"), - const Pair(Namespaces.svg, "foreignObject"), - const Pair(Namespaces.svg, "desc"), - const Pair(Namespaces.svg, "title") +const List scopingElements = [ + Pair(Namespaces.html, "applet"), + Pair(Namespaces.html, "caption"), + Pair(Namespaces.html, "html"), + Pair(Namespaces.html, "marquee"), + Pair(Namespaces.html, "object"), + Pair(Namespaces.html, "table"), + Pair(Namespaces.html, "td"), + Pair(Namespaces.html, "th"), + Pair(Namespaces.mathml, "mi"), + Pair(Namespaces.mathml, "mo"), + Pair(Namespaces.mathml, "mn"), + Pair(Namespaces.mathml, "ms"), + Pair(Namespaces.mathml, "mtext"), + Pair(Namespaces.mathml, "annotation-xml"), + Pair(Namespaces.svg, "foreignObject"), + Pair(Namespaces.svg, "desc"), + Pair(Namespaces.svg, "title") ]; -const formattingElements = const [ - const Pair(Namespaces.html, "a"), - const Pair(Namespaces.html, "b"), - const Pair(Namespaces.html, "big"), - const Pair(Namespaces.html, "code"), - const Pair(Namespaces.html, "em"), - const Pair(Namespaces.html, "font"), - const Pair(Namespaces.html, "i"), - const Pair(Namespaces.html, "nobr"), - const Pair(Namespaces.html, "s"), - const Pair(Namespaces.html, "small"), - const Pair(Namespaces.html, "strike"), - const Pair(Namespaces.html, "strong"), - const Pair(Namespaces.html, "tt"), - const Pair(Namespaces.html, "") +const formattingElements = [ + Pair(Namespaces.html, "a"), + Pair(Namespaces.html, "b"), + Pair(Namespaces.html, "big"), + Pair(Namespaces.html, "code"), + Pair(Namespaces.html, "em"), + Pair(Namespaces.html, "font"), + Pair(Namespaces.html, "i"), + Pair(Namespaces.html, "nobr"), + Pair(Namespaces.html, "s"), + Pair(Namespaces.html, "small"), + Pair(Namespaces.html, "strike"), + Pair(Namespaces.html, "strong"), + Pair(Namespaces.html, "tt"), + Pair(Namespaces.html, "") ]; -const specialElements = const [ - const Pair(Namespaces.html, "address"), - const Pair(Namespaces.html, "applet"), - const Pair(Namespaces.html, "area"), - const Pair(Namespaces.html, "article"), - const Pair(Namespaces.html, "aside"), - const Pair(Namespaces.html, "base"), - const Pair(Namespaces.html, "basefont"), - const Pair(Namespaces.html, "bgsound"), - const Pair(Namespaces.html, "blockquote"), - const Pair(Namespaces.html, "body"), - const Pair(Namespaces.html, "br"), - const Pair(Namespaces.html, "button"), - const Pair(Namespaces.html, "caption"), - const Pair(Namespaces.html, "center"), - const Pair(Namespaces.html, "col"), - const Pair(Namespaces.html, "colgroup"), - const Pair(Namespaces.html, "command"), - const Pair(Namespaces.html, "dd"), - const Pair(Namespaces.html, "details"), - const Pair(Namespaces.html, "dir"), - const Pair(Namespaces.html, "div"), - const Pair(Namespaces.html, "dl"), - const Pair(Namespaces.html, "dt"), - const Pair(Namespaces.html, "embed"), - const Pair(Namespaces.html, "fieldset"), - const Pair(Namespaces.html, "figure"), - const Pair(Namespaces.html, "footer"), - const Pair(Namespaces.html, "form"), - const Pair(Namespaces.html, "frame"), - const Pair(Namespaces.html, "frameset"), - const Pair(Namespaces.html, "h1"), - const Pair(Namespaces.html, "h2"), - const Pair(Namespaces.html, "h3"), - const Pair(Namespaces.html, "h4"), - const Pair(Namespaces.html, "h5"), - const Pair(Namespaces.html, "h6"), - const Pair(Namespaces.html, "head"), - const Pair(Namespaces.html, "header"), - const Pair(Namespaces.html, "hr"), - const Pair(Namespaces.html, "html"), - const Pair(Namespaces.html, "iframe"), +const specialElements = [ + Pair(Namespaces.html, "address"), + Pair(Namespaces.html, "applet"), + Pair(Namespaces.html, "area"), + Pair(Namespaces.html, "article"), + Pair(Namespaces.html, "aside"), + Pair(Namespaces.html, "base"), + Pair(Namespaces.html, "basefont"), + Pair(Namespaces.html, "bgsound"), + Pair(Namespaces.html, "blockquote"), + Pair(Namespaces.html, "body"), + Pair(Namespaces.html, "br"), + Pair(Namespaces.html, "button"), + Pair(Namespaces.html, "caption"), + Pair(Namespaces.html, "center"), + Pair(Namespaces.html, "col"), + Pair(Namespaces.html, "colgroup"), + Pair(Namespaces.html, "command"), + Pair(Namespaces.html, "dd"), + Pair(Namespaces.html, "details"), + Pair(Namespaces.html, "dir"), + Pair(Namespaces.html, "div"), + Pair(Namespaces.html, "dl"), + Pair(Namespaces.html, "dt"), + Pair(Namespaces.html, "embed"), + Pair(Namespaces.html, "fieldset"), + Pair(Namespaces.html, "figure"), + Pair(Namespaces.html, "footer"), + Pair(Namespaces.html, "form"), + Pair(Namespaces.html, "frame"), + Pair(Namespaces.html, "frameset"), + Pair(Namespaces.html, "h1"), + Pair(Namespaces.html, "h2"), + Pair(Namespaces.html, "h3"), + Pair(Namespaces.html, "h4"), + Pair(Namespaces.html, "h5"), + Pair(Namespaces.html, "h6"), + Pair(Namespaces.html, "head"), + Pair(Namespaces.html, "header"), + Pair(Namespaces.html, "hr"), + Pair(Namespaces.html, "html"), + Pair(Namespaces.html, "iframe"), // Note that image is commented out in the spec as "this isn't an // element that can end up on the stack, so it doesn't matter," - const Pair(Namespaces.html, "image"), - const Pair(Namespaces.html, "img"), - const Pair(Namespaces.html, "input"), - const Pair(Namespaces.html, "isindex"), - const Pair(Namespaces.html, "li"), - const Pair(Namespaces.html, "link"), - const Pair(Namespaces.html, "listing"), - const Pair(Namespaces.html, "marquee"), - const Pair(Namespaces.html, "men"), - const Pair(Namespaces.html, "meta"), - const Pair(Namespaces.html, "nav"), - const Pair(Namespaces.html, "noembed"), - const Pair(Namespaces.html, "noframes"), - const Pair(Namespaces.html, "noscript"), - const Pair(Namespaces.html, "object"), - const Pair(Namespaces.html, "ol"), - const Pair(Namespaces.html, "p"), - const Pair(Namespaces.html, "param"), - const Pair(Namespaces.html, "plaintext"), - const Pair(Namespaces.html, "pre"), - const Pair(Namespaces.html, "script"), - const Pair(Namespaces.html, "section"), - const Pair(Namespaces.html, "select"), - const Pair(Namespaces.html, "style"), - const Pair(Namespaces.html, "table"), - const Pair(Namespaces.html, "tbody"), - const Pair(Namespaces.html, "td"), - const Pair(Namespaces.html, "textarea"), - const Pair(Namespaces.html, "tfoot"), - const Pair(Namespaces.html, "th"), - const Pair(Namespaces.html, "thead"), - const Pair(Namespaces.html, "title"), - const Pair(Namespaces.html, "tr"), - const Pair(Namespaces.html, "ul"), - const Pair(Namespaces.html, "wbr"), - const Pair(Namespaces.html, "xmp"), - const Pair(Namespaces.svg, "foreignObject") + Pair(Namespaces.html, "image"), + Pair(Namespaces.html, "img"), + Pair(Namespaces.html, "input"), + Pair(Namespaces.html, "isindex"), + Pair(Namespaces.html, "li"), + Pair(Namespaces.html, "link"), + Pair(Namespaces.html, "listing"), + Pair(Namespaces.html, "marquee"), + Pair(Namespaces.html, "men"), + Pair(Namespaces.html, "meta"), + Pair(Namespaces.html, "nav"), + Pair(Namespaces.html, "noembed"), + Pair(Namespaces.html, "noframes"), + Pair(Namespaces.html, "noscript"), + Pair(Namespaces.html, "object"), + Pair(Namespaces.html, "ol"), + Pair(Namespaces.html, "p"), + Pair(Namespaces.html, "param"), + Pair(Namespaces.html, "plaintext"), + Pair(Namespaces.html, "pre"), + Pair(Namespaces.html, "script"), + Pair(Namespaces.html, "section"), + Pair(Namespaces.html, "select"), + Pair(Namespaces.html, "style"), + Pair(Namespaces.html, "table"), + Pair(Namespaces.html, "tbody"), + Pair(Namespaces.html, "td"), + Pair(Namespaces.html, "textarea"), + Pair(Namespaces.html, "tfoot"), + Pair(Namespaces.html, "th"), + Pair(Namespaces.html, "thead"), + Pair(Namespaces.html, "title"), + Pair(Namespaces.html, "tr"), + Pair(Namespaces.html, "ul"), + Pair(Namespaces.html, "wbr"), + Pair(Namespaces.html, "xmp"), + Pair(Namespaces.svg, "foreignObject") ]; -const htmlIntegrationPointElements = const [ - const Pair(Namespaces.mathml, "annotaion-xml"), - const Pair(Namespaces.svg, "foreignObject"), - const Pair(Namespaces.svg, "desc"), - const Pair(Namespaces.svg, "title") +const htmlIntegrationPointElements = [ + Pair(Namespaces.mathml, "annotaion-xml"), + Pair(Namespaces.svg, "foreignObject"), + Pair(Namespaces.svg, "desc"), + Pair(Namespaces.svg, "title") ]; -const mathmlTextIntegrationPointElements = const [ - const Pair(Namespaces.mathml, "mi"), - const Pair(Namespaces.mathml, "mo"), - const Pair(Namespaces.mathml, "mn"), - const Pair(Namespaces.mathml, "ms"), - const Pair(Namespaces.mathml, "mtext") +const mathmlTextIntegrationPointElements = [ + Pair(Namespaces.mathml, "mi"), + Pair(Namespaces.mathml, "mo"), + Pair(Namespaces.mathml, "mn"), + Pair(Namespaces.mathml, "ms"), + Pair(Namespaces.mathml, "mtext") ]; const spaceCharacters = " \n\r\t\u000C"; @@ -421,7 +421,7 @@ bool isWhitespaceCC(int charCode) { return false; } -const List<String> tableInsertModeElements = const [ +const List<String> tableInsertModeElements = [ "table", "tbody", "tfoot", @@ -487,7 +487,7 @@ bool isHexDigit(String char) { // ASCII chars to.toLowerCase() case, unlike Dart's toLowerCase function. String asciiUpper2Lower(String text) { if (text == null) return null; - var result = new List<int>(text.length); + var result = List<int>(text.length); for (int i = 0; i < text.length; i++) { var c = text.codeUnitAt(i); if (c >= UPPER_A && c <= UPPER_Z) { @@ -495,15 +495,15 @@ String asciiUpper2Lower(String text) { } result[i] = c; } - return new String.fromCharCodes(result); + return String.fromCharCodes(result); } // Heading elements need to be ordered -const headingElements = const ["h1", "h2", "h3", "h4", "h5", "h6"]; +const headingElements = ["h1", "h2", "h3", "h4", "h5", "h6"]; -const cdataElements = const ['title', 'textarea']; +const cdataElements = ['title', 'textarea']; -const rcdataElements = const [ +const rcdataElements = [ 'style', 'script', 'xmp', @@ -513,33 +513,33 @@ const rcdataElements = const [ 'noscript' ]; -const Map<String, List<String>> booleanAttributes = const { - "": const [ +const Map<String, List<String>> booleanAttributes = { + "": [ "irrelevant", ], - "style": const [ + "style": [ "scoped", ], - "img": const [ + "img": [ "ismap", ], - "audio": const ["autoplay", "controls"], - "video": const ["autoplay", "controls"], - "script": const ["defer", "async"], - "details": const [ + "audio": ["autoplay", "controls"], + "video": ["autoplay", "controls"], + "script": ["defer", "async"], + "details": [ "open", ], - "datagrid": const ["multiple", "disabled"], - "command": const ["hidden", "disabled", "checked", "default"], - "hr": const ["noshade"], - "men": const [ + "datagrid": ["multiple", "disabled"], + "command": ["hidden", "disabled", "checked", "default"], + "hr": ["noshade"], + "men": [ "autosubmit", ], - "fieldset": const ["disabled", "readonly"], - "option": const ["disabled", "readonly", "selected"], - "optgroup": const ["disabled", "readonly"], - "button": const ["disabled", "autofocus"], - "input": const [ + "fieldset": ["disabled", "readonly"], + "option": ["disabled", "readonly", "selected"], + "optgroup": ["disabled", "readonly"], + "button": ["disabled", "autofocus"], + "input": [ "disabled", "readonly", "required", @@ -547,13 +547,13 @@ const Map<String, List<String>> booleanAttributes = const { "checked", "ismap" ], - "select": const ["disabled", "readonly", "autofocus", "multiple"], - "output": const ["disabled", "readonly"], + "select": ["disabled", "readonly", "autofocus", "multiple"], + "output": ["disabled", "readonly"], }; // entitiesWindows1252 has to be _ordered_ and needs to have an index. It // therefore can't be a frozenset. -const List<int> entitiesWindows1252 = const [ +const List<int> entitiesWindows1252 = [ 8364, // 0x80 0x20AC EURO SIGN 65533, // 0x81 UNDEFINED 8218, // 0x82 0x201A SINGLE LOW-9 QUOTATION MARK @@ -588,9 +588,9 @@ const List<int> entitiesWindows1252 = const [ 376 // 0x9F 0x0178 LATIN CAPITAL LETTER Y WITH DIAERESIS ]; -const xmlEntities = const ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; +const xmlEntities = ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; -const Map<String, String> entities = const { +const Map<String, String> entities = { "AElig": "\xc6", "AElig;": "\xc6", "AMP": "&", @@ -2824,7 +2824,7 @@ const Map<String, String> entities = const { "zwnj;": "\u200c", }; -const Map<int, String> replacementCharacters = const { +const Map<int, String> replacementCharacters = { 0x00: "\uFFFD", 0x0d: "\u000D", 0x80: "\u20AC", @@ -2861,7 +2861,7 @@ const Map<int, String> replacementCharacters = const { 0x9F: "\u0178" }; -const Map<String, String> encodings = const { +const Map<String, String> encodings = { '437': 'cp437', '850': 'cp850', '852': 'cp852', diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index eca2400b4..939bf41e8 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -15,7 +15,7 @@ class ElementCssClassSet extends _CssClassSetImpl { ElementCssClassSet(this._element); Set<String> readClasses() { - var s = new LinkedHashSet<String>(); + var s = LinkedHashSet<String>(); var classname = _element.className; for (String name in classname.split(' ')) { @@ -32,79 +32,63 @@ class ElementCssClassSet extends _CssClassSetImpl { } } -/** A Set that stores the CSS class names for an element. */ +/// A Set that stores the CSS class names for an element. abstract class CssClassSet implements Set<String> { - /** - * Adds the class [value] to the element if it is not on it, removes it if it - * is. - * - * If [shouldAdd] is true, then we always add that [value] to the element. If - * [shouldAdd] is false then we always remove [value] from the element. - */ + /// Adds the class [value] to the element if it is not on it, removes it if it + /// is. + /// + /// If [shouldAdd] is true, then we always add that [value] to the element. If + /// [shouldAdd] is false then we always remove [value] from the element. bool toggle(String value, [bool shouldAdd]); - /** - * Returns [:true:] if classes cannot be added or removed from this - * [:CssClassSet:]. - */ + /// Returns [:true:] if classes cannot be added or removed from this + /// [:CssClassSet:]. bool get frozen; - /** - * Determine if this element contains the class [value]. - * - * This is the Dart equivalent of jQuery's - * [hasClass](http://api.jquery.com/hasClass/). - */ + /// Determine if this element contains the class [value]. + /// + /// This is the Dart equivalent of jQuery's + /// [hasClass](http://api.jquery.com/hasClass/). bool contains(Object value); - /** - * Add the class [value] to element. - * - * This is the Dart equivalent of jQuery's - * [addClass](http://api.jquery.com/addClass/). - * - * If this corresponds to one element. Returns true if [value] was added to - * the set, otherwise false. - * - * If this corresponds to many elements, null is always returned. - */ + /// Add the class [value] to element. + /// + /// This is the Dart equivalent of jQuery's + /// [addClass](http://api.jquery.com/addClass/). + /// + /// If this corresponds to one element. Returns true if [value] was added to + /// the set, otherwise false. + /// + /// If this corresponds to many elements, null is always returned. bool add(String value); - /** - * Remove the class [value] from element, and return true on successful - * removal. - * - * This is the Dart equivalent of jQuery's - * [removeClass](http://api.jquery.com/removeClass/). - */ + /// Remove the class [value] from element, and return true on successful + /// removal. + /// + /// This is the Dart equivalent of jQuery's + /// [removeClass](http://api.jquery.com/removeClass/). bool remove(Object value); - /** - * Add all classes specified in [iterable] to element. - * - * This is the Dart equivalent of jQuery's - * [addClass](http://api.jquery.com/addClass/). - */ + /// Add all classes specified in [iterable] to element. + /// + /// This is the Dart equivalent of jQuery's + /// [addClass](http://api.jquery.com/addClass/). void addAll(Iterable<String> iterable); - /** - * Remove all classes specified in [iterable] from element. - * - * This is the Dart equivalent of jQuery's - * [removeClass](http://api.jquery.com/removeClass/). - */ + /// Remove all classes specified in [iterable] from element. + /// + /// This is the Dart equivalent of jQuery's + /// [removeClass](http://api.jquery.com/removeClass/). void removeAll(Iterable<Object> iterable); - /** - * Toggles all classes specified in [iterable] on element. - * - * Iterate through [iterable]'s items, and add it if it is not on it, or - * remove it if it is. This is the Dart equivalent of jQuery's - * [toggleClass](http://api.jquery.com/toggleClass/). - * If [shouldAdd] is true, then we always add all the classes in [iterable] - * element. If [shouldAdd] is false then we always remove all the classes in - * [iterable] from the element. - */ + /// Toggles all classes specified in [iterable] on element. + /// + /// Iterate through [iterable]'s items, and add it if it is not on it, or + /// remove it if it is. This is the Dart equivalent of jQuery's + /// [toggleClass](http://api.jquery.com/toggleClass/). + /// If [shouldAdd] is true, then we always add all the classes in [iterable] + /// element. If [shouldAdd] is false then we always remove all the classes in + /// [iterable] from the element. void toggleAll(Iterable<String> iterable, [bool shouldAdd]); } @@ -113,13 +97,11 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { return readClasses().join(' '); } - /** - * Adds the class [value] to the element if it is not on it, removes it if it - * is. - * - * If [shouldAdd] is true, then we always add that [value] to the element. If - * [shouldAdd] is false then we always remove [value] from the element. - */ + /// Adds the class [value] to the element if it is not on it, removes it if it + /// is. + /// + /// If [shouldAdd] is true, then we always add that [value] to the element. If + /// [shouldAdd] is false then we always remove [value] from the element. bool toggle(String value, [bool shouldAdd]) { Set<String> s = readClasses(); bool result = false; @@ -134,10 +116,8 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { return result; } - /** - * Returns [:true:] if classes cannot be added or removed from this - * [:CssClassSet:]. - */ + /// Returns [:true:] if classes cannot be added or removed from this + /// [:CssClassSet:]. bool get frozen => false; Iterator<String> get iterator => readClasses().iterator; @@ -145,38 +125,32 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { int get length => readClasses().length; // interface Set - BEGIN - /** - * Determine if this element contains the class [value]. - * - * This is the Dart equivalent of jQuery's - * [hasClass](http://api.jquery.com/hasClass/). - */ + /// Determine if this element contains the class [value]. + /// + /// This is the Dart equivalent of jQuery's + /// [hasClass](http://api.jquery.com/hasClass/). bool contains(Object value) => readClasses().contains(value); - /** Lookup from the Set interface. Not interesting for a String set. */ + /// Lookup from the Set interface. Not interesting for a String set. String lookup(Object value) => contains(value) ? value as String : null; Set<String> toSet() => readClasses().toSet(); - /** - * Add the class [value] to element. - * - * This is the Dart equivalent of jQuery's - * [addClass](http://api.jquery.com/addClass/). - */ + /// Add the class [value] to element. + /// + /// This is the Dart equivalent of jQuery's + /// [addClass](http://api.jquery.com/addClass/). bool add(String value) { // TODO - figure out if we need to do any validation here // or if the browser natively does enough. return _modify((s) => s.add(value)); } - /** - * Remove the class [value] from element, and return true on successful - * removal. - * - * This is the Dart equivalent of jQuery's - * [removeClass](http://api.jquery.com/removeClass/). - */ + /// Remove the class [value] from element, and return true on successful + /// removal. + /// + /// This is the Dart equivalent of jQuery's + /// [removeClass](http://api.jquery.com/removeClass/). bool remove(Object value) { if (value is! String) return false; Set<String> s = readClasses(); @@ -185,29 +159,25 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { return result; } - /** - * Toggles all classes specified in [iterable] on element. - * - * Iterate through [iterable]'s items, and add it if it is not on it, or - * remove it if it is. This is the Dart equivalent of jQuery's - * [toggleClass](http://api.jquery.com/toggleClass/). - * If [shouldAdd] is true, then we always add all the classes in [iterable] - * element. If [shouldAdd] is false then we always remove all the classes in - * [iterable] from the element. - */ + /// Toggles all classes specified in [iterable] on element. + /// + /// Iterate through [iterable]'s items, and add it if it is not on it, or + /// remove it if it is. This is the Dart equivalent of jQuery's + /// [toggleClass](http://api.jquery.com/toggleClass/). + /// If [shouldAdd] is true, then we always add all the classes in [iterable] + /// element. If [shouldAdd] is false then we always remove all the classes in + /// [iterable] from the element. void toggleAll(Iterable<String> iterable, [bool shouldAdd]) { iterable.forEach((e) => toggle(e, shouldAdd)); } - /** - * Helper method used to modify the set of css classes on this element. - * - * f - callback with: - * s - a Set of all the css class name currently on this element. - * - * After f returns, the modified set is written to the - * className property of this element. - */ + /// Helper method used to modify the set of css classes on this element. + /// + /// f - callback with: + /// s - a Set of all the css class name currently on this element. + /// + /// After f returns, the modified set is written to the + /// className property of this element. bool _modify(bool f(Set<String> s)) { Set<String> s = readClasses(); var ret = f(s); @@ -215,17 +185,13 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { return ret; } - /** - * Read the class names from the Element class property, - * and put them into a set (duplicates are discarded). - * This is intended to be overridden by specific implementations. - */ + /// Read the class names from the Element class property, + /// and put them into a set (duplicates are discarded). + /// This is intended to be overridden by specific implementations. Set<String> readClasses(); - /** - * Join all the elements of a set into one string and write - * back to the element. - * This is intended to be overridden by specific implementations. - */ + /// Join all the elements of a set into one string and write + /// back to the element. + /// This is intended to be overridden by specific implementations. void writeClasses(Set<String> s); } diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index ef5e7088e..280e7dd71 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -19,9 +19,9 @@ class EncodingBytes { String next() { var p = _position = _position + 1; if (p >= length) { - throw new StateError("No more elements"); + throw StateError("No more elements"); } else if (p < 0) { - throw new RangeError(p); + throw RangeError(p); } return _bytes[p]; } @@ -29,9 +29,9 @@ class EncodingBytes { String previous() { var p = _position; if (p >= length) { - throw new StateError("No more elements"); + throw StateError("No more elements"); } else if (p < 0) { - throw new RangeError(p); + throw RangeError(p); } _position = p = p - 1; return _bytes[p]; @@ -39,14 +39,14 @@ class EncodingBytes { set position(int value) { if (_position >= length) { - throw new StateError("No more elements"); + throw StateError("No more elements"); } _position = value; } int get position { if (_position >= length) { - throw new StateError("No more elements"); + throw StateError("No more elements"); } if (_position >= 0) { return _position; @@ -110,7 +110,7 @@ class EncodingBytes { _position = newPosition + bytes.length - 1; return true; } else { - throw new StateError("No more elements"); + throw StateError("No more elements"); } } @@ -137,16 +137,16 @@ class EncodingParser { /// [bytes] - the data to work on for encoding detection. EncodingParser(List<int> bytes) // Note: this is intentionally interpreting bytes as codepoints. - : data = new EncodingBytes(new String.fromCharCodes(bytes).toLowerCase()); + : data = EncodingBytes(String.fromCharCodes(bytes).toLowerCase()); String getEncoding() { final methodDispatch = [ - new _DispatchEntry("<!--", handleComment), - new _DispatchEntry("<meta", handleMeta), - new _DispatchEntry("</", handlePossibleEndTag), - new _DispatchEntry("<!", handleOther), - new _DispatchEntry("<?", handleOther), - new _DispatchEntry("<", handlePossibleStartTag), + _DispatchEntry("<!--", handleComment), + _DispatchEntry("<meta", handleMeta), + _DispatchEntry("</", handlePossibleEndTag), + _DispatchEntry("<!", handleOther), + _DispatchEntry("<?", handleOther), + _DispatchEntry("<", handlePossibleStartTag), ]; try { @@ -191,7 +191,7 @@ class EncodingParser { return false; } } else if (attr[0] == "content") { - var contentParser = new ContentAttrParser(new EncodingBytes(attr[1])); + var contentParser = ContentAttrParser(EncodingBytes(attr[1])); var tentativeEncoding = contentParser.parse(); var codec = codecName(tentativeEncoding); if (codec != null) { diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/inputstream.dart index d68327796..dbcf98bce 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/inputstream.dart @@ -14,7 +14,7 @@ class ConsoleSupport { } // TODO(jmesserly): use lazy init here when supported. -ConsoleSupport consoleSupport = new ConsoleSupport(); +ConsoleSupport consoleSupport = ConsoleSupport(); /// Provides a unicode stream of characters to the HtmlTokenizer. /// @@ -88,7 +88,7 @@ class HtmlInputStream { if (_rawBytes == null) { // TODO(jmesserly): we should accept some kind of stream API too. // Unfortunately dart:io InputStream is async only, which won't work. - throw new ArgumentError("'source' must be a String or " + throw ArgumentError("'source' must be a String or " "List<int> (of bytes). You can also pass a RandomAccessFile if you" "`import 'package:html/parser_console.dart'` and call " "`useConsole()`."); @@ -104,7 +104,7 @@ class HtmlInputStream { } void reset() { - errors = new Queue<String>(); + errors = Queue<String>(); _offset = 0; _lineStarts = <int>[0]; @@ -139,7 +139,7 @@ class HtmlInputStream { // TODO(sigmund): Don't parse the file at all if spans aren't being // generated. - fileInfo = new SourceFile.decoded(_chars, url: sourceUrl); + fileInfo = SourceFile.decoded(_chars, url: sourceUrl); } void detectEncoding([bool parseMeta = true]) { @@ -170,7 +170,7 @@ class HtmlInputStream { if (_rawBytes == null) { // We should never get here -- if encoding is certain we won't try to // change it. - throw new StateError('cannot change encoding when parsing a String.'); + throw StateError('cannot change encoding when parsing a String.'); } newEncoding = codecName(newEncoding); @@ -186,7 +186,7 @@ class HtmlInputStream { charEncodingCertain = true; _rawChars = null; reset(); - throw new ReparseException( + throw ReparseException( 'Encoding changed from $charEncodingName to $newEncoding'); } } @@ -212,7 +212,7 @@ class HtmlInputStream { /// Report the encoding declared by the meta element. String detectEncodingMeta() { - var parser = new EncodingParser(slice(_rawBytes, 0, numBytesMeta)); + var parser = EncodingParser(slice(_rawBytes, 0, numBytesMeta)); var encoding = parser.getEncoding(); if (const ['utf-16', 'utf-16-be', 'utf-16-le'].contains(encoding)) { @@ -229,13 +229,13 @@ class HtmlInputStream { /// Read one character from the stream or queue if available. Return /// EOF when EOF is reached. String char() { - if (_offset >= _chars.length) return EOF; - return new String.fromCharCodes([_chars[_offset++]]); + if (_offset >= _chars.length) return eof; + return String.fromCharCodes([_chars[_offset++]]); } String peekChar() { - if (_offset >= _chars.length) return EOF; - return new String.fromCharCodes([_chars[_offset]]); + if (_offset >= _chars.length) return eof; + return String.fromCharCodes([_chars[_offset]]); } /// Returns a string of characters from the stream up to but not @@ -247,7 +247,7 @@ class HtmlInputStream { _offset++; } - return new String.fromCharCodes(_chars.sublist(start, _offset)); + return String.fromCharCodes(_chars.sublist(start, _offset)); } void unget(String ch) { @@ -312,7 +312,7 @@ bool invalidUnicode(int c) { /// Return the python codec name corresponding to an encoding or null if the /// string doesn't correspond to a valid encoding. String codecName(String encoding) { - final asciiPunctuation = new RegExp( + final asciiPunctuation = RegExp( "[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]"); if (encoding == null) return null; diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 38045d474..050370796 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -2,21 +2,20 @@ library html.src.query; import 'package:csslib/parser.dart' as css; -import 'package:csslib/parser.dart' show TokenKind; -import 'package:csslib/src/messages.dart' show Message; +import 'package:csslib/parser.dart' show TokenKind, Message; import 'package:csslib/visitor.dart'; // the CSSOM import 'package:html/dom.dart'; import 'package:html/src/constants.dart' show isWhitespaceCC; bool matches(Node node, String selector) => - new SelectorEvaluator().matches(node, _parseSelectorList(selector)); + SelectorEvaluator().matches(node, _parseSelectorList(selector)); Element querySelector(Node node, String selector) => - new SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); + SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); List<Element> querySelectorAll(Node node, String selector) { var results = <Element>[]; - new SelectorEvaluator() + SelectorEvaluator() .querySelectorAll(node, _parseSelectorList(selector), results); return results; } @@ -26,7 +25,7 @@ SelectorGroup _parseSelectorList(String selector) { var errors = <Message>[]; var group = css.parseSelectorGroup(selector, errors: errors); if (group == null || errors.isNotEmpty) { - throw new FormatException("'$selector' is not a valid selector: $errors"); + throw FormatException("'$selector' is not a valid selector: $errors"); } return group; } @@ -125,11 +124,11 @@ class SelectorEvaluator extends Visitor { } _unimplemented(SimpleSelector selector) => - new UnimplementedError("'$selector' selector of type " + UnimplementedError("'$selector' selector of type " "${selector.runtimeType} is not implemented"); _unsupported(selector) => - new FormatException("'$selector' is not a valid selector"); + FormatException("'$selector' is not a valid selector"); bool visitPseudoClassSelector(PseudoClassSelector selector) { switch (selector.name) { diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 877a6a3e8..ea0a855b3 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -34,8 +34,8 @@ class StartTagToken extends TagToken { StartTagToken(String name, {this.data, - bool selfClosing: false, - this.selfClosingAcknowledged: false, + bool selfClosing = false, + this.selfClosingAcknowledged = false, this.namespace}) : super(name, selfClosing); @@ -43,7 +43,7 @@ class StartTagToken extends TagToken { } class EndTagToken extends TagToken { - EndTagToken(String name, {bool selfClosing: false}) + EndTagToken(String name, {bool selfClosing = false}) : super(name, selfClosing); int get kind => TokenKind.endTag; @@ -63,7 +63,7 @@ abstract class StringToken extends Token { StringToken(string) : _string = string, - _buffer = string == null ? new StringBuffer() : null; + _buffer = string == null ? StringBuffer() : null; StringToken add(String data) { _buffer.write(data); @@ -111,7 +111,7 @@ class DoctypeToken extends Token { String name = ""; bool correct; - DoctypeToken({this.publicId, this.systemId, this.correct: false}); + DoctypeToken({this.publicId, this.systemId, this.correct = false}); int get kind => TokenKind.doctype; } diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 30092a29e..9f02b6c39 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -55,7 +55,7 @@ class HtmlTokenizer implements Iterator<Token> { // bug prevents us from doing that. See http://dartbug.com/12465 Function state; - final StringBuffer _buffer = new StringBuffer(); + final StringBuffer _buffer = StringBuffer(); int _lastOffset; @@ -67,16 +67,15 @@ class HtmlTokenizer implements Iterator<Token> { HtmlTokenizer(doc, {String encoding, - bool parseMeta: true, - this.lowercaseElementName: true, - this.lowercaseAttrName: true, - bool generateSpans: false, + bool parseMeta = true, + this.lowercaseElementName = true, + this.lowercaseAttrName = true, + this.generateSpans = false, String sourceUrl, - this.attributeSpans: false}) - : stream = new HtmlInputStream( - doc, encoding, parseMeta, generateSpans, sourceUrl), - tokenQueue = new Queue(), - generateSpans = generateSpans { + this.attributeSpans = false}) + : stream = + HtmlInputStream(doc, encoding, parseMeta, generateSpans, sourceUrl), + tokenQueue = Queue() { reset(); } @@ -87,8 +86,8 @@ class HtmlTokenizer implements Iterator<Token> { Token _current; Token get current => _current; - final StringBuffer _attributeName = new StringBuffer(); - final StringBuffer _attributeValue = new StringBuffer(); + final StringBuffer _attributeName = StringBuffer(); + final StringBuffer _attributeValue = StringBuffer(); void _markAttributeEnd(int offset) { _attributes.last.value = '$_attributeValue'; @@ -112,7 +111,7 @@ class HtmlTokenizer implements Iterator<Token> { _attributeName.clear(); _attributeName.write(name); _attributeValue.clear(); - var attr = new TagAttribute(); + var attr = TagAttribute(); _attributes.add(attr); if (attributeSpans) attr.start = stream.position - name.length; } @@ -132,7 +131,7 @@ class HtmlTokenizer implements Iterator<Token> { } } if (stream.errors.isNotEmpty) { - _current = new ParseErrorToken(stream.errors.removeFirst()); + _current = ParseErrorToken(stream.errors.removeFirst()); } else { assert(tokenQueue.isNotEmpty); _current = tokenQueue.removeFirst(); @@ -180,7 +179,7 @@ class HtmlTokenizer implements Iterator<Token> { // Consume all the characters that are in range while making sure we // don't hit an EOF. var c = stream.char(); - while (allowed(c) && c != EOF) { + while (allowed(c) && c != eof) { charStack.add(c); c = stream.char(); } @@ -191,12 +190,12 @@ class HtmlTokenizer implements Iterator<Token> { // Certain characters get replaced with others var char = replacementCharacters[charAsInt]; if (char != null) { - _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", + _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } else if ((0xD800 <= charAsInt && charAsInt <= 0xDFFF) || (charAsInt > 0x10FFFF)) { char = "\uFFFD"; - _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", + _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } else { // Should speed up this check somehow (e.g. move the set to a constant) @@ -241,22 +240,22 @@ class HtmlTokenizer implements Iterator<Token> { 0x10FFFE, 0x10FFFF ].contains(charAsInt)) { - _addToken(new ParseErrorToken("illegal-codepoint-for-numeric-entity", + _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", messageParams: {"charAsInt": charAsInt})); } - char = new String.fromCharCodes([charAsInt]); + char = String.fromCharCodes([charAsInt]); } // Discard the ; if present. Otherwise, put it back on the queue and // invoke parseError on parser. if (c != ";") { - _addToken(new ParseErrorToken("numeric-entity-without-semicolon")); + _addToken(ParseErrorToken("numeric-entity-without-semicolon")); stream.unget(c); } return char; } - void consumeEntity({String allowedChar, bool fromAttribute: false}) { + void consumeEntity({String allowedChar, bool fromAttribute = false}) { // Initialise to the default output for when no entity is matched var output = "&"; @@ -264,7 +263,7 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(charStack[0]) || charStack[0] == '<' || charStack[0] == '&' || - charStack[0] == EOF || + charStack[0] == eof || allowedChar == charStack[0]) { stream.unget(charStack[0]); } else if (charStack[0] == "#") { @@ -284,7 +283,7 @@ class HtmlTokenizer implements Iterator<Token> { output = consumeNumberEntity(hex); } else { // No digits found - _addToken(new ParseErrorToken("expected-numeric-entity")); + _addToken(ParseErrorToken("expected-numeric-entity")); stream.unget(charStack.removeLast()); output = "&${charStack.join()}"; } @@ -297,7 +296,7 @@ class HtmlTokenizer implements Iterator<Token> { var filteredEntityList = entitiesByFirstChar[charStack[0]]; if (filteredEntityList == null) filteredEntityList = const []; - while (charStack.last != EOF) { + while (charStack.last != eof) { var name = charStack.join(); filteredEntityList = filteredEntityList.where((e) => e.startsWith(name)).toList(); @@ -327,7 +326,7 @@ class HtmlTokenizer implements Iterator<Token> { if (entityName != null) { var lastChar = entityName[entityName.length - 1]; if (lastChar != ";") { - _addToken(new ParseErrorToken("named-entity-without-semicolon")); + _addToken(ParseErrorToken("named-entity-without-semicolon")); } if (lastChar != ";" && fromAttribute && @@ -341,7 +340,7 @@ class HtmlTokenizer implements Iterator<Token> { output = '${output}${slice(charStack, entityLen).join()}'; } } else { - _addToken(new ParseErrorToken("expected-named-entity")); + _addToken(ParseErrorToken("expected-named-entity")); stream.unget(charStack.removeLast()); output = "&${charStack.join()}"; } @@ -351,9 +350,9 @@ class HtmlTokenizer implements Iterator<Token> { } else { Token token; if (isWhitespace(output)) { - token = new SpaceCharactersToken(output); + token = SpaceCharactersToken(output); } else { - token = new CharactersToken(output); + token = CharactersToken(output); } _addToken(token); } @@ -376,15 +375,15 @@ class HtmlTokenizer implements Iterator<Token> { } if (token is EndTagToken) { if (_attributes != null) { - _addToken(new ParseErrorToken("attributes-in-end-tag")); + _addToken(ParseErrorToken("attributes-in-end-tag")); } if (token.selfClosing) { - _addToken(new ParseErrorToken("this-closing-flag-on-end-tag")); + _addToken(ParseErrorToken("this-closing-flag-on-end-tag")); } } else if (token is StartTagToken) { // HTML5 specific normalizations to the token stream. // Convert the list into a map where first key wins. - token.data = new LinkedHashMap<Object, String>(); + token.data = LinkedHashMap<Object, String>(); if (_attributes != null) { for (var attr in _attributes) { token.data.putIfAbsent(attr.name, () => attr.value); @@ -408,23 +407,23 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "<") { state = tagOpenState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\u0000")); - } else if (data == EOF) { + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\u0000")); + } else if (data == eof) { // Tokenization ends. return false; } else if (isWhitespace(data)) { // Directly after emitting a token you switch back to the "data // state". At that point spaceCharacters are important so they are // emitted separately. - _addToken(new SpaceCharactersToken( + _addToken(SpaceCharactersToken( '${data}${stream.charsUntil(spaceCharacters, true)}')); // No need to update lastFourChars here, since the first space will // have already been appended to lastFourChars and will have broken // any <!-- or --> sequences } else { var chars = stream.charsUntil("&<\u0000"); - _addToken(new CharactersToken('${data}${chars}')); + _addToken(CharactersToken('${data}${chars}')); } return true; } @@ -441,21 +440,21 @@ class HtmlTokenizer implements Iterator<Token> { state = characterReferenceInRcdata; } else if (data == "<") { state = rcdataLessThanSignState; - } else if (data == EOF) { + } else if (data == eof) { // Tokenization ends. return false; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); } else if (isWhitespace(data)) { // Directly after emitting a token you switch back to the "data // state". At that point spaceCharacters are important so they are // emitted separately. - _addToken(new SpaceCharactersToken( + _addToken(SpaceCharactersToken( '${data}${stream.charsUntil(spaceCharacters, true)}')); } else { var chars = stream.charsUntil("&<"); - _addToken(new CharactersToken('${data}${chars}')); + _addToken(CharactersToken('${data}${chars}')); } return true; } @@ -471,14 +470,14 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "<") { state = rawtextLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); - } else if (data == EOF) { + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); + } else if (data == eof) { // Tokenization ends. return false; } else { var chars = stream.charsUntil("<\u0000"); - _addToken(new CharactersToken("${data}${chars}")); + _addToken(CharactersToken("${data}${chars}")); } return true; } @@ -488,28 +487,28 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "<") { state = scriptDataLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); - } else if (data == EOF) { + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); + } else if (data == eof) { // Tokenization ends. return false; } else { var chars = stream.charsUntil("<\u0000"); - _addToken(new CharactersToken("${data}${chars}")); + _addToken(CharactersToken("${data}${chars}")); } return true; } bool plaintextState() { var data = stream.char(); - if (data == EOF) { + if (data == eof) { // Tokenization ends. return false; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); } else { - _addToken(new CharactersToken('${data}${stream.charsUntil("\u0000")}')); + _addToken(CharactersToken('${data}${stream.charsUntil("\u0000")}')); } return true; } @@ -521,24 +520,24 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "/") { state = closeTagOpenState; } else if (isLetter(data)) { - currentToken = new StartTagToken(data); + currentToken = StartTagToken(data); state = tagNameState; } else if (data == ">") { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(new ParseErrorToken("expected-tag-name-but-got-right-bracket")); - _addToken(new CharactersToken("<>")); + _addToken(ParseErrorToken("expected-tag-name-but-got-right-bracket")); + _addToken(CharactersToken("<>")); state = dataState; } else if (data == "?") { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(new ParseErrorToken("expected-tag-name-but-got-question-mark")); + _addToken(ParseErrorToken("expected-tag-name-but-got-question-mark")); stream.unget(data); state = bogusCommentState; } else { // XXX - _addToken(new ParseErrorToken("expected-tag-name")); - _addToken(new CharactersToken("<")); + _addToken(ParseErrorToken("expected-tag-name")); + _addToken(CharactersToken("<")); stream.unget(data); state = dataState; } @@ -548,19 +547,18 @@ class HtmlTokenizer implements Iterator<Token> { bool closeTagOpenState() { var data = stream.char(); if (isLetter(data)) { - currentToken = new EndTagToken(data); + currentToken = EndTagToken(data); state = tagNameState; } else if (data == ">") { - _addToken( - new ParseErrorToken("expected-closing-tag-but-got-right-bracket")); + _addToken(ParseErrorToken("expected-closing-tag-but-got-right-bracket")); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-closing-tag-but-got-eof")); - _addToken(new CharactersToken("</")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-closing-tag-but-got-eof")); + _addToken(CharactersToken("</")); state = dataState; } else { // XXX data can be _'_... - _addToken(new ParseErrorToken("expected-closing-tag-but-got-char", + _addToken(ParseErrorToken("expected-closing-tag-but-got-char", messageParams: {"data": data})); stream.unget(data); state = bogusCommentState; @@ -574,13 +572,13 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeAttributeNameState; } else if (data == ">") { emitCurrentToken(); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-tag-name")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-tag-name")); state = dataState; } else if (data == "/") { state = selfClosingStartTagState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentTagToken.name = '${currentTagToken.name}\uFFFD'; } else { currentTagToken.name = '${currentTagToken.name}$data'; @@ -596,7 +594,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.clear(); state = rcdataEndTagOpenState; } else { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); stream.unget(data); state = rcdataState; } @@ -609,7 +607,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = rcdataEndTagNameState; } else { - _addToken(new CharactersToken("</")); + _addToken(CharactersToken("</")); stream.unget(data); state = rcdataState; } @@ -626,19 +624,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(new CharactersToken("</$_buffer")); + _addToken(CharactersToken("</$_buffer")); stream.unget(data); state = rcdataState; } @@ -651,7 +649,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.clear(); state = rawtextEndTagOpenState; } else { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); stream.unget(data); state = rawtextState; } @@ -664,7 +662,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = rawtextEndTagNameState; } else { - _addToken(new CharactersToken("</")); + _addToken(CharactersToken("</")); stream.unget(data); state = rawtextState; } @@ -675,19 +673,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(new CharactersToken("</$_buffer")); + _addToken(CharactersToken("</$_buffer")); stream.unget(data); state = rawtextState; } @@ -700,10 +698,10 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.clear(); state = scriptDataEndTagOpenState; } else if (data == "!") { - _addToken(new CharactersToken("<!")); + _addToken(CharactersToken("<!")); state = scriptDataEscapeStartState; } else { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); stream.unget(data); state = scriptDataState; } @@ -716,7 +714,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = scriptDataEndTagNameState; } else { - _addToken(new CharactersToken("</")); + _addToken(CharactersToken("</")); stream.unget(data); state = scriptDataState; } @@ -727,19 +725,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(new CharactersToken("</$_buffer")); + _addToken(CharactersToken("</$_buffer")); stream.unget(data); state = scriptDataState; } @@ -749,7 +747,7 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapeStartState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataEscapeStartDashState; } else { stream.unget(data); @@ -761,7 +759,7 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapeStartDashState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataEscapedDashDashState; } else { stream.unget(data); @@ -773,18 +771,18 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataEscapedDashState; } else if (data == "<") { state = scriptDataEscapedLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); - } else if (data == EOF) { + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); + } else if (data == eof) { state = dataState; } else { var chars = stream.charsUntil("<-\u0000"); - _addToken(new CharactersToken("${data}${chars}")); + _addToken(CharactersToken("${data}${chars}")); } return true; } @@ -792,18 +790,18 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedDashState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataEscapedDashDashState; } else if (data == "<") { state = scriptDataEscapedLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); state = scriptDataEscapedState; - } else if (data == EOF) { + } else if (data == eof) { state = dataState; } else { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); state = scriptDataEscapedState; } return true; @@ -812,20 +810,20 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedDashDashState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); } else if (data == "<") { state = scriptDataEscapedLessThanSignState; } else if (data == ">") { - _addToken(new CharactersToken(">")); + _addToken(CharactersToken(">")); state = scriptDataState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); state = scriptDataEscapedState; - } else if (data == EOF) { + } else if (data == eof) { state = dataState; } else { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); state = scriptDataEscapedState; } return true; @@ -837,12 +835,12 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.clear(); state = scriptDataEscapedEndTagOpenState; } else if (isLetter(data)) { - _addToken(new CharactersToken("<$data")); + _addToken(CharactersToken("<$data")); _buffer.clear(); _buffer.write(data); state = scriptDataDoubleEscapeStartState; } else { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); stream.unget(data); state = scriptDataEscapedState; } @@ -856,7 +854,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = scriptDataEscapedEndTagNameState; } else { - _addToken(new CharactersToken("</")); + _addToken(CharactersToken("</")); stream.unget(data); state = scriptDataEscapedState; } @@ -867,19 +865,19 @@ class HtmlTokenizer implements Iterator<Token> { var appropriate = _tokenIsAppropriate(); var data = stream.char(); if (isWhitespace(data) && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; } else if (data == "/" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; } else if (data == ">" && appropriate) { - currentToken = new EndTagToken('$_buffer'); + currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(new CharactersToken("</$_buffer")); + _addToken(CharactersToken("</$_buffer")); stream.unget(data); state = scriptDataEscapedState; } @@ -889,14 +887,14 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapeStartState() { var data = stream.char(); if (isWhitespace(data) || data == "/" || data == ">") { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); if ('$_buffer'.toLowerCase() == "script") { state = scriptDataDoubleEscapedState; } else { state = scriptDataEscapedState; } } else if (isLetter(data)) { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); _buffer.write(data); } else { stream.unget(data); @@ -908,19 +906,19 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataDoubleEscapedDashState; } else if (data == "<") { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); state = scriptDataDoubleEscapedLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-script-in-script")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-script-in-script")); state = dataState; } else { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); } return true; } @@ -928,20 +926,20 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedDashState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); state = scriptDataDoubleEscapedDashDashState; } else if (data == "<") { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); state = scriptDataDoubleEscapedLessThanSignState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); state = scriptDataDoubleEscapedState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-script-in-script")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-script-in-script")); state = dataState; } else { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); state = scriptDataDoubleEscapedState; } return true; @@ -952,22 +950,22 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedDashDashState() { var data = stream.char(); if (data == "-") { - _addToken(new CharactersToken("-")); + _addToken(CharactersToken("-")); } else if (data == "<") { - _addToken(new CharactersToken("<")); + _addToken(CharactersToken("<")); state = scriptDataDoubleEscapedLessThanSignState; } else if (data == ">") { - _addToken(new CharactersToken(">")); + _addToken(CharactersToken(">")); state = scriptDataState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); - _addToken(new CharactersToken("\uFFFD")); + _addToken(ParseErrorToken("invalid-codepoint")); + _addToken(CharactersToken("\uFFFD")); state = scriptDataDoubleEscapedState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-script-in-script")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-script-in-script")); state = dataState; } else { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); state = scriptDataDoubleEscapedState; } return true; @@ -976,7 +974,7 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedLessThanSignState() { var data = stream.char(); if (data == "/") { - _addToken(new CharactersToken("/")); + _addToken(CharactersToken("/")); _buffer.clear(); state = scriptDataDoubleEscapeEndState; } else { @@ -989,14 +987,14 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapeEndState() { var data = stream.char(); if (isWhitespace(data) || data == "/" || data == ">") { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); if ('$_buffer'.toLowerCase() == "script") { state = scriptDataEscapedState; } else { state = scriptDataDoubleEscapedState; } } else if (isLetter(data)) { - _addToken(new CharactersToken(data)); + _addToken(CharactersToken(data)); _buffer.write(data); } else { stream.unget(data); @@ -1016,15 +1014,15 @@ class HtmlTokenizer implements Iterator<Token> { emitCurrentToken(); } else if (data == "/") { state = selfClosingStartTagState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-attribute-name-but-got-eof")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-attribute-name-but-got-eof")); state = dataState; } else if ("'\"=<".contains(data)) { - _addToken(new ParseErrorToken("invalid-character-in-attribute-name")); + _addToken(ParseErrorToken("invalid-character-in-attribute-name")); _addAttribute(data); state = attributeNameState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _addAttribute("\uFFFD"); state = attributeNameState; } else { @@ -1054,14 +1052,14 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "/") { state = selfClosingStartTagState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _attributeName.write('\uFFFD'); leavingThisState = false; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-attribute-name")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-attribute-name")); state = dataState; } else if ("'\"<".contains(data)) { - _addToken(new ParseErrorToken("invalid-character-in-attribute-name")); + _addToken(ParseErrorToken("invalid-character-in-attribute-name")); _attributeName.write(data); leavingThisState = false; } else { @@ -1080,9 +1078,9 @@ class HtmlTokenizer implements Iterator<Token> { attrName = asciiUpper2Lower(attrName); } _attributes.last.name = attrName; - if (_attributeNames == null) _attributeNames = new Set(); + if (_attributeNames == null) _attributeNames = Set(); if (_attributeNames.contains(attrName)) { - _addToken(new ParseErrorToken("duplicate-attribute")); + _addToken(ParseErrorToken("duplicate-attribute")); } _attributeNames.add(attrName); @@ -1108,14 +1106,14 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "/") { state = selfClosingStartTagState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _addAttribute("\uFFFD"); state = attributeNameState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-end-of-tag-but-got-eof")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-end-of-tag-but-got-eof")); state = dataState; } else if ("'\"<".contains(data)) { - _addToken(new ParseErrorToken("invalid-character-after-attribute-name")); + _addToken(ParseErrorToken("invalid-character-after-attribute-name")); _addAttribute(data); state = attributeNameState; } else { @@ -1140,19 +1138,19 @@ class HtmlTokenizer implements Iterator<Token> { _markAttributeValueStart(0); state = attributeValueSingleQuotedState; } else if (data == ">") { - _addToken(new ParseErrorToken( - "expected-attribute-value-but-got-right-bracket")); + _addToken( + ParseErrorToken("expected-attribute-value-but-got-right-bracket")); emitCurrentToken(); } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _markAttributeValueStart(-1); _attributeValue.write('\uFFFD'); state = attributeValueUnQuotedState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-attribute-value-but-got-eof")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-attribute-value-but-got-eof")); state = dataState; } else if ("=<`".contains(data)) { - _addToken(new ParseErrorToken("equals-in-unquoted-attribute-value")); + _addToken(ParseErrorToken("equals-in-unquoted-attribute-value")); _markAttributeValueStart(-1); _attributeValue.write(data); state = attributeValueUnQuotedState; @@ -1173,10 +1171,10 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "&") { processEntityInAttribute('"'); } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _attributeValue.write('\uFFFD'); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-attribute-value-double-quote")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-attribute-value-double-quote")); _markAttributeValueEnd(-1); state = dataState; } else { @@ -1195,10 +1193,10 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "&") { processEntityInAttribute("'"); } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _attributeValue.write('\uFFFD'); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-attribute-value-single-quote")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-attribute-value-single-quote")); _markAttributeValueEnd(-1); state = dataState; } else { @@ -1218,16 +1216,16 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == ">") { _markAttributeValueEnd(-1); emitCurrentToken(); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-attribute-value-no-quotes")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-attribute-value-no-quotes")); _markAttributeValueEnd(-1); state = dataState; } else if ('"\'=<`'.contains(data)) { - _addToken(new ParseErrorToken( - "unexpected-character-in-unquoted-attribute-value")); + _addToken( + ParseErrorToken("unexpected-character-in-unquoted-attribute-value")); _attributeValue.write(data); } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); _attributeValue.write('\uFFFD'); } else { _attributeValue.write(data); @@ -1244,13 +1242,12 @@ class HtmlTokenizer implements Iterator<Token> { emitCurrentToken(); } else if (data == "/") { state = selfClosingStartTagState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("unexpected-EOF-after-attribute-value")); + } else if (data == eof) { + _addToken(ParseErrorToken("unexpected-EOF-after-attribute-value")); stream.unget(data); state = dataState; } else { - _addToken( - new ParseErrorToken("unexpected-character-after-attribute-value")); + _addToken(ParseErrorToken("unexpected-character-after-attribute-value")); stream.unget(data); state = beforeAttributeNameState; } @@ -1262,13 +1259,12 @@ class HtmlTokenizer implements Iterator<Token> { if (data == ">") { currentTagToken.selfClosing = true; emitCurrentToken(); - } else if (data == EOF) { - _addToken(new ParseErrorToken("unexpected-EOF-after-solidus-in-tag")); + } else if (data == eof) { + _addToken(ParseErrorToken("unexpected-EOF-after-solidus-in-tag")); stream.unget(data); state = dataState; } else { - _addToken( - new ParseErrorToken("unexpected-character-after-soldius-in-tag")); + _addToken(ParseErrorToken("unexpected-character-after-soldius-in-tag")); stream.unget(data); state = beforeAttributeNameState; } @@ -1281,7 +1277,7 @@ class HtmlTokenizer implements Iterator<Token> { // and emit it. var data = stream.charsUntil(">"); data = data.replaceAll("\u0000", "\uFFFD"); - _addToken(new CommentToken(data)); + _addToken(CommentToken(data)); // Eat the character directly after the bogus comment which is either a // ">" or an EOF. @@ -1295,7 +1291,7 @@ class HtmlTokenizer implements Iterator<Token> { if (charStack.last == "-") { charStack.add(stream.char()); if (charStack.last == "-") { - currentToken = new CommentToken(); + currentToken = CommentToken(); state = commentStartState; return true; } @@ -1304,13 +1300,13 @@ class HtmlTokenizer implements Iterator<Token> { for (var expected in const ['oO', 'cC', 'tT', 'yY', 'pP', 'eE']) { var char = stream.char(); charStack.add(char); - if (char == EOF || !expected.contains(char)) { + if (char == eof || !expected.contains(char)) { matched = false; break; } } if (matched) { - currentToken = new DoctypeToken(correct: true); + currentToken = DoctypeToken(correct: true); state = doctypeState; return true; } @@ -1333,7 +1329,7 @@ class HtmlTokenizer implements Iterator<Token> { } } - _addToken(new ParseErrorToken("expected-dashes-or-doctype")); + _addToken(ParseErrorToken("expected-dashes-or-doctype")); while (charStack.isNotEmpty) { stream.unget(charStack.removeLast()); @@ -1347,14 +1343,14 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "-") { state = commentStartDashState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('\uFFFD'); } else if (data == ">") { - _addToken(new ParseErrorToken("incorrect-comment")); + _addToken(ParseErrorToken("incorrect-comment")); _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment")); _addToken(currentToken); state = dataState; } else { @@ -1369,14 +1365,14 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "-") { state = commentEndState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('-\uFFFD'); } else if (data == ">") { - _addToken(new ParseErrorToken("incorrect-comment")); + _addToken(ParseErrorToken("incorrect-comment")); _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment")); _addToken(currentToken); state = dataState; } else { @@ -1391,10 +1387,10 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "-") { state = commentEndDashState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('\uFFFD'); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment")); _addToken(currentToken); state = dataState; } else { @@ -1408,11 +1404,11 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "-") { state = commentEndState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('-\uFFFD'); state = commentState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment-end-dash")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment-end-dash")); _addToken(currentToken); state = dataState; } else { @@ -1428,24 +1424,24 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('--\uFFFD'); state = commentState; } else if (data == "!") { _addToken( - new ParseErrorToken("unexpected-bang-after-double-dash-in-comment")); + ParseErrorToken("unexpected-bang-after-double-dash-in-comment")); state = commentEndBangState; } else if (data == "-") { _addToken( - new ParseErrorToken("unexpected-dash-after-double-dash-in-comment")); + ParseErrorToken("unexpected-dash-after-double-dash-in-comment")); currentStringToken.add(data); - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment-double-dash")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment-double-dash")); _addToken(currentToken); state = dataState; } else { // XXX - _addToken(new ParseErrorToken("unexpected-char-in-comment")); + _addToken(ParseErrorToken("unexpected-char-in-comment")); currentStringToken.add('--').add(data); state = commentState; } @@ -1461,11 +1457,11 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.add('--!'); state = commentEndDashState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentStringToken.add('--!\uFFFD'); state = commentState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-comment-end-bang-state")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-comment-end-bang-state")); _addToken(currentToken); state = dataState; } else { @@ -1479,13 +1475,13 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { state = beforeDoctypeNameState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-doctype-name-but-got-eof")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-doctype-name-but-got-eof")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("need-space-after-doctype")); + _addToken(ParseErrorToken("need-space-after-doctype")); stream.unget(data); state = beforeDoctypeNameState; } @@ -1497,17 +1493,16 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == ">") { - _addToken( - new ParseErrorToken("expected-doctype-name-but-got-right-bracket")); + _addToken(ParseErrorToken("expected-doctype-name-but-got-right-bracket")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.name = "\uFFFD"; state = doctypeNameState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("expected-doctype-name-but-got-eof")); + } else if (data == eof) { + _addToken(ParseErrorToken("expected-doctype-name-but-got-eof")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1528,11 +1523,11 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.name = "${currentDoctypeToken.name}\uFFFD"; state = doctypeNameState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype-name")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype-name")); currentDoctypeToken.correct = false; currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); _addToken(currentToken); @@ -1550,10 +1545,10 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == ">") { _addToken(currentToken); state = dataState; - } else if (data == EOF) { + } else if (data == eof) { currentDoctypeToken.correct = false; stream.unget(data); - _addToken(new ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken("eof-in-doctype")); _addToken(currentToken); state = dataState; } else { @@ -1562,7 +1557,7 @@ class HtmlTokenizer implements Iterator<Token> { var matched = true; for (var expected in const ["uU", "bB", "lL", "iI", "cC"]) { data = stream.char(); - if (data == EOF || !expected.contains(data)) { + if (data == eof || !expected.contains(data)) { matched = false; break; } @@ -1575,7 +1570,7 @@ class HtmlTokenizer implements Iterator<Token> { var matched = true; for (var expected in const ["yY", "sS", "tT", "eE", "mM"]) { data = stream.char(); - if (data == EOF || !expected.contains(data)) { + if (data == eof || !expected.contains(data)) { matched = false; break; } @@ -1591,8 +1586,7 @@ class HtmlTokenizer implements Iterator<Token> { // discarded; only the latest character might be '>' or EOF // and needs to be ungetted stream.unget(data); - _addToken(new ParseErrorToken( - "expected-space-or-right-bracket-in-doctype", + _addToken(ParseErrorToken("expected-space-or-right-bracket-in-doctype", messageParams: {"data": data})); currentDoctypeToken.correct = false; state = bogusDoctypeState; @@ -1605,11 +1599,11 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypePublicIdentifierState; } else if (data == "'" || data == '"') { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); stream.unget(data); state = beforeDoctypePublicIdentifierState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1631,17 +1625,17 @@ class HtmlTokenizer implements Iterator<Token> { currentDoctypeToken.publicId = ""; state = doctypePublicIdentifierSingleQuotedState; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-end-of-doctype")); + _addToken(ParseErrorToken("unexpected-end-of-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1653,15 +1647,15 @@ class HtmlTokenizer implements Iterator<Token> { if (data == '"') { state = afterDoctypePublicIdentifierState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.publicId = "${currentDoctypeToken.publicId}\uFFFD"; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-end-of-doctype")); + _addToken(ParseErrorToken("unexpected-end-of-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1676,15 +1670,15 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "'") { state = afterDoctypePublicIdentifierState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.publicId = "${currentDoctypeToken.publicId}\uFFFD"; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-end-of-doctype")); + _addToken(ParseErrorToken("unexpected-end-of-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1702,20 +1696,20 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == '"') { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.systemId = ""; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.systemId = ""; state = doctypeSystemIdentifierSingleQuotedState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1735,13 +1729,13 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == "'") { currentDoctypeToken.systemId = ""; state = doctypeSystemIdentifierSingleQuotedState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1753,11 +1747,11 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypeSystemIdentifierState; } else if (data == "'" || data == '"') { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); stream.unget(data); state = beforeDoctypeSystemIdentifierState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1779,17 +1773,17 @@ class HtmlTokenizer implements Iterator<Token> { currentDoctypeToken.systemId = ""; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1801,15 +1795,15 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "\"") { state = afterDoctypeSystemIdentifierState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.systemId = "${currentDoctypeToken.systemId}\uFFFD"; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-end-of-doctype")); + _addToken(ParseErrorToken("unexpected-end-of-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1824,15 +1818,15 @@ class HtmlTokenizer implements Iterator<Token> { if (data == "'") { state = afterDoctypeSystemIdentifierState; } else if (data == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); currentDoctypeToken.systemId = "${currentDoctypeToken.systemId}\uFFFD"; } else if (data == ">") { - _addToken(new ParseErrorToken("unexpected-end-of-doctype")); + _addToken(ParseErrorToken("unexpected-end-of-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1849,13 +1843,13 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == ">") { _addToken(currentToken); state = dataState; - } else if (data == EOF) { - _addToken(new ParseErrorToken("eof-in-doctype")); + } else if (data == eof) { + _addToken(ParseErrorToken("eof-in-doctype")); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(new ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken("unexpected-char-in-doctype")); state = bogusDoctypeState; } return true; @@ -1866,7 +1860,7 @@ class HtmlTokenizer implements Iterator<Token> { if (data == ">") { _addToken(currentToken); state = dataState; - } else if (data == EOF) { + } else if (data == eof) { // XXX EMIT stream.unget(data); _addToken(currentToken); @@ -1880,12 +1874,12 @@ class HtmlTokenizer implements Iterator<Token> { int matchedEnd = 0; while (true) { var ch = stream.char(); - if (ch == EOF) { + if (ch == eof) { break; } // Deal with null here rather than in the parser if (ch == "\u0000") { - _addToken(new ParseErrorToken("invalid-codepoint")); + _addToken(ParseErrorToken("invalid-codepoint")); ch = "\uFFFD"; } data.add(ch); @@ -1905,7 +1899,7 @@ class HtmlTokenizer implements Iterator<Token> { } if (data.isNotEmpty) { - _addToken(new CharactersToken(data.join())); + _addToken(CharactersToken(data.join())); } state = dataState; return true; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 12cdbbb20..f6db7ad73 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -72,7 +72,7 @@ class TreeBuilder { final List<Element> openElements = <Element>[]; - final activeFormattingElements = new ActiveFormattingElements(); + final activeFormattingElements = ActiveFormattingElements(); Node headPointer; @@ -97,7 +97,7 @@ class TreeBuilder { insertFromTable = false; - document = new Document(); + document = Document(); } bool elementInScope(target, {String variant}) { @@ -111,29 +111,29 @@ class TreeBuilder { if (variant != null) { switch (variant) { case "button": - listElements2 = const [const Pair(Namespaces.html, "button")]; + listElements2 = const [Pair(Namespaces.html, "button")]; break; case "list": listElements2 = const [ - const Pair(Namespaces.html, "ol"), - const Pair(Namespaces.html, "ul") + Pair(Namespaces.html, "ol"), + Pair(Namespaces.html, "ul") ]; break; case "table": listElements1 = const [ - const Pair(Namespaces.html, "html"), - const Pair(Namespaces.html, "table") + Pair(Namespaces.html, "html"), + Pair(Namespaces.html, "table") ]; break; case "select": listElements1 = const [ - const Pair(Namespaces.html, "optgroup"), - const Pair(Namespaces.html, "option") + Pair(Namespaces.html, "optgroup"), + Pair(Namespaces.html, "option") ]; invert = true; break; default: - throw new StateError('We should never reach this point'); + throw StateError('We should never reach this point'); } } @@ -148,7 +148,7 @@ class TreeBuilder { } } - throw new StateError('We should never reach this point'); + throw StateError('We should never reach this point'); } void reconstructActiveFormattingElements() { @@ -188,9 +188,9 @@ class TreeBuilder { entry = activeFormattingElements[i]; // TODO(jmesserly): optimize this. No need to create a token. - var cloneToken = new StartTagToken(entry.localName, + var cloneToken = StartTagToken(entry.localName, namespace: entry.namespaceUri, - data: new LinkedHashMap.from(entry.attributes)) + data: LinkedHashMap.from(entry.attributes)) ..span = entry.sourceSpan; // Step 9 @@ -236,7 +236,7 @@ class TreeBuilder { } void insertDoctype(DoctypeToken token) { - var doctype = new DocumentType(token.name, token.publicId, token.systemId) + var doctype = DocumentType(token.name, token.publicId, token.systemId) ..sourceSpan = token.span; document.nodes.add(doctype); } @@ -245,7 +245,7 @@ class TreeBuilder { if (parent == null) { parent = openElements.last; } - parent.nodes.add(new Comment(token.data)..sourceSpan = token.span); + parent.nodes.add(Comment(token.data)..sourceSpan = token.span); } /// Create an element but don't insert it anywhere @@ -329,7 +329,7 @@ class TreeBuilder { span.file.span(last.sourceSpan.start.offset, span.end.offset); } } else { - nodes.add(new Text(data)..sourceSpan = span); + nodes.add(Text(data)..sourceSpan = span); } } else { int index = nodes.indexOf(refNode); @@ -337,7 +337,7 @@ class TreeBuilder { Text last = nodes[index - 1]; last.appendData(data); } else { - nodes.insert(index, new Text(data)..sourceSpan = span); + nodes.insert(index, Text(data)..sourceSpan = span); } } } @@ -391,7 +391,7 @@ class TreeBuilder { /// Return the final fragment. DocumentFragment getFragment() { //XXX assert innerHTML - var fragment = new DocumentFragment(); + var fragment = DocumentFragment(); openElements[0].reparentChildren(fragment); return fragment; } diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 909b89962..6d25b5984 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -12,6 +12,7 @@ class Pair<F, S> { const Pair(this.first, this.second); int get hashCode => 37 * first.hashCode + second.hashCode; + bool operator ==(other) => other.first == first && other.second == second; } @@ -62,7 +63,7 @@ bool allWhitespace(String str) { String padWithZeros(String str, int size) { if (str.length == size) return str; - var result = new StringBuffer(); + var result = StringBuffer(); size -= str.length; for (int i = 0; i < size; i++) result.write('0'); result.write(str); @@ -77,9 +78,11 @@ String padWithZeros(String str, int size) { String formatStr(String format, Map data) { if (data == null) return format; data.forEach((key, value) { - var result = new StringBuffer(); + var result = StringBuffer(); var search = '%($key)'; int last = 0, match; + // This is a bug in the linter + // ignore: prefer_contains while ((match = format.indexOf(search, last)) >= 0) { result.write(format.substring(last, match)); match += search.length; @@ -107,8 +110,8 @@ String formatStr(String format, Map data) { result.write(padWithZeros(number, numberSize)); break; default: - throw "not implemented: formatStr does not support format " - "character ${format[match]}"; + throw UnsupportedError("formatStr does not support format " + "character ${format[match]}"); } last = match + 1; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 7aeb9ba8e..3a43cda2c 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,12 +1,12 @@ name: html -version: 0.13.3+3 +version: 0.13.4-dev -description: A library for working with HTML documents. Previously known as html5lib. +description: A library for working with HTML documents. author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/html environment: - sdk: '>=2.0.0-dev.17.0 <3.0.0' + sdk: '>=2.0.0 <3.0.0' dependencies: csslib: '>=0.13.2 <0.15.0' @@ -15,4 +15,5 @@ dependencies: dev_dependencies: path: ^1.6.2 + pedantic: ^1.3.0 test: ^1.3.0 diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 671d0b107..1cf912e79 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -8,8 +8,8 @@ import 'package:html/parser.dart'; main() { group('Element', () { test('classes', () { - final barBaz = new Element.html('<div class=" bar baz"></div>'); - final quxBaz = new Element.html('<div class="qux baz "></div>'); + final barBaz = Element.html('<div class=" bar baz"></div>'); + final quxBaz = Element.html('<div class="qux baz "></div>'); expect(barBaz.className, ' bar baz'); expect(quxBaz.className, 'qux baz '); expect(barBaz.classes, ['bar', 'baz']); @@ -25,11 +25,11 @@ main() { test('getElementById', () { var foo = doc.body.nodes[0]; - var Foo = foo.nodes[2]; + var fooVar = foo.nodes[2]; expect((foo as Element).id, 'foo'); - expect((Foo as Element).id, 'Foo'); + expect((fooVar as Element).id, 'Foo'); expect(doc.getElementById('foo'), foo); - expect(doc.getElementById('Foo'), Foo); + expect(doc.getElementById('Foo'), fooVar); }); test('getElementsByClassName', () { @@ -48,8 +48,8 @@ main() { var foo = doc.body.nodes[0]; var barBaz = foo.nodes[0]; var quxBaz = foo.nodes[1]; - var Foo = foo.nodes[2]; - expect(doc.getElementsByTagName('div'), [foo, barBaz, quxBaz, Foo]); + var fooVar = foo.nodes[2]; + expect(doc.getElementsByTagName('div'), [foo, barBaz, quxBaz, fooVar]); }); }); diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 45c704c02..c112717d6 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -24,17 +24,17 @@ main() { }); test('namespace html elements on', () { - var doc = new HtmlParser('', tree: new TreeBuilder(true)).parse(); + var doc = HtmlParser('', tree: TreeBuilder(true)).parse(); expect((doc.nodes[0] as Element).namespaceUri, Namespaces.html); }); test('namespace html elements off', () { - var doc = new HtmlParser('', tree: new TreeBuilder(false)).parse(); + var doc = HtmlParser('', tree: TreeBuilder(false)).parse(); expect((doc.nodes[0] as Element).namespaceUri, null); }); test('parse error spans - full', () { - var parser = new HtmlParser(''' + var parser = HtmlParser(''' <!DOCTYPE html> <html> <body> @@ -62,7 +62,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('parse error spans - minimal', () { - var parser = new HtmlParser(''' + var parser = HtmlParser(''' <!DOCTYPE html> <html> <body> @@ -85,7 +85,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. var html = '<body><div>$textContent</div>'; var doc = parse(html, generateSpans: true); Text text = doc.body.nodes[0].nodes[0]; - expect(text, new TypeMatcher<Text>()); + expect(text, const TypeMatcher<Text>()); expect(text.data, textContent); expect(text.sourceSpan.start.offset, html.indexOf(textContent)); expect(text.sourceSpan.length, textContent.length); @@ -229,7 +229,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. '''); var n = doc.querySelector('desc'); var keys = n.attributes.keys.toList(); - expect(keys[0], new TypeMatcher<AttributeName>()); + expect(keys[0], const TypeMatcher<AttributeName>()); expect(keys[0].prefix, 'xlink'); expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); expect(keys[0].name, 'type'); @@ -242,7 +242,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('error printing without spans', () { - var parser = new HtmlParser('foo'); + var parser = HtmlParser('foo'); var doc = parser.parse(); expect(doc.body.innerHtml, 'foo'); expect(parser.errors.length, 1); @@ -299,7 +299,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('foreignObject end tag', () { - var p = new HtmlParser(''' + var p = HtmlParser(''' <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1"> <foreignObject width="320px" height="200px"> @@ -313,7 +313,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); group('Encoding pre-parser', () { - getEncoding(String s) => new EncodingParser(s.codeUnits).getEncoding(); + getEncoding(String s) => EncodingParser(s.codeUnits).getEncoding(); test('gets encoding from meta charset', () { expect(getEncoding('<meta charset="utf-16">'), 'utf-16'); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index c0a96cbff..1289f6181 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -20,7 +20,7 @@ String namespaceHtml(String expected) { // We can't do regex replace directly =\ // final namespaceExpected = new RegExp(@"^(\s*)<(\S+)>", multiLine: true); // return expected.replaceAll(namespaceExpected, @"$1<html $2>"); - final namespaceExpected = new RegExp(r"^(\|\s*)<(\S+)>"); + final namespaceExpected = RegExp(r"^(\|\s*)<(\S+)>"); var lines = expected.split("\n"); for (int i = 0; i < lines.length; i++) { var match = namespaceExpected.firstMatch(lines[i]); @@ -42,7 +42,7 @@ void runParserTest( // XXX - move this out into the setup function // concatenate all consecutive character tokens into a single token var builder = treeCtor(namespaceHTMLElements); - var parser = new HtmlParser(input, tree: builder); + var parser = HtmlParser(input, tree: builder); Node document; if (innerHTML != null) { @@ -74,9 +74,9 @@ void main() { test('dart:io', () { // ensure IO support is unregistered expect(inputstream.consoleSupport, - new TypeMatcher<inputstream.ConsoleSupport>()); - var file = new File('$testDataDir/parser_feature/raw_file.html').openSync(); - expect(() => parse(file), throwsA(new TypeMatcher<ArgumentError>())); + const TypeMatcher<inputstream.ConsoleSupport>()); + var file = File('$testDataDir/parser_feature/raw_file.html').openSync(); + expect(() => parse(file), throwsA(const TypeMatcher<ArgumentError>())); parser_console.useConsole(); expect(parse(file).body.innerHtml.trim(), 'Hello world!'); }); @@ -84,7 +84,7 @@ void main() { for (var path in getDataFiles('tree-construction')) { if (!path.endsWith('.dat')) continue; - var tests = new TestData(path, "data"); + var tests = TestData(path, "data"); var testName = pathos.basenameWithoutExtension(path); group(testName, () { @@ -114,9 +114,9 @@ void main() { _nameFor(String input) { // Using jsonDecode to unescape other unicode characters var escapeQuote = input - .replaceAll(new RegExp('\\\\.'), '_') - .replaceAll(new RegExp('\u0000'), '_') + .replaceAll(RegExp('\\\\.'), '_') + .replaceAll(RegExp('\u0000'), '_') .replaceAll('"', '\\"') - .replaceAll(new RegExp('[\n\r\t]'), '_'); + .replaceAll(RegExp('[\n\r\t]'), '_'); return jsonDecode('"$escapeQuote"'); } diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 9066842c2..7ed1cc4da 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -19,10 +19,10 @@ import 'selectors.dart'; Document getTestContentDocument() { var testPath = p.join(testDir, 'selectors', 'level1-content.html'); - return parse(new File(testPath).readAsStringSync()); + return parse(File(testPath).readAsStringSync()); } -var testType = TEST_QSA_BASELINE; // Only run baseline tests. +var testType = testQsaBaseline; // Only run baseline tests. var docType = "html"; // Only run tests suitable for HTML main() { diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 4ffa9a8ed..d87c7951a 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -208,7 +208,7 @@ runValidSelectorTest(String type, root, List<Map<String, dynamic>> selectors, nodeType = "fragment"; break; default: - throw new StateError("Reached unreachable code path."); + throw StateError("Reached unreachable code path."); } for (var i = 0; i < selectors.length; i++) { diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index d25b14bf2..9810f5f07 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -3,16 +3,16 @@ library html.test.selectors.selectors; // Bit-mapped flags to indicate which tests the selector is suitable for -var TEST_QSA_BASELINE = +final testQsaBaseline = 0x01; // querySelector() and querySelectorAll() baseline tests -var TEST_QSA_ADDITIONAL = +final testQsaAdditional = 0x02; // querySelector() and querySelectorAll() additional tests -var TEST_FIND_BASELINE = +final testFindBaseline = 0x04; // find() and findAll() baseline tests, may be unsuitable for querySelector[All] -var TEST_FIND_ADDITIONAL = +final testFindAdditional = 0x08; // find() and findAll() additional tests, may be unsuitable for querySelector[All] -var TEST_MATCH_BASELINE = 0x10; // matches() baseline tests -var TEST_MATCH_ADDITIONAL = 0x20; // matches() additional tests +final testMatchBaseline = 0x10; // matches() baseline tests +var testMatchAdditional = 0x20; // matches() additional tests /* * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. @@ -20,7 +20,7 @@ var TEST_MATCH_ADDITIONAL = 0x20; // matches() additional tests * name: A descriptive name of the selector being tested * selector: The selector to test */ -var invalidSelectors = [ +final invalidSelectors = [ {'name': "Empty String", 'selector': ""}, {'name': "Invalid character", 'selector': "["}, {'name': "Invalid character", 'selector': "]"}, @@ -82,7 +82,7 @@ var validSelectors = [ 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Type selector, matching html element", @@ -90,7 +90,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Type selector, matching body element", @@ -98,7 +98,7 @@ var validSelectors = [ 'expect': ["body"], 'exclude': ["element", "fragment", "detached"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Type selector, matching body element", @@ -106,7 +106,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // Universal Selector @@ -123,7 +123,7 @@ var validSelectors = [ "universal-address1" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -136,7 +136,7 @@ var validSelectors = [ "universal-code2" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -144,7 +144,7 @@ var validSelectors = [ 'selector': "#empty>*", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -163,7 +163,7 @@ var validSelectors = [ "universal-a2" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // Attribute Selectors @@ -173,7 +173,7 @@ var validSelectors = [ 'selector': ".attr-presence-div1[align]", 'expect': ["attr-presence-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -181,7 +181,7 @@ var validSelectors = [ 'selector': ".attr-presence-div2[align]", 'expect': ["attr-presence-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -190,7 +190,7 @@ var validSelectors = [ 'expect': ["attr-presence-a1", "attr-presence-span1"], 'exclude': ["xhtml"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -199,14 +199,14 @@ var validSelectors = [ 'expect': [], 'exclude': ["html"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Attribute presence selector, matching custom data-* attribute", 'selector': "[data-attr-presence]", 'expect': ["attr-presence-pre1", "attr-presence-blockquote1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -214,7 +214,7 @@ var validSelectors = [ 'selector': ".attr-presence-div3[align], .attr-presence-div4[align]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -222,7 +222,7 @@ var validSelectors = [ 'selector': "ul[data-中文]", 'expect': ["attr-presence-ul1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -230,7 +230,7 @@ var validSelectors = [ 'selector': "#attr-presence-select1 option[selected]", 'expect': [] /* no matches */, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -238,7 +238,7 @@ var validSelectors = [ 'selector': "#attr-presence-select2 option[selected]", 'expect': ["attr-presence-select2-option4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -249,7 +249,7 @@ var validSelectors = [ "attr-presence-select3-option3" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - value [att=val] @@ -258,7 +258,7 @@ var validSelectors = [ 'selector': "#attr-value [align=\"center\"]", 'expect': ["attr-value-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -266,7 +266,7 @@ var validSelectors = [ 'selector': "#attr-value [align=\"\"]", 'expect': ["attr-value-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -274,7 +274,7 @@ var validSelectors = [ 'selector': "#attr-value [align=\"c\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -282,7 +282,7 @@ var validSelectors = [ 'selector': "#attr-value [align=\"centera\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -290,7 +290,7 @@ var validSelectors = [ 'selector': "[data-attr-value=\"\\e9\"]", 'expect': ["attr-value-div3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -298,7 +298,7 @@ var validSelectors = [ 'selector': "[data-attr-value\_foo=\"\\e9\"]", 'expect': ["attr-value-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -313,7 +313,7 @@ var validSelectors = [ "attr-value-input9" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -328,7 +328,7 @@ var validSelectors = [ "attr-value-input9" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -342,7 +342,7 @@ var validSelectors = [ "attr-value-input9" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -350,7 +350,7 @@ var validSelectors = [ 'selector': "[data-attr-value=中文]", 'expect': ["attr-value-div5"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - whitespace-separated list [att~=val] @@ -360,7 +360,7 @@ var validSelectors = [ 'selector': "#attr-whitespace [class~=\"div1\"]", 'expect': ["attr-whitespace-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -368,7 +368,7 @@ var validSelectors = [ 'selector': "#attr-whitespace [class~=\"\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -376,7 +376,7 @@ var validSelectors = [ 'selector': "[data-attr-whitespace~=\"div\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -384,7 +384,7 @@ var validSelectors = [ 'selector': "[data-attr-whitespace~=\"\\0000e9\"]", 'expect': ["attr-whitespace-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -392,7 +392,7 @@ var validSelectors = [ 'selector': "[data-attr-whitespace\_foo~=\"\\e9\"]", 'expect': ["attr-whitespace-div5"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -407,7 +407,7 @@ var validSelectors = [ "attr-whitespace-a7" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -422,7 +422,7 @@ var validSelectors = [ "attr-whitespace-a7" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -437,7 +437,7 @@ var validSelectors = [ "attr-whitespace-a7" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -445,7 +445,7 @@ var validSelectors = [ 'selector': "#attr-whitespace a[rel~=\"book mark\"]", 'expect': [] /* no matches */, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -453,7 +453,7 @@ var validSelectors = [ 'selector': "#attr-whitespace [title~=中文]", 'expect': ["attr-whitespace-p1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - hyphen-separated list [att|=val] @@ -463,7 +463,7 @@ var validSelectors = [ 'selector': "#attr-hyphen-div1[lang|=\"en\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -471,7 +471,7 @@ var validSelectors = [ 'selector': "#attr-hyphen-div2[lang|=\"fr\"]", 'expect': ["attr-hyphen-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -479,7 +479,7 @@ var validSelectors = [ 'selector': "#attr-hyphen-div3[lang|=\"en\"]", 'expect': ["attr-hyphen-div3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -487,7 +487,7 @@ var validSelectors = [ 'selector': "#attr-hyphen-div4[lang|=\"es-AR\"]", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // - substring begins-with [att^=val] (Level 3) @@ -497,7 +497,7 @@ var validSelectors = [ 'selector': "#attr-begins a[href^=\"http://www\"]", 'expect': ["attr-begins-a1", "attr-begins-a3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -505,7 +505,7 @@ var validSelectors = [ 'selector': "#attr-begins [lang^=\"en-\"]", 'expect': ["attr-begins-div2", "attr-begins-div4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -513,7 +513,7 @@ var validSelectors = [ 'selector': "#attr-begins [class^=apple]", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': @@ -521,7 +521,7 @@ var validSelectors = [ 'selector': "#attr-begins [class^=' apple']", 'expect': ["attr-begins-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -529,7 +529,7 @@ var validSelectors = [ 'selector': "#attr-begins [class^=\" apple\"]", 'expect': ["attr-begins-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -537,7 +537,7 @@ var validSelectors = [ 'selector': "#attr-begins [class^= apple]", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - substring ends-with [att\$=val] (Level 3) @@ -547,7 +547,7 @@ var validSelectors = [ 'selector': "#attr-ends a[href\$=\".org\"]", 'expect': ["attr-ends-a1", "attr-ends-a3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -555,7 +555,7 @@ var validSelectors = [ 'selector': "#attr-ends [lang\$=\"-CH\"]", 'expect': ["attr-ends-div2", "attr-ends-div4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -563,7 +563,7 @@ var validSelectors = [ 'selector': "#attr-ends [class\$=apple]", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': @@ -571,7 +571,7 @@ var validSelectors = [ 'selector': "#attr-ends [class\$='apple ']", 'expect': ["attr-ends-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -579,7 +579,7 @@ var validSelectors = [ 'selector': "#attr-ends [class\$=\"apple \"]", 'expect': ["attr-ends-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -587,7 +587,7 @@ var validSelectors = [ 'selector': "#attr-ends [class\$=apple ]", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - substring contains [att*=val] (Level 3) @@ -597,7 +597,7 @@ var validSelectors = [ 'selector': "#attr-contains a[href*=\"http://www\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -605,7 +605,7 @@ var validSelectors = [ 'selector': "#attr-contains a[href*=\".org\"]", 'expect': ["attr-contains-a1", "attr-contains-a2"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -613,7 +613,7 @@ var validSelectors = [ 'selector': "#attr-contains a[href*=\".example.\"]", 'expect': ["attr-contains-a1", "attr-contains-a3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -621,7 +621,7 @@ var validSelectors = [ 'selector': "#attr-contains [lang*=\"en-\"]", 'expect': ["attr-contains-div2", "attr-contains-div6"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -629,7 +629,7 @@ var validSelectors = [ 'selector': "#attr-contains [lang*=\"-CH\"]", 'expect': ["attr-contains-div3", "attr-contains-div5"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -637,7 +637,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*=' apple']", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -645,7 +645,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*='orange ']", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -653,7 +653,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*='ple banana ora']", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -661,7 +661,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*=\" apple\"]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -669,7 +669,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*=\"orange \"]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -677,7 +677,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*=\"ple banana ora\"]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -685,7 +685,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*= apple]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -693,7 +693,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*=orange ]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -701,7 +701,7 @@ var validSelectors = [ 'selector': "#attr-contains [class*= banana ]", 'expect': ["attr-contains-p1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // Pseudo-classes @@ -712,7 +712,7 @@ var validSelectors = [ 'expect': ["html"], 'exclude': ["element", "fragment", "detached"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': ":root pseudo-class selector, not matching document root element", @@ -720,7 +720,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - :nth-child(n) (Level 3) @@ -734,7 +734,7 @@ var validSelectors = [ "pseudo-nth-td15" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': ":nth-child selector, matching every third child element", @@ -746,7 +746,7 @@ var validSelectors = [ "pseudo-nth-li12" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -760,7 +760,7 @@ var validSelectors = [ "pseudo-nth-li12" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -768,7 +768,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 :nth-child(4n-1)", 'expect': ["pseudo-nth-em2", "pseudo-nth-span3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-last-child (Level 3) @@ -782,7 +782,7 @@ var validSelectors = [ "pseudo-nth-td16" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -795,7 +795,7 @@ var validSelectors = [ "pseudo-nth-li10" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -809,7 +809,7 @@ var validSelectors = [ "pseudo-nth-li9" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -817,7 +817,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 :nth-last-child(4n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-of-type(n) (Level 3) @@ -826,7 +826,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 em:nth-of-type(3)", 'expect': ["pseudo-nth-em3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -840,7 +840,7 @@ var validSelectors = [ "pseudo-nth-em4" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -848,7 +848,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 span:nth-of-type(2n-1)", 'expect': ["pseudo-nth-span1", "pseudo-nth-span3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-last-of-type(n) (Level 3) @@ -857,7 +857,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 em:nth-last-of-type(3)", 'expect': ["pseudo-nth-em2"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -871,7 +871,7 @@ var validSelectors = [ "pseudo-nth-span3" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -879,7 +879,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :first-of-type (Level 3) @@ -888,7 +888,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 em:first-of-type", 'expect': ["pseudo-nth-em1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -896,7 +896,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 :first-of-type", 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -904,7 +904,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-table1 tr :first-of-type", 'expect': ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :last-of-type (Level 3) @@ -913,7 +913,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 em:last-of-type", 'expect': ["pseudo-nth-em4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -921,7 +921,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-p1 :last-of-type", 'expect': ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -929,7 +929,7 @@ var validSelectors = [ 'selector': "#pseudo-nth-table1 tr :last-of-type", 'expect': ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :first-child @@ -939,7 +939,7 @@ var validSelectors = [ 'selector': "#pseudo-first-child div:first-child", 'expect': ["pseudo-first-child-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -948,7 +948,7 @@ var validSelectors = [ ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -960,7 +960,7 @@ var validSelectors = [ "pseudo-first-child-span5" ], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - :last-child (Level 3) @@ -970,7 +970,7 @@ var validSelectors = [ 'selector': "#pseudo-last-child div:last-child", 'expect': ["pseudo-last-child-div3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -979,7 +979,7 @@ var validSelectors = [ ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': @@ -991,7 +991,7 @@ var validSelectors = [ "pseudo-last-child-span6" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :only-child (Level 3) @@ -1001,7 +1001,7 @@ var validSelectors = [ 'selector': "#pseudo-only :only-child", 'expect': ["pseudo-only-span1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1009,7 +1009,7 @@ var validSelectors = [ 'selector': "#pseudo-only em:only-child", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - :only-of-type (Level 3) @@ -1019,7 +1019,7 @@ var validSelectors = [ 'selector': "#pseudo-only :only-of-type", 'expect': ["pseudo-only-span1", "pseudo-only-em1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1027,7 +1027,7 @@ var validSelectors = [ 'selector': "#pseudo-only em:only-of-type", 'expect': ["pseudo-only-em1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :empty (Level 3) @@ -1036,14 +1036,14 @@ var validSelectors = [ 'selector': "#pseudo-empty p:empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': ":empty pseudo-class selector, matching all empty elements", 'selector': "#pseudo-empty :empty", 'expect': ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :link and :visited @@ -1055,7 +1055,7 @@ var validSelectors = [ 'selector': "#pseudo-link :link, #pseudo-link :visited", 'expect': ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1064,7 +1064,7 @@ var validSelectors = [ 'expect': ["pseudo-link-link1", "pseudo-link-link2"], 'exclude': ["element", "fragment", "detached"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1073,7 +1073,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1082,7 +1082,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // - :target (Level 3) @@ -1093,7 +1093,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': @@ -1102,7 +1102,7 @@ var validSelectors = [ 'expect': ["target"], 'exclude': ["fragment", "detached"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :lang() @@ -1112,7 +1112,7 @@ var validSelectors = [ 'expect': ["pseudo-lang-div1"], 'exclude': ["detached", "fragment"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1121,7 +1121,7 @@ var validSelectors = [ 'expect': [] /*no matches*/, 'exclude': ["document", "element"], 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1129,7 +1129,7 @@ var validSelectors = [ 'selector': "#pseudo-lang-div2:lang(fr)", 'expect': ["pseudo-lang-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1137,14 +1137,14 @@ var validSelectors = [ 'selector': "#pseudo-lang-div3:lang(en)", 'expect': ["pseudo-lang-div3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': ":lang pseudo-class selector, not matching incorrect language", 'selector': "#pseudo-lang-div4:lang(es-AR)", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // - :enabled (Level 3) @@ -1166,7 +1166,7 @@ var validSelectors = [ "pseudo-ui-button1" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :disabled (Level 3) @@ -1188,7 +1188,7 @@ var validSelectors = [ "pseudo-ui-button2" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :checked (Level 3) @@ -1203,7 +1203,7 @@ var validSelectors = [ "pseudo-ui-input15" ], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // - :not(s) (Level 3) @@ -1212,28 +1212,28 @@ var validSelectors = [ 'selector': "#not>:not(div)", 'expect': ["not-p1", "not-p2", "not-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': ":not pseudo-class selector, matching ", 'selector': "#not * :not(:first-child)", 'expect': ["not-em1", "not-em2", "not-em3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*)", 'expect': [] /* no matches */, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': ":not pseudo-class selector, matching nothing", 'selector': ":not(*|*)", 'expect': [] /* no matches */, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // Pseudo-elements @@ -1244,7 +1244,7 @@ var validSelectors = [ 'selector': "#pseudo-element:first-line", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1252,7 +1252,7 @@ var validSelectors = [ 'selector': "#pseudo-element::first-line", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - ::first-letter @@ -1262,7 +1262,7 @@ var validSelectors = [ 'selector': "#pseudo-element:first-letter", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1270,7 +1270,7 @@ var validSelectors = [ 'selector': "#pseudo-element::first-letter", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - ::before @@ -1280,7 +1280,7 @@ var validSelectors = [ 'selector': "#pseudo-element:before", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1288,7 +1288,7 @@ var validSelectors = [ 'selector': "#pseudo-element::before", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // - ::after @@ -1298,7 +1298,7 @@ var validSelectors = [ 'selector': "#pseudo-element:after", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1306,7 +1306,7 @@ var validSelectors = [ 'selector': "#pseudo-element::after", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, // Class Selectors @@ -1315,7 +1315,7 @@ var validSelectors = [ 'selector': ".class-p", 'expect': ["class-p1", "class-p2", "class-p3"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1330,14 +1330,14 @@ var validSelectors = [ "class-div4" ], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Class Selector, chained, with type selector", 'selector': "div.apple.banana.orange", 'expect': ["class-div1", "class-div2", "class-div3", "class-div4"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process. { @@ -1346,7 +1346,7 @@ var validSelectors = [ 'selector': ".台北Táiběi", 'expect': ["class-span1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1354,7 +1354,7 @@ var validSelectors = [ 'selector': ".台北", 'expect': ["class-span1", "class-span2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1362,7 +1362,7 @@ var validSelectors = [ 'selector': ".台北Táiběi.台北", 'expect': ["class-span1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1370,7 +1370,7 @@ var validSelectors = [ 'selector': ".foo\\:bar", 'expect': ["class-span3"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1378,7 +1378,7 @@ var validSelectors = [ 'selector': ".test\\.foo\\[5\\]bar", 'expect': ["class-span4"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // ID Selectors @@ -1387,42 +1387,42 @@ var validSelectors = [ 'selector': "#id #id-div1", 'expect': ["id-div1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div1", 'expect': ["id-div1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID selector, chained, matching element with specified id", 'selector': "#id-div1, #id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID Selector, chained, with type selector", 'selector': "div#id-div1, div#id-div2", 'expect': ["id-div1", "id-div2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID selector, not matching non-existent descendant", 'selector': "#id #none", 'expect': [] /*no matches*/, 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "ID selector, not matching non-existent ancestor", 'selector': "#none #id-div1", 'expect': [] /*no matches*/, 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "ID selector, matching multiple elements with duplicate id", @@ -1434,7 +1434,7 @@ var validSelectors = [ "id-li-duplicate" ], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process. @@ -1443,21 +1443,21 @@ var validSelectors = [ 'selector': "#台北Táiběi", 'expect': ["台北Táiběi"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID selector, matching id value using non-ASCII characters", 'selector': "#台北", 'expect': ["台北"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "ID selector, matching id values using non-ASCII characters", 'selector': "#台北Táiběi, #台北", 'expect': ["台北Táiběi", "台北"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values @@ -1466,14 +1466,14 @@ var validSelectors = [ 'selector': "#\\#foo\\:bar", 'expect': ["#foo:bar"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "ID selector, matching element with id with escaped character", 'selector': "#test\\.foo\\[5\\]bar", 'expect': ["test.foo[5]bar"], 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // Namespaces @@ -1488,21 +1488,21 @@ var validSelectors = [ "any-namespace-div4" ], 'level': 3, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Namespace selector, matching div elements in no namespace only", 'selector': "#no-namespace |div", 'expect': ["no-namespace-div3"], 'level': 3, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Namespace selector, matching any elements in no namespace only", 'selector': "#no-namespace |*", 'expect': ["no-namespace-div3"], 'level': 3, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, // Combinators @@ -1518,7 +1518,7 @@ var validSelectors = [ "descendant-div4" ], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1527,7 +1527,7 @@ var validSelectors = [ 'expect': ["descendant-div1"], 'exclude': ["detached", "fragment"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1535,7 +1535,7 @@ var validSelectors = [ 'selector': "div #descendant-div1", 'expect': ["descendant-div1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1543,7 +1543,7 @@ var validSelectors = [ 'selector': "#descendant #descendant-div2", 'expect': ["descendant-div2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1551,7 +1551,7 @@ var validSelectors = [ 'selector': "#descendant .descendant-div2", 'expect': ["descendant-div2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1559,7 +1559,7 @@ var validSelectors = [ 'selector': ".descendant-div1 .descendant-div3", 'expect': ["descendant-div3"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1567,14 +1567,14 @@ var validSelectors = [ 'selector': "#descendant-div1 #descendant-div4", 'expect': [] /*no matches*/, 'level': 1, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Descendant combinator, whitespace characters", 'selector': "#descendant\t\r\n#descendant-div2", 'expect': ["descendant-div2"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - Child combinator '>' @@ -1584,7 +1584,7 @@ var validSelectors = [ 'selector': "#child>div", 'expect': ["child-div1", "child-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1592,7 +1592,7 @@ var validSelectors = [ 'selector': "div>#child-div1", 'expect': ["child-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1600,7 +1600,7 @@ var validSelectors = [ 'selector': "#child>#child-div1", 'expect': ["child-div1"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1608,7 +1608,7 @@ var validSelectors = [ 'selector': "#child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1616,7 +1616,7 @@ var validSelectors = [ 'selector': ".child-div1>.child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1624,7 +1624,7 @@ var validSelectors = [ 'selector': "#child>#child-div3", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1632,7 +1632,7 @@ var validSelectors = [ 'selector': "#child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': @@ -1640,35 +1640,35 @@ var validSelectors = [ 'selector': ".child-div1>.child-div3", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Child combinator, surrounded by whitespace", 'selector': "#child-div1\t\r\n>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Child combinator, whitespace after", 'selector': "#child-div1>\t\r\n#child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Child combinator, whitespace before", 'selector': "#child-div1\t\r\n>#child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Child combinator, no whitespace", 'selector': "#child-div1>#child-div2", 'expect': ["child-div2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - Adjacent sibling combinator '+' @@ -1678,7 +1678,7 @@ var validSelectors = [ 'selector': "#adjacent-div2+div", 'expect': ["adjacent-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1686,7 +1686,7 @@ var validSelectors = [ 'selector': "div+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1694,7 +1694,7 @@ var validSelectors = [ 'selector': "#adjacent-div2+#adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1702,7 +1702,7 @@ var validSelectors = [ 'selector': "#adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1710,7 +1710,7 @@ var validSelectors = [ 'selector': ".adjacent-div2+.adjacent-div4", 'expect': ["adjacent-div4"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1718,7 +1718,7 @@ var validSelectors = [ 'selector': "#adjacent div+p", 'expect': ["adjacent-p2"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': @@ -1726,35 +1726,35 @@ var validSelectors = [ 'selector': "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", 'expect': [] /*no matches*/, 'level': 2, - 'testType': TEST_QSA_BASELINE + 'testType': testQsaBaseline }, { 'name': "Adjacent sibling combinator, surrounded by whitespace", 'selector': "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Adjacent sibling combinator, whitespace after", 'selector': "#adjacent-p2+\t\r\n#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Adjacent sibling combinator, whitespace before", 'selector': "#adjacent-p2\t\r\n+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Adjacent sibling combinator, no whitespace", 'selector': "#adjacent-p2+#adjacent-p3", 'expect': ["adjacent-p3"], 'level': 2, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, // - General sibling combinator ~ (Level 3) @@ -1764,7 +1764,7 @@ var validSelectors = [ 'selector': "#sibling-div2~div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1772,7 +1772,7 @@ var validSelectors = [ 'selector': "div~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1780,7 +1780,7 @@ var validSelectors = [ 'selector': "#sibling-div2~#sibling-div4", 'expect': ["sibling-div4"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1788,7 +1788,7 @@ var validSelectors = [ 'selector': "#sibling-div2~.sibling-div", 'expect': ["sibling-div4", "sibling-div6"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1796,7 +1796,7 @@ var validSelectors = [ 'selector': "#sibling div~p", 'expect': ["sibling-p2", "sibling-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': @@ -1804,7 +1804,7 @@ var validSelectors = [ 'selector': "#sibling>p~div", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': @@ -1812,35 +1812,35 @@ var validSelectors = [ 'selector': "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", 'expect': [] /*no matches*/, 'level': 3, - 'testType': TEST_QSA_ADDITIONAL + 'testType': testQsaAdditional }, { 'name': "General sibling combinator, surrounded by whitespace", 'selector': "#sibling-p2\t\r\n~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': "General sibling combinator, whitespace after", 'selector': "#sibling-p2~\t\r\n#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': "General sibling combinator, whitespace before", 'selector': "#sibling-p2\t\r\n~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, { 'name': "General sibling combinator, no whitespace", 'selector': "#sibling-p2~#sibling-p3", 'expect': ["sibling-p3"], 'level': 3, - 'testType': TEST_QSA_ADDITIONAL | TEST_MATCH_BASELINE + 'testType': testQsaAdditional | testMatchBaseline }, // Group of selectors (comma) @@ -1849,27 +1849,27 @@ var validSelectors = [ 'selector': "#group em\t\r \n,\t\r \n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Syntax, group of selectors separator, whitespace after", 'selector': "#group em,\t\r\n#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Syntax, group of selectors separator, whitespace before", 'selector': "#group em\t\r\n,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, { 'name': "Syntax, group of selectors separator, no whitespace", 'selector': "#group em,#group strong", 'expect': ["group-em1", "group-strong1"], 'level': 1, - 'testType': TEST_QSA_BASELINE | TEST_MATCH_BASELINE + 'testType': testQsaBaseline | testMatchBaseline }, ]; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 022da355d..0e7358c07 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -15,7 +15,7 @@ Map<String, TreeBuilderFactory> _treeTypes; Map<String, TreeBuilderFactory> get treeTypes { if (_treeTypes == null) { // TODO(jmesserly): add DOM here once it's implemented - _treeTypes = {"simpletree": (useNs) => new TreeBuilder(useNs)}; + _treeTypes = {"simpletree": (useNs) => TreeBuilder(useNs)}; } return _treeTypes; } @@ -25,7 +25,7 @@ final testDir = p.join(p.dirname(p.fromUri(Platform.packageConfig)), 'test'); final testDataDir = p.join(testDir, 'data'); Iterable<String> getDataFiles(String subdirectory) { - var dir = new Directory(p.join(testDataDir, subdirectory)); + var dir = Directory(p.join(testDataDir, subdirectory)); return dir.listSync().where((f) => f is File).map((f) => f.path); } @@ -37,7 +37,7 @@ class TestData extends IterableBase<Map> { TestData(String filename, [this.newTestHeading = "data"]) // Note: can't use readAsLinesSync here because it splits on \r - : _text = new File(filename).readAsStringSync(); + : _text = File(filename).readAsStringSync(); // Note: in Python this was a generator, but since we can't do that in Dart, // it's easier to convert it into an upfront computation. @@ -93,7 +93,7 @@ class TestData extends IterableBase<Map> { /// Serialize the [document] into the html5 test data format. testSerializer(document) { - return (new TestSerializer()..visit(document)).toString(); + return (TestSerializer()..visit(document)).toString(); } /// Serializes the DOM into test format. See [testSerializer]. @@ -102,7 +102,7 @@ class TestSerializer extends TreeVisitor { int _indent = 0; String _spaces = ''; - TestSerializer() : _str = new StringBuffer(); + TestSerializer() : _str = StringBuffer(); String toString() => _str.toString(); @@ -111,11 +111,11 @@ class TestSerializer extends TreeVisitor { set indent(int value) { if (_indent == value) return; - var arr = new List<int>(value); + var arr = List<int>(value); for (int i = 0; i < value; i++) { arr[i] = 32; } - _spaces = new String.fromCharCodes(arr); + _spaces = String.fromCharCodes(arr); _indent = value; } @@ -152,7 +152,7 @@ class TestSerializer extends TreeVisitor { _str.write(node); if (node.attributes.isNotEmpty) { indent += 2; - var keys = new List.from(node.attributes.keys); + var keys = List.from(node.attributes.keys); keys.sort((x, y) => x.compareTo(y)); for (var key in keys) { var v = node.attributes[key]; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 7432cda61..744a49666 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -25,16 +25,16 @@ class TokenizerTestParser { List parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. var bytes = codepointsToUtf8(toCodepoints(str)); - var tokenizer = new HtmlTokenizer(bytes, encoding: 'utf-8'); + var tokenizer = HtmlTokenizer(bytes, encoding: 'utf-8'); outputTokens = []; // Note: we can't get a closure of the state method. However, we can // create a new closure to invoke it via mirrors. var mtok = reflect(tokenizer); - tokenizer.state = () => mtok.invoke(new Symbol(_state), const []).reflectee; + tokenizer.state = () => mtok.invoke(Symbol(_state), const []).reflectee; if (_lastStartTag != null) { - tokenizer.currentToken = new StartTagToken(_lastStartTag); + tokenizer.currentToken = StartTagToken(_lastStartTag); } while (tokenizer.moveNext()) { @@ -182,8 +182,8 @@ void runTokenizerTest(Map testInfo) { if (!testInfo.containsKey('lastStartTag')) { testInfo['lastStartTag'] = null; } - var parser = new TokenizerTestParser( - testInfo['initialState'], testInfo['lastStartTag']); + var parser = + TokenizerTestParser(testInfo['initialState'], testInfo['lastStartTag']); var tokens = parser.parse(testInfo['input']); tokens = concatenateCharacterTokens(tokens); var received = normalizeTokens(tokens); @@ -230,8 +230,8 @@ Map unescape(Map testInfo) { String camelCase(String s) { s = s.toLowerCase(); - var result = new StringBuffer(); - for (var match in new RegExp(r"\W+(\w)(\w+)").allMatches(s)) { + var result = StringBuffer(); + for (var match in RegExp(r"\W+(\w)(\w+)").allMatches(s)) { if (result.length == 0) result.write(s.substring(0, match.start)); result.write(match.group(1).toUpperCase()); result.write(match.group(2)); @@ -243,7 +243,7 @@ void main() { for (var path in getDataFiles('tokenizer')) { if (!path.endsWith('.test')) continue; - var text = new File(path).readAsStringSync(); + var text = File(path).readAsStringSync(); var tests = jsonDecode(text); var testName = pathos.basenameWithoutExtension(path); var testList = tests['tests']; From 93b5360e23110fd2e35bc07d801fb39a20497ac4 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 16 Jan 2019 20:09:44 -0800 Subject: [PATCH 096/212] Update test expectations for source_span output (dart-lang/html#87) Version `1.5.0` of `source_span` changed the output format. Update the tests which hardcoded the expected output to the new format. --- pkgs/html/test/parser_feature_test.dart | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index c112717d6..2591a2d35 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -57,8 +57,10 @@ main() { expect(error.toString(), ''' On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. - <!DOCTYPE html> - ^^^^^^^^^^^^^^^'''); + ╷ +4 │ <!DOCTYPE html> + │ ^^^^^^^^^^^^^^^ + ╵'''); }); test('parse error spans - minimal', () { @@ -253,8 +255,10 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. parser.errors[0].toString(), 'ParserError on line 1, column 4: Unexpected non-space characters. ' 'Expected DOCTYPE.\n' - 'foo\n' - ' ^'); + ' ╷\n' + '1 │ foo\n' + ' │ ^\n' + ' ╵'); }); test('Element.text', () { From 036bb6ef9c447f0acddb447d4b6811e167a99d82 Mon Sep 17 00:00:00 2001 From: William Hesse <whesse@google.com> Date: Mon, 4 Mar 2019 17:45:24 +0100 Subject: [PATCH 097/212] Add warning to changelog about tag 0.13.3+3 --- pkgs/html/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 321fd3ea4..adf3929f8 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -4,6 +4,9 @@ ## 0.13.3+3 +* Do not use this tag in our systems - there was an earlier version of it + pointing to a different commit, that is still in some caches. + * Fix missing_return analyzer errors in `processStartTag` and `processEndTag` methods. From f9df5e555e607f0ebbd630b67e50a9d4959291cf Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Fri, 1 Mar 2019 13:50:31 -0800 Subject: [PATCH 098/212] fix tiny lint issues --- pkgs/html/analysis_options.yaml | 9 +++++++-- pkgs/html/lib/dom_parsing.dart | 2 +- pkgs/html/lib/parser.dart | 2 +- pkgs/html/lib/src/encoding_parser.dart | 4 ++-- pkgs/html/lib/src/tokenizer.dart | 18 +++++++++--------- pkgs/html/lib/src/utils.dart | 2 +- pkgs/html/test/support.dart | 2 +- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 91416258e..2d3a54d6d 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -9,6 +9,7 @@ linter: rules: #- annotate_overrides #- avoid_function_literals_in_foreach_calls + - avoid_empty_else - avoid_init_to_null - avoid_null_checks_in_equality_operators - avoid_relative_lib_imports @@ -44,18 +45,20 @@ linter: #- prefer_collection_literals #- prefer_conditional_assignment - prefer_const_constructors + - prefer_equal_for_default_values - prefer_final_fields - prefer_initializing_formals #- prefer_interpolation_to_compose_strings #- prefer_single_quotes #- prefer_typing_uninitialized_variables + - prefer_generic_function_type_aliases + - prefer_is_not_empty - slash_for_doc_comments - test_types_in_equals - - super_goes_last - - test_types_in_equals - throw_in_finally - type_init_formals #- unnecessary_brace_in_string_interps + - unnecessary_brace_in_string_interps - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas @@ -63,3 +66,5 @@ linter: - unnecessary_null_aware_assignments - unnecessary_statements - unnecessary_this + - unrelated_type_equality_checks + - valid_regexps diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 4fc370707..ba2fccfca 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -104,7 +104,7 @@ class CodeMarkupVisitor extends TreeVisitor { visitComment(Comment node) { var data = htmlSerializeEscape(node.data); - _str.write('<code class="markup comment">&lt;!--${data}--></code>'); + _str.write('<code class="markup comment">&lt;!--$data--></code>'); } } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 3f3217871..58ae1c896 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1190,7 +1190,7 @@ class AfterHeadPhase extends Phase { } } -typedef Token TokenProccessor(Token token); +typedef TokenProccessor = Token Function(Token token); class InBodyPhase extends Phase { bool dropNewline = false; diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 280e7dd71..d61e76a22 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -121,7 +121,7 @@ class EncodingBytes { } } -typedef bool _MethodHandler(); +typedef _MethodHandler = bool Function(); class _DispatchEntry { final String pattern; @@ -373,4 +373,4 @@ bool isSpaceOrAngleBracket(String char) { return char == ">" || char == "<" || isWhitespace(char); } -typedef bool CharPreciate(String char); +typedef CharPreciate = bool Function(String char); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 9f02b6c39..48d63658c 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -337,7 +337,7 @@ class HtmlTokenizer implements Iterator<Token> { } else { output = entities[entityName]; stream.unget(charStack.removeLast()); - output = '${output}${slice(charStack, entityLen).join()}'; + output = '$output${slice(charStack, entityLen).join()}'; } } else { _addToken(ParseErrorToken("expected-named-entity")); @@ -417,13 +417,13 @@ class HtmlTokenizer implements Iterator<Token> { // state". At that point spaceCharacters are important so they are // emitted separately. _addToken(SpaceCharactersToken( - '${data}${stream.charsUntil(spaceCharacters, true)}')); + '$data${stream.charsUntil(spaceCharacters, true)}')); // No need to update lastFourChars here, since the first space will // have already been appended to lastFourChars and will have broken // any <!-- or --> sequences } else { var chars = stream.charsUntil("&<\u0000"); - _addToken(CharactersToken('${data}${chars}')); + _addToken(CharactersToken('$data$chars')); } return true; } @@ -451,10 +451,10 @@ class HtmlTokenizer implements Iterator<Token> { // state". At that point spaceCharacters are important so they are // emitted separately. _addToken(SpaceCharactersToken( - '${data}${stream.charsUntil(spaceCharacters, true)}')); + '$data${stream.charsUntil(spaceCharacters, true)}')); } else { var chars = stream.charsUntil("&<"); - _addToken(CharactersToken('${data}${chars}')); + _addToken(CharactersToken('$data$chars')); } return true; } @@ -477,7 +477,7 @@ class HtmlTokenizer implements Iterator<Token> { return false; } else { var chars = stream.charsUntil("<\u0000"); - _addToken(CharactersToken("${data}${chars}")); + _addToken(CharactersToken("$data$chars")); } return true; } @@ -494,7 +494,7 @@ class HtmlTokenizer implements Iterator<Token> { return false; } else { var chars = stream.charsUntil("<\u0000"); - _addToken(CharactersToken("${data}${chars}")); + _addToken(CharactersToken("$data$chars")); } return true; } @@ -508,7 +508,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(ParseErrorToken("invalid-codepoint")); _addToken(CharactersToken("\uFFFD")); } else { - _addToken(CharactersToken('${data}${stream.charsUntil("\u0000")}')); + _addToken(CharactersToken('$data${stream.charsUntil("\u0000")}')); } return true; } @@ -782,7 +782,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else { var chars = stream.charsUntil("<-\u0000"); - _addToken(CharactersToken("${data}${chars}")); + _addToken(CharactersToken("$data$chars")); } return true; } diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 6d25b5984..3c0249438 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -3,7 +3,7 @@ library utils; import 'constants.dart'; -typedef bool Predicate(); +typedef Predicate = bool Function(); class Pair<F, S> { final F first; diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 0e7358c07..8afbee032 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -9,7 +9,7 @@ import 'package:html/src/treebuilder.dart'; import 'package:html/dom.dart'; import 'package:html/dom_parsing.dart'; -typedef TreeBuilder TreeBuilderFactory(bool namespaceHTMLElements); +typedef TreeBuilderFactory = TreeBuilder Function(bool namespaceHTMLElements); Map<String, TreeBuilderFactory> _treeTypes; Map<String, TreeBuilderFactory> get treeTypes { From d235d543c2a336e7a5a320d5f9bd168483fa10de Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Mon, 4 Mar 2019 09:22:29 -0800 Subject: [PATCH 099/212] Fixes to readme and pubspec, prepare for 0.13.4+1 --- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/README.md | 43 ++++++++---------------------------------- pkgs/html/pubspec.yaml | 4 ++-- 3 files changed, 14 insertions(+), 37 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index adf3929f8..14eb41cd5 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.13.4+1 + +* Fixes to readme and pubspec. + ## 0.13.4 * Require Dart 2.0 stable. diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 27db3ceac..21cc312da 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -1,31 +1,14 @@ -html5 parser in dart -==================== +This is a pure [Dart][dart] [html5 parser][html5parse]. +It's a port of [html5lib](https://github.com/html5lib/html5lib-python) from +Python. +Since it's 100% Dart you can use it safely from a script or server side app. -This is a pure [Dart][dart] [html5 parser][html5parse]. It's a port of -[html5lib](https://github.com/html5lib/html5lib-python) from Python. Since it's 100% -Dart you can use it safely from a script or server side app. +(Formerly known as `package:html5lib`.) -Eventually the parse tree API will be compatible with [dart:html][d_html], so -the same code will work on the client and the server. - -(Formerly known as _html5lib_.) - -Installation ------------- - -Add this to your `pubspec.yaml` (or create it): -```yaml -dependencies: - html: any -``` -Then run the [Pub Package Manager][pub] (comes with the Dart SDK): - - pub install - -Usage ------ +# Usage Parsing HTML is easy! + ```dart import 'package:html/parser.dart' show parse; import 'package:html/dom.dart'; @@ -41,15 +24,5 @@ You can pass a String or list of bytes to `parse`. There's also `parseFragment` for parsing a document fragment, and `HtmlParser` if you want more low level control. -Running Tests -------------- - -```bash -./test/run.sh -``` - -[dart]: http://www.dartlang.org/ +[dart]: https://www.dartlang.org/ [html5parse]: http://dev.w3.org/html5/spec/parsing.html -[d_html]: http://api.dartlang.org/docs/continuous/dart_html.html -[files]: http://html5lib.googlecode.com/hg/python/html5lib/ -[pub]: http://www.dartlang.org/docs/pub-package-manager/ diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 3a43cda2c..b3cf48832 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,7 +1,7 @@ name: html -version: 0.13.4-dev +version: 0.13.4+1 -description: A library for working with HTML documents. +description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/html From 3ec1d9cfc93c6e8ef17b9e29cad1a28a081489a8 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 5 Apr 2019 12:40:51 -0700 Subject: [PATCH 100/212] Remove broken link from readme Fixes https://github.com/dart-lang/html/issues/91 --- pkgs/html/README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 21cc312da..9706dacd0 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -1,9 +1,6 @@ -This is a pure [Dart][dart] [html5 parser][html5parse]. +This is a pure Dart HTML5 parser. It's a port of [html5lib](https://github.com/html5lib/html5lib-python) from Python. -Since it's 100% Dart you can use it safely from a script or server side app. - -(Formerly known as `package:html5lib`.) # Usage @@ -24,5 +21,4 @@ You can pass a String or list of bytes to `parse`. There's also `parseFragment` for parsing a document fragment, and `HtmlParser` if you want more low level control. -[dart]: https://www.dartlang.org/ [html5parse]: http://dev.w3.org/html5/spec/parsing.html From e5cd13df64866a4a8eec1765cfc1327be8554cc4 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Mon, 8 Apr 2019 13:15:55 -0700 Subject: [PATCH 101/212] Remove support for deprecated encodings and parser_console.dart library (dart-lang/html#93) --- pkgs/html/.travis.yml | 5 +- pkgs/html/CHANGELOG.md | 7 + pkgs/html/lib/parser_console.dart | 42 ---- pkgs/html/lib/src/char_encodings.dart | 172 +------------ pkgs/html/lib/src/constants.dart | 16 +- pkgs/html/lib/src/encoding_parser.dart | 199 ++++++++------- ...nputstream.dart => html_input_stream.dart} | 41 +-- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/utf.dart | 237 ++++++++++++++++++ pkgs/html/pubspec.yaml | 4 +- .../test/data/parser_feature/raw_file.html | 6 - pkgs/html/test/parser_feature_test.dart | 2 +- pkgs/html/test/parser_test.dart | 19 +- 13 files changed, 378 insertions(+), 374 deletions(-) delete mode 100644 pkgs/html/lib/parser_console.dart rename pkgs/html/lib/src/{inputstream.dart => html_input_stream.dart} (85%) create mode 100644 pkgs/html/lib/src/utf.dart delete mode 100644 pkgs/html/test/data/parser_feature/raw_file.html diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 714aa8610..337cecabf 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -1,9 +1,12 @@ language: dart + dart: - dev + - 2.0.0 + dart_task: - test: -p vm - - test: -p chrome,firefox + - test: -p chrome - dartanalyzer: --fatal-warnings --fatal-infos . matrix: diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 14eb41cd5..2ddbae760 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.14.0 + +*BREAKING CHANGES* + +- Drop support for encodings other than UTF-8 and ASCII. +- Removed `parser_console.dart` library. + ## 0.13.4+1 * Fixes to readme and pubspec. diff --git a/pkgs/html/lib/parser_console.dart b/pkgs/html/lib/parser_console.dart deleted file mode 100644 index 28dee1417..000000000 --- a/pkgs/html/lib/parser_console.dart +++ /dev/null @@ -1,42 +0,0 @@ -/// This library adds `dart:io` support to the HTML5 parser. Call -/// [initDartIOSupport] before calling the [parse] methods and they will accept -/// a [RandomAccessFile] as input, in addition to the other input types. -library parser_console; - -import 'dart:io'; -import 'parser.dart'; -import 'src/inputstream.dart' as inputstream; - -/// Adds support to the [HtmlParser] for running on a console VM. In particular -/// this means it will be able to handle `dart:io` and [RandomAccessFile]s as -/// input to the various [parse] methods. -void useConsole() { - inputstream.consoleSupport = _ConsoleSupport(); -} - -class _ConsoleSupport extends inputstream.ConsoleSupport { - List<int> bytesFromFile(source) { - if (source is! RandomAccessFile) return null; - return readAllBytesFromFile(source); - } -} - -// TODO(jmesserly): this should be `RandomAccessFile.readAllBytes`. -/// Synchronously reads all bytes from the [file]. -List<int> readAllBytesFromFile(RandomAccessFile file) { - int length = file.lengthSync(); - var bytes = List<int>(length); - - int bytesRead = 0; - while (bytesRead < length) { - int read = file.readIntoSync(bytes, bytesRead, length - bytesRead); - if (read <= 0) { - // This could happen if, for example, the file was resized while - // we're reading. Just shrink the bytes array and move on. - bytes = bytes.sublist(0, bytesRead); - break; - } - bytesRead += read; - } - return bytes; -} diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index ba10a4a39..6120056ba 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -1,8 +1,4 @@ -/// Decodes bytes using the correct name. See [decodeBytes]. -library char_encodings; - -import 'dart:collection'; -import 'package:utf/utf.dart'; +import 'utf.dart'; // TODO(jmesserly): this function is conspicuously absent from dart:utf. /// Returns true if the [bytes] starts with a UTF-8 byte order mark. @@ -21,15 +17,9 @@ bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { /// Decodes the [bytes] with the provided [encoding] and returns an iterable for /// the codepoints. Supports the major unicode encodings as well as ascii and /// and windows-1252 encodings. -Iterable<int> decodeBytes(String encoding, List<int> bytes, - [int offset = 0, - int length, - int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { - if (length == null) length = bytes.length; - final replace = replacementCodepoint; +Iterable<int> decodeBytes(String encoding, List<int> bytes) { switch (encoding) { case 'ascii': - bytes = bytes.sublist(offset, offset + length); // TODO(jmesserly): this was taken from runtime/bin/string_stream.dart for (int byte in bytes) { if (byte > 127) { @@ -41,32 +31,18 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes, } return bytes; - case 'windows-1252': - case 'cp1252': - return decodeWindows1252AsIterable(bytes, offset, length, replace); - case 'utf-8': // NOTE: to match the behavior of the other decode functions, we eat the // utf-8 BOM here. - if (hasUtf8Bom(bytes, offset, length)) { + + var offset = 0; + var length = bytes.length; + + if (hasUtf8Bom(bytes)) { offset += 3; length -= 3; } - return decodeUtf8AsIterable(bytes, offset, length, replace); - - case 'utf-16': - return decodeUtf16AsIterable(bytes, offset, length, replace); - case 'utf-16-be': - return decodeUtf16beAsIterable(bytes, offset, length, true, replace); - case 'utf-16-le': - return decodeUtf16leAsIterable(bytes, offset, length, true, replace); - - case 'utf-32': - return decodeUtf32AsIterable(bytes, offset, length, replace); - case 'utf-32-be': - return decodeUtf32beAsIterable(bytes, offset, length, true, replace); - case 'utf-32-le': - return decodeUtf32leAsIterable(bytes, offset, length, true, replace); + return decodeUtf8AsIterable(bytes, offset, length); default: throw ArgumentError('Encoding $encoding not supported'); @@ -94,135 +70,3 @@ List<int> toCodepoints(String input) { } return newCodes; } - -/// Decodes [windows-1252](http://en.wikipedia.org/wiki/Windows-1252) bytes as -/// an iterable. Thus, the consumer can only convert as much of the input as -/// needed. Set the [replacementCharacter] to null to throw an [ArgumentError] -/// rather than replace the bad value. -IterableWindows1252Decoder decodeWindows1252AsIterable(List<int> bytes, - [int offset = 0, - int length, - int replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) { - return IterableWindows1252Decoder( - bytes, offset, length, replacementCodepoint); -} - -/// Return type of [decodeWindows1252AsIterable] and variants. The Iterable type -/// provides an iterator on demand and the iterator will only translate bytes -/// as requested by the user of the iterator. (Note: results are not cached.) -class IterableWindows1252Decoder extends IterableBase<int> { - final List<int> bytes; - final int offset; - final int length; - final int replacementCodepoint; - - IterableWindows1252Decoder(this.bytes, - [this.offset = 0, - this.length, - this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]); - - Windows1252Decoder get iterator => - Windows1252Decoder(bytes, offset, length, replacementCodepoint); -} - -/// Provides an iterator of Unicode codepoints from windows-1252 encoded bytes. -/// The parameters can set an offset into a list of bytes (as int), limit the -/// length of the values to be decoded, and override the default Unicode -/// replacement character. Set the replacementCharacter to null to throw an -/// ArgumentError rather than replace the bad value. The return value -/// from this method can be used as an Iterable (e.g. in a for-loop). -class Windows1252Decoder implements Iterator<int> { - final int replacementCodepoint; - final List<int> _bytes; - int _offset; - final int _length; - - Windows1252Decoder(List<int> bytes, - [int offset = 0, - int length, - this.replacementCodepoint = UNICODE_REPLACEMENT_CHARACTER_CODEPOINT]) - : _bytes = bytes, - _offset = offset - 1, - _length = length == null ? bytes.length : length; - - bool get _inRange => _offset >= 0 && _offset < _length; - int get current => _inRange ? _mapChar(_bytes[_offset]) : null; - - bool moveNext() { - _offset++; - return _inRange; - } - - int _mapChar(int char) { - // TODO(jmesserly): this is duplicating entitiesWindows1252 and - // replacementCharacters from constants.dart - switch (char) { - case 0x80: - return 0x20AC; // EURO SIGN - case 0x82: - return 0x201A; // SINGLE LOW-9 QUOTATION MARK - case 0x83: - return 0x0192; // LATIN SMALL LETTER F WITH HOOK - case 0x84: - return 0x201E; // DOUBLE LOW-9 QUOTATION MARK - case 0x85: - return 0x2026; // HORIZONTAL ELLIPSIS - case 0x86: - return 0x2020; // DAGGER - case 0x87: - return 0x2021; // DOUBLE DAGGER - case 0x88: - return 0x02C6; // MODIFIER LETTER CIRCUMFLEX ACCENT - case 0x89: - return 0x2030; // PER MILLE SIGN - case 0x8A: - return 0x0160; // LATIN CAPITAL LETTER S WITH CARON - case 0x8B: - return 0x2039; // SINGLE LEFT-POINTING ANGLE QUOTATION MARK - case 0x8C: - return 0x0152; // LATIN CAPITAL LIGATURE OE - case 0x8E: - return 0x017D; // LATIN CAPITAL LETTER Z WITH CARON - case 0x91: - return 0x2018; // LEFT SINGLE QUOTATION MARK - case 0x92: - return 0x2019; // RIGHT SINGLE QUOTATION MARK - case 0x93: - return 0x201C; // LEFT DOUBLE QUOTATION MARK - case 0x94: - return 0x201D; // RIGHT DOUBLE QUOTATION MARK - case 0x95: - return 0x2022; // BULLET - case 0x96: - return 0x2013; // EN DASH - case 0x97: - return 0x2014; // EM DASH - case 0x98: - return 0x02DC; // SMALL TILDE - case 0x99: - return 0x2122; // TRADE MARK SIGN - case 0x9A: - return 0x0161; // LATIN SMALL LETTER S WITH CARON - case 0x9B: - return 0x203A; // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK - case 0x9C: - return 0x0153; // LATIN SMALL LIGATURE OE - case 0x9E: - return 0x017E; // LATIN SMALL LETTER Z WITH CARON - case 0x9F: - return 0x0178; // LATIN CAPITAL LETTER Y WITH DIAERESIS - - case 0x81: - case 0x8D: - case 0x8F: - case 0x90: - case 0x9D: - if (replacementCodepoint == null) { - throw ArgumentError( - "Invalid windows-1252 code point $char at $_offset"); - } - return replacementCodepoint; - } - return char; - } -} diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index fc0c6a1a3..34addfc08 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -29,10 +29,10 @@ const Map<String, String> errorMessages = { "Entity used with illegal number (windows-1252 reference).", "cant-convert-numeric-entity": "Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x).", + "(codepoint U+%(charAsInt)08x).", "illegal-codepoint-for-numeric-entity": "Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x.", + "U+%(charAsInt)08x.", "numeric-entity-without-semicolon": "Numeric entity didn't end with ';'.", "expected-numeric-entity-but-got-eof": "Numeric entity expected. Got end of file instead.", @@ -46,7 +46,7 @@ const Map<String, String> errorMessages = { "Expected tag name. Got '>' instead.", "expected-tag-name-but-got-question-mark": "Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)", + "support processing instructions.)", "expected-tag-name": "Expected tag name. Got something else instead", "expected-closing-tag-but-got-right-bracket": "Expected closing tag. Got '>' instead. Ignoring '</>'.", @@ -133,7 +133,7 @@ const Map<String, String> errorMessages = { "missing-end-tags": "Missing end tags (%(name)s).", "unexpected-start-tag-implies-end-tag": "Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s).", + "implies end tag (%(endName)s).", "unexpected-start-tag-treated-as": "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", "deprecated-tag": "Unexpected start tag %(name)s. Don't use it!", @@ -165,7 +165,7 @@ const Map<String, String> errorMessages = { "unexpected-form-in-table": "Unexpected form in table context.", "unexpected-start-tag-implies-table-voodoo": "Unexpected start tag (%(name)s) in " - "table context caused voodoo mode.", + "table context caused voodoo mode.", "unexpected-end-tag-implies-table-voodoo": "Unexpected end tag (%(name)s) in " "table context caused voodoo mode.", "unexpected-cell-in-table-body": "Unexpected table cell start tag (%(name)s) " @@ -180,12 +180,12 @@ const Map<String, String> errorMessages = { "Unexpected end tag (%(name)s) in the table row phase. Ignored.", "unexpected-select-in-select": "Unexpected select start tag in the select phase " - "treated as select end tag.", + "treated as select end tag.", "unexpected-input-in-select": "Unexpected input start tag in the select phase.", "unexpected-start-tag-in-select": "Unexpected start tag token (%(name)s in the select phase. " - "Ignored.", + "Ignored.", "unexpected-end-tag-in-select": "Unexpected end tag (%(name)s) in the select phase. Ignored.", "unexpected-table-element-start-tag-in-select-in-table": @@ -204,7 +204,7 @@ const Map<String, String> errorMessages = { " in the frameset phase. Ignored.", "unexpected-frameset-in-frameset-innerhtml": "Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML).", + "in the frameset phase (innerHTML).", "unexpected-end-tag-in-frameset": "Unexpected end tag token (%(name)s)" " in the frameset phase. Ignored.", "unexpected-char-after-frameset": "Unexpected non-space characters in the " diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index d61e76a22..d0f40d6f9 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -1,7 +1,5 @@ -library encoding_parser; - import 'constants.dart'; -import 'inputstream.dart'; +import 'html_input_stream.dart'; // TODO(jmesserly): I converted StopIteration to StateError("No more elements"). // Seems strange to throw this from outside of an iterator though. @@ -10,15 +8,15 @@ import 'inputstream.dart'; /// raised. class EncodingBytes { final String _bytes; - int _position = -1; + int __position = -1; EncodingBytes(this._bytes); - int get length => _bytes.length; + int get _length => _bytes.length; - String next() { - var p = _position = _position + 1; - if (p >= length) { + String _next() { + var p = __position = __position + 1; + if (p >= _length) { throw StateError("No more elements"); } else if (p < 0) { throw RangeError(p); @@ -26,59 +24,59 @@ class EncodingBytes { return _bytes[p]; } - String previous() { - var p = _position; - if (p >= length) { + String _previous() { + var p = __position; + if (p >= _length) { throw StateError("No more elements"); } else if (p < 0) { throw RangeError(p); } - _position = p = p - 1; + __position = p = p - 1; return _bytes[p]; } - set position(int value) { - if (_position >= length) { + set _position(int value) { + if (__position >= _length) { throw StateError("No more elements"); } - _position = value; + __position = value; } - int get position { - if (_position >= length) { + int get _position { + if (__position >= _length) { throw StateError("No more elements"); } - if (_position >= 0) { - return _position; + if (__position >= 0) { + return __position; } else { return 0; } } - String get currentByte => _bytes[position]; + String get _currentByte => _bytes[_position]; /// Skip past a list of characters. Defaults to skipping [isWhitespace]. - String skipChars([CharPreciate skipChars]) { + String _skipChars([_CharPredicate skipChars]) { if (skipChars == null) skipChars = isWhitespace; - var p = position; // use property for the error-checking - while (p < length) { + var p = _position; // use property for the error-checking + while (p < _length) { var c = _bytes[p]; if (!skipChars(c)) { - _position = p; + __position = p; return c; } p += 1; } - _position = p; + __position = p; return null; } - String skipUntil(CharPreciate untilChars) { - var p = position; - while (p < length) { + String _skipUntil(_CharPredicate untilChars) { + var p = _position; + while (p < _length) { var c = _bytes[p]; if (untilChars(c)) { - _position = p; + __position = p; return c; } p += 1; @@ -89,14 +87,14 @@ class EncodingBytes { /// Look for a sequence of bytes at the start of a string. If the bytes /// are found return true and advance the position to the byte after the /// match. Otherwise return false and leave the position alone. - bool matchBytes(String bytes) { - var p = position; + bool _matchBytes(String bytes) { + var p = _position; if (_bytes.length < p + bytes.length) { return false; } var data = _bytes.substring(p, p + bytes.length); if (data == bytes) { - position += bytes.length; + _position += bytes.length; return true; } return false; @@ -104,19 +102,19 @@ class EncodingBytes { /// Look for the next sequence of bytes matching a given sequence. If /// a match is found advance the position to the last byte of the match - bool jumpTo(String bytes) { - var newPosition = _bytes.indexOf(bytes, position); + bool _jumpTo(String bytes) { + var newPosition = _bytes.indexOf(bytes, _position); if (newPosition >= 0) { - _position = newPosition + bytes.length - 1; + __position = newPosition + bytes.length - 1; return true; } else { throw StateError("No more elements"); } } - String slice(int start, [int end]) { - if (end == null) end = length; - if (end < 0) end += length; + String _slice(int start, [int end]) { + if (end == null) end = _length; + if (end < 0) end += _length; return _bytes.substring(start, end); } } @@ -126,68 +124,69 @@ typedef _MethodHandler = bool Function(); class _DispatchEntry { final String pattern; final _MethodHandler handler; + _DispatchEntry(this.pattern, this.handler); } /// Mini parser for detecting character encoding from meta elements. class EncodingParser { - final EncodingBytes data; - String encoding; + final EncodingBytes _data; + String _encoding; /// [bytes] - the data to work on for encoding detection. EncodingParser(List<int> bytes) // Note: this is intentionally interpreting bytes as codepoints. - : data = EncodingBytes(String.fromCharCodes(bytes).toLowerCase()); + : _data = EncodingBytes(String.fromCharCodes(bytes).toLowerCase()); String getEncoding() { final methodDispatch = [ - _DispatchEntry("<!--", handleComment), - _DispatchEntry("<meta", handleMeta), - _DispatchEntry("</", handlePossibleEndTag), - _DispatchEntry("<!", handleOther), - _DispatchEntry("<?", handleOther), - _DispatchEntry("<", handlePossibleStartTag), + _DispatchEntry("<!--", _handleComment), + _DispatchEntry("<meta", _handleMeta), + _DispatchEntry("</", _handlePossibleEndTag), + _DispatchEntry("<!", _handleOther), + _DispatchEntry("<?", _handleOther), + _DispatchEntry("<", _handlePossibleStartTag), ]; try { for (;;) { for (var dispatch in methodDispatch) { - if (data.matchBytes(dispatch.pattern)) { + if (_data._matchBytes(dispatch.pattern)) { var keepParsing = dispatch.handler(); if (keepParsing) break; // We found an encoding. Stop. - return encoding; + return _encoding; } } - data.position += 1; + _data._position += 1; } } on StateError catch (_) { // Catch this here to match behavior of Python's StopIteration // TODO(jmesserly): refactor to not use exceptions } - return encoding; + return _encoding; } /// Skip over comments. - bool handleComment() => data.jumpTo("-->"); + bool _handleComment() => _data._jumpTo("-->"); - bool handleMeta() { - if (!isWhitespace(data.currentByte)) { + bool _handleMeta() { + if (!isWhitespace(_data._currentByte)) { // if we have <meta not followed by a space so just keep going return true; } // We have a valid meta element we want to search for attributes while (true) { // Try to find the next attribute after the current position - var attr = getAttribute(); + var attr = _getAttribute(); if (attr == null) return true; if (attr[0] == "charset") { var tentativeEncoding = attr[1]; var codec = codecName(tentativeEncoding); if (codec != null) { - encoding = codec; + _encoding = codec; return false; } } else if (attr[0] == "content") { @@ -195,54 +194,54 @@ class EncodingParser { var tentativeEncoding = contentParser.parse(); var codec = codecName(tentativeEncoding); if (codec != null) { - encoding = codec; + _encoding = codec; return false; } } } } - bool handlePossibleStartTag() => handlePossibleTag(false); + bool _handlePossibleStartTag() => _handlePossibleTag(false); - bool handlePossibleEndTag() { - data.next(); - return handlePossibleTag(true); + bool _handlePossibleEndTag() { + _data._next(); + return _handlePossibleTag(true); } - bool handlePossibleTag(bool endTag) { - if (!isLetter(data.currentByte)) { + bool _handlePossibleTag(bool endTag) { + if (!isLetter(_data._currentByte)) { //If the next byte is not an ascii letter either ignore this //fragment (possible start tag case) or treat it according to //handleOther if (endTag) { - data.previous(); - handleOther(); + _data._previous(); + _handleOther(); } return true; } - var c = data.skipUntil(isSpaceOrAngleBracket); + var c = _data._skipUntil(_isSpaceOrAngleBracket); if (c == "<") { // return to the first step in the overall "two step" algorithm // reprocessing the < byte - data.previous(); + _data._previous(); } else { //Read all attributes - var attr = getAttribute(); + var attr = _getAttribute(); while (attr != null) { - attr = getAttribute(); + attr = _getAttribute(); } } return true; } - bool handleOther() => data.jumpTo(">"); + bool _handleOther() => _data._jumpTo(">"); /// Return a name,value pair for the next attribute in the stream, /// if one is found, or null - List<String> getAttribute() { + List<String> _getAttribute() { // Step 1 (skip chars) - var c = data.skipChars((x) => x == "/" || isWhitespace(x)); + var c = _data._skipChars((x) => x == "/" || isWhitespace(x)); // Step 2 if (c == ">" || c == null) { return null; @@ -258,8 +257,8 @@ class EncodingParser { break; } else if (isWhitespace(c)) { // Step 6! - c = data.skipChars(); - c = data.next(); + c = _data._skipChars(); + c = _data._next(); break; } else if (c == "/" || c == ">") { return [attrName.join(), ""]; @@ -269,27 +268,27 @@ class EncodingParser { attrName.add(c); } // Step 5 - c = data.next(); + c = _data._next(); } // Step 7 if (c != "=") { - data.previous(); + _data._previous(); return [attrName.join(), ""]; } // Step 8 - data.next(); + _data._next(); // Step 9 - c = data.skipChars(); + c = _data._skipChars(); // Step 10 if (c == "'" || c == '"') { // 10.1 var quoteChar = c; while (true) { // 10.2 - c = data.next(); + c = _data._next(); if (c == quoteChar) { // 10.3 - data.next(); + _data._next(); return [attrName.join(), attrValue.join()]; } else if (isLetter(c)) { // 10.4 @@ -310,8 +309,8 @@ class EncodingParser { } // Step 11 while (true) { - c = data.next(); - if (isSpaceOrAngleBracket(c)) { + c = _data._next(); + if (_isSpaceOrAngleBracket(c)) { return [attrName.join(), attrValue.join()]; } else if (c == null) { return null; @@ -333,34 +332,34 @@ class ContentAttrParser { try { // Check if the attr name is charset // otherwise return - data.jumpTo("charset"); - data.position += 1; - data.skipChars(); - if (data.currentByte != "=") { + data._jumpTo("charset"); + data._position += 1; + data._skipChars(); + if (data._currentByte != "=") { // If there is no = sign keep looking for attrs return null; } - data.position += 1; - data.skipChars(); + data._position += 1; + data._skipChars(); // Look for an encoding between matching quote marks - if (data.currentByte == '"' || data.currentByte == "'") { - var quoteMark = data.currentByte; - data.position += 1; - var oldPosition = data.position; - if (data.jumpTo(quoteMark)) { - return data.slice(oldPosition, data.position); + if (data._currentByte == '"' || data._currentByte == "'") { + var quoteMark = data._currentByte; + data._position += 1; + var oldPosition = data._position; + if (data._jumpTo(quoteMark)) { + return data._slice(oldPosition, data._position); } else { return null; } } else { // Unquoted value - var oldPosition = data.position; + var oldPosition = data._position; try { - data.skipUntil(isWhitespace); - return data.slice(oldPosition, data.position); + data._skipUntil(isWhitespace); + return data._slice(oldPosition, data._position); } on StateError catch (_) { //Return the whole remaining value - return data.slice(oldPosition); + return data._slice(oldPosition); } } } on StateError catch (_) { @@ -369,8 +368,8 @@ class ContentAttrParser { } } -bool isSpaceOrAngleBracket(String char) { +bool _isSpaceOrAngleBracket(String char) { return char == ">" || char == "<" || isWhitespace(char); } -typedef CharPreciate = bool Function(String char); +typedef _CharPredicate = bool Function(String char); diff --git a/pkgs/html/lib/src/inputstream.dart b/pkgs/html/lib/src/html_input_stream.dart similarity index 85% rename from pkgs/html/lib/src/inputstream.dart rename to pkgs/html/lib/src/html_input_stream.dart index dbcf98bce..84d2f1345 100644 --- a/pkgs/html/lib/src/inputstream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -1,21 +1,12 @@ -library inputstream; - import 'dart:collection'; -import 'package:utf/utf.dart'; + import 'package:source_span/source_span.dart'; + import 'char_encodings.dart'; import 'constants.dart'; import 'encoding_parser.dart'; import 'utils.dart'; -/// Hooks to call into dart:io without directly referencing it. -class ConsoleSupport { - List<int> bytesFromFile(source) => null; -} - -// TODO(jmesserly): use lazy init here when supported. -ConsoleSupport consoleSupport = ConsoleSupport(); - /// Provides a unicode stream of characters to the HtmlTokenizer. /// /// This class takes care of character encoding and removing or replacing @@ -26,7 +17,7 @@ class HtmlInputStream { static const int numBytesMeta = 512; /// Encoding to use if no other information can be found. - static const String defaultEncoding = 'windows-1252'; + static const String defaultEncoding = 'utf-8'; /// The name of the character encoding. String charEncodingName; @@ -81,18 +72,8 @@ class HtmlInputStream { } else if (source is List<int>) { _rawBytes = source; } else { - // TODO(jmesserly): it's unfortunate we need to read all bytes in advance, - // but it's necessary because of how the UTF decoders work. - _rawBytes = consoleSupport.bytesFromFile(source); - - if (_rawBytes == null) { - // TODO(jmesserly): we should accept some kind of stream API too. - // Unfortunately dart:io InputStream is async only, which won't work. - throw ArgumentError("'source' must be a String or " - "List<int> (of bytes). You can also pass a RandomAccessFile if you" - "`import 'package:html/parser_console.dart'` and call " - "`useConsole()`."); - } + throw ArgumentError.value( + source, 'source', 'Must be a String or List<int>.'); } // Detect encoding iff no explicit "transport level" encoding is supplied @@ -121,7 +102,7 @@ class HtmlInputStream { if (c == NEWLINE) continue; } - if (invalidUnicode(c)) errors.add('invalid-codepoint'); + if (_invalidUnicode(c)) errors.add('invalid-codepoint'); if (0xD800 <= c && c <= 0xDFFF) { c = 0xFFFD; @@ -199,14 +180,6 @@ class HtmlInputStream { if (hasUtf8Bom(_rawBytes)) { return 'utf-8'; } - // Note: we don't need to remember whether it was big or little endian - // because the decoder will do that later. It will also eat the BOM for us. - if (hasUtf16Bom(_rawBytes)) { - return 'utf-16'; - } - if (hasUtf32Bom(_rawBytes)) { - return 'utf-32'; - } return null; } @@ -262,7 +235,7 @@ class HtmlInputStream { // TODO(jmesserly): the Python code used a regex to check for this. But // Dart doesn't let you create a regexp with invalid characters. -bool invalidUnicode(int c) { +bool _invalidUnicode(int c) { if (0x0001 <= c && c <= 0x0008) return true; if (0x000E <= c && c <= 0x001F) return true; if (0x007F <= c && c <= 0x009F) return true; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 48d63658c..638663ec0 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -3,7 +3,7 @@ library tokenizer; import 'dart:collection'; import 'package:html/parser.dart' show HtmlParser; import 'constants.dart'; -import 'inputstream.dart'; +import 'html_input_stream.dart'; import 'token.dart'; import 'utils.dart'; diff --git a/pkgs/html/lib/src/utf.dart b/pkgs/html/lib/src/utf.dart new file mode 100644 index 000000000..a635db8b8 --- /dev/null +++ b/pkgs/html/lib/src/utf.dart @@ -0,0 +1,237 @@ +// Large portions of this code where taken from https://github.com/dart-lang/utf + +import "dart:collection"; + +const int _replacementCodepoint = 0xfffd; + +const int _UNICODE_VALID_RANGE_MAX = 0x10ffff; +const int _UNICODE_UTF16_RESERVED_LO = 0xd800; +const int _UNICODE_UTF16_RESERVED_HI = 0xdfff; + +const int _UTF8_ONE_BYTE_MAX = 0x7f; +const int _UTF8_TWO_BYTE_MAX = 0x7ff; +const int _UTF8_THREE_BYTE_MAX = 0xffff; + +const int _UTF8_LO_SIX_BIT_MASK = 0x3f; + +const int _UTF8_FIRST_BYTE_OF_TWO_BASE = 0xc0; +const int _UTF8_FIRST_BYTE_OF_THREE_BASE = 0xe0; +const int _UTF8_FIRST_BYTE_OF_FOUR_BASE = 0xf0; +const int _UTF8_FIRST_BYTE_OF_FIVE_BASE = 0xf8; +const int _UTF8_FIRST_BYTE_OF_SIX_BASE = 0xfc; + +const int _UTF8_FIRST_BYTE_BOUND_EXCL = 0xfe; + +/// Decodes the UTF-8 bytes as an iterable. Thus, the consumer can only convert +/// as much of the input as needed. Set the replacementCharacter to null to +/// throw an ArgumentError rather than replace the bad value. +Iterable<int> decodeUtf8AsIterable(List<int> bytes, int offset, int length) => + _IterableUtf8Decoder(bytes, offset, length); + +/// Return type of [decodeUtf8AsIterable] and variants. The Iterable type +/// provides an iterator on demand and the iterator will only translate bytes +/// as requested by the user of the iterator. (Note: results are not cached.) +// TODO(floitsch): Consider removing the extend and switch to implements since +// that's cheaper to allocate. +class _IterableUtf8Decoder extends IterableBase<int> { + final List<int> bytes; + final int offset; + final int length; + + _IterableUtf8Decoder(this.bytes, this.offset, this.length); + + _Utf8Decoder get iterator => _Utf8Decoder(bytes, offset, length); +} + +/// Provides an iterator of Unicode codepoints from UTF-8 encoded bytes. The +/// parameters can set an offset into a list of bytes (as int), limit the length +/// of the values to be decoded, and override the default Unicode replacement +/// character. Set the replacementCharacter to null to throw an +/// ArgumentError rather than replace the bad value. The return value +/// from this method can be used as an Iterable (e.g. in a for-loop). +class _Utf8Decoder implements Iterator<int> { + final _ListRangeIterator utf8EncodedBytesIterator; + int _current; + + _Utf8Decoder(List<int> utf8EncodedBytes, int offset, int length) + : utf8EncodedBytesIterator = + (_ListRange(utf8EncodedBytes, offset, length)).iterator; + + _Utf8Decoder._fromListRangeIterator(_ListRange source) + : utf8EncodedBytesIterator = source.iterator; + + /// Decode the remaininder of the characters in this decoder + /// into a [List<int>]. + List<int> decodeRest() { + List<int> codepoints = List<int>(utf8EncodedBytesIterator.remaining); + int i = 0; + while (moveNext()) { + codepoints[i++] = current; + } + if (i == codepoints.length) { + return codepoints; + } else { + List<int> truncCodepoints = List<int>(i); + truncCodepoints.setRange(0, i, codepoints); + return truncCodepoints; + } + } + + int get current => _current; + + bool moveNext() { + _current = null; + + if (!utf8EncodedBytesIterator.moveNext()) return false; + + int value = utf8EncodedBytesIterator.current; + int additionalBytes = 0; + + if (value < 0) { + if (_replacementCodepoint != null) { + _current = _replacementCodepoint; + return true; + } else { + throw ArgumentError( + "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); + } + } else if (value <= _UTF8_ONE_BYTE_MAX) { + _current = value; + return true; + } else if (value < _UTF8_FIRST_BYTE_OF_TWO_BASE) { + if (_replacementCodepoint != null) { + _current = _replacementCodepoint; + return true; + } else { + throw ArgumentError( + "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); + } + } else if (value < _UTF8_FIRST_BYTE_OF_THREE_BASE) { + value -= _UTF8_FIRST_BYTE_OF_TWO_BASE; + additionalBytes = 1; + } else if (value < _UTF8_FIRST_BYTE_OF_FOUR_BASE) { + value -= _UTF8_FIRST_BYTE_OF_THREE_BASE; + additionalBytes = 2; + } else if (value < _UTF8_FIRST_BYTE_OF_FIVE_BASE) { + value -= _UTF8_FIRST_BYTE_OF_FOUR_BASE; + additionalBytes = 3; + } else if (value < _UTF8_FIRST_BYTE_OF_SIX_BASE) { + value -= _UTF8_FIRST_BYTE_OF_FIVE_BASE; + additionalBytes = 4; + } else if (value < _UTF8_FIRST_BYTE_BOUND_EXCL) { + value -= _UTF8_FIRST_BYTE_OF_SIX_BASE; + additionalBytes = 5; + } else if (_replacementCodepoint != null) { + _current = _replacementCodepoint; + return true; + } else { + throw ArgumentError( + "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); + } + int j = 0; + while (j < additionalBytes && utf8EncodedBytesIterator.moveNext()) { + int nextValue = utf8EncodedBytesIterator.current; + if (nextValue > _UTF8_ONE_BYTE_MAX && + nextValue < _UTF8_FIRST_BYTE_OF_TWO_BASE) { + value = ((value << 6) | (nextValue & _UTF8_LO_SIX_BIT_MASK)); + } else { + // if sequence-starting code unit, reposition cursor to start here + if (nextValue >= _UTF8_FIRST_BYTE_OF_TWO_BASE) { + utf8EncodedBytesIterator.backup(); + } + break; + } + j++; + } + bool validSequence = (j == additionalBytes && + (value < _UNICODE_UTF16_RESERVED_LO || + value > _UNICODE_UTF16_RESERVED_HI)); + bool nonOverlong = (additionalBytes == 1 && value > _UTF8_ONE_BYTE_MAX) || + (additionalBytes == 2 && value > _UTF8_TWO_BYTE_MAX) || + (additionalBytes == 3 && value > _UTF8_THREE_BYTE_MAX); + bool inRange = value <= _UNICODE_VALID_RANGE_MAX; + if (validSequence && nonOverlong && inRange) { + _current = value; + return true; + } else if (_replacementCodepoint != null) { + _current = _replacementCodepoint; + return true; + } else { + throw ArgumentError( + "Invalid UTF8 at ${utf8EncodedBytesIterator.position - j}"); + } + } +} + +/// _ListRange in an internal type used to create a lightweight Interable on a +/// range within a source list. DO NOT MODIFY the underlying list while +/// iterating over it. The results of doing so are undefined. +// TODO(floitsch): Consider removing the extend and switch to implements since +// that's cheaper to allocate. +class _ListRange extends IterableBase<int> { + final List<int> _source; + final int _offset; + final int _length; + + _ListRange(List<int> source, [int offset = 0, int length]) + : _source = source, + _offset = offset, + _length = (length == null ? source.length - offset : length) { + if (_offset < 0 || _offset > _source.length) { + throw RangeError.value(_offset); + } + if (_length != null && (_length < 0)) { + throw RangeError.value(_length); + } + if (_length + _offset > _source.length) { + throw RangeError.value(_length + _offset); + } + } + + _ListRangeIterator get iterator => + _ListRangeIteratorImpl(_source, _offset, _offset + _length); + + int get length => _length; +} + +/// The ListRangeIterator provides more capabilities than a standard iterator, +/// including the ability to get the current position, count remaining items, +/// and move forward/backward within the iterator. +abstract class _ListRangeIterator implements Iterator<int> { + bool moveNext(); + + int get current; + + int get position; + + void backup([int by]); + + int get remaining; + + void skip([int count]); +} + +class _ListRangeIteratorImpl implements _ListRangeIterator { + final List<int> _source; + int _offset; + final int _end; + + _ListRangeIteratorImpl(this._source, int offset, this._end) + : _offset = offset - 1; + + int get current => _source[_offset]; + + bool moveNext() => ++_offset < _end; + + int get position => _offset; + + void backup([int by = 1]) { + _offset -= by; + } + + int get remaining => _end - _offset - 1; + + void skip([int count = 1]) { + _offset += count; + } +} diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index b3cf48832..92e502e9e 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.4+1 +version: 0.14.0-dev description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> @@ -11,9 +11,9 @@ environment: dependencies: csslib: '>=0.13.2 <0.15.0' source_span: '>=1.0.0 <2.0.0' - utf: '>=0.9.0 <0.10.0' dev_dependencies: path: ^1.6.2 pedantic: ^1.3.0 test: ^1.3.0 + utf: '>=0.9.0 <0.10.0' diff --git a/pkgs/html/test/data/parser_feature/raw_file.html b/pkgs/html/test/data/parser_feature/raw_file.html deleted file mode 100644 index bcdbf76f9..000000000 --- a/pkgs/html/test/data/parser_feature/raw_file.html +++ /dev/null @@ -1,6 +0,0 @@ -<!doctype html> -<html> -<body> -Hello world! -</body> -</html> diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 2591a2d35..0889f44ce 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -1,13 +1,13 @@ /// Additional feature tests that aren't based on test data. library parser_feature_test; -import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:html/src/constants.dart'; import 'package:html/src/encoding_parser.dart'; import 'package:html/src/treebuilder.dart'; import 'package:source_span/source_span.dart'; +import 'package:test/test.dart'; main() { _testElementSpans(); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 1289f6181..1db15868d 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -2,13 +2,12 @@ library parser_test; import 'dart:convert'; -import 'dart:io'; -import 'package:path/path.dart' as pathos; -import 'package:test/test.dart'; + import 'package:html/dom.dart'; import 'package:html/parser.dart'; -import 'package:html/parser_console.dart' as parser_console; -import 'package:html/src/inputstream.dart' as inputstream; +import 'package:path/path.dart' as pathos; +import 'package:test/test.dart'; + import 'support.dart'; // Run the parse error checks @@ -71,16 +70,6 @@ void runParserTest( } void main() { - test('dart:io', () { - // ensure IO support is unregistered - expect(inputstream.consoleSupport, - const TypeMatcher<inputstream.ConsoleSupport>()); - var file = File('$testDataDir/parser_feature/raw_file.html').openSync(); - expect(() => parse(file), throwsA(const TypeMatcher<ArgumentError>())); - parser_console.useConsole(); - expect(parse(file).body.innerHtml.trim(), 'Hello world!'); - }); - for (var path in getDataFiles('tree-construction')) { if (!path.endsWith('.dat')) continue; From 5f59a77e7867a8062871d52768f844bb61308ee8 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Mon, 8 Apr 2019 17:18:04 -0700 Subject: [PATCH 102/212] Prepare to release 0.14.0 (dart-lang/html#94) --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 92e502e9e..81dcae981 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.14.0-dev +version: 0.14.0 description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> From 2470cd8b1f6d27fc706950bfd485a93c68dc3565 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" <lrn@google.com> Date: Tue, 9 Apr 2019 16:15:53 +0200 Subject: [PATCH 103/212] Don't depend on `pacakge:utf` (dart-lang/html#95) --- pkgs/html/lib/src/char_encodings.dart | 44 +---- pkgs/html/lib/src/utf.dart | 237 -------------------------- pkgs/html/pubspec.yaml | 3 +- pkgs/html/test/tokenizer_test.dart | 4 +- 4 files changed, 8 insertions(+), 280 deletions(-) delete mode 100644 pkgs/html/lib/src/utf.dart diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart index 6120056ba..95755d042 100644 --- a/pkgs/html/lib/src/char_encodings.dart +++ b/pkgs/html/lib/src/char_encodings.dart @@ -1,4 +1,4 @@ -import 'utf.dart'; +import 'dart:convert' show ascii, utf8; // TODO(jmesserly): this function is conspicuously absent from dart:utf. /// Returns true if the [bytes] starts with a UTF-8 byte order mark. @@ -20,29 +20,12 @@ bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { Iterable<int> decodeBytes(String encoding, List<int> bytes) { switch (encoding) { case 'ascii': - // TODO(jmesserly): this was taken from runtime/bin/string_stream.dart - for (int byte in bytes) { - if (byte > 127) { - // TODO(jmesserly): ideally this would be DecoderException, like the - // one thrown in runtime/bin/string_stream.dart, but we don't want to - // depend on dart:io. - throw FormatException("Illegal ASCII character $byte"); - } - } - return bytes; + return ascii.decode(bytes).runes; case 'utf-8': - // NOTE: to match the behavior of the other decode functions, we eat the - // utf-8 BOM here. - - var offset = 0; - var length = bytes.length; - - if (hasUtf8Bom(bytes)) { - offset += 3; - length -= 3; - } - return decodeUtf8AsIterable(bytes, offset, length); + // NOTE: To match the behavior of the other decode functions, we eat the + // UTF-8 BOM here. This is the default behavior of `utf8.decode`. + return utf8.decode(bytes).runes; default: throw ArgumentError('Encoding $encoding not supported'); @@ -53,20 +36,5 @@ Iterable<int> decodeBytes(String encoding, List<int> bytes) { /// Returns the code points for the [input]. This works like [String.charCodes] /// but it decodes UTF-16 surrogate pairs. List<int> toCodepoints(String input) { - var newCodes = <int>[]; - for (int i = 0; i < input.length; i++) { - var c = input.codeUnitAt(i); - if (0xD800 <= c && c <= 0xDBFF) { - int next = i + 1; - if (next < input.length) { - var d = input.codeUnitAt(next); - if (0xDC00 <= d && d <= 0xDFFF) { - c = 0x10000 + ((c - 0xD800) << 10) + (d - 0xDC00); - i = next; - } - } - } - newCodes.add(c); - } - return newCodes; + return input.runes.toList(); } diff --git a/pkgs/html/lib/src/utf.dart b/pkgs/html/lib/src/utf.dart deleted file mode 100644 index a635db8b8..000000000 --- a/pkgs/html/lib/src/utf.dart +++ /dev/null @@ -1,237 +0,0 @@ -// Large portions of this code where taken from https://github.com/dart-lang/utf - -import "dart:collection"; - -const int _replacementCodepoint = 0xfffd; - -const int _UNICODE_VALID_RANGE_MAX = 0x10ffff; -const int _UNICODE_UTF16_RESERVED_LO = 0xd800; -const int _UNICODE_UTF16_RESERVED_HI = 0xdfff; - -const int _UTF8_ONE_BYTE_MAX = 0x7f; -const int _UTF8_TWO_BYTE_MAX = 0x7ff; -const int _UTF8_THREE_BYTE_MAX = 0xffff; - -const int _UTF8_LO_SIX_BIT_MASK = 0x3f; - -const int _UTF8_FIRST_BYTE_OF_TWO_BASE = 0xc0; -const int _UTF8_FIRST_BYTE_OF_THREE_BASE = 0xe0; -const int _UTF8_FIRST_BYTE_OF_FOUR_BASE = 0xf0; -const int _UTF8_FIRST_BYTE_OF_FIVE_BASE = 0xf8; -const int _UTF8_FIRST_BYTE_OF_SIX_BASE = 0xfc; - -const int _UTF8_FIRST_BYTE_BOUND_EXCL = 0xfe; - -/// Decodes the UTF-8 bytes as an iterable. Thus, the consumer can only convert -/// as much of the input as needed. Set the replacementCharacter to null to -/// throw an ArgumentError rather than replace the bad value. -Iterable<int> decodeUtf8AsIterable(List<int> bytes, int offset, int length) => - _IterableUtf8Decoder(bytes, offset, length); - -/// Return type of [decodeUtf8AsIterable] and variants. The Iterable type -/// provides an iterator on demand and the iterator will only translate bytes -/// as requested by the user of the iterator. (Note: results are not cached.) -// TODO(floitsch): Consider removing the extend and switch to implements since -// that's cheaper to allocate. -class _IterableUtf8Decoder extends IterableBase<int> { - final List<int> bytes; - final int offset; - final int length; - - _IterableUtf8Decoder(this.bytes, this.offset, this.length); - - _Utf8Decoder get iterator => _Utf8Decoder(bytes, offset, length); -} - -/// Provides an iterator of Unicode codepoints from UTF-8 encoded bytes. The -/// parameters can set an offset into a list of bytes (as int), limit the length -/// of the values to be decoded, and override the default Unicode replacement -/// character. Set the replacementCharacter to null to throw an -/// ArgumentError rather than replace the bad value. The return value -/// from this method can be used as an Iterable (e.g. in a for-loop). -class _Utf8Decoder implements Iterator<int> { - final _ListRangeIterator utf8EncodedBytesIterator; - int _current; - - _Utf8Decoder(List<int> utf8EncodedBytes, int offset, int length) - : utf8EncodedBytesIterator = - (_ListRange(utf8EncodedBytes, offset, length)).iterator; - - _Utf8Decoder._fromListRangeIterator(_ListRange source) - : utf8EncodedBytesIterator = source.iterator; - - /// Decode the remaininder of the characters in this decoder - /// into a [List<int>]. - List<int> decodeRest() { - List<int> codepoints = List<int>(utf8EncodedBytesIterator.remaining); - int i = 0; - while (moveNext()) { - codepoints[i++] = current; - } - if (i == codepoints.length) { - return codepoints; - } else { - List<int> truncCodepoints = List<int>(i); - truncCodepoints.setRange(0, i, codepoints); - return truncCodepoints; - } - } - - int get current => _current; - - bool moveNext() { - _current = null; - - if (!utf8EncodedBytesIterator.moveNext()) return false; - - int value = utf8EncodedBytesIterator.current; - int additionalBytes = 0; - - if (value < 0) { - if (_replacementCodepoint != null) { - _current = _replacementCodepoint; - return true; - } else { - throw ArgumentError( - "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); - } - } else if (value <= _UTF8_ONE_BYTE_MAX) { - _current = value; - return true; - } else if (value < _UTF8_FIRST_BYTE_OF_TWO_BASE) { - if (_replacementCodepoint != null) { - _current = _replacementCodepoint; - return true; - } else { - throw ArgumentError( - "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); - } - } else if (value < _UTF8_FIRST_BYTE_OF_THREE_BASE) { - value -= _UTF8_FIRST_BYTE_OF_TWO_BASE; - additionalBytes = 1; - } else if (value < _UTF8_FIRST_BYTE_OF_FOUR_BASE) { - value -= _UTF8_FIRST_BYTE_OF_THREE_BASE; - additionalBytes = 2; - } else if (value < _UTF8_FIRST_BYTE_OF_FIVE_BASE) { - value -= _UTF8_FIRST_BYTE_OF_FOUR_BASE; - additionalBytes = 3; - } else if (value < _UTF8_FIRST_BYTE_OF_SIX_BASE) { - value -= _UTF8_FIRST_BYTE_OF_FIVE_BASE; - additionalBytes = 4; - } else if (value < _UTF8_FIRST_BYTE_BOUND_EXCL) { - value -= _UTF8_FIRST_BYTE_OF_SIX_BASE; - additionalBytes = 5; - } else if (_replacementCodepoint != null) { - _current = _replacementCodepoint; - return true; - } else { - throw ArgumentError( - "Invalid UTF8 at ${utf8EncodedBytesIterator.position}"); - } - int j = 0; - while (j < additionalBytes && utf8EncodedBytesIterator.moveNext()) { - int nextValue = utf8EncodedBytesIterator.current; - if (nextValue > _UTF8_ONE_BYTE_MAX && - nextValue < _UTF8_FIRST_BYTE_OF_TWO_BASE) { - value = ((value << 6) | (nextValue & _UTF8_LO_SIX_BIT_MASK)); - } else { - // if sequence-starting code unit, reposition cursor to start here - if (nextValue >= _UTF8_FIRST_BYTE_OF_TWO_BASE) { - utf8EncodedBytesIterator.backup(); - } - break; - } - j++; - } - bool validSequence = (j == additionalBytes && - (value < _UNICODE_UTF16_RESERVED_LO || - value > _UNICODE_UTF16_RESERVED_HI)); - bool nonOverlong = (additionalBytes == 1 && value > _UTF8_ONE_BYTE_MAX) || - (additionalBytes == 2 && value > _UTF8_TWO_BYTE_MAX) || - (additionalBytes == 3 && value > _UTF8_THREE_BYTE_MAX); - bool inRange = value <= _UNICODE_VALID_RANGE_MAX; - if (validSequence && nonOverlong && inRange) { - _current = value; - return true; - } else if (_replacementCodepoint != null) { - _current = _replacementCodepoint; - return true; - } else { - throw ArgumentError( - "Invalid UTF8 at ${utf8EncodedBytesIterator.position - j}"); - } - } -} - -/// _ListRange in an internal type used to create a lightweight Interable on a -/// range within a source list. DO NOT MODIFY the underlying list while -/// iterating over it. The results of doing so are undefined. -// TODO(floitsch): Consider removing the extend and switch to implements since -// that's cheaper to allocate. -class _ListRange extends IterableBase<int> { - final List<int> _source; - final int _offset; - final int _length; - - _ListRange(List<int> source, [int offset = 0, int length]) - : _source = source, - _offset = offset, - _length = (length == null ? source.length - offset : length) { - if (_offset < 0 || _offset > _source.length) { - throw RangeError.value(_offset); - } - if (_length != null && (_length < 0)) { - throw RangeError.value(_length); - } - if (_length + _offset > _source.length) { - throw RangeError.value(_length + _offset); - } - } - - _ListRangeIterator get iterator => - _ListRangeIteratorImpl(_source, _offset, _offset + _length); - - int get length => _length; -} - -/// The ListRangeIterator provides more capabilities than a standard iterator, -/// including the ability to get the current position, count remaining items, -/// and move forward/backward within the iterator. -abstract class _ListRangeIterator implements Iterator<int> { - bool moveNext(); - - int get current; - - int get position; - - void backup([int by]); - - int get remaining; - - void skip([int count]); -} - -class _ListRangeIteratorImpl implements _ListRangeIterator { - final List<int> _source; - int _offset; - final int _end; - - _ListRangeIteratorImpl(this._source, int offset, this._end) - : _offset = offset - 1; - - int get current => _source[_offset]; - - bool moveNext() => ++_offset < _end; - - int get position => _offset; - - void backup([int by = 1]) { - _offset -= by; - } - - int get remaining => _end - _offset - 1; - - void skip([int count = 1]) { - _offset += count; - } -} diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 81dcae981..90c3b3363 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.14.0 +version: 0.14.1-dev description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> @@ -16,4 +16,3 @@ dev_dependencies: path: ^1.6.2 pedantic: ^1.3.0 test: ^1.3.0 - utf: '>=0.9.0 <0.10.0' diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 744a49666..59dd2aad8 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -7,10 +7,8 @@ import 'dart:io'; import 'dart:mirrors'; import 'package:path/path.dart' as pathos; import 'package:test/test.dart'; -import 'package:html/src/char_encodings.dart'; import 'package:html/src/token.dart'; import 'package:html/src/tokenizer.dart'; -import 'package:utf/utf.dart'; import 'support.dart'; class TokenizerTestParser { @@ -24,7 +22,7 @@ class TokenizerTestParser { List parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. - var bytes = codepointsToUtf8(toCodepoints(str)); + var bytes = utf8.encode(str); var tokenizer = HtmlTokenizer(bytes, encoding: 'utf-8'); outputTokens = []; From 9329a1aa7cf37145a14488774521ed29e794440f Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 10 Apr 2019 17:35:05 -0700 Subject: [PATCH 104/212] Code cleanup (dart-lang/html#96) --- pkgs/html/lib/src/char_encodings.dart | 40 ------------------------ pkgs/html/lib/src/html_input_stream.dart | 37 +++++++++++++++++++--- 2 files changed, 33 insertions(+), 44 deletions(-) delete mode 100644 pkgs/html/lib/src/char_encodings.dart diff --git a/pkgs/html/lib/src/char_encodings.dart b/pkgs/html/lib/src/char_encodings.dart deleted file mode 100644 index 95755d042..000000000 --- a/pkgs/html/lib/src/char_encodings.dart +++ /dev/null @@ -1,40 +0,0 @@ -import 'dart:convert' show ascii, utf8; - -// TODO(jmesserly): this function is conspicuously absent from dart:utf. -/// Returns true if the [bytes] starts with a UTF-8 byte order mark. -/// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is -/// used in HTML to detect the UTF- -bool hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { - int end = length != null ? offset + length : bytes.length; - return (offset + 3) <= end && - bytes[offset] == 0xEF && - bytes[offset + 1] == 0xBB && - bytes[offset + 2] == 0xBF; -} - -// TODO(jmesserly): it's unfortunate that this has to be one-shot on the entire -// file, but dart:utf does not expose stream-based decoders yet. -/// Decodes the [bytes] with the provided [encoding] and returns an iterable for -/// the codepoints. Supports the major unicode encodings as well as ascii and -/// and windows-1252 encodings. -Iterable<int> decodeBytes(String encoding, List<int> bytes) { - switch (encoding) { - case 'ascii': - return ascii.decode(bytes).runes; - - case 'utf-8': - // NOTE: To match the behavior of the other decode functions, we eat the - // UTF-8 BOM here. This is the default behavior of `utf8.decode`. - return utf8.decode(bytes).runes; - - default: - throw ArgumentError('Encoding $encoding not supported'); - } -} - -// TODO(jmesserly): use dart:utf once http://dartbug.com/6476 is fixed. -/// Returns the code points for the [input]. This works like [String.charCodes] -/// but it decodes UTF-16 surrogate pairs. -List<int> toCodepoints(String input) { - return input.runes.toList(); -} diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 84d2f1345..42b174171 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -1,8 +1,8 @@ import 'dart:collection'; +import 'dart:convert' show ascii, utf8; import 'package:source_span/source_span.dart'; -import 'char_encodings.dart'; import 'constants.dart'; import 'encoding_parser.dart'; import 'utils.dart'; @@ -66,7 +66,7 @@ class HtmlInputStream { this.sourceUrl]) : charEncodingName = codecName(encoding) { if (source is String) { - _rawChars = toCodepoints(source); + _rawChars = source.runes.toList(); charEncodingName = 'utf-8'; charEncodingCertain = true; } else if (source is List<int>) { @@ -92,7 +92,7 @@ class HtmlInputStream { _chars = <int>[]; if (_rawChars == null) { - _rawChars = decodeBytes(charEncodingName, _rawBytes); + _rawChars = _decodeBytes(charEncodingName, _rawBytes); } bool skipNewline = false; @@ -177,7 +177,7 @@ class HtmlInputStream { /// encoding otherwise return null. String detectBOM() { // Try detecting the BOM using bytes from the string - if (hasUtf8Bom(_rawBytes)) { + if (_hasUtf8Bom(_rawBytes)) { return 'utf-8'; } return null; @@ -292,3 +292,32 @@ String codecName(String encoding) { var canonicalName = encoding.replaceAll(asciiPunctuation, '').toLowerCase(); return encodings[canonicalName]; } + +/// Returns true if the [bytes] starts with a UTF-8 byte order mark. +/// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is +/// used in HTML to detect the UTF- +bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { + int end = length != null ? offset + length : bytes.length; + return (offset + 3) <= end && + bytes[offset] == 0xEF && + bytes[offset + 1] == 0xBB && + bytes[offset + 2] == 0xBF; +} + +/// Decodes the [bytes] with the provided [encoding] and returns an iterable for +/// the codepoints. Supports the major unicode encodings as well as ascii and +/// and windows-1252 encodings. +Iterable<int> _decodeBytes(String encoding, List<int> bytes) { + switch (encoding) { + case 'ascii': + return ascii.decode(bytes).runes; + + case 'utf-8': + // NOTE: To match the behavior of the other decode functions, we eat the + // UTF-8 BOM here. This is the default behavior of `utf8.decode`. + return utf8.decode(bytes).runes; + + default: + throw ArgumentError('Encoding $encoding not supported'); + } +} From dcf628d8b7f16e635f7ad413833a383315521b78 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 10 Apr 2019 18:09:30 -0700 Subject: [PATCH 105/212] Support the latest pkg:csslib on the 0.13 version path (dart-lang/html#97) If folks have not upgraded to the latest pkg:html, they should still be able to get the latest pkg:csslib (This is particularly important since there is a pkg:analyzer dependency here that moves slowly.) --- pkgs/html/.travis.yml | 4 +++- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/lib/src/constants.dart | 16 ++++++++-------- pkgs/html/pubspec.yaml | 4 ++-- 4 files changed, 17 insertions(+), 11 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 714aa8610..353f809a9 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -1,6 +1,8 @@ language: dart dart: + - 2.0.0 - dev + dart_task: - test: -p vm - test: -p chrome,firefox @@ -13,7 +15,7 @@ matrix: # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, v0_13] cache: directories: diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 14eb41cd5..350ac5084 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.13.4+2 + +- Support `package:css` `>=0.13.2 <0.16.0`. + ## 0.13.4+1 * Fixes to readme and pubspec. diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index fc0c6a1a3..34addfc08 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -29,10 +29,10 @@ const Map<String, String> errorMessages = { "Entity used with illegal number (windows-1252 reference).", "cant-convert-numeric-entity": "Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x).", + "(codepoint U+%(charAsInt)08x).", "illegal-codepoint-for-numeric-entity": "Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x.", + "U+%(charAsInt)08x.", "numeric-entity-without-semicolon": "Numeric entity didn't end with ';'.", "expected-numeric-entity-but-got-eof": "Numeric entity expected. Got end of file instead.", @@ -46,7 +46,7 @@ const Map<String, String> errorMessages = { "Expected tag name. Got '>' instead.", "expected-tag-name-but-got-question-mark": "Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)", + "support processing instructions.)", "expected-tag-name": "Expected tag name. Got something else instead", "expected-closing-tag-but-got-right-bracket": "Expected closing tag. Got '>' instead. Ignoring '</>'.", @@ -133,7 +133,7 @@ const Map<String, String> errorMessages = { "missing-end-tags": "Missing end tags (%(name)s).", "unexpected-start-tag-implies-end-tag": "Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s).", + "implies end tag (%(endName)s).", "unexpected-start-tag-treated-as": "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", "deprecated-tag": "Unexpected start tag %(name)s. Don't use it!", @@ -165,7 +165,7 @@ const Map<String, String> errorMessages = { "unexpected-form-in-table": "Unexpected form in table context.", "unexpected-start-tag-implies-table-voodoo": "Unexpected start tag (%(name)s) in " - "table context caused voodoo mode.", + "table context caused voodoo mode.", "unexpected-end-tag-implies-table-voodoo": "Unexpected end tag (%(name)s) in " "table context caused voodoo mode.", "unexpected-cell-in-table-body": "Unexpected table cell start tag (%(name)s) " @@ -180,12 +180,12 @@ const Map<String, String> errorMessages = { "Unexpected end tag (%(name)s) in the table row phase. Ignored.", "unexpected-select-in-select": "Unexpected select start tag in the select phase " - "treated as select end tag.", + "treated as select end tag.", "unexpected-input-in-select": "Unexpected input start tag in the select phase.", "unexpected-start-tag-in-select": "Unexpected start tag token (%(name)s in the select phase. " - "Ignored.", + "Ignored.", "unexpected-end-tag-in-select": "Unexpected end tag (%(name)s) in the select phase. Ignored.", "unexpected-table-element-start-tag-in-select-in-table": @@ -204,7 +204,7 @@ const Map<String, String> errorMessages = { " in the frameset phase. Ignored.", "unexpected-frameset-in-frameset-innerhtml": "Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML).", + "in the frameset phase (innerHTML).", "unexpected-end-tag-in-frameset": "Unexpected end tag token (%(name)s)" " in the frameset phase. Ignored.", "unexpected-char-after-frameset": "Unexpected non-space characters in the " diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index b3cf48832..e13c01ae3 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.13.4+1 +version: 0.13.4+2 description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> @@ -9,7 +9,7 @@ environment: sdk: '>=2.0.0 <3.0.0' dependencies: - csslib: '>=0.13.2 <0.15.0' + csslib: '>=0.13.2 <0.16.0' source_span: '>=1.0.0 <2.0.0' utf: '>=0.9.0 <0.10.0' From 6d868672ae2e89cf672d801be3ea9e988cde6c71 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 24 Apr 2019 16:37:44 -0700 Subject: [PATCH 106/212] Support the latest pkg:css, prepare to release 0.14.0+2 (dart-lang/html#103) --- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/pubspec.yaml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 139ec419a..020817914 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.14.0+2 + +- Support `package:css` `>=0.13.2 <0.17.0`. + ## 0.14.0+1 - Support `package:css` `>=0.13.2 <0.16.0`. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 4480d4190..fcd9ca065 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.14.0+1 +version: 0.14.0+2 description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> @@ -9,7 +9,7 @@ environment: sdk: '>=2.0.0 <3.0.0' dependencies: - csslib: '>=0.13.2 <0.16.0' + csslib: '>=0.13.2 <0.17.0' source_span: '>=1.0.0 <2.0.0' dev_dependencies: From 2f306e4cf03419a14fad01f95cb0ffb58751cb74 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Thu, 9 May 2019 11:51:21 -0700 Subject: [PATCH 107/212] fix latest pedantic lints (dart-lang/html#106) --- pkgs/html/lib/dom.dart | 20 +++++++++++++++----- pkgs/html/lib/dom_parsing.dart | 4 +++- pkgs/html/lib/src/utils.dart | 4 +++- pkgs/html/test/support.dart | 8 ++++++-- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 1a6e7ed45..715ce83fe 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -223,7 +223,9 @@ abstract class Node { void _addOuterHtml(StringBuffer str); void _addInnerHtml(StringBuffer str) { - for (Node child in nodes) child._addOuterHtml(str); + for (Node child in nodes) { + child._addOuterHtml(str); + } } Node remove() { @@ -704,7 +706,9 @@ class NodeList extends ListProxy<Node> { // are removed from the original NodeList (if any) from the end, which // is faster. var list = _flattenDocFragments(collection); - for (var node in list.reversed) _setParent(node); + for (var node in list.reversed) { + _setParent(node); + } super.addAll(list); } @@ -721,7 +725,9 @@ class NodeList extends ListProxy<Node> { Node removeAt(int i) => super.removeAt(i)..parentNode = null; void clear() { - for (var node in this) node.parentNode = null; + for (var node in this) { + node.parentNode = null; + } super.clear(); } @@ -757,7 +763,9 @@ class NodeList extends ListProxy<Node> { } void removeRange(int start, int rangeLength) { - for (int i = start; i < rangeLength; i++) this[i].parentNode = null; + for (int i = start; i < rangeLength; i++) { + this[i].parentNode = null; + } super.removeRange(start, rangeLength); } @@ -778,7 +786,9 @@ class NodeList extends ListProxy<Node> { void insertAll(int index, Iterable<Node> collection) { // Note: we need to be careful how we copy nodes. See note in addAll. var list = _flattenDocFragments(collection); - for (var node in list.reversed) _setParent(node); + for (var node in list.reversed) { + _setParent(node); + } super.insertAll(index, list); } diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index ba2fccfca..27eedb3be 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -28,7 +28,9 @@ class TreeVisitor { visitChildren(Node node) { // Allow for mutations (remove works) while iterating. - for (var child in node.nodes.toList()) visit(child); + for (var child in node.nodes.toList()) { + visit(child); + } } /// The fallback handler if the more specific visit method hasn't been diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 3c0249438..54b578bc7 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -65,7 +65,9 @@ String padWithZeros(String str, int size) { if (str.length == size) return str; var result = StringBuffer(); size -= str.length; - for (int i = 0; i < size; i++) result.write('0'); + for (int i = 0; i < size; i++) { + result.write('0'); + } result.write(str); return result.toString(); } diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 8afbee032..d97bff2e1 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -132,7 +132,9 @@ class TestSerializer extends TreeVisitor { visitChildren(Node node) { indent += 2; - for (var child in node.nodes) visit(child); + for (var child in node.nodes) { + visit(child); + } indent -= 2; } @@ -140,7 +142,9 @@ class TestSerializer extends TreeVisitor { _visitDocumentOrFragment(node) { indent += 1; - for (var child in node.nodes) visit(child); + for (var child in node.nodes) { + visit(child); + } indent -= 1; } From f446b88c22fb99364ac99e1621d296dec1f4740b Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Sat, 6 Jul 2019 16:12:50 -0400 Subject: [PATCH 108/212] fix latest pedantic lints (dart-lang/html#107) --- pkgs/html/lib/dom.dart | 3 +-- pkgs/html/test/support.dart | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 715ce83fe..08d1c1240 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -830,8 +830,7 @@ class FilteredElementList extends IterableBase<Element> // // TODO(nweiz): we don't always need to create a new list. For example // forEach, every, any, ... could directly work on the _childNodes. - List<Element> get _filtered => - List<Element>.from(_childNodes.where((n) => n is Element)); + List<Element> get _filtered => _childNodes.whereType<Element>().toList(); void forEach(void f(Element element)) { _filtered.forEach(f); diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index d97bff2e1..83e137a91 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -26,7 +26,7 @@ final testDataDir = p.join(testDir, 'data'); Iterable<String> getDataFiles(String subdirectory) { var dir = Directory(p.join(testDataDir, subdirectory)); - return dir.listSync().where((f) => f is File).map((f) => f.path); + return dir.listSync().whereType<File>().map((f) => f.path); } // TODO(jmesserly): make this class simpler. We could probably split on From e5d5b1dcfb5b618422c2802a6c16417f789656d7 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 10 Jul 2019 15:57:24 -0700 Subject: [PATCH 109/212] fix lint (dart-lang/html#108) --- pkgs/html/test/tokenizer_test.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 59dd2aad8..ccb9d8cf7 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -5,15 +5,17 @@ library tokenizer_test; import 'dart:convert'; import 'dart:io'; import 'dart:mirrors'; -import 'package:path/path.dart' as pathos; -import 'package:test/test.dart'; + import 'package:html/src/token.dart'; import 'package:html/src/tokenizer.dart'; +import 'package:path/path.dart' as pathos; +import 'package:test/test.dart'; + import 'support.dart'; class TokenizerTestParser { - String _state; - String _lastStartTag; + final String _state; + final String _lastStartTag; List outputTokens; TokenizerTestParser(String initialState, [String lastStartTag]) From df1f11b774763bda05be452d5f1c842fbfb703d0 Mon Sep 17 00:00:00 2001 From: cvolzke4 <45087979+cvolzke4@users.noreply.github.com> Date: Fri, 20 Sep 2019 09:06:20 +1000 Subject: [PATCH 110/212] Fix spans generated for HTML with higher-plane unicode characters (dart-lang/html#109) --- pkgs/html/.travis.yml | 2 +- pkgs/html/CHANGELOG.md | 4 ++ pkgs/html/lib/src/html_input_stream.dart | 57 ++++++++++++++----- pkgs/html/pubspec.yaml | 2 +- .../tokenizer/unicodeCharsSurrogates.test | 24 ++++++++ pkgs/html/test/tokenizer_test.dart | 47 +++++++++------ 6 files changed, 103 insertions(+), 33 deletions(-) create mode 100644 pkgs/html/test/data/tokenizer/unicodeCharsSurrogates.test diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 337cecabf..00333322d 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev - - 2.0.0 + - 2.3.0 dart_task: - test: -p vm diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 020817914..9bd9d29bf 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.14.0+3 + +- Fix spans generated for HTML with higher-plane unicode characters (eg. emojis) + ## 0.14.0+2 - Support `package:css` `>=0.13.2 <0.17.0`. diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 42b174171..4590c5d83 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -33,7 +33,7 @@ class HtmlInputStream { List<int> _rawBytes; /// Raw UTF-16 codes, used if a Dart String is passed in. - Iterable<int> _rawChars; + List<int> _rawChars; Queue<String> errors; @@ -66,7 +66,7 @@ class HtmlInputStream { this.sourceUrl]) : charEncodingName = codecName(encoding) { if (source is String) { - _rawChars = source.runes.toList(); + _rawChars = source.codeUnits; charEncodingName = 'utf-8'; charEncodingCertain = true; } else if (source is List<int>) { @@ -96,17 +96,27 @@ class HtmlInputStream { } bool skipNewline = false; - for (var c in _rawChars) { + bool wasSurrogatePair = false; + for (int i = 0; i < _rawChars.length; i++) { + int c = _rawChars[i]; if (skipNewline) { skipNewline = false; if (c == NEWLINE) continue; } - if (_invalidUnicode(c)) errors.add('invalid-codepoint'); + final isSurrogatePair = _isSurrogatePair(_rawChars, i); + if (!isSurrogatePair && !wasSurrogatePair) { + if (_invalidUnicode(c)) { + errors.add('invalid-codepoint'); - if (0xD800 <= c && c <= 0xDFFF) { - c = 0xFFFD; - } else if (c == RETURN) { + if (0xD800 <= c && c <= 0xDFFF) { + c = 0xFFFD; + } + } + } + wasSurrogatePair = isSurrogatePair; + + if (c == RETURN) { skipNewline = true; c = NEWLINE; } @@ -203,21 +213,38 @@ class HtmlInputStream { /// EOF when EOF is reached. String char() { if (_offset >= _chars.length) return eof; - return String.fromCharCodes([_chars[_offset++]]); + return _isSurrogatePair(_chars, _offset) + ? String.fromCharCodes([_chars[_offset++], _chars[_offset++]]) + : String.fromCharCodes([_chars[_offset++]]); } String peekChar() { if (_offset >= _chars.length) return eof; - return String.fromCharCodes([_chars[_offset]]); + return _isSurrogatePair(_chars, _offset) + ? String.fromCharCodes([_chars[_offset], _chars[_offset + 1]]) + : String.fromCharCodes([_chars[_offset]]); + } + + // Whether the current and next chars indicate a surrogate pair. + bool _isSurrogatePair(List<int> chars, int i) { + return i + 1 < chars.length && + _isLeadSurrogate(chars[i]) && + _isTrailSurrogate(chars[i + 1]); } + // Is then code (a 16-bit unsigned integer) a UTF-16 lead surrogate. + bool _isLeadSurrogate(int code) => (code & 0xFC00) == 0xD800; + + // Is then code (a 16-bit unsigned integer) a UTF-16 trail surrogate. + bool _isTrailSurrogate(int code) => (code & 0xFC00) == 0xDC00; + /// Returns a string of characters from the stream up to but not /// including any character in 'characters' or EOF. String charsUntil(String characters, [bool opposite = false]) { int start = _offset; String c; while ((c = peekChar()) != null && characters.contains(c) == opposite) { - _offset++; + _offset += c.codeUnits.length; } return String.fromCharCodes(_chars.sublist(start, _offset)); @@ -227,7 +254,7 @@ class HtmlInputStream { // Only one character is allowed to be ungotten at once - it must // be consumed again before any further call to unget if (ch != null) { - _offset--; + _offset -= ch.codeUnits.length; assert(peekChar() == ch); } } @@ -304,18 +331,18 @@ bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { bytes[offset + 2] == 0xBF; } -/// Decodes the [bytes] with the provided [encoding] and returns an iterable for +/// Decodes the [bytes] with the provided [encoding] and returns a list for /// the codepoints. Supports the major unicode encodings as well as ascii and /// and windows-1252 encodings. -Iterable<int> _decodeBytes(String encoding, List<int> bytes) { +List<int> _decodeBytes(String encoding, List<int> bytes) { switch (encoding) { case 'ascii': - return ascii.decode(bytes).runes; + return ascii.decode(bytes).codeUnits; case 'utf-8': // NOTE: To match the behavior of the other decode functions, we eat the // UTF-8 BOM here. This is the default behavior of `utf8.decode`. - return utf8.decode(bytes).runes; + return utf8.decode(bytes).codeUnits; default: throw ArgumentError('Encoding $encoding not supported'); diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index fcd9ca065..b5eaa1a37 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -6,7 +6,7 @@ author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/html environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.3.0 <3.0.0' dependencies: csslib: '>=0.13.2 <0.17.0' diff --git a/pkgs/html/test/data/tokenizer/unicodeCharsSurrogates.test b/pkgs/html/test/data/tokenizer/unicodeCharsSurrogates.test new file mode 100644 index 000000000..9b56a98fd --- /dev/null +++ b/pkgs/html/test/data/tokenizer/unicodeCharsSurrogates.test @@ -0,0 +1,24 @@ +{"tests" : [ +{"description": "Unicode surrogate (emoji)", +"input": "\uD83D\uDC3C", +"output":[["Character", "\uD83D\uDC3C"]]}, + +{"description": "Unicode surrogate (emoji) prefixed by characters", +"input": "before\uD83D\uDC3C", +"output":[["Character", "before\uD83D\uDC3C"]]}, + +{"description": "Unicode surrogate (emoji) suffixed by characters", +"input": "\uD83D\uDC3Cafter", +"output":[["Character", "\uD83D\uDC3Cafter"]]}, + +{"description":"Quoted attribute with surrogate unicode content", +"generateSpans": true, +"input":"<a href='\uD83D\uDC3C'/>", +"output":[["StartTag","a",{"href":"\uD83D\uDC3C"},true,0,14]]}, + +{"description":"Surrogate unicode content followed by attribute", +"generateSpans": true, +"input":"\uD83D\uDC3C<a href='b'/>", +"output":[["Character", "\uD83D\uDC3C", 0, 2],["StartTag","a",{"href":"b"},true,2,15]]} +] +} \ No newline at end of file diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index ccb9d8cf7..3d2aeb32a 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -16,16 +16,20 @@ import 'support.dart'; class TokenizerTestParser { final String _state; final String _lastStartTag; + final bool _generateSpans; List outputTokens; - TokenizerTestParser(String initialState, [String lastStartTag]) + TokenizerTestParser(String initialState, + [String lastStartTag, bool generateSpans = false]) : _state = initialState, - _lastStartTag = lastStartTag; + _lastStartTag = lastStartTag, + _generateSpans = generateSpans; List parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. var bytes = utf8.encode(str); - var tokenizer = HtmlTokenizer(bytes, encoding: 'utf-8'); + var tokenizer = + HtmlTokenizer(bytes, encoding: 'utf-8', generateSpans: _generateSpans); outputTokens = []; // Note: we can't get a closure of the state method. However, we can @@ -68,20 +72,21 @@ class TokenizerTestParser { } void processDoctype(DoctypeToken token) { - outputTokens.add( + addOutputToken(token, ["DOCTYPE", token.name, token.publicId, token.systemId, token.correct]); } void processStartTag(StartTagToken token) { - outputTokens.add(["StartTag", token.name, token.data, token.selfClosing]); + addOutputToken( + token, ["StartTag", token.name, token.data, token.selfClosing]); } void processEndTag(EndTagToken token) { - outputTokens.add(["EndTag", token.name, token.selfClosing]); + addOutputToken(token, ["EndTag", token.name, token.selfClosing]); } void processComment(StringToken token) { - outputTokens.add(["Comment", token.data]); + addOutputToken(token, ["Comment", token.data]); } void processSpaceCharacters(StringToken token) { @@ -89,7 +94,7 @@ class TokenizerTestParser { } void processCharacters(StringToken token) { - outputTokens.add(["Character", token.data]); + addOutputToken(token, ["Character", token.data]); } void processEOF(token) {} @@ -98,7 +103,15 @@ class TokenizerTestParser { // TODO(jmesserly): when debugging test failures it can be useful to add // logging here like `print('ParseError $token');`. It would be nice to // use the actual logging library. - outputTokens.add(["ParseError", token.data]); + addOutputToken(token, ["ParseError", token.data]); + } + + void addOutputToken(Token token, List array) { + outputTokens.add([ + ...array, + if (token.span != null && _generateSpans) token.span.start.offset, + if (token.span != null && _generateSpans) token.span.end.offset, + ]); } } @@ -138,16 +151,18 @@ List normalizeTokens(List tokens) { void expectTokensMatch( List expectedTokens, List receivedTokens, bool ignoreErrorOrder, [bool ignoreErrors = false, String message]) { - var checkSelfClosing = false; + // If the 'selfClosing' attribute is not included in the expected test tokens, + // remove it from the received token. + var removeSelfClosing = false; for (var token in expectedTokens) { - if (token[0] == "StartTag" && token.length == 4 || - token[0] == "EndTag" && token.length == 3) { - checkSelfClosing = true; + if (token[0] == "StartTag" && token.length == 3 || + token[0] == "EndTag" && token.length == 2) { + removeSelfClosing = true; break; } } - if (!checkSelfClosing) { + if (removeSelfClosing) { for (var token in receivedTokens) { if (token[0] == "StartTag" || token[0] == "EndTag") { token.removeLast(); @@ -182,8 +197,8 @@ void runTokenizerTest(Map testInfo) { if (!testInfo.containsKey('lastStartTag')) { testInfo['lastStartTag'] = null; } - var parser = - TokenizerTestParser(testInfo['initialState'], testInfo['lastStartTag']); + var parser = TokenizerTestParser(testInfo['initialState'], + testInfo['lastStartTag'], testInfo['generateSpans'] ?? false); var tokens = parser.parse(testInfo['input']); tokens = concatenateCharacterTokens(tokens); var received = normalizeTokens(tokens); From b66bc504d5753c71549d36d145e03da6861a4f65 Mon Sep 17 00:00:00 2001 From: Nicholas Shahan <nshahan@google.com> Date: Mon, 30 Sep 2019 09:47:23 -0700 Subject: [PATCH 111/212] Bump version in pubspec in preparation to publish (dart-lang/html#110) --- pkgs/html/CHANGELOG.md | 5 +++-- pkgs/html/pubspec.yaml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 9bd9d29bf..21fc0411b 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,6 +1,7 @@ ## 0.14.0+3 -- Fix spans generated for HTML with higher-plane unicode characters (eg. emojis) +- Fix spans generated for HTML with higher-plane unicode characters + (eg. emojis). ## 0.14.0+2 @@ -73,7 +74,7 @@ #### Pub version 0.12.2+2 * Support `csslib` versions `0.13.x`. - + #### Pub version 0.12.2+1 * Exclude `.packages` file from the published package. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index b5eaa1a37..71f41db94 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.14.0+2 +version: 0.14.0+3 description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> From bb459abba2e6b15c4961de405eb6dbc87748341b Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Tue, 10 Dec 2019 16:41:35 -0800 Subject: [PATCH 112/212] Fix newly enforced package:pedantic lints (dart-lang/html#111) - always_declare_return_types - annotate_overrides - omit_local_variable_types - prefer_conditional_assignment - prefer_if_null_operators - prefer_single_quotes - use_function_type_syntax_for_parameters Ignore prefer_collection_literals lints since they would require incorrect code where a `{}` (statically a `Map`) is assigned to a static `LinkedHashMap`. See https://github.com/dart-lang/linter/issues/1649 --- pkgs/html/analysis_options.yaml | 2 + pkgs/html/lib/dom.dart | 186 +- pkgs/html/lib/dom_parsing.dart | 78 +- pkgs/html/lib/parser.dart | 1889 +++--- pkgs/html/lib/src/constants.dart | 5263 +++++++++-------- pkgs/html/lib/src/css_class_set.dart | 36 +- pkgs/html/lib/src/encoding_parser.dart | 60 +- pkgs/html/lib/src/html_input_stream.dart | 18 +- pkgs/html/lib/src/list_proxy.dart | 12 + pkgs/html/lib/src/query_selector.dart | 18 +- pkgs/html/lib/src/token.dart | 9 +- pkgs/html/lib/src/tokenizer.dart | 693 +-- pkgs/html/lib/src/treebuilder.dart | 51 +- pkgs/html/lib/src/utils.dart | 18 +- pkgs/html/test/dom_test.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 16 +- pkgs/html/test/parser_test.dart | 22 +- .../test/selectors/level1_baseline_test.dart | 50 +- pkgs/html/test/selectors/level1_lib.dart | 198 +- pkgs/html/test/selectors/selectors.dart | 1392 ++--- pkgs/html/test/support.dart | 39 +- pkgs/html/test/tokenizer_test.dart | 65 +- 22 files changed, 5188 insertions(+), 4929 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 2d3a54d6d..b8dcf936a 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,6 +1,8 @@ include: package:pedantic/analysis_options.yaml analyzer: errors: + # https://github.com/dart-lang/linter/issues/1649 + prefer_collection_literals: ignore unused_element: error unused_import: error unused_local_variable: error diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 08d1c1240..835d8da92 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -36,6 +36,7 @@ class AttributeName implements Comparable { const AttributeName(this.prefix, this.name, this.namespace); + @override String toString() { // Implement: // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments @@ -45,24 +46,26 @@ class AttributeName implements Comparable { return prefix != null ? '$prefix:$name' : name; } + @override int get hashCode { - int h = prefix.hashCode; + var h = prefix.hashCode; h = 37 * (h & 0x1FFFFF) + name.hashCode; h = 37 * (h & 0x1FFFFF) + namespace.hashCode; return h & 0x3FFFFFFF; } + @override int compareTo(other) { // Not sure about this sort order if (other is! AttributeName) return 1; - int cmp = (prefix != null ? prefix : "") - .compareTo((other.prefix != null ? other.prefix : "")); + var cmp = (prefix ?? '').compareTo((other.prefix ?? '')); if (cmp != 0) return cmp; cmp = name.compareTo(other.name); if (cmp != 0) return cmp; return namespace.compareTo(other.namespace); } + @override bool operator ==(x) { if (x is! AttributeName) return false; return prefix == x.prefix && name == x.name && namespace == x.namespace; @@ -184,12 +187,7 @@ abstract class Node { return _attributeValueSpans; } - List<Element> get children { - if (_elements == null) { - _elements = FilteredElementList(this); - } - return _elements; - } + List<Element> get children => _elements ??= FilteredElementList(this); /// Returns a copy of this node. /// @@ -223,7 +221,7 @@ abstract class Node { void _addOuterHtml(StringBuffer str); void _addInnerHtml(StringBuffer str) { - for (Node child in nodes) { + for (var child in nodes) { child._addOuterHtml(str); } } @@ -301,7 +299,7 @@ abstract class Node { } } - _clone(Node shallowClone, bool deep) { + Node _clone(Node shallowClone, bool deep) { if (deep) { for (var child in nodes) { shallowClone.append(child.clone(true)); @@ -316,6 +314,7 @@ class Document extends Node Document() : super._(); factory Document.html(String html) => parse(html); + @override int get nodeType => Node.DOCUMENT_NODE; // TODO(jmesserly): optmize this if needed @@ -331,10 +330,13 @@ class Document extends Node // to dom_parsing, where we keep other custom APIs? String get outerHtml => _outerHtml; - String toString() => "#document"; + @override + String toString() => '#document'; + @override void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); + @override Document clone(bool deep) => _clone(Document(), deep); Element createElement(String tag) => Element.tag(tag); @@ -353,6 +355,7 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { DocumentFragment() : super._(); factory DocumentFragment.html(String html) => parseFragment(html); + @override int get nodeType => Node.DOCUMENT_FRAGMENT_NODE; /// Returns a fragment of HTML or XML that represents the element and its @@ -363,13 +366,18 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { // to dom_parsing, where we keep other custom APIs? String get outerHtml => _outerHtml; - String toString() => "#document-fragment"; + @override + String toString() => '#document-fragment'; + @override DocumentFragment clone(bool deep) => _clone(DocumentFragment(), deep); + @override void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); + @override String get text => _getText(this); + @override set text(String value) => _setText(this, value); } @@ -380,24 +388,28 @@ class DocumentType extends Node { DocumentType(this.name, this.publicId, this.systemId) : super._(); + @override int get nodeType => Node.DOCUMENT_TYPE_NODE; + @override String toString() { if (publicId != null || systemId != null) { // TODO(jmesserly): the html5 serialization spec does not add these. But // it seems useful, and the parser can handle it, so for now keeping it. - var pid = publicId != null ? publicId : ''; - var sid = systemId != null ? systemId : ''; + var pid = publicId ?? ''; + var sid = systemId ?? ''; return '<!DOCTYPE $name "$pid" "$sid">'; } else { return '<!DOCTYPE $name>'; } } + @override void _addOuterHtml(StringBuffer str) { str.write(toString()); } + @override DocumentType clone(bool deep) => DocumentType(name, publicId, systemId); } @@ -408,20 +420,24 @@ class Text extends Node { dynamic _data; Text(String data) - : _data = data != null ? data : '', + : _data = data ?? '', super._(); + @override int get nodeType => Node.TEXT_NODE; String get data => _data = _data.toString(); set data(String value) { - _data = value != null ? value : ''; + _data = value ?? ''; } + @override String toString() => '"$data"'; + @override void _addOuterHtml(StringBuffer str) => writeTextNodeAsHtml(str, this); + @override Text clone(bool deep) => Text(data); void appendData(String data) { @@ -430,7 +446,9 @@ class Text extends Node { sb.write(data); } + @override String get text => data; + @override set text(String value) { data = value; } @@ -484,7 +502,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // 2) Verify that the html does not contain leading or trailing text nodes. // 3) Verify that the html does not contain both <head> and <body> tags. // 4) Detatch the created element from its dummy parent. - String parentTag = 'div'; + var parentTag = 'div'; String tag; final match = _startTagRegexp.firstMatch(html); if (match != null) { @@ -509,13 +527,14 @@ class Element extends Node with _ParentNode, _ElementAndDocument { return element; } + @override int get nodeType => Node.ELEMENT_NODE; // TODO(jmesserly): we can make this faster Element get previousElementSibling { if (parentNode == null) return null; var siblings = parentNode.nodes; - for (int i = siblings.indexOf(this) - 1; i >= 0; i--) { + for (var i = siblings.indexOf(this) - 1; i >= 0; i--) { var s = siblings[i]; if (s is Element) return s; } @@ -525,19 +544,22 @@ class Element extends Node with _ParentNode, _ElementAndDocument { Element get nextElementSibling { if (parentNode == null) return null; var siblings = parentNode.nodes; - for (int i = siblings.indexOf(this) + 1; i < siblings.length; i++) { + for (var i = siblings.indexOf(this) + 1; i < siblings.length; i++) { var s = siblings[i]; if (s is Element) return s; } return null; } + @override String toString() { var prefix = Namespaces.getPrefix(namespaceUri); return "<${prefix == null ? '' : '$prefix '}$localName>"; } + @override String get text => _getText(this); + @override set text(String value) => _setText(this, value); /// Returns a fragment of HTML or XML that represents the element and its @@ -557,6 +579,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { nodes.addAll(parseFragment(value, container: localName).nodes); } + @override void _addOuterHtml(StringBuffer str) { // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments // Element is the most complicated one. @@ -611,6 +634,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { return prefix == null ? '' : '$prefix:'; } + @override Element clone(bool deep) { var result = Element._(localName, namespaceUri) ..attributes = LinkedHashMap.from(attributes); @@ -620,7 +644,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // http://dom.spec.whatwg.org/#dom-element-id String get id { var result = attributes['id']; - return result != null ? result : ''; + return result ?? ''; } set id(String value) { @@ -630,7 +654,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // http://dom.spec.whatwg.org/#dom-element-classname String get className { var result = attributes['class']; - return result != null ? result : ''; + return result ?? ''; } set className(String value) { @@ -653,17 +677,23 @@ class Comment extends Node { Comment(this.data) : super._(); + @override int get nodeType => Node.COMMENT_NODE; - String toString() => "<!-- $data -->"; + @override + String toString() => '<!-- $data -->'; + @override void _addOuterHtml(StringBuffer str) { - str.write("<!--$data-->"); + str.write('<!--$data-->'); } + @override Comment clone(bool deep) => Comment(data); + @override String get text => data; + @override set text(String value) { data = value; } @@ -687,6 +717,7 @@ class NodeList extends ListProxy<Node> { return node; } + @override void add(Node value) { if (value is DocumentFragment) { addAll(value.nodes); @@ -697,6 +728,7 @@ class NodeList extends ListProxy<Node> { void addLast(Node value) => add(value); + @override void addAll(Iterable<Node> collection) { // Note: we need to be careful if collection is another NodeList. // In particular: @@ -712,6 +744,7 @@ class NodeList extends ListProxy<Node> { super.addAll(list); } + @override void insert(int index, Node value) { if (value is DocumentFragment) { insertAll(index, value.nodes); @@ -720,10 +753,13 @@ class NodeList extends ListProxy<Node> { } } + @override Node removeLast() => super.removeLast()..parentNode = null; + @override Node removeAt(int i) => super.removeAt(i)..parentNode = null; + @override void clear() { for (var node in this) { node.parentNode = null; @@ -731,6 +767,7 @@ class NodeList extends ListProxy<Node> { super.clear(); } + @override void operator []=(int index, Node value) { if (value is DocumentFragment) { removeAt(index); @@ -743,46 +780,52 @@ class NodeList extends ListProxy<Node> { // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see // http://code.google.com/p/dart/issues/detail?id=5371 + @override void setRange(int start, int rangeLength, Iterable<Node> from, [int startFrom = 0]) { - List<Node> fromVar = from as List<Node>; + var fromVar = from as List<Node>; if (fromVar is NodeList) { // Note: this is presumed to make a copy fromVar = fromVar.sublist(startFrom, startFrom + rangeLength); } // Note: see comment in [addAll]. We need to be careful about the order of // operations if [from] is also a NodeList. - for (int i = rangeLength - 1; i >= 0; i--) { + for (var i = rangeLength - 1; i >= 0; i--) { this[start + i] = fromVar[startFrom + i]; } } + @override void replaceRange(int start, int end, Iterable<Node> newContents) { removeRange(start, end); insertAll(start, newContents); } + @override void removeRange(int start, int rangeLength) { - for (int i = start; i < rangeLength; i++) { + for (var i = start; i < rangeLength; i++) { this[i].parentNode = null; } super.removeRange(start, rangeLength); } - void removeWhere(bool test(Node e)) { + @override + void removeWhere(bool Function(Node) test) { for (var node in where(test)) { node.parentNode = null; } super.removeWhere(test); } - void retainWhere(bool test(Node e)) { + @override + void retainWhere(bool Function(Node) test) { for (var node in where((n) => !test(n))) { node.parentNode = null; } super.retainWhere(test); } + @override void insertAll(int index, Iterable<Node> collection) { // Note: we need to be careful how we copy nodes. See note in addAll. var list = _flattenDocFragments(collection); @@ -832,70 +875,85 @@ class FilteredElementList extends IterableBase<Element> // forEach, every, any, ... could directly work on the _childNodes. List<Element> get _filtered => _childNodes.whereType<Element>().toList(); - void forEach(void f(Element element)) { + @override + void forEach(void Function(Element) f) { _filtered.forEach(f); } + @override void operator []=(int index, Element value) { this[index].replaceWith(value); } + @override set length(int newLength) { final len = length; if (newLength >= len) { return; } else if (newLength < 0) { - throw ArgumentError("Invalid list length"); + throw ArgumentError('Invalid list length'); } removeRange(newLength, len); } - String join([String separator = ""]) => _filtered.join(separator); + @override + String join([String separator = '']) => _filtered.join(separator); + @override void add(Element value) { _childNodes.add(value); } + @override void addAll(Iterable<Element> iterable) { - for (Element element in iterable) { + for (var element in iterable) { add(element); } } + @override bool contains(Object element) { return element is Element && _childNodes.contains(element); } + @override Iterable<Element> get reversed => _filtered.reversed; - void sort([int compare(Element a, Element b)]) { + @override + void sort([int Function(Element, Element) compare]) { throw UnsupportedError('TODO(jacobr): should we impl?'); } + @override void setRange(int start, int end, Iterable<Element> iterable, [int skipCount = 0]) { throw UnimplementedError(); } + @override void fillRange(int start, int end, [Element fillValue]) { throw UnimplementedError(); } + @override void replaceRange(int start, int end, Iterable<Element> iterable) { throw UnimplementedError(); } + @override void removeRange(int start, int end) { _filtered.sublist(start, end).forEach((el) => el.remove()); } + @override void clear() { // Currently, ElementList#clear clears even non-element nodes, so we follow // that behavior. _childNodes.clear(); } + @override Element removeLast() { final result = last; if (result != null) { @@ -904,28 +962,35 @@ class FilteredElementList extends IterableBase<Element> return result; } - Iterable<T> map<T>(T f(Element element)) => _filtered.map(f); - Iterable<Element> where(bool f(Element element)) => _filtered.where(f); - Iterable<T> expand<T>(Iterable<T> f(Element element)) => _filtered.expand(f); + @override + Iterable<T> map<T>(T Function(Element) f) => _filtered.map(f); + @override + Iterable<Element> where(bool Function(Element) f) => _filtered.where(f); + @override + Iterable<T> expand<T>(Iterable<T> Function(Element) f) => _filtered.expand(f); + @override void insert(int index, Element value) { _childNodes.insert(index, value); } + @override void insertAll(int index, Iterable<Element> iterable) { _childNodes.insertAll(index, iterable); } + @override Element removeAt(int index) { final result = this[index]; result.remove(); return result; } + @override bool remove(Object element) { if (element is! Element) return false; - for (int i = 0; i < length; i++) { - Element indexElement = this[i]; + for (var i = 0; i < length; i++) { + var indexElement = this[i]; if (identical(indexElement, element)) { indexElement.remove(); return true; @@ -934,59 +999,82 @@ class FilteredElementList extends IterableBase<Element> return false; } - Element reduce(Element combine(Element value, Element element)) { + @override + Element reduce(Element Function(Element, Element) combine) { return _filtered.reduce(combine); } - T fold<T>(T initialValue, T combine(T previousValue, Element element)) { + @override + T fold<T>( + T initialValue, T Function(T previousValue, Element element) combine) { return _filtered.fold(initialValue, combine); } - bool every(bool f(Element element)) => _filtered.every(f); - bool any(bool f(Element element)) => _filtered.any(f); + @override + bool every(bool Function(Element) f) => _filtered.every(f); + @override + bool any(bool Function(Element) f) => _filtered.any(f); + @override List<Element> toList({bool growable = true}) => List<Element>.from(this, growable: growable); + @override Set<Element> toSet() => Set<Element>.from(this); - Element firstWhere(bool test(Element value), {Element orElse()}) { + @override + Element firstWhere(bool Function(Element) test, {Element Function() orElse}) { return _filtered.firstWhere(test, orElse: orElse); } - Element lastWhere(bool test(Element value), {Element orElse()}) { + @override + Element lastWhere(bool Function(Element) test, {Element Function() orElse}) { return _filtered.lastWhere(test, orElse: orElse); } - Element singleWhere(bool test(Element value), {Element orElse()}) { + @override + Element singleWhere(bool Function(Element) test, + {Element Function() orElse}) { if (orElse != null) throw UnimplementedError('orElse'); return _filtered.singleWhere(test); } + @override Element elementAt(int index) { return this[index]; } + @override bool get isEmpty => _filtered.isEmpty; + @override int get length => _filtered.length; + @override Element operator [](int index) => _filtered[index]; + @override Iterator<Element> get iterator => _filtered.iterator; + @override List<Element> sublist(int start, [int end]) => _filtered.sublist(start, end); + @override Iterable<Element> getRange(int start, int end) => _filtered.getRange(start, end); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.indexOf() expects Object as the argument. + @override int indexOf(Object element, [int start = 0]) => _filtered.indexOf(element, start); // TODO(sigmund): this should be typed Element, but we currently run into a // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. + @override int lastIndexOf(Object element, [int start]) { - if (start == null) start = length - 1; + start ??= length - 1; return _filtered.lastIndexOf(element, start); } + @override Element get first => _filtered.first; + @override Element get last => _filtered.last; + @override Element get single => _filtered.single; } @@ -1002,9 +1090,11 @@ void _setText(Node node, String value) { class _ConcatTextVisitor extends TreeVisitor { final _str = StringBuffer(); + @override String toString() => _str.toString(); - visitText(Text node) { + @override + void visitText(Text node) { _str.write(node.data); } } diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 27eedb3be..f16018c36 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -7,7 +7,7 @@ import 'src/constants.dart' show rcdataElements; /// A simple tree visitor for the DOM nodes. class TreeVisitor { - visit(Node node) { + void visit(Node node) { switch (node.nodeType) { case Node.ELEMENT_NODE: return visitElement(node); @@ -26,7 +26,7 @@ class TreeVisitor { } } - visitChildren(Node node) { + void visitChildren(Node node) { // Allow for mutations (remove works) while iterating. for (var child in node.nodes.toList()) { visit(child); @@ -36,20 +36,20 @@ class TreeVisitor { /// The fallback handler if the more specific visit method hasn't been /// overriden. Only use this from a subclass of [TreeVisitor], otherwise /// call [visit] instead. - visitNodeFallback(Node node) => visitChildren(node); + void visitNodeFallback(Node node) => visitChildren(node); - visitDocument(Document node) => visitNodeFallback(node); + void visitDocument(Document node) => visitNodeFallback(node); - visitDocumentType(DocumentType node) => visitNodeFallback(node); + void visitDocumentType(DocumentType node) => visitNodeFallback(node); - visitText(Text node) => visitNodeFallback(node); + void visitText(Text node) => visitNodeFallback(node); // TODO(jmesserly): visit attributes. - visitElement(Element node) => visitNodeFallback(node); + void visitElement(Element node) => visitNodeFallback(node); - visitComment(Comment node) => visitNodeFallback(node); + void visitComment(Comment node) => visitNodeFallback(node); - visitDocumentFragment(DocumentFragment node) => visitNodeFallback(node); + void visitDocumentFragment(DocumentFragment node) => visitNodeFallback(node); } /// Converts the DOM tree into an HTML string with code markup suitable for @@ -67,24 +67,29 @@ class CodeMarkupVisitor extends TreeVisitor { CodeMarkupVisitor() : _str = StringBuffer(); + @override String toString() => _str.toString(); - visitDocument(Document node) { - _str.write("<pre>"); + @override + void visitDocument(Document node) { + _str.write('<pre>'); visitChildren(node); - _str.write("</pre>"); + _str.write('</pre>'); } - visitDocumentType(DocumentType node) { + @override + void visitDocumentType(DocumentType node) { _str.write('<code class="markup doctype">&lt;!DOCTYPE ${node.name}>' '</code>'); } - visitText(Text node) { + @override + void visitText(Text node) { writeTextNodeAsHtml(_str, node); } - visitElement(Element node) { + @override + void visitElement(Element node) { final tag = node.localName; _str.write('&lt;<code class="markup element-name">$tag</code>'); if (node.attributes.isNotEmpty) { @@ -95,16 +100,17 @@ class CodeMarkupVisitor extends TreeVisitor { }); } if (node.nodes.isNotEmpty) { - _str.write(">"); + _str.write('>'); visitChildren(node); } else if (isVoidElement(tag)) { - _str.write(">"); + _str.write('>'); return; } _str.write('&lt;/<code class="markup element-name">$tag</code>>'); } - visitComment(Comment node) { + @override + void visitComment(Comment node) { var data = htmlSerializeEscape(node.data); _str.write('<code class="markup comment">&lt;!--$data--></code>'); } @@ -131,7 +137,7 @@ String htmlSerializeEscape(String text, {bool attributeMode = false}) { // TODO(jmesserly): is it faster to build up a list of codepoints? // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. StringBuffer result; - for (int i = 0; i < text.length; i++) { + for (var i = 0; i < text.length; i++) { var ch = text[i]; String replace; switch (ch) { @@ -152,7 +158,7 @@ String htmlSerializeEscape(String text, {bool attributeMode = false}) { break; } if (replace != null) { - if (result == null) result = StringBuffer(text.substring(0, i)); + result ??= StringBuffer(text.substring(0, i)); result.write(replace); } else if (result != null) { result.write(ch); @@ -168,22 +174,22 @@ String htmlSerializeEscape(String text, {bool attributeMode = false}) { /// See also: <http://dev.w3.org/html5/markup/syntax.html#void-elements>. bool isVoidElement(String tagName) { switch (tagName) { - case "area": - case "base": - case "br": - case "col": - case "command": - case "embed": - case "hr": - case "img": - case "input": - case "keygen": - case "link": - case "meta": - case "param": - case "source": - case "track": - case "wbr": + case 'area': + case 'base': + case 'br': + case 'col': + case 'command': + case 'embed': + case 'hr': + case 'img': + case 'input': + case 'keygen': + case 'link': + case 'meta': + case 'param': + case 'source': + case 'track': + case 'wbr': return true; } return false; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 58ae1c896..c4eafb67f 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -56,7 +56,7 @@ Document parse(input, /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. DocumentFragment parseFragment(input, - {String container = "div", + {String container = 'div', String encoding, bool generateSpans = false, String sourceUrl}) { @@ -86,7 +86,7 @@ class HtmlParser { // TODO(jmesserly): use enum? /// "quirks" / "limited quirks" / "no quirks" - String compatMode = "no quirks"; + String compatMode = 'no quirks'; /// innerHTML container when parsing document fragment. String innerHTML; @@ -150,7 +150,7 @@ class HtmlParser { this.generateSpans = false, String sourceUrl, TreeBuilder tree}) - : tree = tree != null ? tree : TreeBuilder(true), + : tree = tree ?? TreeBuilder(true), tokenizer = (input is HtmlTokenizer ? input : HtmlTokenizer(input, @@ -203,7 +203,7 @@ class HtmlParser { /// Parse an html5 document fragment into a tree. /// Pass a [container] to change the type of the containing element. /// After parsing, [errors] will be populated with parse errors, if any. - DocumentFragment parseFragment([String container = "div"]) { + DocumentFragment parseFragment([String container = 'div']) { if (container == null) throw ArgumentError('container'); innerHTML = container.toLowerCase(); _parse(); @@ -232,7 +232,7 @@ class HtmlParser { firstStartTag = false; errors.clear(); // "quirks" / "limited quirks" / "no quirks" - compatMode = "no quirks"; + compatMode = 'no quirks'; if (innerHTMLMode) { if (cdataElements.contains(innerHTML)) { @@ -258,11 +258,11 @@ class HtmlParser { } bool isHTMLIntegrationPoint(Element element) { - if (element.localName == "annotation-xml" && + if (element.localName == 'annotation-xml' && element.namespaceUri == Namespaces.mathml) { - var enc = element.attributes["encoding"]; + var enc = element.attributes['encoding']; if (enc != null) enc = asciiUpper2Lower(enc); - return enc == "text/html" || enc == "application/xhtml+xml"; + return enc == 'text/html' || enc == 'application/xhtml+xml'; } else { return htmlIntegrationPointElements .contains(Pair(element.namespaceUri, element.localName)); @@ -282,8 +282,8 @@ class HtmlParser { if (isMathMLTextIntegrationPoint(node)) { if (type == TokenKind.startTag && - (token as StartTagToken).name != "mglyph" && - (token as StartTagToken).name != "malignmark") { + (token as StartTagToken).name != 'mglyph' && + (token as StartTagToken).name != 'malignmark') { return false; } if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { @@ -291,9 +291,9 @@ class HtmlParser { } } - if (node.localName == "annotation-xml" && + if (node.localName == 'annotation-xml' && type == TokenKind.startTag && - (token as StartTagToken).name == "svg") { + (token as StartTagToken).name == 'svg') { return false; } @@ -322,7 +322,7 @@ class HtmlParser { parseError(error.span, error.data, error.messageParams); newToken = null; } else { - Phase localPhase = phase; + var localPhase = phase; if (inForeignContent(token, type)) { localPhase = _inForeignContentPhase; } @@ -352,8 +352,8 @@ class HtmlParser { if (token is StartTagToken) { if (token.selfClosing && !token.selfClosingAcknowledged) { - parseError(token.span, "non-void-element-with-trailing-solidus", - {"name": token.name}); + parseError(token.span, 'non-void-element-with-trailing-solidus', + {'name': token.name}); } } } @@ -390,76 +390,76 @@ class HtmlParser { } void adjustMathMLAttributes(StartTagToken token) { - var orig = token.data.remove("definitionurl"); + var orig = token.data.remove('definitionurl'); if (orig != null) { - token.data["definitionURL"] = orig; + token.data['definitionURL'] = orig; } } void adjustSVGAttributes(StartTagToken token) { final replacements = const { - "attributename": "attributeName", - "attributetype": "attributeType", - "basefrequency": "baseFrequency", - "baseprofile": "baseProfile", - "calcmode": "calcMode", - "clippathunits": "clipPathUnits", - "contentscripttype": "contentScriptType", - "contentstyletype": "contentStyleType", - "diffuseconstant": "diffuseConstant", - "edgemode": "edgeMode", - "externalresourcesrequired": "externalResourcesRequired", - "filterres": "filterRes", - "filterunits": "filterUnits", - "glyphref": "glyphRef", - "gradienttransform": "gradientTransform", - "gradientunits": "gradientUnits", - "kernelmatrix": "kernelMatrix", - "kernelunitlength": "kernelUnitLength", - "keypoints": "keyPoints", - "keysplines": "keySplines", - "keytimes": "keyTimes", - "lengthadjust": "lengthAdjust", - "limitingconeangle": "limitingConeAngle", - "markerheight": "markerHeight", - "markerunits": "markerUnits", - "markerwidth": "markerWidth", - "maskcontentunits": "maskContentUnits", - "maskunits": "maskUnits", - "numoctaves": "numOctaves", - "pathlength": "pathLength", - "patterncontentunits": "patternContentUnits", - "patterntransform": "patternTransform", - "patternunits": "patternUnits", - "pointsatx": "pointsAtX", - "pointsaty": "pointsAtY", - "pointsatz": "pointsAtZ", - "preservealpha": "preserveAlpha", - "preserveaspectratio": "preserveAspectRatio", - "primitiveunits": "primitiveUnits", - "refx": "refX", - "refy": "refY", - "repeatcount": "repeatCount", - "repeatdur": "repeatDur", - "requiredextensions": "requiredExtensions", - "requiredfeatures": "requiredFeatures", - "specularconstant": "specularConstant", - "specularexponent": "specularExponent", - "spreadmethod": "spreadMethod", - "startoffset": "startOffset", - "stddeviation": "stdDeviation", - "stitchtiles": "stitchTiles", - "surfacescale": "surfaceScale", - "systemlanguage": "systemLanguage", - "tablevalues": "tableValues", - "targetx": "targetX", - "targety": "targetY", - "textlength": "textLength", - "viewbox": "viewBox", - "viewtarget": "viewTarget", - "xchannelselector": "xChannelSelector", - "ychannelselector": "yChannelSelector", - "zoomandpan": "zoomAndPan" + 'attributename': 'attributeName', + 'attributetype': 'attributeType', + 'basefrequency': 'baseFrequency', + 'baseprofile': 'baseProfile', + 'calcmode': 'calcMode', + 'clippathunits': 'clipPathUnits', + 'contentscripttype': 'contentScriptType', + 'contentstyletype': 'contentStyleType', + 'diffuseconstant': 'diffuseConstant', + 'edgemode': 'edgeMode', + 'externalresourcesrequired': 'externalResourcesRequired', + 'filterres': 'filterRes', + 'filterunits': 'filterUnits', + 'glyphref': 'glyphRef', + 'gradienttransform': 'gradientTransform', + 'gradientunits': 'gradientUnits', + 'kernelmatrix': 'kernelMatrix', + 'kernelunitlength': 'kernelUnitLength', + 'keypoints': 'keyPoints', + 'keysplines': 'keySplines', + 'keytimes': 'keyTimes', + 'lengthadjust': 'lengthAdjust', + 'limitingconeangle': 'limitingConeAngle', + 'markerheight': 'markerHeight', + 'markerunits': 'markerUnits', + 'markerwidth': 'markerWidth', + 'maskcontentunits': 'maskContentUnits', + 'maskunits': 'maskUnits', + 'numoctaves': 'numOctaves', + 'pathlength': 'pathLength', + 'patterncontentunits': 'patternContentUnits', + 'patterntransform': 'patternTransform', + 'patternunits': 'patternUnits', + 'pointsatx': 'pointsAtX', + 'pointsaty': 'pointsAtY', + 'pointsatz': 'pointsAtZ', + 'preservealpha': 'preserveAlpha', + 'preserveaspectratio': 'preserveAspectRatio', + 'primitiveunits': 'primitiveUnits', + 'refx': 'refX', + 'refy': 'refY', + 'repeatcount': 'repeatCount', + 'repeatdur': 'repeatDur', + 'requiredextensions': 'requiredExtensions', + 'requiredfeatures': 'requiredFeatures', + 'specularconstant': 'specularConstant', + 'specularexponent': 'specularExponent', + 'spreadmethod': 'spreadMethod', + 'startoffset': 'startOffset', + 'stddeviation': 'stdDeviation', + 'stitchtiles': 'stitchTiles', + 'surfacescale': 'surfaceScale', + 'systemlanguage': 'systemLanguage', + 'tablevalues': 'tableValues', + 'targetx': 'targetX', + 'targety': 'targetY', + 'textlength': 'textLength', + 'viewbox': 'viewBox', + 'viewtarget': 'viewTarget', + 'xchannelselector': 'xChannelSelector', + 'ychannelselector': 'yChannelSelector', + 'zoomandpan': 'zoomAndPan' }; for (var originalName in token.data.keys.toList()) { var svgName = replacements[originalName]; @@ -473,18 +473,18 @@ class HtmlParser { // TODO(jmesserly): I don't like mixing non-string objects with strings in // the Node.attributes Map. Is there another solution? final replacements = const { - "xlink:actuate": AttributeName("xlink", "actuate", Namespaces.xlink), - "xlink:arcrole": AttributeName("xlink", "arcrole", Namespaces.xlink), - "xlink:href": AttributeName("xlink", "href", Namespaces.xlink), - "xlink:role": AttributeName("xlink", "role", Namespaces.xlink), - "xlink:show": AttributeName("xlink", "show", Namespaces.xlink), - "xlink:title": AttributeName("xlink", "title", Namespaces.xlink), - "xlink:type": AttributeName("xlink", "type", Namespaces.xlink), - "xml:base": AttributeName("xml", "base", Namespaces.xml), - "xml:lang": AttributeName("xml", "lang", Namespaces.xml), - "xml:space": AttributeName("xml", "space", Namespaces.xml), - "xmlns": AttributeName(null, "xmlns", Namespaces.xmlns), - "xmlns:xlink": AttributeName("xmlns", "xlink", Namespaces.xmlns) + 'xlink:actuate': AttributeName('xlink', 'actuate', Namespaces.xlink), + 'xlink:arcrole': AttributeName('xlink', 'arcrole', Namespaces.xlink), + 'xlink:href': AttributeName('xlink', 'href', Namespaces.xlink), + 'xlink:role': AttributeName('xlink', 'role', Namespaces.xlink), + 'xlink:show': AttributeName('xlink', 'show', Namespaces.xlink), + 'xlink:title': AttributeName('xlink', 'title', Namespaces.xlink), + 'xlink:type': AttributeName('xlink', 'type', Namespaces.xlink), + 'xml:base': AttributeName('xml', 'base', Namespaces.xml), + 'xml:lang': AttributeName('xml', 'lang', Namespaces.xml), + 'xml:space': AttributeName('xml', 'space', Namespaces.xml), + 'xmlns': AttributeName(null, 'xmlns', Namespaces.xmlns), + 'xmlns:xlink': AttributeName('xmlns', 'xlink', Namespaces.xmlns) }; for (var originalName in token.data.keys.toList()) { @@ -500,7 +500,7 @@ class HtmlParser { // specification.) for (var node in tree.openElements.reversed) { var nodeName = node.localName; - bool last = node == tree.openElements[0]; + var last = node == tree.openElements[0]; if (last) { assert(innerHTMLMode); nodeName = innerHTML; @@ -508,10 +508,10 @@ class HtmlParser { // Check for conditions that should only happen in the innerHTML // case switch (nodeName) { - case "select": - case "colgroup": - case "head": - case "html": + case 'select': + case 'colgroup': + case 'head': + case 'html': assert(innerHTMLMode); break; } @@ -519,46 +519,46 @@ class HtmlParser { continue; } switch (nodeName) { - case "select": + case 'select': phase = _inSelectPhase; return; - case "td": + case 'td': phase = _inCellPhase; return; - case "th": + case 'th': phase = _inCellPhase; return; - case "tr": + case 'tr': phase = _inRowPhase; return; - case "tbody": + case 'tbody': phase = _inTableBodyPhase; return; - case "thead": + case 'thead': phase = _inTableBodyPhase; return; - case "tfoot": + case 'tfoot': phase = _inTableBodyPhase; return; - case "caption": + case 'caption': phase = _inCaptionPhase; return; - case "colgroup": + case 'colgroup': phase = _inColumnGroupPhase; return; - case "table": + case 'table': phase = _inTablePhase; return; - case "head": + case 'head': phase = _inBodyPhase; return; - case "body": + case 'body': phase = _inBodyPhase; return; - case "frameset": + case 'frameset': phase = _inFramesetPhase; return; - case "html": + case 'html': phase = _beforeHeadPhase; return; } @@ -569,11 +569,11 @@ class HtmlParser { /// Generic RCDATA/RAWTEXT Parsing algorithm /// [contentType] - RCDATA or RAWTEXT void parseRCDataRawtext(Token token, String contentType) { - assert(contentType == "RAWTEXT" || contentType == "RCDATA"); + assert(contentType == 'RAWTEXT' || contentType == 'RCDATA'); tree.insertElement(token); - if (contentType == "RAWTEXT") { + if (contentType == 'RAWTEXT') { tokenizer.state = tokenizer.rawtextState; } else { tokenizer.state = tokenizer.rcdataState; @@ -615,7 +615,7 @@ class Phase { } Token processDoctype(DoctypeToken token) { - parser.parseError(token.span, "unexpected-doctype"); + parser.parseError(token.span, 'unexpected-doctype'); return null; } @@ -634,8 +634,8 @@ class Phase { } Token startTagHtml(StartTagToken token) { - if (parser.firstStartTag == false && token.name == "html") { - parser.parseError(token.span, "non-html-root"); + if (parser.firstStartTag == false && token.name == 'html') { + parser.parseError(token.span, 'non-html-root'); } // XXX Need a check here to see if the first start tag token emitted is // this token... If it's not, invoke parser.parseError(). @@ -653,7 +653,7 @@ class Phase { /// Helper method for popping openElements. void popOpenElementsUntil(EndTagToken token) { - String name = token.name; + var name = token.name; var node = tree.openElements.removeLast(); while (node.localName != name) { node = tree.openElements.removeLast(); @@ -667,152 +667,157 @@ class Phase { class InitialPhase extends Phase { InitialPhase(parser) : super(parser); + @override Token processSpaceCharacters(SpaceCharactersToken token) { return null; } + @override Token processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } + @override Token processDoctype(DoctypeToken token) { var name = token.name; - String publicId = token.publicId; + var publicId = token.publicId; var systemId = token.systemId; var correct = token.correct; - if ((name != "html" || + if ((name != 'html' || publicId != null || - systemId != null && systemId != "about:legacy-compat")) { - parser.parseError(token.span, "unknown-doctype"); + systemId != null && systemId != 'about:legacy-compat')) { + parser.parseError(token.span, 'unknown-doctype'); } - if (publicId == null) { - publicId = ""; - } + publicId ??= ''; tree.insertDoctype(token); - if (publicId != "") { + if (publicId != '') { publicId = asciiUpper2Lower(publicId); } if (!correct || - token.name != "html" || + token.name != 'html' || startsWithAny(publicId, const [ - "+//silmaril//dtd html pro v0r11 19970101//", - "-//advasoft ltd//dtd html 3.0 aswedit + extensions//", - "-//as//dtd html 3.0 aswedit + extensions//", - "-//ietf//dtd html 2.0 level 1//", - "-//ietf//dtd html 2.0 level 2//", - "-//ietf//dtd html 2.0 strict level 1//", - "-//ietf//dtd html 2.0 strict level 2//", - "-//ietf//dtd html 2.0 strict//", - "-//ietf//dtd html 2.0//", - "-//ietf//dtd html 2.1e//", - "-//ietf//dtd html 3.0//", - "-//ietf//dtd html 3.2 final//", - "-//ietf//dtd html 3.2//", - "-//ietf//dtd html 3//", - "-//ietf//dtd html level 0//", - "-//ietf//dtd html level 1//", - "-//ietf//dtd html level 2//", - "-//ietf//dtd html level 3//", - "-//ietf//dtd html strict level 0//", - "-//ietf//dtd html strict level 1//", - "-//ietf//dtd html strict level 2//", - "-//ietf//dtd html strict level 3//", - "-//ietf//dtd html strict//", - "-//ietf//dtd html//", - "-//metrius//dtd metrius presentational//", - "-//microsoft//dtd internet explorer 2.0 html strict//", - "-//microsoft//dtd internet explorer 2.0 html//", - "-//microsoft//dtd internet explorer 2.0 tables//", - "-//microsoft//dtd internet explorer 3.0 html strict//", - "-//microsoft//dtd internet explorer 3.0 html//", - "-//microsoft//dtd internet explorer 3.0 tables//", - "-//netscape comm. corp.//dtd html//", - "-//netscape comm. corp.//dtd strict html//", + '+//silmaril//dtd html pro v0r11 19970101//', + '-//advasoft ltd//dtd html 3.0 aswedit + extensions//', + '-//as//dtd html 3.0 aswedit + extensions//', + '-//ietf//dtd html 2.0 level 1//', + '-//ietf//dtd html 2.0 level 2//', + '-//ietf//dtd html 2.0 strict level 1//', + '-//ietf//dtd html 2.0 strict level 2//', + '-//ietf//dtd html 2.0 strict//', + '-//ietf//dtd html 2.0//', + '-//ietf//dtd html 2.1e//', + '-//ietf//dtd html 3.0//', + '-//ietf//dtd html 3.2 final//', + '-//ietf//dtd html 3.2//', + '-//ietf//dtd html 3//', + '-//ietf//dtd html level 0//', + '-//ietf//dtd html level 1//', + '-//ietf//dtd html level 2//', + '-//ietf//dtd html level 3//', + '-//ietf//dtd html strict level 0//', + '-//ietf//dtd html strict level 1//', + '-//ietf//dtd html strict level 2//', + '-//ietf//dtd html strict level 3//', + '-//ietf//dtd html strict//', + '-//ietf//dtd html//', + '-//metrius//dtd metrius presentational//', + '-//microsoft//dtd internet explorer 2.0 html strict//', + '-//microsoft//dtd internet explorer 2.0 html//', + '-//microsoft//dtd internet explorer 2.0 tables//', + '-//microsoft//dtd internet explorer 3.0 html strict//', + '-//microsoft//dtd internet explorer 3.0 html//', + '-//microsoft//dtd internet explorer 3.0 tables//', + '-//netscape comm. corp.//dtd html//', + '-//netscape comm. corp.//dtd strict html//', "-//o'reilly and associates//dtd html 2.0//", "-//o'reilly and associates//dtd html extended 1.0//", "-//o'reilly and associates//dtd html extended relaxed 1.0//", - "-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//", - "-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//", - "-//spyglass//dtd html 2.0 extended//", - "-//sq//dtd html 2.0 hotmetal + extensions//", - "-//sun microsystems corp.//dtd hotjava html//", - "-//sun microsystems corp.//dtd hotjava strict html//", - "-//w3c//dtd html 3 1995-03-24//", - "-//w3c//dtd html 3.2 draft//", - "-//w3c//dtd html 3.2 final//", - "-//w3c//dtd html 3.2//", - "-//w3c//dtd html 3.2s draft//", - "-//w3c//dtd html 4.0 frameset//", - "-//w3c//dtd html 4.0 transitional//", - "-//w3c//dtd html experimental 19960712//", - "-//w3c//dtd html experimental 970421//", - "-//w3c//dtd w3 html//", - "-//w3o//dtd w3 html 3.0//", - "-//webtechs//dtd mozilla html 2.0//", - "-//webtechs//dtd mozilla html//" + '-//softquad software//dtd hotmetal pro 6.0::19990601::extensions to html 4.0//', + '-//softquad//dtd hotmetal pro 4.0::19971010::extensions to html 4.0//', + '-//spyglass//dtd html 2.0 extended//', + '-//sq//dtd html 2.0 hotmetal + extensions//', + '-//sun microsystems corp.//dtd hotjava html//', + '-//sun microsystems corp.//dtd hotjava strict html//', + '-//w3c//dtd html 3 1995-03-24//', + '-//w3c//dtd html 3.2 draft//', + '-//w3c//dtd html 3.2 final//', + '-//w3c//dtd html 3.2//', + '-//w3c//dtd html 3.2s draft//', + '-//w3c//dtd html 4.0 frameset//', + '-//w3c//dtd html 4.0 transitional//', + '-//w3c//dtd html experimental 19960712//', + '-//w3c//dtd html experimental 970421//', + '-//w3c//dtd w3 html//', + '-//w3o//dtd w3 html 3.0//', + '-//webtechs//dtd mozilla html 2.0//', + '-//webtechs//dtd mozilla html//' ]) || const [ - "-//w3o//dtd w3 html strict 3.0//en//", - "-/w3c/dtd html 4.0 transitional/en", - "html" + '-//w3o//dtd w3 html strict 3.0//en//', + '-/w3c/dtd html 4.0 transitional/en', + 'html' ].contains(publicId) || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//" + '-//w3c//dtd html 4.01 frameset//', + '-//w3c//dtd html 4.01 transitional//' ]) && systemId == null || systemId != null && systemId.toLowerCase() == - "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd") { - parser.compatMode = "quirks"; + 'http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd') { + parser.compatMode = 'quirks'; } else if (startsWithAny(publicId, const [ - "-//w3c//dtd xhtml 1.0 frameset//", - "-//w3c//dtd xhtml 1.0 transitional//" + '-//w3c//dtd xhtml 1.0 frameset//', + '-//w3c//dtd xhtml 1.0 transitional//' ]) || startsWithAny(publicId, const [ - "-//w3c//dtd html 4.01 frameset//", - "-//w3c//dtd html 4.01 transitional//" + '-//w3c//dtd html 4.01 frameset//', + '-//w3c//dtd html 4.01 transitional//' ]) && systemId != null) { - parser.compatMode = "limited quirks"; + parser.compatMode = 'limited quirks'; } parser.phase = parser._beforeHtmlPhase; return null; } void anythingElse() { - parser.compatMode = "quirks"; + parser.compatMode = 'quirks'; parser.phase = parser._beforeHtmlPhase; } + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "expected-doctype-but-got-chars"); + parser.parseError(token.span, 'expected-doctype-but-got-chars'); anythingElse(); return token; } + @override Token processStartTag(StartTagToken token) { parser.parseError( - token.span, "expected-doctype-but-got-start-tag", {"name": token.name}); + token.span, 'expected-doctype-but-got-start-tag', {'name': token.name}); anythingElse(); return token; } + @override Token processEndTag(EndTagToken token) { parser.parseError( - token.span, "expected-doctype-but-got-end-tag", {"name": token.name}); + token.span, 'expected-doctype-but-got-end-tag', {'name': token.name}); anythingElse(); return token; } + @override bool processEOF() { - parser.parseError(parser._lastSpan, "expected-doctype-but-got-eof"); + parser.parseError(parser._lastSpan, 'expected-doctype-but-got-eof'); anythingElse(); return true; } @@ -824,49 +829,56 @@ class BeforeHtmlPhase extends Phase { // helper methods void insertHtmlElement() { tree.insertRoot( - StartTagToken("html", data: LinkedHashMap<dynamic, String>())); + StartTagToken('html', data: LinkedHashMap<dynamic, String>())); parser.phase = parser._beforeHeadPhase; } // other + @override bool processEOF() { insertHtmlElement(); return true; } + @override Token processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return null; } + @override Token processCharacters(CharactersToken token) { insertHtmlElement(); return token; } + @override + @override Token processStartTag(StartTagToken token) { - if (token.name == "html") { + if (token.name == 'html') { parser.firstStartTag = true; } insertHtmlElement(); return token; } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "head": - case "body": - case "html": - case "br": + case 'head': + case 'body': + case 'html': + case 'br': insertHtmlElement(); return token; default: parser.parseError( - token.span, "unexpected-end-tag-before-html", {"name": token.name}); + token.span, 'unexpected-end-tag-before-html', {'name': token.name}); return null; } } @@ -875,6 +887,7 @@ class BeforeHtmlPhase extends Phase { class BeforeHeadPhase extends Phase { BeforeHeadPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { case 'html': @@ -887,12 +900,13 @@ class BeforeHeadPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "head": - case "body": - case "html": - case "br": + case 'head': + case 'body': + case 'html': + case 'br': return endTagImplyHead(token); default: endTagOther(token); @@ -900,20 +914,24 @@ class BeforeHeadPhase extends Phase { } } + @override bool processEOF() { - startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); return true; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return null; } + @override Token processCharacters(CharactersToken token) { - startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); return token; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -925,50 +943,51 @@ class BeforeHeadPhase extends Phase { } Token startTagOther(StartTagToken token) { - startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); return token; } Token endTagImplyHead(EndTagToken token) { - startTagHead(StartTagToken("head", data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); return token; } void endTagOther(EndTagToken token) { parser.parseError( - token.span, "end-tag-after-implied-root", {"name": token.name}); + token.span, 'end-tag-after-implied-root', {'name': token.name}); } } class InHeadPhase extends Phase { InHeadPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "title": + case 'title': startTagTitle(token); return null; - case "noscript": - case "noframes": - case "style": + case 'noscript': + case 'noframes': + case 'style': startTagNoScriptNoFramesStyle(token); return null; - case "script": + case 'script': startTagScript(token); return null; - case "base": - case "basefont": - case "bgsound": - case "command": - case "link": + case 'base': + case 'basefont': + case 'bgsound': + case 'command': + case 'link': startTagBaseLinkCommand(token); return null; - case "meta": + case 'meta': startTagMeta(token); return null; - case "head": + case 'head': startTagHead(token); return null; default: @@ -976,14 +995,15 @@ class InHeadPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "head": + case 'head': endTagHead(token); return null; - case "br": - case "html": - case "body": + case 'br': + case 'html': + case 'body': return endTagHtmlBodyBr(token); default: endTagOther(token); @@ -992,22 +1012,25 @@ class InHeadPhase extends Phase { } // the real thing + @override bool processEOF() { anythingElse(); return true; } + @override Token processCharacters(CharactersToken token) { anythingElse(); return token; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } void startTagHead(StartTagToken token) { - parser.parseError(token.span, "two-heads-are-not-better-than-one"); + parser.parseError(token.span, 'two-heads-are-not-better-than-one'); } void startTagBaseLinkCommand(StartTagToken token) { @@ -1023,8 +1046,8 @@ class InHeadPhase extends Phase { var attributes = token.data; if (!parser.tokenizer.stream.charEncodingCertain) { - var charset = attributes["charset"]; - var content = attributes["content"]; + var charset = attributes['charset']; + var content = attributes['content']; if (charset != null) { parser.tokenizer.stream.changeEncoding(charset); } else if (content != null) { @@ -1036,12 +1059,12 @@ class InHeadPhase extends Phase { } void startTagTitle(StartTagToken token) { - parser.parseRCDataRawtext(token, "RCDATA"); + parser.parseRCDataRawtext(token, 'RCDATA'); } void startTagNoScriptNoFramesStyle(StartTagToken token) { // Need to decide whether to implement the scripting-disabled case - parser.parseRCDataRawtext(token, "RAWTEXT"); + parser.parseRCDataRawtext(token, 'RAWTEXT'); } void startTagScript(StartTagToken token) { @@ -1058,7 +1081,7 @@ class InHeadPhase extends Phase { void endTagHead(EndTagToken token) { var node = parser.tree.openElements.removeLast(); - assert(node.localName == "head"); + assert(node.localName == 'head'); node.endSourceSpan = token.span; parser.phase = parser._afterHeadPhase; } @@ -1069,11 +1092,11 @@ class InHeadPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } void anythingElse() { - endTagHead(EndTagToken("head")); + endTagHead(EndTagToken('head')); } } @@ -1085,28 +1108,29 @@ class InHeadPhase extends Phase { class AfterHeadPhase extends Phase { AfterHeadPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "body": + case 'body': startTagBody(token); return null; - case "frameset": + case 'frameset': startTagFrameset(token); return null; - case "base": - case "basefont": - case "bgsound": - case "link": - case "meta": - case "noframes": - case "script": - case "style": - case "title": + case 'base': + case 'basefont': + case 'bgsound': + case 'link': + case 'meta': + case 'noframes': + case 'script': + case 'style': + case 'title': startTagFromHead(token); return null; - case "head": + case 'head': startTagHead(token); return null; default: @@ -1114,11 +1138,12 @@ class AfterHeadPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "body": - case "html": - case "br": + case 'body': + case 'html': + case 'br': return endTagHtmlBodyBr(token); default: endTagOther(token); @@ -1126,16 +1151,19 @@ class AfterHeadPhase extends Phase { } } + @override bool processEOF() { anythingElse(); return true; } + @override Token processCharacters(CharactersToken token) { anythingElse(); return token; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -1152,12 +1180,12 @@ class AfterHeadPhase extends Phase { } void startTagFromHead(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-out-of-my-head", - {"name": token.name}); + parser.parseError(token.span, 'unexpected-start-tag-out-of-my-head', + {'name': token.name}); tree.openElements.add(tree.headPointer); parser._inHeadPhase.processStartTag(token); for (var node in tree.openElements.reversed) { - if (node.localName == "head") { + if (node.localName == 'head') { tree.openElements.remove(node); break; } @@ -1165,7 +1193,7 @@ class AfterHeadPhase extends Phase { } void startTagHead(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-start-tag', {'name': token.name}); } Token startTagOther(StartTagToken token) { @@ -1179,12 +1207,12 @@ class AfterHeadPhase extends Phase { } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } void anythingElse() { tree.insertElement( - StartTagToken("body", data: LinkedHashMap<dynamic, String>())); + StartTagToken('body', data: LinkedHashMap<dynamic, String>())); parser.phase = parser._inBodyPhase; parser.framesetOK = true; } @@ -1199,171 +1227,172 @@ class InBodyPhase extends Phase { // the really-really-really-very crazy mode InBodyPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "base": - case "basefont": - case "bgsound": - case "command": - case "link": - case "meta": - case "noframes": - case "script": - case "style": - case "title": + case 'base': + case 'basefont': + case 'bgsound': + case 'command': + case 'link': + case 'meta': + case 'noframes': + case 'script': + case 'style': + case 'title': return startTagProcessInHead(token); - case "body": + case 'body': startTagBody(token); return null; - case "frameset": + case 'frameset': startTagFrameset(token); return null; - case "address": - case "article": - case "aside": - case "blockquote": - case "center": - case "details": - case "dir": - case "div": - case "dl": - case "fieldset": - case "figcaption": - case "figure": - case "footer": - case "header": - case "hgroup": - case "menu": - case "nav": - case "ol": - case "p": - case "section": - case "summary": - case "ul": + case 'address': + case 'article': + case 'aside': + case 'blockquote': + case 'center': + case 'details': + case 'dir': + case 'div': + case 'dl': + case 'fieldset': + case 'figcaption': + case 'figure': + case 'footer': + case 'header': + case 'hgroup': + case 'menu': + case 'nav': + case 'ol': + case 'p': + case 'section': + case 'summary': + case 'ul': startTagCloseP(token); return null; // headingElements - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": + case 'h1': + case 'h2': + case 'h3': + case 'h4': + case 'h5': + case 'h6': startTagHeading(token); return null; - case "pre": - case "listing": + case 'pre': + case 'listing': startTagPreListing(token); return null; - case "form": + case 'form': startTagForm(token); return null; - case "li": - case "dd": - case "dt": + case 'li': + case 'dd': + case 'dt': startTagListItem(token); return null; - case "plaintext": + case 'plaintext': startTagPlaintext(token); return null; - case "a": + case 'a': startTagA(token); return null; - case "b": - case "big": - case "code": - case "em": - case "font": - case "i": - case "s": - case "small": - case "strike": - case "strong": - case "tt": - case "u": + case 'b': + case 'big': + case 'code': + case 'em': + case 'font': + case 'i': + case 's': + case 'small': + case 'strike': + case 'strong': + case 'tt': + case 'u': startTagFormatting(token); return null; - case "nobr": + case 'nobr': startTagNobr(token); return null; - case "button": + case 'button': return startTagButton(token); - case "applet": - case "marquee": - case "object": + case 'applet': + case 'marquee': + case 'object': startTagAppletMarqueeObject(token); return null; - case "xmp": + case 'xmp': startTagXmp(token); return null; - case "table": + case 'table': startTagTable(token); return null; - case "area": - case "br": - case "embed": - case "img": - case "keygen": - case "wbr": + case 'area': + case 'br': + case 'embed': + case 'img': + case 'keygen': + case 'wbr': startTagVoidFormatting(token); return null; - case "param": - case "source": - case "track": + case 'param': + case 'source': + case 'track': startTagParamSource(token); return null; - case "input": + case 'input': startTagInput(token); return null; - case "hr": + case 'hr': startTagHr(token); return null; - case "image": + case 'image': startTagImage(token); return null; - case "isindex": + case 'isindex': startTagIsIndex(token); return null; - case "textarea": + case 'textarea': startTagTextarea(token); return null; - case "iframe": + case 'iframe': startTagIFrame(token); return null; - case "noembed": - case "noscript": + case 'noembed': + case 'noscript': startTagRawtext(token); return null; - case "select": + case 'select': startTagSelect(token); return null; - case "rp": - case "rt": + case 'rp': + case 'rt': startTagRpRt(token); return null; - case "option": - case "optgroup": + case 'option': + case 'optgroup': startTagOpt(token); return null; - case "math": + case 'math': startTagMath(token); return null; - case "svg": + case 'svg': startTagSvg(token); return null; - case "caption": - case "col": - case "colgroup": - case "frame": - case "head": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": + case 'caption': + case 'col': + case 'colgroup': + case 'frame': + case 'head': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': startTagMisplaced(token); return null; default: @@ -1371,80 +1400,81 @@ class InBodyPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "body": + case 'body': endTagBody(token); return null; - case "html": + case 'html': return endTagHtml(token); - case "address": - case "article": - case "aside": - case "blockquote": - case "center": - case "details": - case "dir": - case "div": - case "dl": - case "fieldset": - case "figcaption": - case "figure": - case "footer": - case "header": - case "hgroup": - case "listing": - case "menu": - case "nav": - case "ol": - case "pre": - case "section": - case "summary": - case "ul": + case 'address': + case 'article': + case 'aside': + case 'blockquote': + case 'center': + case 'details': + case 'dir': + case 'div': + case 'dl': + case 'fieldset': + case 'figcaption': + case 'figure': + case 'footer': + case 'header': + case 'hgroup': + case 'listing': + case 'menu': + case 'nav': + case 'ol': + case 'pre': + case 'section': + case 'summary': + case 'ul': endTagBlock(token); return null; - case "form": + case 'form': endTagForm(token); return null; - case "p": + case 'p': endTagP(token); return null; - case "dd": - case "dt": - case "li": + case 'dd': + case 'dt': + case 'li': endTagListItem(token); return null; // headingElements - case "h1": - case "h2": - case "h3": - case "h4": - case "h5": - case "h6": + case 'h1': + case 'h2': + case 'h3': + case 'h4': + case 'h5': + case 'h6': endTagHeading(token); return null; - case "a": - case "b": - case "big": - case "code": - case "em": - case "font": - case "i": - case "nobr": - case "s": - case "small": - case "strike": - case "strong": - case "tt": - case "u": + case 'a': + case 'b': + case 'big': + case 'code': + case 'em': + case 'font': + case 'i': + case 'nobr': + case 's': + case 'small': + case 'strike': + case 'strong': + case 'tt': + case 'u': endTagFormatting(token); return null; - case "applet": - case "marquee": - case "object": + case 'applet': + case 'marquee': + case 'object': endTagAppletMarqueeObject(token); return null; - case "br": + case 'br': endTagBr(token); return null; default: @@ -1491,24 +1521,25 @@ class InBodyPhase extends Phase { } // the real deal + @override bool processEOF() { for (var node in tree.openElements.reversed) { switch (node.localName) { - case "dd": - case "dt": - case "li": - case "p": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": - case "body": - case "html": + case 'dd': + case 'dt': + case 'li': + case 'p': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': + case 'body': + case 'html': continue; } - parser.parseError(node.sourceSpan, "expected-closing-tag-but-got-eof"); + parser.parseError(node.sourceSpan, 'expected-closing-tag-but-got-eof'); break; } //Stop parsing @@ -1520,9 +1551,9 @@ class InBodyPhase extends Phase { // want to drop leading newlines var data = token.data; dropNewline = false; - if (data.startsWith("\n")) { + if (data.startsWith('\n')) { var lastOpen = tree.openElements.last; - if (const ["pre", "listing", "textarea"].contains(lastOpen.localName) && + if (const ['pre', 'listing', 'textarea'].contains(lastOpen.localName) && !lastOpen.hasContent()) { data = data.substring(1); } @@ -1533,8 +1564,9 @@ class InBodyPhase extends Phase { } } + @override Token processCharacters(CharactersToken token) { - if (token.data == "\u0000") { + if (token.data == '\u0000') { //The tokenizer should always emit null on its own return null; } @@ -1546,6 +1578,7 @@ class InBodyPhase extends Phase { return null; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { if (dropNewline) { processSpaceCharactersDropNewline(token); @@ -1561,9 +1594,9 @@ class InBodyPhase extends Phase { } void startTagBody(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag", {"name": "body"}); + parser.parseError(token.span, 'unexpected-start-tag', {'name': 'body'}); if (tree.openElements.length == 1 || - tree.openElements[1].localName != "body") { + tree.openElements[1].localName != 'body') { assert(parser.innerHTMLMode); } else { parser.framesetOK = false; @@ -1574,15 +1607,15 @@ class InBodyPhase extends Phase { } void startTagFrameset(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag", {"name": "frameset"}); + parser.parseError(token.span, 'unexpected-start-tag', {'name': 'frameset'}); if ((tree.openElements.length == 1 || - tree.openElements[1].localName != "body")) { + tree.openElements[1].localName != 'body')) { assert(parser.innerHTMLMode); } else if (parser.framesetOK) { if (tree.openElements[1].parentNode != null) { tree.openElements[1].parentNode.nodes.remove(tree.openElements[1]); } - while (tree.openElements.last.localName != "html") { + while (tree.openElements.last.localName != 'html') { tree.openElements.removeLast(); } tree.insertElement(token); @@ -1591,15 +1624,15 @@ class InBodyPhase extends Phase { } void startTagCloseP(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.insertElement(token); } void startTagPreListing(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.insertElement(token); parser.framesetOK = false; @@ -1608,10 +1641,10 @@ class InBodyPhase extends Phase { void startTagForm(StartTagToken token) { if (tree.formPointer != null) { - parser.parseError(token.span, "unexpected-start-tag", {"name": "form"}); + parser.parseError(token.span, 'unexpected-start-tag', {'name': 'form'}); } else { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.insertElement(token); tree.formPointer = tree.openElements.last; @@ -1622,9 +1655,9 @@ class InBodyPhase extends Phase { parser.framesetOK = false; final stopNamesMap = const { - "li": ["li"], - "dt": ["dt", "dd"], - "dd": ["dt", "dd"] + 'li': ['li'], + 'dt': ['dt', 'dd'], + 'dd': ['dt', 'dd'] }; var stopNames = stopNamesMap[token.name]; for (var node in tree.openElements.reversed) { @@ -1633,44 +1666,44 @@ class InBodyPhase extends Phase { break; } if (specialElements.contains(getElementNameTuple(node)) && - !const ["address", "div", "p"].contains(node.localName)) { + !const ['address', 'div', 'p'].contains(node.localName)) { break; } } - if (tree.elementInScope("p", variant: "button")) { - parser.phase.processEndTag(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + parser.phase.processEndTag(EndTagToken('p')); } tree.insertElement(token); } void startTagPlaintext(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.insertElement(token); parser.tokenizer.state = parser.tokenizer.plaintextState; } void startTagHeading(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } if (headingElements.contains(tree.openElements.last.localName)) { parser - .parseError(token.span, "unexpected-start-tag", {"name": token.name}); + .parseError(token.span, 'unexpected-start-tag', {'name': token.name}); tree.openElements.removeLast(); } tree.insertElement(token); } void startTagA(StartTagToken token) { - var afeAElement = tree.elementInActiveFormattingElements("a"); + var afeAElement = tree.elementInActiveFormattingElements('a'); if (afeAElement != null) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "a", "endName": "a"}); - endTagFormatting(EndTagToken("a")); + parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', + {'startName': 'a', 'endName': 'a'}); + endTagFormatting(EndTagToken('a')); tree.openElements.remove(afeAElement); tree.activeFormattingElements.remove(afeAElement); } @@ -1685,10 +1718,10 @@ class InBodyPhase extends Phase { void startTagNobr(StartTagToken token) { tree.reconstructActiveFormattingElements(); - if (tree.elementInScope("nobr")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "nobr", "endName": "nobr"}); - processEndTag(EndTagToken("nobr")); + if (tree.elementInScope('nobr')) { + parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', + {'startName': 'nobr', 'endName': 'nobr'}); + processEndTag(EndTagToken('nobr')); // XXX Need tests that trigger the following tree.reconstructActiveFormattingElements(); } @@ -1696,10 +1729,10 @@ class InBodyPhase extends Phase { } Token startTagButton(StartTagToken token) { - if (tree.elementInScope("button")) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "button", "endName": "button"}); - processEndTag(EndTagToken("button")); + if (tree.elementInScope('button')) { + parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', + {'startName': 'button', 'endName': 'button'}); + processEndTag(EndTagToken('button')); return token; } else { tree.reconstructActiveFormattingElements(); @@ -1717,18 +1750,18 @@ class InBodyPhase extends Phase { } void startTagXmp(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.reconstructActiveFormattingElements(); parser.framesetOK = false; - parser.parseRCDataRawtext(token, "RAWTEXT"); + parser.parseRCDataRawtext(token, 'RAWTEXT'); } void startTagTable(StartTagToken token) { - if (parser.compatMode != "quirks") { - if (tree.elementInScope("p", variant: "button")) { - processEndTag(EndTagToken("p")); + if (parser.compatMode != 'quirks') { + if (tree.elementInScope('p', variant: 'button')) { + processEndTag(EndTagToken('p')); } } tree.insertElement(token); @@ -1747,7 +1780,7 @@ class InBodyPhase extends Phase { void startTagInput(StartTagToken token) { var savedFramesetOK = parser.framesetOK; startTagVoidFormatting(token); - if (asciiUpper2Lower(token.data["type"]) == "hidden") { + if (asciiUpper2Lower(token.data['type']) == 'hidden') { //input type=hidden doesn't change framesetOK parser.framesetOK = savedFramesetOK; } @@ -1760,8 +1793,8 @@ class InBodyPhase extends Phase { } void startTagHr(StartTagToken token) { - if (tree.elementInScope("p", variant: "button")) { - endTagP(EndTagToken("p")); + if (tree.elementInScope('p', variant: 'button')) { + endTagP(EndTagToken('p')); } tree.insertElement(token); tree.openElements.removeLast(); @@ -1771,43 +1804,41 @@ class InBodyPhase extends Phase { void startTagImage(StartTagToken token) { // No really... - parser.parseError(token.span, "unexpected-start-tag-treated-as", - {"originalName": "image", "newName": "img"}); + parser.parseError(token.span, 'unexpected-start-tag-treated-as', + {'originalName': 'image', 'newName': 'img'}); processStartTag( - StartTagToken("img", data: token.data, selfClosing: token.selfClosing)); + StartTagToken('img', data: token.data, selfClosing: token.selfClosing)); } void startTagIsIndex(StartTagToken token) { - parser.parseError(token.span, "deprecated-tag", {"name": "isindex"}); + parser.parseError(token.span, 'deprecated-tag', {'name': 'isindex'}); if (tree.formPointer != null) { return; } - var formAttrs = LinkedHashMap<dynamic, String>(); - var dataAction = token.data["action"]; + var formAttrs = <dynamic, String>{}; + var dataAction = token.data['action']; if (dataAction != null) { - formAttrs["action"] = dataAction; + formAttrs['action'] = dataAction; } - processStartTag(StartTagToken("form", data: formAttrs)); + processStartTag(StartTagToken('form', data: formAttrs)); processStartTag( - StartTagToken("hr", data: LinkedHashMap<dynamic, String>())); + StartTagToken('hr', data: LinkedHashMap<dynamic, String>())); processStartTag( - StartTagToken("label", data: LinkedHashMap<dynamic, String>())); + StartTagToken('label', data: LinkedHashMap<dynamic, String>())); // XXX Localization ... - var prompt = token.data["prompt"]; - if (prompt == null) { - prompt = "This is a searchable index. Enter search keywords: "; - } + var prompt = token.data['prompt']; + prompt ??= 'This is a searchable index. Enter search keywords: '; processCharacters(CharactersToken(prompt)); var attributes = LinkedHashMap<dynamic, String>.from(token.data); attributes.remove('action'); attributes.remove('prompt'); - attributes["name"] = "isindex"; - processStartTag(StartTagToken("input", + attributes['name'] = 'isindex'; + processStartTag(StartTagToken('input', data: attributes, selfClosing: token.selfClosing)); - processEndTag(EndTagToken("label")); + processEndTag(EndTagToken('label')); processStartTag( - StartTagToken("hr", data: LinkedHashMap<dynamic, String>())); - processEndTag(EndTagToken("form")); + StartTagToken('hr', data: LinkedHashMap<dynamic, String>())); + processEndTag(EndTagToken('form')); } void startTagTextarea(StartTagToken token) { @@ -1824,12 +1855,12 @@ class InBodyPhase extends Phase { /// iframe, noembed noframes, noscript(if scripting enabled). void startTagRawtext(StartTagToken token) { - parser.parseRCDataRawtext(token, "RAWTEXT"); + parser.parseRCDataRawtext(token, 'RAWTEXT'); } void startTagOpt(StartTagToken token) { - if (tree.openElements.last.localName == "option") { - parser.phase.processEndTag(EndTagToken("option")); + if (tree.openElements.last.localName == 'option') { + parser.phase.processEndTag(EndTagToken('option')); } tree.reconstructActiveFormattingElements(); parser.tree.insertElement(token); @@ -1853,10 +1884,10 @@ class InBodyPhase extends Phase { } void startTagRpRt(StartTagToken token) { - if (tree.elementInScope("ruby")) { + if (tree.elementInScope('ruby')) { tree.generateImpliedEndTags(); var last = tree.openElements.last; - if (last.localName != "ruby") { + if (last.localName != 'ruby') { parser.parseError(last.sourceSpan, 'undefined-error'); } } @@ -1898,7 +1929,7 @@ class InBodyPhase extends Phase { /// "tr", "noscript" void startTagMisplaced(StartTagToken token) { parser.parseError( - token.span, "unexpected-start-tag-ignored", {"name": token.name}); + token.span, 'unexpected-start-tag-ignored', {'name': token.name}); } Token startTagOther(StartTagToken token) { @@ -1908,50 +1939,50 @@ class InBodyPhase extends Phase { } void endTagP(EndTagToken token) { - if (!tree.elementInScope("p", variant: "button")) { + if (!tree.elementInScope('p', variant: 'button')) { startTagCloseP( - StartTagToken("p", data: LinkedHashMap<dynamic, String>())); - parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); - endTagP(EndTagToken("p")); + StartTagToken('p', data: LinkedHashMap<dynamic, String>())); + parser.parseError(token.span, 'unexpected-end-tag', {'name': 'p'}); + endTagP(EndTagToken('p')); } else { - tree.generateImpliedEndTags("p"); - if (tree.openElements.last.localName != "p") { - parser.parseError(token.span, "unexpected-end-tag", {"name": "p"}); + tree.generateImpliedEndTags('p'); + if (tree.openElements.last.localName != 'p') { + parser.parseError(token.span, 'unexpected-end-tag', {'name': 'p'}); } popOpenElementsUntil(token); } } void endTagBody(EndTagToken token) { - if (!tree.elementInScope("body")) { + if (!tree.elementInScope('body')) { parser.parseError(token.span, 'undefined-error'); return; - } else if (tree.openElements.last.localName == "body") { + } else if (tree.openElements.last.localName == 'body') { tree.openElements.last.endSourceSpan = token.span; } else { - for (Element node in slice(tree.openElements, 2)) { + for (var node in slice(tree.openElements, 2)) { switch (node.localName) { - case "dd": - case "dt": - case "li": - case "optgroup": - case "option": - case "p": - case "rp": - case "rt": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": - case "body": - case "html": + case 'dd': + case 'dt': + case 'li': + case 'optgroup': + case 'option': + case 'p': + case 'rp': + case 'rt': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': + case 'body': + case 'html': continue; } // Not sure this is the correct name for the parse error - parser.parseError(token.span, "expected-one-end-tag-but-got-another", - {"gotName": "body", "expectedName": node.localName}); + parser.parseError(token.span, 'expected-one-end-tag-but-got-another', + {'gotName': 'body', 'expectedName': node.localName}); break; } } @@ -1960,8 +1991,8 @@ class InBodyPhase extends Phase { Token endTagHtml(EndTagToken token) { //We repeat the test for the body end tag token being ignored here - if (tree.elementInScope("body")) { - endTagBody(EndTagToken("body")); + if (tree.elementInScope('body')) { + endTagBody(EndTagToken('body')); return token; } return null; @@ -1969,7 +2000,7 @@ class InBodyPhase extends Phase { void endTagBlock(EndTagToken token) { //Put us back in the right whitespace handling mode - if (token.name == "pre") { + if (token.name == 'pre') { dropNewline = false; } var inScope = tree.elementInScope(token.name); @@ -1977,7 +2008,7 @@ class InBodyPhase extends Phase { tree.generateImpliedEndTags(); } if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); + parser.parseError(token.span, 'end-tag-too-early', {'name': token.name}); } if (inScope) { popOpenElementsUntil(token); @@ -1988,12 +2019,12 @@ class InBodyPhase extends Phase { var node = tree.formPointer; tree.formPointer = null; if (node == null || !tree.elementInScope(node)) { - parser.parseError(token.span, "unexpected-end-tag", {"name": "form"}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': 'form'}); } else { tree.generateImpliedEndTags(); if (tree.openElements.last != node) { parser.parseError( - token.span, "end-tag-too-early-ignored", {"name": "form"}); + token.span, 'end-tag-too-early-ignored', {'name': 'form'}); } tree.openElements.remove(node); node.endSourceSpan = token.span; @@ -2002,18 +2033,18 @@ class InBodyPhase extends Phase { void endTagListItem(EndTagToken token) { String variant; - if (token.name == "li") { - variant = "list"; + if (token.name == 'li') { + variant = 'list'; } else { variant = null; } if (!tree.elementInScope(token.name, variant: variant)) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } else { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { parser - .parseError(token.span, "end-tag-too-early", {"name": token.name}); + .parseError(token.span, 'end-tag-too-early', {'name': token.name}); } popOpenElementsUntil(token); } @@ -2027,12 +2058,12 @@ class InBodyPhase extends Phase { } } if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); + parser.parseError(token.span, 'end-tag-too-early', {'name': token.name}); } for (var item in headingElements) { if (tree.elementInScope(item)) { - Element node = tree.openElements.removeLast(); + var node = tree.openElements.removeLast(); while (!headingElements.contains(node.localName)) { node = tree.openElements.removeLast(); } @@ -2051,7 +2082,7 @@ class InBodyPhase extends Phase { // updated spec. This needs a pass over it to verify that it still matches. // In particular the html5lib Python code skiped "step 4", I'm not sure why. // XXX Better parseError messages appreciated. - int outerLoopCounter = 0; + var outerLoopCounter = 0; while (outerLoopCounter < 8) { outerLoopCounter += 1; @@ -2062,12 +2093,12 @@ class InBodyPhase extends Phase { (tree.openElements.contains(formattingElement) && !tree.elementInScope(formattingElement.localName))) { parser.parseError( - token.span, "adoption-agency-1.1", {"name": token.name}); + token.span, 'adoption-agency-1.1', {'name': token.name}); return; // Step 1 paragraph 2 } else if (!tree.openElements.contains(formattingElement)) { parser.parseError( - token.span, "adoption-agency-1.2", {"name": token.name}); + token.span, 'adoption-agency-1.2', {'name': token.name}); tree.activeFormattingElements.remove(formattingElement); return; } @@ -2075,14 +2106,14 @@ class InBodyPhase extends Phase { // Step 1 paragraph 3 if (formattingElement != tree.openElements.last) { parser.parseError( - token.span, "adoption-agency-1.3", {"name": token.name}); + token.span, 'adoption-agency-1.3', {'name': token.name}); } // Step 2 // Start of the adoption agency algorithm proper var afeIndex = tree.openElements.indexOf(formattingElement); Node furthestBlock; - for (Node element in slice(tree.openElements, afeIndex)) { + for (var element in slice(tree.openElements, afeIndex)) { if (specialElements.contains(getElementNameTuple(element))) { furthestBlock = element; break; @@ -2090,7 +2121,7 @@ class InBodyPhase extends Phase { } // Step 3 if (furthestBlock == null) { - Element element = tree.openElements.removeLast(); + var element = tree.openElements.removeLast(); while (element != formattingElement) { element = tree.openElements.removeLast(); } @@ -2111,9 +2142,9 @@ class InBodyPhase extends Phase { var bookmark = tree.activeFormattingElements.indexOf(formattingElement); // Step 6 - Node lastNode = furthestBlock; + var lastNode = furthestBlock; var node = furthestBlock; - int innerLoopCounter = 0; + var innerLoopCounter = 0; var index = tree.openElements.indexOf(node); while (innerLoopCounter < 3) { @@ -2162,7 +2193,7 @@ class InBodyPhase extends Phase { lastNode.parentNode.nodes.remove(lastNode); } - if (const ["table", "tbody", "tfoot", "thead", "tr"] + if (const ['table', 'tbody', 'tfoot', 'thead', 'tr'] .contains(commonAncestor.localName)) { var nodePos = tree.getTableMisnestedNodePosition(); nodePos[0].insertBefore(lastNode, nodePos[1]); @@ -2196,7 +2227,7 @@ class InBodyPhase extends Phase { tree.generateImpliedEndTags(); } if (tree.openElements.last.localName != token.name) { - parser.parseError(token.span, "end-tag-too-early", {"name": token.name}); + parser.parseError(token.span, 'end-tag-too-early', {'name': token.name}); } if (tree.elementInScope(token.name)) { popOpenElementsUntil(token); @@ -2205,11 +2236,11 @@ class InBodyPhase extends Phase { } void endTagBr(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-treated-as", - {"originalName": "br", "newName": "br element"}); + parser.parseError(token.span, 'unexpected-end-tag-treated-as', + {'originalName': 'br', 'newName': 'br element'}); tree.reconstructActiveFormattingElements(); tree.insertElement( - StartTagToken("br", data: LinkedHashMap<dynamic, String>())); + StartTagToken('br', data: LinkedHashMap<dynamic, String>())); tree.openElements.removeLast(); } @@ -2219,7 +2250,7 @@ class InBodyPhase extends Phase { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { parser.parseError( - token.span, "unexpected-end-tag", {"name": token.name}); + token.span, 'unexpected-end-tag', {'name': token.name}); } while (tree.openElements.removeLast() != node) { // noop @@ -2229,7 +2260,7 @@ class InBodyPhase extends Phase { } else { if (specialElements.contains(getElementNameTuple(node))) { parser.parseError( - token.span, "unexpected-end-tag", {"name": token.name}); + token.span, 'unexpected-end-tag', {'name': token.name}); break; } } @@ -2241,11 +2272,13 @@ class TextPhase extends Phase { TextPhase(parser) : super(parser); // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name + @override // ignore: missing_return Token processStartTag(StartTagToken token) { assert(false); } + @override Token processEndTag(EndTagToken token) { if (token.name == 'script') { endTagScript(token); @@ -2255,14 +2288,16 @@ class TextPhase extends Phase { return null; } + @override Token processCharacters(CharactersToken token) { tree.insertText(token.data, token.span); return null; } + @override bool processEOF() { var last = tree.openElements.last; - parser.parseError(last.sourceSpan, "expected-named-closing-tag-but-got-eof", + parser.parseError(last.sourceSpan, 'expected-named-closing-tag-but-got-eof', {'name': last.localName}); tree.openElements.removeLast(); parser.phase = parser.originalPhase; @@ -2271,7 +2306,7 @@ class TextPhase extends Phase { void endTagScript(EndTagToken token) { var node = tree.openElements.removeLast(); - assert(node.localName == "script"); + assert(node.localName == 'script'); parser.phase = parser.originalPhase; //The rest of this method is all stuff that only happens if //document.write works @@ -2287,36 +2322,37 @@ class InTablePhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table InTablePhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "caption": + case 'caption': startTagCaption(token); return null; - case "colgroup": + case 'colgroup': startTagColgroup(token); return null; - case "col": + case 'col': return startTagCol(token); - case "tbody": - case "tfoot": - case "thead": + case 'tbody': + case 'tfoot': + case 'thead': startTagRowGroup(token); return null; - case "td": - case "th": - case "tr": + case 'td': + case 'th': + case 'tr': return startTagImplyTbody(token); - case "table": + case 'table': return startTagTable(token); - case "style": - case "script": + case 'style': + case 'script': return startTagStyleScript(token); - case "input": + case 'input': startTagInput(token); return null; - case "form": + case 'form': startTagForm(token); return null; default: @@ -2325,22 +2361,23 @@ class InTablePhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "table": + case 'table': endTagTable(token); return null; - case "body": - case "caption": - case "col": - case "colgroup": - case "html": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": + case 'body': + case 'caption': + case 'col': + case 'colgroup': + case 'html': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': endTagIgnore(token); return null; default: @@ -2351,9 +2388,9 @@ class InTablePhase extends Phase { // helper methods void clearStackToTableContext() { - // "clear the stack back to a table context" - while (tree.openElements.last.localName != "table" && - tree.openElements.last.localName != "html") { + // 'clear the stack back to a table context' + while (tree.openElements.last.localName != 'table' && + tree.openElements.last.localName != 'html') { //parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) tree.openElements.removeLast(); @@ -2362,10 +2399,11 @@ class InTablePhase extends Phase { } // processing methods + @override bool processEOF() { var last = tree.openElements.last; - if (last.localName != "html") { - parser.parseError(last.sourceSpan, "eof-in-table"); + if (last.localName != 'html') { + parser.parseError(last.sourceSpan, 'eof-in-table'); } else { assert(parser.innerHTMLMode); } @@ -2373,6 +2411,7 @@ class InTablePhase extends Phase { return false; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { var originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; @@ -2381,6 +2420,7 @@ class InTablePhase extends Phase { return null; } + @override Token processCharacters(CharactersToken token) { var originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; @@ -2412,7 +2452,7 @@ class InTablePhase extends Phase { Token startTagCol(StartTagToken token) { startTagColgroup( - StartTagToken("colgroup", data: LinkedHashMap<dynamic, String>())); + StartTagToken('colgroup', data: LinkedHashMap<dynamic, String>())); return token; } @@ -2424,14 +2464,14 @@ class InTablePhase extends Phase { Token startTagImplyTbody(StartTagToken token) { startTagRowGroup( - StartTagToken("tbody", data: LinkedHashMap<dynamic, String>())); + StartTagToken('tbody', data: LinkedHashMap<dynamic, String>())); return token; } Token startTagTable(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-end-tag", - {"startName": "table", "endName": "table"}); - parser.phase.processEndTag(EndTagToken("table")); + parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', + {'startName': 'table', 'endName': 'table'}); + parser.phase.processEndTag(EndTagToken('table')); if (!parser.innerHTMLMode) { return token; } @@ -2443,8 +2483,8 @@ class InTablePhase extends Phase { } void startTagInput(StartTagToken token) { - if (asciiUpper2Lower(token.data["type"]) == "hidden") { - parser.parseError(token.span, "unexpected-hidden-input-in-table"); + if (asciiUpper2Lower(token.data['type']) == 'hidden') { + parser.parseError(token.span, 'unexpected-hidden-input-in-table'); tree.insertElement(token); // XXX associate with form tree.openElements.removeLast(); @@ -2454,7 +2494,7 @@ class InTablePhase extends Phase { } void startTagForm(StartTagToken token) { - parser.parseError(token.span, "unexpected-form-in-table"); + parser.parseError(token.span, 'unexpected-form-in-table'); if (tree.formPointer == null) { tree.insertElement(token); tree.formPointer = tree.openElements.last; @@ -2463,8 +2503,8 @@ class InTablePhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-implies-table-voodoo", - {"name": token.name}); + parser.parseError(token.span, 'unexpected-start-tag-implies-table-voodoo', + {'name': token.name}); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processStartTag(token); @@ -2472,14 +2512,14 @@ class InTablePhase extends Phase { } void endTagTable(EndTagToken token) { - if (tree.elementInScope("table", variant: "table")) { + if (tree.elementInScope('table', variant: 'table')) { tree.generateImpliedEndTags(); var last = tree.openElements.last; - if (last.localName != "table") { - parser.parseError(token.span, "end-tag-too-early-named", - {"gotName": "table", "expectedName": last.localName}); + if (last.localName != 'table') { + parser.parseError(token.span, 'end-tag-too-early-named', + {'gotName': 'table', 'expectedName': last.localName}); } - while (tree.openElements.last.localName != "table") { + while (tree.openElements.last.localName != 'table') { tree.openElements.removeLast(); } var node = tree.openElements.removeLast(); @@ -2488,17 +2528,17 @@ class InTablePhase extends Phase { } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } } void endTagIgnore(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } void endTagOther(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag-implies-table-voodoo", - {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag-implies-table-voodoo', + {'name': token.name}); // Do the table magic! tree.insertFromTable = true; parser._inBodyPhase.processEndTag(token); @@ -2533,26 +2573,30 @@ class InTableTextPhase extends Phase { characterTokens = <StringToken>[]; } + @override Token processComment(CommentToken token) { flushCharacters(); parser.phase = originalPhase; return token; } + @override bool processEOF() { flushCharacters(); parser.phase = originalPhase; return true; } + @override Token processCharacters(CharactersToken token) { - if (token.data == "\u0000") { + if (token.data == '\u0000') { return null; } characterTokens.add(token); return null; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { //pretty sure we should never reach here characterTokens.add(token); @@ -2560,12 +2604,14 @@ class InTableTextPhase extends Phase { return null; } + @override Token processStartTag(StartTagToken token) { flushCharacters(); parser.phase = originalPhase; return token; } + @override Token processEndTag(EndTagToken token) { flushCharacters(); parser.phase = originalPhase; @@ -2577,42 +2623,44 @@ class InCaptionPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-caption InCaptionPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "caption": - case "col": - case "colgroup": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": + case 'caption': + case 'col': + case 'colgroup': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': return startTagTableElement(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "caption": + case 'caption': endTagCaption(token); return null; - case "table": + case 'table': return endTagTable(token); - case "body": - case "col": - case "colgroup": - case "html": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": + case 'body': + case 'col': + case 'colgroup': + case 'html': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': endTagIgnore(token); return null; default: @@ -2621,23 +2669,25 @@ class InCaptionPhase extends Phase { } bool ignoreEndTagCaption() { - return !tree.elementInScope("caption", variant: "table"); + return !tree.elementInScope('caption', variant: 'table'); } + @override bool processEOF() { parser._inBodyPhase.processEOF(); return false; } + @override Token processCharacters(CharactersToken token) { return parser._inBodyPhase.processCharacters(token); } Token startTagTableElement(StartTagToken token) { - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); //XXX Have to duplicate logic here to find out if the tag is ignored var ignoreEndTag = ignoreEndTagCaption(); - parser.phase.processEndTag(EndTagToken("caption")); + parser.phase.processEndTag(EndTagToken('caption')); if (!ignoreEndTag) { return token; } @@ -2652,13 +2702,13 @@ class InCaptionPhase extends Phase { if (!ignoreEndTagCaption()) { // AT this code is quite similar to endTagTable in "InTable" tree.generateImpliedEndTags(); - if (tree.openElements.last.localName != "caption") { - parser.parseError(token.span, "expected-one-end-tag-but-got-another", { - "gotName": "caption", - "expectedName": tree.openElements.last.localName + if (tree.openElements.last.localName != 'caption') { + parser.parseError(token.span, 'expected-one-end-tag-but-got-another', { + 'gotName': 'caption', + 'expectedName': tree.openElements.last.localName }); } - while (tree.openElements.last.localName != "caption") { + while (tree.openElements.last.localName != 'caption') { tree.openElements.removeLast(); } var node = tree.openElements.removeLast(); @@ -2668,14 +2718,14 @@ class InCaptionPhase extends Phase { } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } } Token endTagTable(EndTagToken token) { - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); var ignoreEndTag = ignoreEndTagCaption(); - parser.phase.processEndTag(EndTagToken("caption")); + parser.phase.processEndTag(EndTagToken('caption')); if (!ignoreEndTag) { return token; } @@ -2683,7 +2733,7 @@ class InCaptionPhase extends Phase { } void endTagIgnore(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } Token endTagOther(EndTagToken token) { @@ -2695,11 +2745,12 @@ class InColumnGroupPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-column InColumnGroupPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "col": + case 'col': startTagCol(token); return null; default: @@ -2707,12 +2758,13 @@ class InColumnGroupPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "colgroup": + case 'colgroup': endTagColgroup(token); return null; - case "col": + case 'col': endTagCol(token); return null; default: @@ -2721,23 +2773,25 @@ class InColumnGroupPhase extends Phase { } bool ignoreEndTagColgroup() { - return tree.openElements.last.localName == "html"; + return tree.openElements.last.localName == 'html'; } + @override bool processEOF() { var ignoreEndTag = ignoreEndTagColgroup(); if (ignoreEndTag) { assert(parser.innerHTMLMode); return false; } else { - endTagColgroup(EndTagToken("colgroup")); + endTagColgroup(EndTagToken('colgroup')); return true; } } + @override Token processCharacters(CharactersToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(EndTagToken("colgroup")); + endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } @@ -2748,7 +2802,7 @@ class InColumnGroupPhase extends Phase { Token startTagOther(StartTagToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(EndTagToken("colgroup")); + endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } @@ -2756,7 +2810,7 @@ class InColumnGroupPhase extends Phase { if (ignoreEndTagColgroup()) { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } else { var node = tree.openElements.removeLast(); node.endSourceSpan = token.span; @@ -2765,12 +2819,12 @@ class InColumnGroupPhase extends Phase { } void endTagCol(EndTagToken token) { - parser.parseError(token.span, "no-end-tag", {"name": "col"}); + parser.parseError(token.span, 'no-end-tag', {'name': 'col'}); } Token endTagOther(EndTagToken token) { var ignoreEndTag = ignoreEndTagColgroup(); - endTagColgroup(EndTagToken("colgroup")); + endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } } @@ -2779,45 +2833,47 @@ class InTableBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table0 InTableBodyPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "tr": + case 'tr': startTagTr(token); return null; - case "td": - case "th": + case 'td': + case 'th': return startTagTableCell(token); - case "caption": - case "col": - case "colgroup": - case "tbody": - case "tfoot": - case "thead": + case 'caption': + case 'col': + case 'colgroup': + case 'tbody': + case 'tfoot': + case 'thead': return startTagTableOther(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "tbody": - case "tfoot": - case "thead": + case 'tbody': + case 'tfoot': + case 'thead': endTagTableRowGroup(token); return null; - case "table": + case 'table': return endTagTable(token); - case "body": - case "caption": - case "col": - case "colgroup": - case "html": - case "td": - case "th": - case "tr": + case 'body': + case 'caption': + case 'col': + case 'colgroup': + case 'html': + case 'td': + case 'th': + case 'tr': endTagIgnore(token); return null; default: @@ -2827,27 +2883,30 @@ class InTableBodyPhase extends Phase { // helper methods void clearStackToTableBodyContext() { - var tableTags = const ["tbody", "tfoot", "thead", "html"]; + var tableTags = const ['tbody', 'tfoot', 'thead', 'html']; while (!tableTags.contains(tree.openElements.last.localName)) { //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) tree.openElements.removeLast(); } - if (tree.openElements.last.localName == "html") { + if (tree.openElements.last.localName == 'html') { assert(parser.innerHTMLMode); } } // the rest + @override bool processEOF() { parser._inTablePhase.processEOF(); return false; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return parser._inTablePhase.processSpaceCharacters(token); } + @override Token processCharacters(CharactersToken token) { return parser._inTablePhase.processCharacters(token); } @@ -2860,8 +2919,8 @@ class InTableBodyPhase extends Phase { Token startTagTableCell(StartTagToken token) { parser.parseError( - token.span, "unexpected-cell-in-table-body", {"name": token.name}); - startTagTr(StartTagToken("tr", data: LinkedHashMap<dynamic, String>())); + token.span, 'unexpected-cell-in-table-body', {'name': token.name}); + startTagTr(StartTagToken('tr', data: LinkedHashMap<dynamic, String>())); return token; } @@ -2872,36 +2931,36 @@ class InTableBodyPhase extends Phase { } void endTagTableRowGroup(EndTagToken token) { - if (tree.elementInScope(token.name, variant: "table")) { + if (tree.elementInScope(token.name, variant: 'table')) { clearStackToTableBodyContext(); var node = tree.openElements.removeLast(); node.endSourceSpan = token.span; parser.phase = parser._inTablePhase; } else { parser.parseError( - token.span, "unexpected-end-tag-in-table-body", {"name": token.name}); + token.span, 'unexpected-end-tag-in-table-body', {'name': token.name}); } } Token endTagTable(TagToken token) { // XXX AT Any ideas on how to share this with endTagTable? - if (tree.elementInScope("tbody", variant: "table") || - tree.elementInScope("thead", variant: "table") || - tree.elementInScope("tfoot", variant: "table")) { + if (tree.elementInScope('tbody', variant: 'table') || + tree.elementInScope('thead', variant: 'table') || + tree.elementInScope('tfoot', variant: 'table')) { clearStackToTableBodyContext(); endTagTableRowGroup(EndTagToken(tree.openElements.last.localName)); return token; } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } return null; } void endTagIgnore(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-in-table-body", {"name": token.name}); + token.span, 'unexpected-end-tag-in-table-body', {'name': token.name}); } Token endTagOther(EndTagToken token) { @@ -2913,45 +2972,47 @@ class InRowPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-row InRowPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "td": - case "th": + case 'td': + case 'th': startTagTableCell(token); return null; - case "caption": - case "col": - case "colgroup": - case "tbody": - case "tfoot": - case "thead": - case "tr": + case 'caption': + case 'col': + case 'colgroup': + case 'tbody': + case 'tfoot': + case 'thead': + case 'tr': return startTagTableOther(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "tr": + case 'tr': endTagTr(token); return null; - case "table": + case 'table': return endTagTable(token); - case "tbody": - case "tfoot": - case "thead": + case 'tbody': + case 'tfoot': + case 'thead': return endTagTableRowGroup(token); - case "body": - case "caption": - case "col": - case "colgroup": - case "html": - case "td": - case "th": + case 'body': + case 'caption': + case 'col': + case 'colgroup': + case 'html': + case 'td': + case 'th': endTagIgnore(token); return null; default: @@ -2963,30 +3024,33 @@ class InRowPhase extends Phase { void clearStackToTableRowContext() { while (true) { var last = tree.openElements.last; - if (last.localName == "tr" || last.localName == "html") break; + if (last.localName == 'tr' || last.localName == 'html') break; parser.parseError( last.sourceSpan, - "unexpected-implied-end-tag-in-table-row", - {"name": tree.openElements.last.localName}); + 'unexpected-implied-end-tag-in-table-row', + {'name': tree.openElements.last.localName}); tree.openElements.removeLast(); } } bool ignoreEndTagTr() { - return !tree.elementInScope("tr", variant: "table"); + return !tree.elementInScope('tr', variant: 'table'); } // the rest + @override bool processEOF() { parser._inTablePhase.processEOF(); return false; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return parser._inTablePhase.processSpaceCharacters(token); } + @override Token processCharacters(CharactersToken token) { return parser._inTablePhase.processCharacters(token); } @@ -2999,8 +3063,8 @@ class InRowPhase extends Phase { } Token startTagTableOther(StartTagToken token) { - bool ignoreEndTag = ignoreEndTagTr(); - endTagTr(EndTagToken("tr")); + var ignoreEndTag = ignoreEndTagTr(); + endTagTr(EndTagToken('tr')); // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; } @@ -3018,31 +3082,31 @@ class InRowPhase extends Phase { } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } } Token endTagTable(EndTagToken token) { var ignoreEndTag = ignoreEndTagTr(); - endTagTr(EndTagToken("tr")); + endTagTr(EndTagToken('tr')); // Reprocess the current tag if the tr end tag was not ignored // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; } Token endTagTableRowGroup(EndTagToken token) { - if (tree.elementInScope(token.name, variant: "table")) { - endTagTr(EndTagToken("tr")); + if (tree.elementInScope(token.name, variant: 'table')) { + endTagTr(EndTagToken('tr')); return token; } else { - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); return null; } } void endTagIgnore(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-in-table-row", {"name": token.name}); + token.span, 'unexpected-end-tag-in-table-row', {'name': token.name}); } Token endTagOther(EndTagToken token) { @@ -3054,43 +3118,45 @@ class InCellPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-cell InCellPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "caption": - case "col": - case "colgroup": - case "tbody": - case "td": - case "tfoot": - case "th": - case "thead": - case "tr": + case 'caption': + case 'col': + case 'colgroup': + case 'tbody': + case 'td': + case 'tfoot': + case 'th': + case 'thead': + case 'tr': return startTagTableOther(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "td": - case "th": + case 'td': + case 'th': endTagTableCell(token); return null; - case "body": - case "caption": - case "col": - case "colgroup": - case "html": + case 'body': + case 'caption': + case 'col': + case 'colgroup': + case 'html': endTagIgnore(token); return null; - case "table": - case "tbody": - case "tfoot": - case "thead": - case "tr": + case 'table': + case 'tbody': + case 'tfoot': + case 'thead': + case 'tr': return endTagImply(token); default: return endTagOther(token); @@ -3099,32 +3165,34 @@ class InCellPhase extends Phase { // helper void closeCell() { - if (tree.elementInScope("td", variant: "table")) { - endTagTableCell(EndTagToken("td")); - } else if (tree.elementInScope("th", variant: "table")) { - endTagTableCell(EndTagToken("th")); + if (tree.elementInScope('td', variant: 'table')) { + endTagTableCell(EndTagToken('td')); + } else if (tree.elementInScope('th', variant: 'table')) { + endTagTableCell(EndTagToken('th')); } } // the rest + @override bool processEOF() { parser._inBodyPhase.processEOF(); return false; } + @override Token processCharacters(CharactersToken token) { return parser._inBodyPhase.processCharacters(token); } Token startTagTableOther(StartTagToken token) { - if (tree.elementInScope("td", variant: "table") || - tree.elementInScope("th", variant: "table")) { + if (tree.elementInScope('td', variant: 'table') || + tree.elementInScope('th', variant: 'table')) { closeCell(); return token; } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); return null; } } @@ -3134,11 +3202,11 @@ class InCellPhase extends Phase { } void endTagTableCell(EndTagToken token) { - if (tree.elementInScope(token.name, variant: "table")) { + if (tree.elementInScope(token.name, variant: 'table')) { tree.generateImpliedEndTags(token.name); if (tree.openElements.last.localName != token.name) { parser.parseError( - token.span, "unexpected-cell-end-tag", {"name": token.name}); + token.span, 'unexpected-cell-end-tag', {'name': token.name}); popOpenElementsUntil(token); } else { var node = tree.openElements.removeLast(); @@ -3147,21 +3215,21 @@ class InCellPhase extends Phase { tree.clearActiveFormattingElements(); parser.phase = parser._inRowPhase; } else { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } } void endTagIgnore(EndTagToken token) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } Token endTagImply(EndTagToken token) { - if (tree.elementInScope(token.name, variant: "table")) { + if (tree.elementInScope(token.name, variant: 'table')) { closeCell(); return token; } else { // sometimes innerHTML case - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } return null; } @@ -3174,39 +3242,41 @@ class InCellPhase extends Phase { class InSelectPhase extends Phase { InSelectPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "option": + case 'option': startTagOption(token); return null; - case "optgroup": + case 'optgroup': startTagOptgroup(token); return null; - case "select": + case 'select': startTagSelect(token); return null; - case "input": - case "keygen": - case "textarea": + case 'input': + case 'keygen': + case 'textarea': return startTagInput(token); - case "script": + case 'script': return startTagScript(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "option": + case 'option': endTagOption(token); return null; - case "optgroup": + case 'optgroup': endTagOptgroup(token); return null; - case "select": + case 'select': endTagSelect(token); return null; default: @@ -3216,18 +3286,20 @@ class InSelectPhase extends Phase { } // http://www.whatwg.org/specs/web-apps/current-work///in-select + @override bool processEOF() { var last = tree.openElements.last; - if (last.localName != "html") { - parser.parseError(last.sourceSpan, "eof-in-select"); + if (last.localName != 'html') { + parser.parseError(last.sourceSpan, 'eof-in-select'); } else { assert(parser.innerHTMLMode); } return false; } + @override Token processCharacters(CharactersToken token) { - if (token.data == "\u0000") { + if (token.data == '\u0000') { return null; } tree.insertText(token.data, token.span); @@ -3236,31 +3308,31 @@ class InSelectPhase extends Phase { void startTagOption(StartTagToken token) { // We need to imply </option> if <option> is the current node. - if (tree.openElements.last.localName == "option") { + if (tree.openElements.last.localName == 'option') { tree.openElements.removeLast(); } tree.insertElement(token); } void startTagOptgroup(StartTagToken token) { - if (tree.openElements.last.localName == "option") { + if (tree.openElements.last.localName == 'option') { tree.openElements.removeLast(); } - if (tree.openElements.last.localName == "optgroup") { + if (tree.openElements.last.localName == 'optgroup') { tree.openElements.removeLast(); } tree.insertElement(token); } void startTagSelect(StartTagToken token) { - parser.parseError(token.span, "unexpected-select-in-select"); - endTagSelect(EndTagToken("select")); + parser.parseError(token.span, 'unexpected-select-in-select'); + endTagSelect(EndTagToken('select')); } Token startTagInput(StartTagToken token) { - parser.parseError(token.span, "unexpected-input-in-select"); - if (tree.elementInScope("select", variant: "select")) { - endTagSelect(EndTagToken("select")); + parser.parseError(token.span, 'unexpected-input-in-select'); + if (tree.elementInScope('select', variant: 'select')) { + endTagSelect(EndTagToken('select')); return token; } else { assert(parser.innerHTMLMode); @@ -3274,95 +3346,99 @@ class InSelectPhase extends Phase { Token startTagOther(StartTagToken token) { parser.parseError( - token.span, "unexpected-start-tag-in-select", {"name": token.name}); + token.span, 'unexpected-start-tag-in-select', {'name': token.name}); return null; } void endTagOption(EndTagToken token) { - if (tree.openElements.last.localName == "option") { + if (tree.openElements.last.localName == 'option') { var node = tree.openElements.removeLast(); node.endSourceSpan = token.span; } else { parser.parseError( - token.span, "unexpected-end-tag-in-select", {"name": "option"}); + token.span, 'unexpected-end-tag-in-select', {'name': 'option'}); } } void endTagOptgroup(EndTagToken token) { // </optgroup> implicitly closes <option> - if (tree.openElements.last.localName == "option" && + if (tree.openElements.last.localName == 'option' && tree.openElements[tree.openElements.length - 2].localName == - "optgroup") { + 'optgroup') { tree.openElements.removeLast(); } // It also closes </optgroup> - if (tree.openElements.last.localName == "optgroup") { + if (tree.openElements.last.localName == 'optgroup') { var node = tree.openElements.removeLast(); node.endSourceSpan = token.span; // But nothing else } else { parser.parseError( - token.span, "unexpected-end-tag-in-select", {"name": "optgroup"}); + token.span, 'unexpected-end-tag-in-select', {'name': 'optgroup'}); } } void endTagSelect(EndTagToken token) { - if (tree.elementInScope("select", variant: "select")) { + if (tree.elementInScope('select', variant: 'select')) { popOpenElementsUntil(token); parser.resetInsertionMode(); } else { // innerHTML case assert(parser.innerHTMLMode); - parser.parseError(token.span, "undefined-error"); + parser.parseError(token.span, 'undefined-error'); } } void endTagOther(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-in-select", {"name": token.name}); + token.span, 'unexpected-end-tag-in-select', {'name': token.name}); } } class InSelectInTablePhase extends Phase { InSelectInTablePhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "caption": - case "table": - case "tbody": - case "tfoot": - case "thead": - case "tr": - case "td": - case "th": + case 'caption': + case 'table': + case 'tbody': + case 'tfoot': + case 'thead': + case 'tr': + case 'td': + case 'th': return startTagTable(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "caption": - case "table": - case "tbody": - case "tfoot": - case "thead": - case "tr": - case "td": - case "th": + case 'caption': + case 'table': + case 'tbody': + case 'tfoot': + case 'thead': + case 'tr': + case 'td': + case 'th': return endTagTable(token); default: return endTagOther(token); } } + @override bool processEOF() { parser._inSelectPhase.processEOF(); return false; } + @override Token processCharacters(CharactersToken token) { return parser._inSelectPhase.processCharacters(token); } @@ -3370,9 +3446,9 @@ class InSelectInTablePhase extends Phase { Token startTagTable(StartTagToken token) { parser.parseError( token.span, - "unexpected-table-element-start-tag-in-select-in-table", - {"name": token.name}); - endTagOther(EndTagToken("select")); + 'unexpected-table-element-start-tag-in-select-in-table', + {'name': token.name}); + endTagOther(EndTagToken('select')); return token; } @@ -3383,10 +3459,10 @@ class InSelectInTablePhase extends Phase { Token endTagTable(EndTagToken token) { parser.parseError( token.span, - "unexpected-table-element-end-tag-in-select-in-table", - {"name": token.name}); - if (tree.elementInScope(token.name, variant: "table")) { - endTagOther(EndTagToken("select")); + 'unexpected-table-element-end-tag-in-select-in-table', + {'name': token.name}); + if (tree.elementInScope(token.name, variant: 'table')) { + endTagOther(EndTagToken('select')); return token; } return null; @@ -3450,42 +3526,42 @@ class InForeignContentPhase extends Phase { void adjustSVGTagNames(token) { final replacements = const { - "altglyph": "altGlyph", - "altglyphdef": "altGlyphDef", - "altglyphitem": "altGlyphItem", - "animatecolor": "animateColor", - "animatemotion": "animateMotion", - "animatetransform": "animateTransform", - "clippath": "clipPath", - "feblend": "feBlend", - "fecolormatrix": "feColorMatrix", - "fecomponenttransfer": "feComponentTransfer", - "fecomposite": "feComposite", - "feconvolvematrix": "feConvolveMatrix", - "fediffuselighting": "feDiffuseLighting", - "fedisplacementmap": "feDisplacementMap", - "fedistantlight": "feDistantLight", - "feflood": "feFlood", - "fefunca": "feFuncA", - "fefuncb": "feFuncB", - "fefuncg": "feFuncG", - "fefuncr": "feFuncR", - "fegaussianblur": "feGaussianBlur", - "feimage": "feImage", - "femerge": "feMerge", - "femergenode": "feMergeNode", - "femorphology": "feMorphology", - "feoffset": "feOffset", - "fepointlight": "fePointLight", - "fespecularlighting": "feSpecularLighting", - "fespotlight": "feSpotLight", - "fetile": "feTile", - "feturbulence": "feTurbulence", - "foreignobject": "foreignObject", - "glyphref": "glyphRef", - "lineargradient": "linearGradient", - "radialgradient": "radialGradient", - "textpath": "textPath" + 'altglyph': 'altGlyph', + 'altglyphdef': 'altGlyphDef', + 'altglyphitem': 'altGlyphItem', + 'animatecolor': 'animateColor', + 'animatemotion': 'animateMotion', + 'animatetransform': 'animateTransform', + 'clippath': 'clipPath', + 'feblend': 'feBlend', + 'fecolormatrix': 'feColorMatrix', + 'fecomponenttransfer': 'feComponentTransfer', + 'fecomposite': 'feComposite', + 'feconvolvematrix': 'feConvolveMatrix', + 'fediffuselighting': 'feDiffuseLighting', + 'fedisplacementmap': 'feDisplacementMap', + 'fedistantlight': 'feDistantLight', + 'feflood': 'feFlood', + 'fefunca': 'feFuncA', + 'fefuncb': 'feFuncB', + 'fefuncg': 'feFuncG', + 'fefuncr': 'feFuncR', + 'fegaussianblur': 'feGaussianBlur', + 'feimage': 'feImage', + 'femerge': 'feMerge', + 'femergenode': 'feMergeNode', + 'femorphology': 'feMorphology', + 'feoffset': 'feOffset', + 'fepointlight': 'fePointLight', + 'fespecularlighting': 'feSpecularLighting', + 'fespotlight': 'feSpotLight', + 'fetile': 'feTile', + 'feturbulence': 'feTurbulence', + 'foreignobject': 'foreignObject', + 'glyphref': 'glyphRef', + 'lineargradient': 'linearGradient', + 'radialgradient': 'radialGradient', + 'textpath': 'textPath' }; var replace = replacements[token.name]; @@ -3494,24 +3570,26 @@ class InForeignContentPhase extends Phase { } } + @override Token processCharacters(CharactersToken token) { - if (token.data == "\u0000") { - token.replaceData("\uFFFD"); + if (token.data == '\u0000') { + token.replaceData('\uFFFD'); } else if (parser.framesetOK && !allWhitespace(token.data)) { parser.framesetOK = false; } return super.processCharacters(token); } + @override Token processStartTag(StartTagToken token) { var currentNode = tree.openElements.last; if (breakoutElements.contains(token.name) || - (token.name == "font" && - (token.data.containsKey("color") || - token.data.containsKey("face") || - token.data.containsKey("size")))) { + (token.name == 'font' && + (token.data.containsKey('color') || + token.data.containsKey('face') || + token.data.containsKey('size')))) { parser.parseError(token.span, - "unexpected-html-element-in-foreign-content", {'name': token.name}); + 'unexpected-html-element-in-foreign-content', {'name': token.name}); while (tree.openElements.last.namespaceUri != tree.defaultNamespace && !parser.isHTMLIntegrationPoint(tree.openElements.last) && !parser.isMathMLTextIntegrationPoint(tree.openElements.last)) { @@ -3536,11 +3614,12 @@ class InForeignContentPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { var nodeIndex = tree.openElements.length - 1; var node = tree.openElements.last; if (asciiUpper2Lower(node.localName) != token.name) { - parser.parseError(token.span, "unexpected-end-tag", {"name": token.name}); + parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } Token newToken; @@ -3575,13 +3654,15 @@ class InForeignContentPhase extends Phase { class AfterBodyPhase extends Phase { AfterBodyPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { - if (token.name == "html") return startTagHtml(token); + if (token.name == 'html') return startTagHtml(token); return startTagOther(token); } + @override Token processEndTag(EndTagToken token) { - if (token.name == "html") { + if (token.name == 'html') { endTagHtml(token); return null; } @@ -3589,8 +3670,10 @@ class AfterBodyPhase extends Phase { } //Stop parsing + @override bool processEOF() => false; + @override Token processComment(CommentToken token) { // This is needed because data is to be appended to the <html> element // here and not to whatever is currently open. @@ -3598,19 +3681,21 @@ class AfterBodyPhase extends Phase { return null; } + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "unexpected-char-after-body"); + parser.parseError(token.span, 'unexpected-char-after-body'); parser.phase = parser._inBodyPhase; return token; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } Token startTagOther(StartTagToken token) { parser.parseError( - token.span, "unexpected-start-tag-after-body", {"name": token.name}); + token.span, 'unexpected-start-tag-after-body', {'name': token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3623,7 +3708,7 @@ class AfterBodyPhase extends Phase { } } if (parser.innerHTMLMode) { - parser.parseError(token.span, "unexpected-end-tag-after-body-innerhtml"); + parser.parseError(token.span, 'unexpected-end-tag-after-body-innerhtml'); } else { parser.phase = parser._afterAfterBodyPhase; } @@ -3631,7 +3716,7 @@ class AfterBodyPhase extends Phase { Token endTagOther(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-after-body", {"name": token.name}); + token.span, 'unexpected-end-tag-after-body', {'name': token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3641,26 +3726,28 @@ class InFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-frameset InFramesetPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "frameset": + case 'frameset': startTagFrameset(token); return null; - case "frame": + case 'frame': startTagFrame(token); return null; - case "noframes": + case 'noframes': return startTagNoframes(token); default: return startTagOther(token); } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "frameset": + case 'frameset': endTagFrameset(token); return null; default: @@ -3669,18 +3756,20 @@ class InFramesetPhase extends Phase { } } + @override bool processEOF() { var last = tree.openElements.last; - if (last.localName != "html") { - parser.parseError(last.sourceSpan, "eof-in-frameset"); + if (last.localName != 'html') { + parser.parseError(last.sourceSpan, 'eof-in-frameset'); } else { assert(parser.innerHTMLMode); } return false; } + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "unexpected-char-in-frameset"); + parser.parseError(token.span, 'unexpected-char-in-frameset'); return null; } @@ -3699,21 +3788,21 @@ class InFramesetPhase extends Phase { Token startTagOther(StartTagToken token) { parser.parseError( - token.span, "unexpected-start-tag-in-frameset", {"name": token.name}); + token.span, 'unexpected-start-tag-in-frameset', {'name': token.name}); return null; } void endTagFrameset(EndTagToken token) { - if (tree.openElements.last.localName == "html") { + if (tree.openElements.last.localName == 'html') { // innerHTML case parser.parseError( - token.span, "unexpected-frameset-in-frameset-innerhtml"); + token.span, 'unexpected-frameset-in-frameset-innerhtml'); } else { var node = tree.openElements.removeLast(); node.endSourceSpan = token.span; } if (!parser.innerHTMLMode && - tree.openElements.last.localName != "frameset") { + tree.openElements.last.localName != 'frameset') { // If we're not in innerHTML mode and the the current node is not a // "frameset" element (anymore) then switch. parser.phase = parser._afterFramesetPhase; @@ -3722,7 +3811,7 @@ class InFramesetPhase extends Phase { void endTagOther(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-in-frameset", {"name": token.name}); + token.span, 'unexpected-end-tag-in-frameset', {'name': token.name}); } } @@ -3730,11 +3819,12 @@ class AfterFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///after3 AfterFramesetPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "noframes": + case 'noframes': return startTagNoframes(token); default: startTagOther(token); @@ -3742,9 +3832,10 @@ class AfterFramesetPhase extends Phase { } } + @override Token processEndTag(EndTagToken token) { switch (token.name) { - case "html": + case 'html': endTagHtml(token); return null; default: @@ -3754,10 +3845,12 @@ class AfterFramesetPhase extends Phase { } // Stop parsing + @override bool processEOF() => false; + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "unexpected-char-after-frameset"); + parser.parseError(token.span, 'unexpected-char-after-frameset'); return null; } @@ -3766,8 +3859,8 @@ class AfterFramesetPhase extends Phase { } void startTagOther(StartTagToken token) { - parser.parseError(token.span, "unexpected-start-tag-after-frameset", - {"name": token.name}); + parser.parseError(token.span, 'unexpected-start-tag-after-frameset', + {'name': token.name}); } void endTagHtml(EndTagToken token) { @@ -3776,49 +3869,56 @@ class AfterFramesetPhase extends Phase { void endTagOther(EndTagToken token) { parser.parseError( - token.span, "unexpected-end-tag-after-frameset", {"name": token.name}); + token.span, 'unexpected-end-tag-after-frameset', {'name': token.name}); } } class AfterAfterBodyPhase extends Phase { AfterAfterBodyPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { if (token.name == 'html') return startTagHtml(token); return startTagOther(token); } + @override bool processEOF() => false; + @override Token processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return parser._inBodyPhase.processSpaceCharacters(token); } + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "expected-eof-but-got-char"); + parser.parseError(token.span, 'expected-eof-but-got-char'); parser.phase = parser._inBodyPhase; return token; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } Token startTagOther(StartTagToken token) { parser.parseError( - token.span, "expected-eof-but-got-start-tag", {"name": token.name}); + token.span, 'expected-eof-but-got-start-tag', {'name': token.name}); parser.phase = parser._inBodyPhase; return token; } + @override Token processEndTag(EndTagToken token) { parser.parseError( - token.span, "expected-eof-but-got-end-tag", {"name": token.name}); + token.span, 'expected-eof-but-got-end-tag', {'name': token.name}); parser.phase = parser._inBodyPhase; return token; } @@ -3827,11 +3927,12 @@ class AfterAfterBodyPhase extends Phase { class AfterAfterFramesetPhase extends Phase { AfterAfterFramesetPhase(parser) : super(parser); + @override Token processStartTag(StartTagToken token) { switch (token.name) { - case "html": + case 'html': return startTagHtml(token); - case "noframes": + case 'noframes': return startTagNoFrames(token); default: startTagOther(token); @@ -3839,22 +3940,27 @@ class AfterAfterFramesetPhase extends Phase { } } + @override bool processEOF() => false; + @override Token processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } + @override Token processSpaceCharacters(SpaceCharactersToken token) { return parser._inBodyPhase.processSpaceCharacters(token); } + @override Token processCharacters(CharactersToken token) { - parser.parseError(token.span, "expected-eof-but-got-char"); + parser.parseError(token.span, 'expected-eof-but-got-char'); return null; } + @override Token startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -3865,12 +3971,13 @@ class AfterAfterFramesetPhase extends Phase { void startTagOther(StartTagToken token) { parser.parseError( - token.span, "expected-eof-but-got-start-tag", {"name": token.name}); + token.span, 'expected-eof-but-got-start-tag', {'name': token.name}); } + @override Token processEndTag(EndTagToken token) { parser.parseError( - token.span, "expected-eof-but-got-end-tag", {"name": token.name}); + token.span, 'expected-eof-but-got-end-tag', {'name': token.name}); return null; } } @@ -3878,6 +3985,7 @@ class AfterAfterFramesetPhase extends Phase { /// Error in parsed document. class ParseError implements SourceSpanException { final String errorCode; + @override final SourceSpan span; final Map data; @@ -3893,8 +4001,10 @@ class ParseError implements SourceSpanException { /// [span.getLocationMessage] and [toString] are equivalent. Otherwise, /// [span.getLocationMessage] will not show any source url information, but /// [toString] will include 'ParserError:' as a prefix. + @override String get message => formatStr(errorMessages[errorCode], data); + @override String toString({color}) { var res = span.message(message, color: color); return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; @@ -3903,7 +4013,6 @@ class ParseError implements SourceSpanException { /// Convenience function to get the pair of namespace and localName. Pair<String, String> getElementNameTuple(Element e) { - var ns = e.namespaceUri; - if (ns == null) ns = Namespaces.html; + var ns = e.namespaceUri ?? Namespaces.html; return Pair(ns, e.localName); } diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 34addfc08..e8d0f62a9 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -11,7 +11,8 @@ final String eof = null; class ReparseException implements Exception { final String message; ReparseException(this.message); - String toString() => "ReparseException: $message"; + @override + String toString() => 'ReparseException: $message'; } // TODO(jmesserly): assuming the programmatic name is not important, it would be @@ -20,228 +21,228 @@ class ReparseException implements Exception { /// style string formatting, as implemented by [formatStr]. That function only /// supports the subset of format functionality used here. const Map<String, String> errorMessages = { - "null-character": "Null character in input stream, replaced with U+FFFD.", - "invalid-codepoint": "Invalid codepoint in stream.", - "incorrectly-placed-solidus": "Solidus (/) incorrectly placed in tag.", - "incorrect-cr-newline-entity": - "Incorrect CR newline entity, replaced with LF.", - "illegal-windows-1252-entity": - "Entity used with illegal number (windows-1252 reference).", - "cant-convert-numeric-entity": + 'null-character': 'Null character in input stream, replaced with U+FFFD.', + 'invalid-codepoint': 'Invalid codepoint in stream.', + 'incorrectly-placed-solidus': 'Solidus (/) incorrectly placed in tag.', + 'incorrect-cr-newline-entity': + 'Incorrect CR newline entity, replaced with LF.', + 'illegal-windows-1252-entity': + 'Entity used with illegal number (windows-1252 reference).', + 'cant-convert-numeric-entity': "Numeric entity couldn't be converted to character " - "(codepoint U+%(charAsInt)08x).", - "illegal-codepoint-for-numeric-entity": - "Numeric entity represents an illegal codepoint: " - "U+%(charAsInt)08x.", - "numeric-entity-without-semicolon": "Numeric entity didn't end with ';'.", - "expected-numeric-entity-but-got-eof": - "Numeric entity expected. Got end of file instead.", - "expected-numeric-entity": "Numeric entity expected but none found.", - "named-entity-without-semicolon": "Named entity didn't end with ';'.", - "expected-named-entity": "Named entity expected. Got none.", - "attributes-in-end-tag": "End tag contains unexpected attributes.", + '(codepoint U+%(charAsInt)08x).', + 'illegal-codepoint-for-numeric-entity': + 'Numeric entity represents an illegal codepoint: ' + 'U+%(charAsInt)08x.', + 'numeric-entity-without-semicolon': "Numeric entity didn't end with ';'.", + 'expected-numeric-entity-but-got-eof': + 'Numeric entity expected. Got end of file instead.', + 'expected-numeric-entity': 'Numeric entity expected but none found.', + 'named-entity-without-semicolon': "Named entity didn't end with ';'.", + 'expected-named-entity': 'Named entity expected. Got none.', + 'attributes-in-end-tag': 'End tag contains unexpected attributes.', 'self-closing-flag-on-end-tag': - "End tag contains unexpected self-closing flag.", - "expected-tag-name-but-got-right-bracket": + 'End tag contains unexpected self-closing flag.', + 'expected-tag-name-but-got-right-bracket': "Expected tag name. Got '>' instead.", - "expected-tag-name-but-got-question-mark": + 'expected-tag-name-but-got-question-mark': "Expected tag name. Got '?' instead. (HTML doesn't " - "support processing instructions.)", - "expected-tag-name": "Expected tag name. Got something else instead", - "expected-closing-tag-but-got-right-bracket": + 'support processing instructions.)', + 'expected-tag-name': 'Expected tag name. Got something else instead', + 'expected-closing-tag-but-got-right-bracket': "Expected closing tag. Got '>' instead. Ignoring '</>'.", - "expected-closing-tag-but-got-eof": - "Expected closing tag. Unexpected end of file.", - "expected-closing-tag-but-got-char": + 'expected-closing-tag-but-got-eof': + 'Expected closing tag. Unexpected end of file.', + 'expected-closing-tag-but-got-char': "Expected closing tag. Unexpected character '%(data)s' found.", - "eof-in-tag-name": "Unexpected end of file in the tag name.", - "expected-attribute-name-but-got-eof": - "Unexpected end of file. Expected attribute name instead.", - "eof-in-attribute-name": "Unexpected end of file in attribute name.", - "invalid-character-in-attribute-name": "Invalid character in attribute name", - "duplicate-attribute": "Dropped duplicate attribute on tag.", - "expected-end-of-tag-name-but-got-eof": - "Unexpected end of file. Expected = or end of tag.", - "expected-attribute-value-but-got-eof": - "Unexpected end of file. Expected attribute value.", - "expected-attribute-value-but-got-right-bracket": + 'eof-in-tag-name': 'Unexpected end of file in the tag name.', + 'expected-attribute-name-but-got-eof': + 'Unexpected end of file. Expected attribute name instead.', + 'eof-in-attribute-name': 'Unexpected end of file in attribute name.', + 'invalid-character-in-attribute-name': 'Invalid character in attribute name', + 'duplicate-attribute': 'Dropped duplicate attribute on tag.', + 'expected-end-of-tag-name-but-got-eof': + 'Unexpected end of file. Expected = or end of tag.', + 'expected-attribute-value-but-got-eof': + 'Unexpected end of file. Expected attribute value.', + 'expected-attribute-value-but-got-right-bracket': "Expected attribute value. Got '>' instead.", - 'equals-in-unquoted-attribute-value': "Unexpected = in unquoted attribute", + 'equals-in-unquoted-attribute-value': 'Unexpected = in unquoted attribute', 'unexpected-character-in-unquoted-attribute-value': - "Unexpected character in unquoted attribute", - "invalid-character-after-attribute-name": - "Unexpected character after attribute name.", - "unexpected-character-after-attribute-value": - "Unexpected character after attribute value.", - "eof-in-attribute-value-double-quote": - "Unexpected end of file in attribute value (\".", - "eof-in-attribute-value-single-quote": + 'Unexpected character in unquoted attribute', + 'invalid-character-after-attribute-name': + 'Unexpected character after attribute name.', + 'unexpected-character-after-attribute-value': + 'Unexpected character after attribute value.', + 'eof-in-attribute-value-double-quote': + 'Unexpected end of file in attribute value (\".', + 'eof-in-attribute-value-single-quote': "Unexpected end of file in attribute value (').", - "eof-in-attribute-value-no-quotes": - "Unexpected end of file in attribute value.", - "unexpected-EOF-after-solidus-in-tag": - "Unexpected end of file in tag. Expected >", - "unexpected-character-after-soldius-in-tag": - "Unexpected character after / in tag. Expected >", - "expected-dashes-or-doctype": "Expected '--' or 'DOCTYPE'. Not found.", - "unexpected-bang-after-double-dash-in-comment": - "Unexpected ! after -- in comment", - "unexpected-space-after-double-dash-in-comment": - "Unexpected space after -- in comment", - "incorrect-comment": "Incorrect comment.", - "eof-in-comment": "Unexpected end of file in comment.", - "eof-in-comment-end-dash": "Unexpected end of file in comment (-)", - "unexpected-dash-after-double-dash-in-comment": + 'eof-in-attribute-value-no-quotes': + 'Unexpected end of file in attribute value.', + 'unexpected-EOF-after-solidus-in-tag': + 'Unexpected end of file in tag. Expected >', + 'unexpected-character-after-soldius-in-tag': + 'Unexpected character after / in tag. Expected >', + 'expected-dashes-or-doctype': "Expected '--' or 'DOCTYPE'. Not found.", + 'unexpected-bang-after-double-dash-in-comment': + 'Unexpected ! after -- in comment', + 'unexpected-space-after-double-dash-in-comment': + 'Unexpected space after -- in comment', + 'incorrect-comment': 'Incorrect comment.', + 'eof-in-comment': 'Unexpected end of file in comment.', + 'eof-in-comment-end-dash': 'Unexpected end of file in comment (-)', + 'unexpected-dash-after-double-dash-in-comment': "Unexpected '-' after '--' found in comment.", - "eof-in-comment-double-dash": "Unexpected end of file in comment (--).", - "eof-in-comment-end-space-state": "Unexpected end of file in comment.", - "eof-in-comment-end-bang-state": "Unexpected end of file in comment.", - "unexpected-char-in-comment": "Unexpected character in comment found.", - "need-space-after-doctype": "No space after literal string 'DOCTYPE'.", - "expected-doctype-name-but-got-right-bracket": - "Unexpected > character. Expected DOCTYPE name.", - "expected-doctype-name-but-got-eof": - "Unexpected end of file. Expected DOCTYPE name.", - "eof-in-doctype-name": "Unexpected end of file in DOCTYPE name.", - "eof-in-doctype": "Unexpected end of file in DOCTYPE.", - "expected-space-or-right-bracket-in-doctype": + 'eof-in-comment-double-dash': 'Unexpected end of file in comment (--).', + 'eof-in-comment-end-space-state': 'Unexpected end of file in comment.', + 'eof-in-comment-end-bang-state': 'Unexpected end of file in comment.', + 'unexpected-char-in-comment': 'Unexpected character in comment found.', + 'need-space-after-doctype': "No space after literal string 'DOCTYPE'.", + 'expected-doctype-name-but-got-right-bracket': + 'Unexpected > character. Expected DOCTYPE name.', + 'expected-doctype-name-but-got-eof': + 'Unexpected end of file. Expected DOCTYPE name.', + 'eof-in-doctype-name': 'Unexpected end of file in DOCTYPE name.', + 'eof-in-doctype': 'Unexpected end of file in DOCTYPE.', + 'expected-space-or-right-bracket-in-doctype': "Expected space or '>'. Got '%(data)s'", - "unexpected-end-of-doctype": "Unexpected end of DOCTYPE.", - "unexpected-char-in-doctype": "Unexpected character in DOCTYPE.", - "eof-in-innerhtml": "XXX innerHTML EOF", - "unexpected-doctype": "Unexpected DOCTYPE. Ignored.", - "non-html-root": "html needs to be the first start tag.", - "expected-doctype-but-got-eof": "Unexpected End of file. Expected DOCTYPE.", - "unknown-doctype": "Erroneous DOCTYPE.", - "expected-doctype-but-got-chars": - "Unexpected non-space characters. Expected DOCTYPE.", - "expected-doctype-but-got-start-tag": - "Unexpected start tag (%(name)s). Expected DOCTYPE.", - "expected-doctype-but-got-end-tag": - "Unexpected end tag (%(name)s). Expected DOCTYPE.", - "end-tag-after-implied-root": - "Unexpected end tag (%(name)s) after the (implied) root element.", - "expected-named-closing-tag-but-got-eof": - "Unexpected end of file. Expected end tag (%(name)s).", - "two-heads-are-not-better-than-one": - "Unexpected start tag head in existing head. Ignored.", - "unexpected-end-tag": "Unexpected end tag (%(name)s). Ignored.", - "unexpected-start-tag-out-of-my-head": - "Unexpected start tag (%(name)s) that can be in head. Moved.", - "unexpected-start-tag": "Unexpected start tag (%(name)s).", - "missing-end-tag": "Missing end tag (%(name)s).", - "missing-end-tags": "Missing end tags (%(name)s).", - "unexpected-start-tag-implies-end-tag": - "Unexpected start tag (%(startName)s) " - "implies end tag (%(endName)s).", - "unexpected-start-tag-treated-as": - "Unexpected start tag (%(originalName)s). Treated as %(newName)s.", - "deprecated-tag": "Unexpected start tag %(name)s. Don't use it!", - "unexpected-start-tag-ignored": "Unexpected start tag %(name)s. Ignored.", - "expected-one-end-tag-but-got-another": "Unexpected end tag (%(gotName)s). " - "Missing end tag (%(expectedName)s).", - "end-tag-too-early": - "End tag (%(name)s) seen too early. Expected other end tag.", - "end-tag-too-early-named": - "Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).", - "end-tag-too-early-ignored": "End tag (%(name)s) seen too early. Ignored.", - "adoption-agency-1.1": "End tag (%(name)s) violates step 1, " - "paragraph 1 of the adoption agency algorithm.", - "adoption-agency-1.2": "End tag (%(name)s) violates step 1, " - "paragraph 2 of the adoption agency algorithm.", - "adoption-agency-1.3": "End tag (%(name)s) violates step 1, " - "paragraph 3 of the adoption agency algorithm.", - "unexpected-end-tag-treated-as": - "Unexpected end tag (%(originalName)s). Treated as %(newName)s.", - "no-end-tag": "This element (%(name)s) has no end tag.", - "unexpected-implied-end-tag-in-table": - "Unexpected implied end tag (%(name)s) in the table phase.", - "unexpected-implied-end-tag-in-table-body": - "Unexpected implied end tag (%(name)s) in the table body phase.", - "unexpected-char-implies-table-voodoo": "Unexpected non-space characters in " - "table context caused voodoo mode.", - "unexpected-hidden-input-in-table": - "Unexpected input with type hidden in table context.", - "unexpected-form-in-table": "Unexpected form in table context.", - "unexpected-start-tag-implies-table-voodoo": - "Unexpected start tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-end-tag-implies-table-voodoo": "Unexpected end tag (%(name)s) in " - "table context caused voodoo mode.", - "unexpected-cell-in-table-body": "Unexpected table cell start tag (%(name)s) " - "in the table body phase.", - "unexpected-cell-end-tag": "Got table cell end tag (%(name)s) " - "while required end tags are missing.", - "unexpected-end-tag-in-table-body": - "Unexpected end tag (%(name)s) in the table body phase. Ignored.", - "unexpected-implied-end-tag-in-table-row": - "Unexpected implied end tag (%(name)s) in the table row phase.", - "unexpected-end-tag-in-table-row": - "Unexpected end tag (%(name)s) in the table row phase. Ignored.", - "unexpected-select-in-select": - "Unexpected select start tag in the select phase " - "treated as select end tag.", - "unexpected-input-in-select": - "Unexpected input start tag in the select phase.", - "unexpected-start-tag-in-select": - "Unexpected start tag token (%(name)s in the select phase. " - "Ignored.", - "unexpected-end-tag-in-select": - "Unexpected end tag (%(name)s) in the select phase. Ignored.", - "unexpected-table-element-start-tag-in-select-in-table": - "Unexpected table element start tag (%(name)s) in the select in table phase.", - "unexpected-table-element-end-tag-in-select-in-table": - "Unexpected table element end tag (%(name)s) in the select in table phase.", - "unexpected-char-after-body": - "Unexpected non-space characters in the after body phase.", - "unexpected-start-tag-after-body": "Unexpected start tag token (%(name)s)" - " in the after body phase.", - "unexpected-end-tag-after-body": "Unexpected end tag token (%(name)s)" - " in the after body phase.", - "unexpected-char-in-frameset": - "Unepxected characters in the frameset phase. Characters ignored.", - "unexpected-start-tag-in-frameset": "Unexpected start tag token (%(name)s)" - " in the frameset phase. Ignored.", - "unexpected-frameset-in-frameset-innerhtml": - "Unexpected end tag token (frameset) " - "in the frameset phase (innerHTML).", - "unexpected-end-tag-in-frameset": "Unexpected end tag token (%(name)s)" - " in the frameset phase. Ignored.", - "unexpected-char-after-frameset": "Unexpected non-space characters in the " - "after frameset phase. Ignored.", - "unexpected-start-tag-after-frameset": "Unexpected start tag (%(name)s)" - " in the after frameset phase. Ignored.", - "unexpected-end-tag-after-frameset": "Unexpected end tag (%(name)s)" - " in the after frameset phase. Ignored.", - "unexpected-end-tag-after-body-innerhtml": - "Unexpected end tag after body(innerHtml)", - "expected-eof-but-got-char": - "Unexpected non-space characters. Expected end of file.", - "expected-eof-but-got-start-tag": "Unexpected start tag (%(name)s)" - ". Expected end of file.", - "expected-eof-but-got-end-tag": "Unexpected end tag (%(name)s)" - ". Expected end of file.", - "eof-in-table": "Unexpected end of file. Expected table content.", - "eof-in-select": "Unexpected end of file. Expected select content.", - "eof-in-frameset": "Unexpected end of file. Expected frameset content.", - "eof-in-script-in-script": "Unexpected end of file. Expected script content.", - "eof-in-foreign-lands": "Unexpected end of file. Expected foreign content", - "non-void-element-with-trailing-solidus": - "Trailing solidus not allowed on element %(name)s", - "unexpected-html-element-in-foreign-content": - "Element %(name)s not allowed in a non-html context", - "unexpected-end-tag-before-html": - "Unexpected end tag (%(name)s) before html.", - "undefined-error": "Undefined error (this sucks and should be fixed)", + 'unexpected-end-of-doctype': 'Unexpected end of DOCTYPE.', + 'unexpected-char-in-doctype': 'Unexpected character in DOCTYPE.', + 'eof-in-innerhtml': 'XXX innerHTML EOF', + 'unexpected-doctype': 'Unexpected DOCTYPE. Ignored.', + 'non-html-root': 'html needs to be the first start tag.', + 'expected-doctype-but-got-eof': 'Unexpected End of file. Expected DOCTYPE.', + 'unknown-doctype': 'Erroneous DOCTYPE.', + 'expected-doctype-but-got-chars': + 'Unexpected non-space characters. Expected DOCTYPE.', + 'expected-doctype-but-got-start-tag': + 'Unexpected start tag (%(name)s). Expected DOCTYPE.', + 'expected-doctype-but-got-end-tag': + 'Unexpected end tag (%(name)s). Expected DOCTYPE.', + 'end-tag-after-implied-root': + 'Unexpected end tag (%(name)s) after the (implied) root element.', + 'expected-named-closing-tag-but-got-eof': + 'Unexpected end of file. Expected end tag (%(name)s).', + 'two-heads-are-not-better-than-one': + 'Unexpected start tag head in existing head. Ignored.', + 'unexpected-end-tag': 'Unexpected end tag (%(name)s). Ignored.', + 'unexpected-start-tag-out-of-my-head': + 'Unexpected start tag (%(name)s) that can be in head. Moved.', + 'unexpected-start-tag': 'Unexpected start tag (%(name)s).', + 'missing-end-tag': 'Missing end tag (%(name)s).', + 'missing-end-tags': 'Missing end tags (%(name)s).', + 'unexpected-start-tag-implies-end-tag': + 'Unexpected start tag (%(startName)s) ' + 'implies end tag (%(endName)s).', + 'unexpected-start-tag-treated-as': + 'Unexpected start tag (%(originalName)s). Treated as %(newName)s.', + 'deprecated-tag': "Unexpected start tag %(name)s. Don't use it!", + 'unexpected-start-tag-ignored': 'Unexpected start tag %(name)s. Ignored.', + 'expected-one-end-tag-but-got-another': 'Unexpected end tag (%(gotName)s). ' + 'Missing end tag (%(expectedName)s).', + 'end-tag-too-early': + 'End tag (%(name)s) seen too early. Expected other end tag.', + 'end-tag-too-early-named': + 'Unexpected end tag (%(gotName)s). Expected end tag (%(expectedName)s).', + 'end-tag-too-early-ignored': 'End tag (%(name)s) seen too early. Ignored.', + 'adoption-agency-1.1': 'End tag (%(name)s) violates step 1, ' + 'paragraph 1 of the adoption agency algorithm.', + 'adoption-agency-1.2': 'End tag (%(name)s) violates step 1, ' + 'paragraph 2 of the adoption agency algorithm.', + 'adoption-agency-1.3': 'End tag (%(name)s) violates step 1, ' + 'paragraph 3 of the adoption agency algorithm.', + 'unexpected-end-tag-treated-as': + 'Unexpected end tag (%(originalName)s). Treated as %(newName)s.', + 'no-end-tag': 'This element (%(name)s) has no end tag.', + 'unexpected-implied-end-tag-in-table': + 'Unexpected implied end tag (%(name)s) in the table phase.', + 'unexpected-implied-end-tag-in-table-body': + 'Unexpected implied end tag (%(name)s) in the table body phase.', + 'unexpected-char-implies-table-voodoo': 'Unexpected non-space characters in ' + 'table context caused voodoo mode.', + 'unexpected-hidden-input-in-table': + 'Unexpected input with type hidden in table context.', + 'unexpected-form-in-table': 'Unexpected form in table context.', + 'unexpected-start-tag-implies-table-voodoo': + 'Unexpected start tag (%(name)s) in ' + 'table context caused voodoo mode.', + 'unexpected-end-tag-implies-table-voodoo': 'Unexpected end tag (%(name)s) in ' + 'table context caused voodoo mode.', + 'unexpected-cell-in-table-body': 'Unexpected table cell start tag (%(name)s) ' + 'in the table body phase.', + 'unexpected-cell-end-tag': 'Got table cell end tag (%(name)s) ' + 'while required end tags are missing.', + 'unexpected-end-tag-in-table-body': + 'Unexpected end tag (%(name)s) in the table body phase. Ignored.', + 'unexpected-implied-end-tag-in-table-row': + 'Unexpected implied end tag (%(name)s) in the table row phase.', + 'unexpected-end-tag-in-table-row': + 'Unexpected end tag (%(name)s) in the table row phase. Ignored.', + 'unexpected-select-in-select': + 'Unexpected select start tag in the select phase ' + 'treated as select end tag.', + 'unexpected-input-in-select': + 'Unexpected input start tag in the select phase.', + 'unexpected-start-tag-in-select': + 'Unexpected start tag token (%(name)s in the select phase. ' + 'Ignored.', + 'unexpected-end-tag-in-select': + 'Unexpected end tag (%(name)s) in the select phase. Ignored.', + 'unexpected-table-element-start-tag-in-select-in-table': + 'Unexpected table element start tag (%(name)s) in the select in table phase.', + 'unexpected-table-element-end-tag-in-select-in-table': + 'Unexpected table element end tag (%(name)s) in the select in table phase.', + 'unexpected-char-after-body': + 'Unexpected non-space characters in the after body phase.', + 'unexpected-start-tag-after-body': 'Unexpected start tag token (%(name)s)' + ' in the after body phase.', + 'unexpected-end-tag-after-body': 'Unexpected end tag token (%(name)s)' + ' in the after body phase.', + 'unexpected-char-in-frameset': + 'Unepxected characters in the frameset phase. Characters ignored.', + 'unexpected-start-tag-in-frameset': 'Unexpected start tag token (%(name)s)' + ' in the frameset phase. Ignored.', + 'unexpected-frameset-in-frameset-innerhtml': + 'Unexpected end tag token (frameset) ' + 'in the frameset phase (innerHTML).', + 'unexpected-end-tag-in-frameset': 'Unexpected end tag token (%(name)s)' + ' in the frameset phase. Ignored.', + 'unexpected-char-after-frameset': 'Unexpected non-space characters in the ' + 'after frameset phase. Ignored.', + 'unexpected-start-tag-after-frameset': 'Unexpected start tag (%(name)s)' + ' in the after frameset phase. Ignored.', + 'unexpected-end-tag-after-frameset': 'Unexpected end tag (%(name)s)' + ' in the after frameset phase. Ignored.', + 'unexpected-end-tag-after-body-innerhtml': + 'Unexpected end tag after body(innerHtml)', + 'expected-eof-but-got-char': + 'Unexpected non-space characters. Expected end of file.', + 'expected-eof-but-got-start-tag': 'Unexpected start tag (%(name)s)' + '. Expected end of file.', + 'expected-eof-but-got-end-tag': 'Unexpected end tag (%(name)s)' + '. Expected end of file.', + 'eof-in-table': 'Unexpected end of file. Expected table content.', + 'eof-in-select': 'Unexpected end of file. Expected select content.', + 'eof-in-frameset': 'Unexpected end of file. Expected frameset content.', + 'eof-in-script-in-script': 'Unexpected end of file. Expected script content.', + 'eof-in-foreign-lands': 'Unexpected end of file. Expected foreign content', + 'non-void-element-with-trailing-solidus': + 'Trailing solidus not allowed on element %(name)s', + 'unexpected-html-element-in-foreign-content': + 'Element %(name)s not allowed in a non-html context', + 'unexpected-end-tag-before-html': + 'Unexpected end tag (%(name)s) before html.', + 'undefined-error': 'Undefined error (this sucks and should be fixed)', }; class Namespaces { - static const html = "http://www.w3.org/1999/xhtml"; - static const mathml = "http://www.w3.org/1998/Math/MathML"; - static const svg = "http://www.w3.org/2000/svg"; - static const xlink = "http://www.w3.org/1999/xlink"; - static const xml = "http://www.w3.org/XML/1998/namespace"; - static const xmlns = "http://www.w3.org/2000/xmlns/"; + static const html = 'http://www.w3.org/1999/xhtml'; + static const mathml = 'http://www.w3.org/1998/Math/MathML'; + static const svg = 'http://www.w3.org/2000/svg'; + static const xlink = 'http://www.w3.org/1999/xlink'; + static const xml = 'http://www.w3.org/XML/1998/namespace'; + static const xmlns = 'http://www.w3.org/2000/xmlns/'; Namespaces._(); static String getPrefix(String url) { @@ -265,141 +266,141 @@ class Namespaces { } const List scopingElements = [ - Pair(Namespaces.html, "applet"), - Pair(Namespaces.html, "caption"), - Pair(Namespaces.html, "html"), - Pair(Namespaces.html, "marquee"), - Pair(Namespaces.html, "object"), - Pair(Namespaces.html, "table"), - Pair(Namespaces.html, "td"), - Pair(Namespaces.html, "th"), - Pair(Namespaces.mathml, "mi"), - Pair(Namespaces.mathml, "mo"), - Pair(Namespaces.mathml, "mn"), - Pair(Namespaces.mathml, "ms"), - Pair(Namespaces.mathml, "mtext"), - Pair(Namespaces.mathml, "annotation-xml"), - Pair(Namespaces.svg, "foreignObject"), - Pair(Namespaces.svg, "desc"), - Pair(Namespaces.svg, "title") + Pair(Namespaces.html, 'applet'), + Pair(Namespaces.html, 'caption'), + Pair(Namespaces.html, 'html'), + Pair(Namespaces.html, 'marquee'), + Pair(Namespaces.html, 'object'), + Pair(Namespaces.html, 'table'), + Pair(Namespaces.html, 'td'), + Pair(Namespaces.html, 'th'), + Pair(Namespaces.mathml, 'mi'), + Pair(Namespaces.mathml, 'mo'), + Pair(Namespaces.mathml, 'mn'), + Pair(Namespaces.mathml, 'ms'), + Pair(Namespaces.mathml, 'mtext'), + Pair(Namespaces.mathml, 'annotation-xml'), + Pair(Namespaces.svg, 'foreignObject'), + Pair(Namespaces.svg, 'desc'), + Pair(Namespaces.svg, 'title') ]; const formattingElements = [ - Pair(Namespaces.html, "a"), - Pair(Namespaces.html, "b"), - Pair(Namespaces.html, "big"), - Pair(Namespaces.html, "code"), - Pair(Namespaces.html, "em"), - Pair(Namespaces.html, "font"), - Pair(Namespaces.html, "i"), - Pair(Namespaces.html, "nobr"), - Pair(Namespaces.html, "s"), - Pair(Namespaces.html, "small"), - Pair(Namespaces.html, "strike"), - Pair(Namespaces.html, "strong"), - Pair(Namespaces.html, "tt"), - Pair(Namespaces.html, "") + Pair(Namespaces.html, 'a'), + Pair(Namespaces.html, 'b'), + Pair(Namespaces.html, 'big'), + Pair(Namespaces.html, 'code'), + Pair(Namespaces.html, 'em'), + Pair(Namespaces.html, 'font'), + Pair(Namespaces.html, 'i'), + Pair(Namespaces.html, 'nobr'), + Pair(Namespaces.html, 's'), + Pair(Namespaces.html, 'small'), + Pair(Namespaces.html, 'strike'), + Pair(Namespaces.html, 'strong'), + Pair(Namespaces.html, 'tt'), + Pair(Namespaces.html, '') ]; const specialElements = [ - Pair(Namespaces.html, "address"), - Pair(Namespaces.html, "applet"), - Pair(Namespaces.html, "area"), - Pair(Namespaces.html, "article"), - Pair(Namespaces.html, "aside"), - Pair(Namespaces.html, "base"), - Pair(Namespaces.html, "basefont"), - Pair(Namespaces.html, "bgsound"), - Pair(Namespaces.html, "blockquote"), - Pair(Namespaces.html, "body"), - Pair(Namespaces.html, "br"), - Pair(Namespaces.html, "button"), - Pair(Namespaces.html, "caption"), - Pair(Namespaces.html, "center"), - Pair(Namespaces.html, "col"), - Pair(Namespaces.html, "colgroup"), - Pair(Namespaces.html, "command"), - Pair(Namespaces.html, "dd"), - Pair(Namespaces.html, "details"), - Pair(Namespaces.html, "dir"), - Pair(Namespaces.html, "div"), - Pair(Namespaces.html, "dl"), - Pair(Namespaces.html, "dt"), - Pair(Namespaces.html, "embed"), - Pair(Namespaces.html, "fieldset"), - Pair(Namespaces.html, "figure"), - Pair(Namespaces.html, "footer"), - Pair(Namespaces.html, "form"), - Pair(Namespaces.html, "frame"), - Pair(Namespaces.html, "frameset"), - Pair(Namespaces.html, "h1"), - Pair(Namespaces.html, "h2"), - Pair(Namespaces.html, "h3"), - Pair(Namespaces.html, "h4"), - Pair(Namespaces.html, "h5"), - Pair(Namespaces.html, "h6"), - Pair(Namespaces.html, "head"), - Pair(Namespaces.html, "header"), - Pair(Namespaces.html, "hr"), - Pair(Namespaces.html, "html"), - Pair(Namespaces.html, "iframe"), + Pair(Namespaces.html, 'address'), + Pair(Namespaces.html, 'applet'), + Pair(Namespaces.html, 'area'), + Pair(Namespaces.html, 'article'), + Pair(Namespaces.html, 'aside'), + Pair(Namespaces.html, 'base'), + Pair(Namespaces.html, 'basefont'), + Pair(Namespaces.html, 'bgsound'), + Pair(Namespaces.html, 'blockquote'), + Pair(Namespaces.html, 'body'), + Pair(Namespaces.html, 'br'), + Pair(Namespaces.html, 'button'), + Pair(Namespaces.html, 'caption'), + Pair(Namespaces.html, 'center'), + Pair(Namespaces.html, 'col'), + Pair(Namespaces.html, 'colgroup'), + Pair(Namespaces.html, 'command'), + Pair(Namespaces.html, 'dd'), + Pair(Namespaces.html, 'details'), + Pair(Namespaces.html, 'dir'), + Pair(Namespaces.html, 'div'), + Pair(Namespaces.html, 'dl'), + Pair(Namespaces.html, 'dt'), + Pair(Namespaces.html, 'embed'), + Pair(Namespaces.html, 'fieldset'), + Pair(Namespaces.html, 'figure'), + Pair(Namespaces.html, 'footer'), + Pair(Namespaces.html, 'form'), + Pair(Namespaces.html, 'frame'), + Pair(Namespaces.html, 'frameset'), + Pair(Namespaces.html, 'h1'), + Pair(Namespaces.html, 'h2'), + Pair(Namespaces.html, 'h3'), + Pair(Namespaces.html, 'h4'), + Pair(Namespaces.html, 'h5'), + Pair(Namespaces.html, 'h6'), + Pair(Namespaces.html, 'head'), + Pair(Namespaces.html, 'header'), + Pair(Namespaces.html, 'hr'), + Pair(Namespaces.html, 'html'), + Pair(Namespaces.html, 'iframe'), // Note that image is commented out in the spec as "this isn't an // element that can end up on the stack, so it doesn't matter," - Pair(Namespaces.html, "image"), - Pair(Namespaces.html, "img"), - Pair(Namespaces.html, "input"), - Pair(Namespaces.html, "isindex"), - Pair(Namespaces.html, "li"), - Pair(Namespaces.html, "link"), - Pair(Namespaces.html, "listing"), - Pair(Namespaces.html, "marquee"), - Pair(Namespaces.html, "men"), - Pair(Namespaces.html, "meta"), - Pair(Namespaces.html, "nav"), - Pair(Namespaces.html, "noembed"), - Pair(Namespaces.html, "noframes"), - Pair(Namespaces.html, "noscript"), - Pair(Namespaces.html, "object"), - Pair(Namespaces.html, "ol"), - Pair(Namespaces.html, "p"), - Pair(Namespaces.html, "param"), - Pair(Namespaces.html, "plaintext"), - Pair(Namespaces.html, "pre"), - Pair(Namespaces.html, "script"), - Pair(Namespaces.html, "section"), - Pair(Namespaces.html, "select"), - Pair(Namespaces.html, "style"), - Pair(Namespaces.html, "table"), - Pair(Namespaces.html, "tbody"), - Pair(Namespaces.html, "td"), - Pair(Namespaces.html, "textarea"), - Pair(Namespaces.html, "tfoot"), - Pair(Namespaces.html, "th"), - Pair(Namespaces.html, "thead"), - Pair(Namespaces.html, "title"), - Pair(Namespaces.html, "tr"), - Pair(Namespaces.html, "ul"), - Pair(Namespaces.html, "wbr"), - Pair(Namespaces.html, "xmp"), - Pair(Namespaces.svg, "foreignObject") + Pair(Namespaces.html, 'image'), + Pair(Namespaces.html, 'img'), + Pair(Namespaces.html, 'input'), + Pair(Namespaces.html, 'isindex'), + Pair(Namespaces.html, 'li'), + Pair(Namespaces.html, 'link'), + Pair(Namespaces.html, 'listing'), + Pair(Namespaces.html, 'marquee'), + Pair(Namespaces.html, 'men'), + Pair(Namespaces.html, 'meta'), + Pair(Namespaces.html, 'nav'), + Pair(Namespaces.html, 'noembed'), + Pair(Namespaces.html, 'noframes'), + Pair(Namespaces.html, 'noscript'), + Pair(Namespaces.html, 'object'), + Pair(Namespaces.html, 'ol'), + Pair(Namespaces.html, 'p'), + Pair(Namespaces.html, 'param'), + Pair(Namespaces.html, 'plaintext'), + Pair(Namespaces.html, 'pre'), + Pair(Namespaces.html, 'script'), + Pair(Namespaces.html, 'section'), + Pair(Namespaces.html, 'select'), + Pair(Namespaces.html, 'style'), + Pair(Namespaces.html, 'table'), + Pair(Namespaces.html, 'tbody'), + Pair(Namespaces.html, 'td'), + Pair(Namespaces.html, 'textarea'), + Pair(Namespaces.html, 'tfoot'), + Pair(Namespaces.html, 'th'), + Pair(Namespaces.html, 'thead'), + Pair(Namespaces.html, 'title'), + Pair(Namespaces.html, 'tr'), + Pair(Namespaces.html, 'ul'), + Pair(Namespaces.html, 'wbr'), + Pair(Namespaces.html, 'xmp'), + Pair(Namespaces.svg, 'foreignObject') ]; const htmlIntegrationPointElements = [ - Pair(Namespaces.mathml, "annotaion-xml"), - Pair(Namespaces.svg, "foreignObject"), - Pair(Namespaces.svg, "desc"), - Pair(Namespaces.svg, "title") + Pair(Namespaces.mathml, 'annotaion-xml'), + Pair(Namespaces.svg, 'foreignObject'), + Pair(Namespaces.svg, 'desc'), + Pair(Namespaces.svg, 'title') ]; const mathmlTextIntegrationPointElements = [ - Pair(Namespaces.mathml, "mi"), - Pair(Namespaces.mathml, "mo"), - Pair(Namespaces.mathml, "mn"), - Pair(Namespaces.mathml, "ms"), - Pair(Namespaces.mathml, "mtext") + Pair(Namespaces.mathml, 'mi'), + Pair(Namespaces.mathml, 'mo'), + Pair(Namespaces.mathml, 'mn'), + Pair(Namespaces.mathml, 'ms'), + Pair(Namespaces.mathml, 'mtext') ]; -const spaceCharacters = " \n\r\t\u000C"; +const spaceCharacters = ' \n\r\t\u000C'; const int NEWLINE = 10; const int RETURN = 13; @@ -422,11 +423,11 @@ bool isWhitespaceCC(int charCode) { } const List<String> tableInsertModeElements = [ - "table", - "tbody", - "tfoot", - "thead", - "tr" + 'table', + 'tbody', + 'tfoot', + 'thead', + 'tr' ]; // TODO(jmesserly): remove these in favor of the test functions @@ -443,13 +444,13 @@ bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char); // Note: this is intentially ASCII only bool isLetter(String char) { if (char == null) return false; - int cc = char.codeUnitAt(0); + var cc = char.codeUnitAt(0); return cc >= LOWER_A && cc <= LOWER_Z || cc >= UPPER_A && cc <= UPPER_Z; } bool isDigit(String char) { if (char == null) return false; - int cc = char.codeUnitAt(0); + var cc = char.codeUnitAt(0); return cc >= ZERO && cc < ZERO + 10; } @@ -488,7 +489,7 @@ bool isHexDigit(String char) { String asciiUpper2Lower(String text) { if (text == null) return null; var result = List<int>(text.length); - for (int i = 0; i < text.length; i++) { + for (var i = 0; i < text.length; i++) { var c = text.codeUnitAt(i); if (c >= UPPER_A && c <= UPPER_Z) { c += LOWER_A - UPPER_A; @@ -499,7 +500,7 @@ String asciiUpper2Lower(String text) { } // Heading elements need to be ordered -const headingElements = ["h1", "h2", "h3", "h4", "h5", "h6"]; +const headingElements = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']; const cdataElements = ['title', 'textarea']; @@ -514,41 +515,41 @@ const rcdataElements = [ ]; const Map<String, List<String>> booleanAttributes = { - "": [ - "irrelevant", + '': [ + 'irrelevant', ], - "style": [ - "scoped", + 'style': [ + 'scoped', ], - "img": [ - "ismap", + 'img': [ + 'ismap', ], - "audio": ["autoplay", "controls"], - "video": ["autoplay", "controls"], - "script": ["defer", "async"], - "details": [ - "open", + 'audio': ['autoplay', 'controls'], + 'video': ['autoplay', 'controls'], + 'script': ['defer', 'async'], + 'details': [ + 'open', ], - "datagrid": ["multiple", "disabled"], - "command": ["hidden", "disabled", "checked", "default"], - "hr": ["noshade"], - "men": [ - "autosubmit", + 'datagrid': ['multiple', 'disabled'], + 'command': ['hidden', 'disabled', 'checked', 'default'], + 'hr': ['noshade'], + 'men': [ + 'autosubmit', ], - "fieldset": ["disabled", "readonly"], - "option": ["disabled", "readonly", "selected"], - "optgroup": ["disabled", "readonly"], - "button": ["disabled", "autofocus"], - "input": [ - "disabled", - "readonly", - "required", - "autofocus", - "checked", - "ismap" + 'fieldset': ['disabled', 'readonly'], + 'option': ['disabled', 'readonly', 'selected'], + 'optgroup': ['disabled', 'readonly'], + 'button': ['disabled', 'autofocus'], + 'input': [ + 'disabled', + 'readonly', + 'required', + 'autofocus', + 'checked', + 'ismap' ], - "select": ["disabled", "readonly", "autofocus", "multiple"], - "output": ["disabled", "readonly"], + 'select': ['disabled', 'readonly', 'autofocus', 'multiple'], + 'output': ['disabled', 'readonly'], }; // entitiesWindows1252 has to be _ordered_ and needs to have an index. It @@ -591,2274 +592,2274 @@ const List<int> entitiesWindows1252 = [ const xmlEntities = ['lt;', 'gt;', 'amp;', 'apos;', 'quot;']; const Map<String, String> entities = { - "AElig": "\xc6", - "AElig;": "\xc6", - "AMP": "&", - "AMP;": "&", - "Aacute": "\xc1", - "Aacute;": "\xc1", - "Abreve;": "\u0102", - "Acirc": "\xc2", - "Acirc;": "\xc2", - "Acy;": "\u0410", - "Afr;": "\u{01d504}", - "Agrave": "\xc0", - "Agrave;": "\xc0", - "Alpha;": "\u0391", - "Amacr;": "\u0100", - "And;": "\u2a53", - "Aogon;": "\u0104", - "Aopf;": "\u{01d538}", - "ApplyFunction;": "\u2061", - "Aring": "\xc5", - "Aring;": "\xc5", - "Ascr;": "\u{01d49c}", - "Assign;": "\u2254", - "Atilde": "\xc3", - "Atilde;": "\xc3", - "Auml": "\xc4", - "Auml;": "\xc4", - "Backslash;": "\u2216", - "Barv;": "\u2ae7", - "Barwed;": "\u2306", - "Bcy;": "\u0411", - "Because;": "\u2235", - "Bernoullis;": "\u212c", - "Beta;": "\u0392", - "Bfr;": "\u{01d505}", - "Bopf;": "\u{01d539}", - "Breve;": "\u02d8", - "Bscr;": "\u212c", - "Bumpeq;": "\u224e", - "CHcy;": "\u0427", - "COPY": "\xa9", - "COPY;": "\xa9", - "Cacute;": "\u0106", - "Cap;": "\u22d2", - "CapitalDifferentialD;": "\u2145", - "Cayleys;": "\u212d", - "Ccaron;": "\u010c", - "Ccedil": "\xc7", - "Ccedil;": "\xc7", - "Ccirc;": "\u0108", - "Cconint;": "\u2230", - "Cdot;": "\u010a", - "Cedilla;": "\xb8", - "CenterDot;": "\xb7", - "Cfr;": "\u212d", - "Chi;": "\u03a7", - "CircleDot;": "\u2299", - "CircleMinus;": "\u2296", - "CirclePlus;": "\u2295", - "CircleTimes;": "\u2297", - "ClockwiseContourIntegral;": "\u2232", - "CloseCurlyDoubleQuote;": "\u201d", - "CloseCurlyQuote;": "\u2019", - "Colon;": "\u2237", - "Colone;": "\u2a74", - "Congruent;": "\u2261", - "Conint;": "\u222f", - "ContourIntegral;": "\u222e", - "Copf;": "\u2102", - "Coproduct;": "\u2210", - "CounterClockwiseContourIntegral;": "\u2233", - "Cross;": "\u2a2f", - "Cscr;": "\u{01d49e}", - "Cup;": "\u22d3", - "CupCap;": "\u224d", - "DD;": "\u2145", - "DDotrahd;": "\u2911", - "DJcy;": "\u0402", - "DScy;": "\u0405", - "DZcy;": "\u040f", - "Dagger;": "\u2021", - "Darr;": "\u21a1", - "Dashv;": "\u2ae4", - "Dcaron;": "\u010e", - "Dcy;": "\u0414", - "Del;": "\u2207", - "Delta;": "\u0394", - "Dfr;": "\u{01d507}", - "DiacriticalAcute;": "\xb4", - "DiacriticalDot;": "\u02d9", - "DiacriticalDoubleAcute;": "\u02dd", - "DiacriticalGrave;": "`", - "DiacriticalTilde;": "\u02dc", - "Diamond;": "\u22c4", - "DifferentialD;": "\u2146", - "Dopf;": "\u{01d53b}", - "Dot;": "\xa8", - "DotDot;": "\u20dc", - "DotEqual;": "\u2250", - "DoubleContourIntegral;": "\u222f", - "DoubleDot;": "\xa8", - "DoubleDownArrow;": "\u21d3", - "DoubleLeftArrow;": "\u21d0", - "DoubleLeftRightArrow;": "\u21d4", - "DoubleLeftTee;": "\u2ae4", - "DoubleLongLeftArrow;": "\u27f8", - "DoubleLongLeftRightArrow;": "\u27fa", - "DoubleLongRightArrow;": "\u27f9", - "DoubleRightArrow;": "\u21d2", - "DoubleRightTee;": "\u22a8", - "DoubleUpArrow;": "\u21d1", - "DoubleUpDownArrow;": "\u21d5", - "DoubleVerticalBar;": "\u2225", - "DownArrow;": "\u2193", - "DownArrowBar;": "\u2913", - "DownArrowUpArrow;": "\u21f5", - "DownBreve;": "\u0311", - "DownLeftRightVector;": "\u2950", - "DownLeftTeeVector;": "\u295e", - "DownLeftVector;": "\u21bd", - "DownLeftVectorBar;": "\u2956", - "DownRightTeeVector;": "\u295f", - "DownRightVector;": "\u21c1", - "DownRightVectorBar;": "\u2957", - "DownTee;": "\u22a4", - "DownTeeArrow;": "\u21a7", - "Downarrow;": "\u21d3", - "Dscr;": "\u{01d49f}", - "Dstrok;": "\u0110", - "ENG;": "\u014a", - "ETH": "\xd0", - "ETH;": "\xd0", - "Eacute": "\xc9", - "Eacute;": "\xc9", - "Ecaron;": "\u011a", - "Ecirc": "\xca", - "Ecirc;": "\xca", - "Ecy;": "\u042d", - "Edot;": "\u0116", - "Efr;": "\u{01d508}", - "Egrave": "\xc8", - "Egrave;": "\xc8", - "Element;": "\u2208", - "Emacr;": "\u0112", - "EmptySmallSquare;": "\u25fb", - "EmptyVerySmallSquare;": "\u25ab", - "Eogon;": "\u0118", - "Eopf;": "\u{01d53c}", - "Epsilon;": "\u0395", - "Equal;": "\u2a75", - "EqualTilde;": "\u2242", - "Equilibrium;": "\u21cc", - "Escr;": "\u2130", - "Esim;": "\u2a73", - "Eta;": "\u0397", - "Euml": "\xcb", - "Euml;": "\xcb", - "Exists;": "\u2203", - "ExponentialE;": "\u2147", - "Fcy;": "\u0424", - "Ffr;": "\u{01d509}", - "FilledSmallSquare;": "\u25fc", - "FilledVerySmallSquare;": "\u25aa", - "Fopf;": "\u{01d53d}", - "ForAll;": "\u2200", - "Fouriertrf;": "\u2131", - "Fscr;": "\u2131", - "GJcy;": "\u0403", - "GT": ">", - "GT;": ">", - "Gamma;": "\u0393", - "Gammad;": "\u03dc", - "Gbreve;": "\u011e", - "Gcedil;": "\u0122", - "Gcirc;": "\u011c", - "Gcy;": "\u0413", - "Gdot;": "\u0120", - "Gfr;": "\u{01d50a}", - "Gg;": "\u22d9", - "Gopf;": "\u{01d53e}", - "GreaterEqual;": "\u2265", - "GreaterEqualLess;": "\u22db", - "GreaterFullEqual;": "\u2267", - "GreaterGreater;": "\u2aa2", - "GreaterLess;": "\u2277", - "GreaterSlantEqual;": "\u2a7e", - "GreaterTilde;": "\u2273", - "Gscr;": "\u{01d4a2}", - "Gt;": "\u226b", - "HARDcy;": "\u042a", - "Hacek;": "\u02c7", - "Hat;": "^", - "Hcirc;": "\u0124", - "Hfr;": "\u210c", - "HilbertSpace;": "\u210b", - "Hopf;": "\u210d", - "HorizontalLine;": "\u2500", - "Hscr;": "\u210b", - "Hstrok;": "\u0126", - "HumpDownHump;": "\u224e", - "HumpEqual;": "\u224f", - "IEcy;": "\u0415", - "IJlig;": "\u0132", - "IOcy;": "\u0401", - "Iacute": "\xcd", - "Iacute;": "\xcd", - "Icirc": "\xce", - "Icirc;": "\xce", - "Icy;": "\u0418", - "Idot;": "\u0130", - "Ifr;": "\u2111", - "Igrave": "\xcc", - "Igrave;": "\xcc", - "Im;": "\u2111", - "Imacr;": "\u012a", - "ImaginaryI;": "\u2148", - "Implies;": "\u21d2", - "Int;": "\u222c", - "Integral;": "\u222b", - "Intersection;": "\u22c2", - "InvisibleComma;": "\u2063", - "InvisibleTimes;": "\u2062", - "Iogon;": "\u012e", - "Iopf;": "\u{01d540}", - "Iota;": "\u0399", - "Iscr;": "\u2110", - "Itilde;": "\u0128", - "Iukcy;": "\u0406", - "Iuml": "\xcf", - "Iuml;": "\xcf", - "Jcirc;": "\u0134", - "Jcy;": "\u0419", - "Jfr;": "\u{01d50d}", - "Jopf;": "\u{01d541}", - "Jscr;": "\u{01d4a5}", - "Jsercy;": "\u0408", - "Jukcy;": "\u0404", - "KHcy;": "\u0425", - "KJcy;": "\u040c", - "Kappa;": "\u039a", - "Kcedil;": "\u0136", - "Kcy;": "\u041a", - "Kfr;": "\u{01d50e}", - "Kopf;": "\u{01d542}", - "Kscr;": "\u{01d4a6}", - "LJcy;": "\u0409", - "LT": "<", - "LT;": "<", - "Lacute;": "\u0139", - "Lambda;": "\u039b", - "Lang;": "\u27ea", - "Laplacetrf;": "\u2112", - "Larr;": "\u219e", - "Lcaron;": "\u013d", - "Lcedil;": "\u013b", - "Lcy;": "\u041b", - "LeftAngleBracket;": "\u27e8", - "LeftArrow;": "\u2190", - "LeftArrowBar;": "\u21e4", - "LeftArrowRightArrow;": "\u21c6", - "LeftCeiling;": "\u2308", - "LeftDoubleBracket;": "\u27e6", - "LeftDownTeeVector;": "\u2961", - "LeftDownVector;": "\u21c3", - "LeftDownVectorBar;": "\u2959", - "LeftFloor;": "\u230a", - "LeftRightArrow;": "\u2194", - "LeftRightVector;": "\u294e", - "LeftTee;": "\u22a3", - "LeftTeeArrow;": "\u21a4", - "LeftTeeVector;": "\u295a", - "LeftTriangle;": "\u22b2", - "LeftTriangleBar;": "\u29cf", - "LeftTriangleEqual;": "\u22b4", - "LeftUpDownVector;": "\u2951", - "LeftUpTeeVector;": "\u2960", - "LeftUpVector;": "\u21bf", - "LeftUpVectorBar;": "\u2958", - "LeftVector;": "\u21bc", - "LeftVectorBar;": "\u2952", - "Leftarrow;": "\u21d0", - "Leftrightarrow;": "\u21d4", - "LessEqualGreater;": "\u22da", - "LessFullEqual;": "\u2266", - "LessGreater;": "\u2276", - "LessLess;": "\u2aa1", - "LessSlantEqual;": "\u2a7d", - "LessTilde;": "\u2272", - "Lfr;": "\u{01d50f}", - "Ll;": "\u22d8", - "Lleftarrow;": "\u21da", - "Lmidot;": "\u013f", - "LongLeftArrow;": "\u27f5", - "LongLeftRightArrow;": "\u27f7", - "LongRightArrow;": "\u27f6", - "Longleftarrow;": "\u27f8", - "Longleftrightarrow;": "\u27fa", - "Longrightarrow;": "\u27f9", - "Lopf;": "\u{01d543}", - "LowerLeftArrow;": "\u2199", - "LowerRightArrow;": "\u2198", - "Lscr;": "\u2112", - "Lsh;": "\u21b0", - "Lstrok;": "\u0141", - "Lt;": "\u226a", - "Map;": "\u2905", - "Mcy;": "\u041c", - "MediumSpace;": "\u205f", - "Mellintrf;": "\u2133", - "Mfr;": "\u{01d510}", - "MinusPlus;": "\u2213", - "Mopf;": "\u{01d544}", - "Mscr;": "\u2133", - "Mu;": "\u039c", - "NJcy;": "\u040a", - "Nacute;": "\u0143", - "Ncaron;": "\u0147", - "Ncedil;": "\u0145", - "Ncy;": "\u041d", - "NegativeMediumSpace;": "\u200b", - "NegativeThickSpace;": "\u200b", - "NegativeThinSpace;": "\u200b", - "NegativeVeryThinSpace;": "\u200b", - "NestedGreaterGreater;": "\u226b", - "NestedLessLess;": "\u226a", - "NewLine;": "\n", - "Nfr;": "\u{01d511}", - "NoBreak;": "\u2060", - "NonBreakingSpace;": "\xa0", - "Nopf;": "\u2115", - "Not;": "\u2aec", - "NotCongruent;": "\u2262", - "NotCupCap;": "\u226d", - "NotDoubleVerticalBar;": "\u2226", - "NotElement;": "\u2209", - "NotEqual;": "\u2260", - "NotEqualTilde;": "\u2242\u0338", - "NotExists;": "\u2204", - "NotGreater;": "\u226f", - "NotGreaterEqual;": "\u2271", - "NotGreaterFullEqual;": "\u2267\u0338", - "NotGreaterGreater;": "\u226b\u0338", - "NotGreaterLess;": "\u2279", - "NotGreaterSlantEqual;": "\u2a7e\u0338", - "NotGreaterTilde;": "\u2275", - "NotHumpDownHump;": "\u224e\u0338", - "NotHumpEqual;": "\u224f\u0338", - "NotLeftTriangle;": "\u22ea", - "NotLeftTriangleBar;": "\u29cf\u0338", - "NotLeftTriangleEqual;": "\u22ec", - "NotLess;": "\u226e", - "NotLessEqual;": "\u2270", - "NotLessGreater;": "\u2278", - "NotLessLess;": "\u226a\u0338", - "NotLessSlantEqual;": "\u2a7d\u0338", - "NotLessTilde;": "\u2274", - "NotNestedGreaterGreater;": "\u2aa2\u0338", - "NotNestedLessLess;": "\u2aa1\u0338", - "NotPrecedes;": "\u2280", - "NotPrecedesEqual;": "\u2aaf\u0338", - "NotPrecedesSlantEqual;": "\u22e0", - "NotReverseElement;": "\u220c", - "NotRightTriangle;": "\u22eb", - "NotRightTriangleBar;": "\u29d0\u0338", - "NotRightTriangleEqual;": "\u22ed", - "NotSquareSubset;": "\u228f\u0338", - "NotSquareSubsetEqual;": "\u22e2", - "NotSquareSuperset;": "\u2290\u0338", - "NotSquareSupersetEqual;": "\u22e3", - "NotSubset;": "\u2282\u20d2", - "NotSubsetEqual;": "\u2288", - "NotSucceeds;": "\u2281", - "NotSucceedsEqual;": "\u2ab0\u0338", - "NotSucceedsSlantEqual;": "\u22e1", - "NotSucceedsTilde;": "\u227f\u0338", - "NotSuperset;": "\u2283\u20d2", - "NotSupersetEqual;": "\u2289", - "NotTilde;": "\u2241", - "NotTildeEqual;": "\u2244", - "NotTildeFullEqual;": "\u2247", - "NotTildeTilde;": "\u2249", - "NotVerticalBar;": "\u2224", - "Nscr;": "\u{01d4a9}", - "Ntilde": "\xd1", - "Ntilde;": "\xd1", - "Nu;": "\u039d", - "OElig;": "\u0152", - "Oacute": "\xd3", - "Oacute;": "\xd3", - "Ocirc": "\xd4", - "Ocirc;": "\xd4", - "Ocy;": "\u041e", - "Odblac;": "\u0150", - "Ofr;": "\u{01d512}", - "Ograve": "\xd2", - "Ograve;": "\xd2", - "Omacr;": "\u014c", - "Omega;": "\u03a9", - "Omicron;": "\u039f", - "Oopf;": "\u{01d546}", - "OpenCurlyDoubleQuote;": "\u201c", - "OpenCurlyQuote;": "\u2018", - "Or;": "\u2a54", - "Oscr;": "\u{01d4aa}", - "Oslash": "\xd8", - "Oslash;": "\xd8", - "Otilde": "\xd5", - "Otilde;": "\xd5", - "Otimes;": "\u2a37", - "Ouml": "\xd6", - "Ouml;": "\xd6", - "OverBar;": "\u203e", - "OverBrace;": "\u23de", - "OverBracket;": "\u23b4", - "OverParenthesis;": "\u23dc", - "PartialD;": "\u2202", - "Pcy;": "\u041f", - "Pfr;": "\u{01d513}", - "Phi;": "\u03a6", - "Pi;": "\u03a0", - "PlusMinus;": "\xb1", - "Poincareplane;": "\u210c", - "Popf;": "\u2119", - "Pr;": "\u2abb", - "Precedes;": "\u227a", - "PrecedesEqual;": "\u2aaf", - "PrecedesSlantEqual;": "\u227c", - "PrecedesTilde;": "\u227e", - "Prime;": "\u2033", - "Product;": "\u220f", - "Proportion;": "\u2237", - "Proportional;": "\u221d", - "Pscr;": "\u{01d4ab}", - "Psi;": "\u03a8", - "QUOT": "\"", - "QUOT;": "\"", - "Qfr;": "\u{01d514}", - "Qopf;": "\u211a", - "Qscr;": "\u{01d4ac}", - "RBarr;": "\u2910", - "REG": "\xae", - "REG;": "\xae", - "Racute;": "\u0154", - "Rang;": "\u27eb", - "Rarr;": "\u21a0", - "Rarrtl;": "\u2916", - "Rcaron;": "\u0158", - "Rcedil;": "\u0156", - "Rcy;": "\u0420", - "Re;": "\u211c", - "ReverseElement;": "\u220b", - "ReverseEquilibrium;": "\u21cb", - "ReverseUpEquilibrium;": "\u296f", - "Rfr;": "\u211c", - "Rho;": "\u03a1", - "RightAngleBracket;": "\u27e9", - "RightArrow;": "\u2192", - "RightArrowBar;": "\u21e5", - "RightArrowLeftArrow;": "\u21c4", - "RightCeiling;": "\u2309", - "RightDoubleBracket;": "\u27e7", - "RightDownTeeVector;": "\u295d", - "RightDownVector;": "\u21c2", - "RightDownVectorBar;": "\u2955", - "RightFloor;": "\u230b", - "RightTee;": "\u22a2", - "RightTeeArrow;": "\u21a6", - "RightTeeVector;": "\u295b", - "RightTriangle;": "\u22b3", - "RightTriangleBar;": "\u29d0", - "RightTriangleEqual;": "\u22b5", - "RightUpDownVector;": "\u294f", - "RightUpTeeVector;": "\u295c", - "RightUpVector;": "\u21be", - "RightUpVectorBar;": "\u2954", - "RightVector;": "\u21c0", - "RightVectorBar;": "\u2953", - "Rightarrow;": "\u21d2", - "Ropf;": "\u211d", - "RoundImplies;": "\u2970", - "Rrightarrow;": "\u21db", - "Rscr;": "\u211b", - "Rsh;": "\u21b1", - "RuleDelayed;": "\u29f4", - "SHCHcy;": "\u0429", - "SHcy;": "\u0428", - "SOFTcy;": "\u042c", - "Sacute;": "\u015a", - "Sc;": "\u2abc", - "Scaron;": "\u0160", - "Scedil;": "\u015e", - "Scirc;": "\u015c", - "Scy;": "\u0421", - "Sfr;": "\u{01d516}", - "ShortDownArrow;": "\u2193", - "ShortLeftArrow;": "\u2190", - "ShortRightArrow;": "\u2192", - "ShortUpArrow;": "\u2191", - "Sigma;": "\u03a3", - "SmallCircle;": "\u2218", - "Sopf;": "\u{01d54a}", - "Sqrt;": "\u221a", - "Square;": "\u25a1", - "SquareIntersection;": "\u2293", - "SquareSubset;": "\u228f", - "SquareSubsetEqual;": "\u2291", - "SquareSuperset;": "\u2290", - "SquareSupersetEqual;": "\u2292", - "SquareUnion;": "\u2294", - "Sscr;": "\u{01d4ae}", - "Star;": "\u22c6", - "Sub;": "\u22d0", - "Subset;": "\u22d0", - "SubsetEqual;": "\u2286", - "Succeeds;": "\u227b", - "SucceedsEqual;": "\u2ab0", - "SucceedsSlantEqual;": "\u227d", - "SucceedsTilde;": "\u227f", - "SuchThat;": "\u220b", - "Sum;": "\u2211", - "Sup;": "\u22d1", - "Superset;": "\u2283", - "SupersetEqual;": "\u2287", - "Supset;": "\u22d1", - "THORN": "\xde", - "THORN;": "\xde", - "TRADE;": "\u2122", - "TSHcy;": "\u040b", - "TScy;": "\u0426", - "Tab;": "\t", - "Tau;": "\u03a4", - "Tcaron;": "\u0164", - "Tcedil;": "\u0162", - "Tcy;": "\u0422", - "Tfr;": "\u{01d517}", - "Therefore;": "\u2234", - "Theta;": "\u0398", - "ThickSpace;": "\u205f\u200a", - "ThinSpace;": "\u2009", - "Tilde;": "\u223c", - "TildeEqual;": "\u2243", - "TildeFullEqual;": "\u2245", - "TildeTilde;": "\u2248", - "Topf;": "\u{01d54b}", - "TripleDot;": "\u20db", - "Tscr;": "\u{01d4af}", - "Tstrok;": "\u0166", - "Uacute": "\xda", - "Uacute;": "\xda", - "Uarr;": "\u219f", - "Uarrocir;": "\u2949", - "Ubrcy;": "\u040e", - "Ubreve;": "\u016c", - "Ucirc": "\xdb", - "Ucirc;": "\xdb", - "Ucy;": "\u0423", - "Udblac;": "\u0170", - "Ufr;": "\u{01d518}", - "Ugrave": "\xd9", - "Ugrave;": "\xd9", - "Umacr;": "\u016a", - "UnderBar;": "_", - "UnderBrace;": "\u23df", - "UnderBracket;": "\u23b5", - "UnderParenthesis;": "\u23dd", - "Union;": "\u22c3", - "UnionPlus;": "\u228e", - "Uogon;": "\u0172", - "Uopf;": "\u{01d54c}", - "UpArrow;": "\u2191", - "UpArrowBar;": "\u2912", - "UpArrowDownArrow;": "\u21c5", - "UpDownArrow;": "\u2195", - "UpEquilibrium;": "\u296e", - "UpTee;": "\u22a5", - "UpTeeArrow;": "\u21a5", - "Uparrow;": "\u21d1", - "Updownarrow;": "\u21d5", - "UpperLeftArrow;": "\u2196", - "UpperRightArrow;": "\u2197", - "Upsi;": "\u03d2", - "Upsilon;": "\u03a5", - "Uring;": "\u016e", - "Uscr;": "\u{01d4b0}", - "Utilde;": "\u0168", - "Uuml": "\xdc", - "Uuml;": "\xdc", - "VDash;": "\u22ab", - "Vbar;": "\u2aeb", - "Vcy;": "\u0412", - "Vdash;": "\u22a9", - "Vdashl;": "\u2ae6", - "Vee;": "\u22c1", - "Verbar;": "\u2016", - "Vert;": "\u2016", - "VerticalBar;": "\u2223", - "VerticalLine;": "|", - "VerticalSeparator;": "\u2758", - "VerticalTilde;": "\u2240", - "VeryThinSpace;": "\u200a", - "Vfr;": "\u{01d519}", - "Vopf;": "\u{01d54d}", - "Vscr;": "\u{01d4b1}", - "Vvdash;": "\u22aa", - "Wcirc;": "\u0174", - "Wedge;": "\u22c0", - "Wfr;": "\u{01d51a}", - "Wopf;": "\u{01d54e}", - "Wscr;": "\u{01d4b2}", - "Xfr;": "\u{01d51b}", - "Xi;": "\u039e", - "Xopf;": "\u{01d54f}", - "Xscr;": "\u{01d4b3}", - "YAcy;": "\u042f", - "YIcy;": "\u0407", - "YUcy;": "\u042e", - "Yacute": "\xdd", - "Yacute;": "\xdd", - "Ycirc;": "\u0176", - "Ycy;": "\u042b", - "Yfr;": "\u{01d51c}", - "Yopf;": "\u{01d550}", - "Yscr;": "\u{01d4b4}", - "Yuml;": "\u0178", - "ZHcy;": "\u0416", - "Zacute;": "\u0179", - "Zcaron;": "\u017d", - "Zcy;": "\u0417", - "Zdot;": "\u017b", - "ZeroWidthSpace;": "\u200b", - "Zeta;": "\u0396", - "Zfr;": "\u2128", - "Zopf;": "\u2124", - "Zscr;": "\u{01d4b5}", - "aacute": "\xe1", - "aacute;": "\xe1", - "abreve;": "\u0103", - "ac;": "\u223e", - "acE;": "\u223e\u0333", - "acd;": "\u223f", - "acirc": "\xe2", - "acirc;": "\xe2", - "acute": "\xb4", - "acute;": "\xb4", - "acy;": "\u0430", - "aelig": "\xe6", - "aelig;": "\xe6", - "af;": "\u2061", - "afr;": "\u{01d51e}", - "agrave": "\xe0", - "agrave;": "\xe0", - "alefsym;": "\u2135", - "aleph;": "\u2135", - "alpha;": "\u03b1", - "amacr;": "\u0101", - "amalg;": "\u2a3f", - "amp": "&", - "amp;": "&", - "and;": "\u2227", - "andand;": "\u2a55", - "andd;": "\u2a5c", - "andslope;": "\u2a58", - "andv;": "\u2a5a", - "ang;": "\u2220", - "ange;": "\u29a4", - "angle;": "\u2220", - "angmsd;": "\u2221", - "angmsdaa;": "\u29a8", - "angmsdab;": "\u29a9", - "angmsdac;": "\u29aa", - "angmsdad;": "\u29ab", - "angmsdae;": "\u29ac", - "angmsdaf;": "\u29ad", - "angmsdag;": "\u29ae", - "angmsdah;": "\u29af", - "angrt;": "\u221f", - "angrtvb;": "\u22be", - "angrtvbd;": "\u299d", - "angsph;": "\u2222", - "angst;": "\xc5", - "angzarr;": "\u237c", - "aogon;": "\u0105", - "aopf;": "\u{01d552}", - "ap;": "\u2248", - "apE;": "\u2a70", - "apacir;": "\u2a6f", - "ape;": "\u224a", - "apid;": "\u224b", - "apos;": "'", - "approx;": "\u2248", - "approxeq;": "\u224a", - "aring": "\xe5", - "aring;": "\xe5", - "ascr;": "\u{01d4b6}", - "ast;": "*", - "asymp;": "\u2248", - "asympeq;": "\u224d", - "atilde": "\xe3", - "atilde;": "\xe3", - "auml": "\xe4", - "auml;": "\xe4", - "awconint;": "\u2233", - "awint;": "\u2a11", - "bNot;": "\u2aed", - "backcong;": "\u224c", - "backepsilon;": "\u03f6", - "backprime;": "\u2035", - "backsim;": "\u223d", - "backsimeq;": "\u22cd", - "barvee;": "\u22bd", - "barwed;": "\u2305", - "barwedge;": "\u2305", - "bbrk;": "\u23b5", - "bbrktbrk;": "\u23b6", - "bcong;": "\u224c", - "bcy;": "\u0431", - "bdquo;": "\u201e", - "becaus;": "\u2235", - "because;": "\u2235", - "bemptyv;": "\u29b0", - "bepsi;": "\u03f6", - "bernou;": "\u212c", - "beta;": "\u03b2", - "beth;": "\u2136", - "between;": "\u226c", - "bfr;": "\u{01d51f}", - "bigcap;": "\u22c2", - "bigcirc;": "\u25ef", - "bigcup;": "\u22c3", - "bigodot;": "\u2a00", - "bigoplus;": "\u2a01", - "bigotimes;": "\u2a02", - "bigsqcup;": "\u2a06", - "bigstar;": "\u2605", - "bigtriangledown;": "\u25bd", - "bigtriangleup;": "\u25b3", - "biguplus;": "\u2a04", - "bigvee;": "\u22c1", - "bigwedge;": "\u22c0", - "bkarow;": "\u290d", - "blacklozenge;": "\u29eb", - "blacksquare;": "\u25aa", - "blacktriangle;": "\u25b4", - "blacktriangledown;": "\u25be", - "blacktriangleleft;": "\u25c2", - "blacktriangleright;": "\u25b8", - "blank;": "\u2423", - "blk12;": "\u2592", - "blk14;": "\u2591", - "blk34;": "\u2593", - "block;": "\u2588", - "bne;": "=\u20e5", - "bnequiv;": "\u2261\u20e5", - "bnot;": "\u2310", - "bopf;": "\u{01d553}", - "bot;": "\u22a5", - "bottom;": "\u22a5", - "bowtie;": "\u22c8", - "boxDL;": "\u2557", - "boxDR;": "\u2554", - "boxDl;": "\u2556", - "boxDr;": "\u2553", - "boxH;": "\u2550", - "boxHD;": "\u2566", - "boxHU;": "\u2569", - "boxHd;": "\u2564", - "boxHu;": "\u2567", - "boxUL;": "\u255d", - "boxUR;": "\u255a", - "boxUl;": "\u255c", - "boxUr;": "\u2559", - "boxV;": "\u2551", - "boxVH;": "\u256c", - "boxVL;": "\u2563", - "boxVR;": "\u2560", - "boxVh;": "\u256b", - "boxVl;": "\u2562", - "boxVr;": "\u255f", - "boxbox;": "\u29c9", - "boxdL;": "\u2555", - "boxdR;": "\u2552", - "boxdl;": "\u2510", - "boxdr;": "\u250c", - "boxh;": "\u2500", - "boxhD;": "\u2565", - "boxhU;": "\u2568", - "boxhd;": "\u252c", - "boxhu;": "\u2534", - "boxminus;": "\u229f", - "boxplus;": "\u229e", - "boxtimes;": "\u22a0", - "boxuL;": "\u255b", - "boxuR;": "\u2558", - "boxul;": "\u2518", - "boxur;": "\u2514", - "boxv;": "\u2502", - "boxvH;": "\u256a", - "boxvL;": "\u2561", - "boxvR;": "\u255e", - "boxvh;": "\u253c", - "boxvl;": "\u2524", - "boxvr;": "\u251c", - "bprime;": "\u2035", - "breve;": "\u02d8", - "brvbar": "\xa6", - "brvbar;": "\xa6", - "bscr;": "\u{01d4b7}", - "bsemi;": "\u204f", - "bsim;": "\u223d", - "bsime;": "\u22cd", - "bsol;": "\\", - "bsolb;": "\u29c5", - "bsolhsub;": "\u27c8", - "bull;": "\u2022", - "bullet;": "\u2022", - "bump;": "\u224e", - "bumpE;": "\u2aae", - "bumpe;": "\u224f", - "bumpeq;": "\u224f", - "cacute;": "\u0107", - "cap;": "\u2229", - "capand;": "\u2a44", - "capbrcup;": "\u2a49", - "capcap;": "\u2a4b", - "capcup;": "\u2a47", - "capdot;": "\u2a40", - "caps;": "\u2229\ufe00", - "caret;": "\u2041", - "caron;": "\u02c7", - "ccaps;": "\u2a4d", - "ccaron;": "\u010d", - "ccedil": "\xe7", - "ccedil;": "\xe7", - "ccirc;": "\u0109", - "ccups;": "\u2a4c", - "ccupssm;": "\u2a50", - "cdot;": "\u010b", - "cedil": "\xb8", - "cedil;": "\xb8", - "cemptyv;": "\u29b2", - "cent": "\xa2", - "cent;": "\xa2", - "centerdot;": "\xb7", - "cfr;": "\u{01d520}", - "chcy;": "\u0447", - "check;": "\u2713", - "checkmark;": "\u2713", - "chi;": "\u03c7", - "cir;": "\u25cb", - "cirE;": "\u29c3", - "circ;": "\u02c6", - "circeq;": "\u2257", - "circlearrowleft;": "\u21ba", - "circlearrowright;": "\u21bb", - "circledR;": "\xae", - "circledS;": "\u24c8", - "circledast;": "\u229b", - "circledcirc;": "\u229a", - "circleddash;": "\u229d", - "cire;": "\u2257", - "cirfnint;": "\u2a10", - "cirmid;": "\u2aef", - "cirscir;": "\u29c2", - "clubs;": "\u2663", - "clubsuit;": "\u2663", - "colon;": ":", - "colone;": "\u2254", - "coloneq;": "\u2254", - "comma;": ",", - "commat;": "@", - "comp;": "\u2201", - "compfn;": "\u2218", - "complement;": "\u2201", - "complexes;": "\u2102", - "cong;": "\u2245", - "congdot;": "\u2a6d", - "conint;": "\u222e", - "copf;": "\u{01d554}", - "coprod;": "\u2210", - "copy": "\xa9", - "copy;": "\xa9", - "copysr;": "\u2117", - "crarr;": "\u21b5", - "cross;": "\u2717", - "cscr;": "\u{01d4b8}", - "csub;": "\u2acf", - "csube;": "\u2ad1", - "csup;": "\u2ad0", - "csupe;": "\u2ad2", - "ctdot;": "\u22ef", - "cudarrl;": "\u2938", - "cudarrr;": "\u2935", - "cuepr;": "\u22de", - "cuesc;": "\u22df", - "cularr;": "\u21b6", - "cularrp;": "\u293d", - "cup;": "\u222a", - "cupbrcap;": "\u2a48", - "cupcap;": "\u2a46", - "cupcup;": "\u2a4a", - "cupdot;": "\u228d", - "cupor;": "\u2a45", - "cups;": "\u222a\ufe00", - "curarr;": "\u21b7", - "curarrm;": "\u293c", - "curlyeqprec;": "\u22de", - "curlyeqsucc;": "\u22df", - "curlyvee;": "\u22ce", - "curlywedge;": "\u22cf", - "curren": "\xa4", - "curren;": "\xa4", - "curvearrowleft;": "\u21b6", - "curvearrowright;": "\u21b7", - "cuvee;": "\u22ce", - "cuwed;": "\u22cf", - "cwconint;": "\u2232", - "cwint;": "\u2231", - "cylcty;": "\u232d", - "dArr;": "\u21d3", - "dHar;": "\u2965", - "dagger;": "\u2020", - "daleth;": "\u2138", - "darr;": "\u2193", - "dash;": "\u2010", - "dashv;": "\u22a3", - "dbkarow;": "\u290f", - "dblac;": "\u02dd", - "dcaron;": "\u010f", - "dcy;": "\u0434", - "dd;": "\u2146", - "ddagger;": "\u2021", - "ddarr;": "\u21ca", - "ddotseq;": "\u2a77", - "deg": "\xb0", - "deg;": "\xb0", - "delta;": "\u03b4", - "demptyv;": "\u29b1", - "dfisht;": "\u297f", - "dfr;": "\u{01d521}", - "dharl;": "\u21c3", - "dharr;": "\u21c2", - "diam;": "\u22c4", - "diamond;": "\u22c4", - "diamondsuit;": "\u2666", - "diams;": "\u2666", - "die;": "\xa8", - "digamma;": "\u03dd", - "disin;": "\u22f2", - "div;": "\xf7", - "divide": "\xf7", - "divide;": "\xf7", - "divideontimes;": "\u22c7", - "divonx;": "\u22c7", - "djcy;": "\u0452", - "dlcorn;": "\u231e", - "dlcrop;": "\u230d", - "dollar;": "\$", - "dopf;": "\u{01d555}", - "dot;": "\u02d9", - "doteq;": "\u2250", - "doteqdot;": "\u2251", - "dotminus;": "\u2238", - "dotplus;": "\u2214", - "dotsquare;": "\u22a1", - "doublebarwedge;": "\u2306", - "downarrow;": "\u2193", - "downdownarrows;": "\u21ca", - "downharpoonleft;": "\u21c3", - "downharpoonright;": "\u21c2", - "drbkarow;": "\u2910", - "drcorn;": "\u231f", - "drcrop;": "\u230c", - "dscr;": "\u{01d4b9}", - "dscy;": "\u0455", - "dsol;": "\u29f6", - "dstrok;": "\u0111", - "dtdot;": "\u22f1", - "dtri;": "\u25bf", - "dtrif;": "\u25be", - "duarr;": "\u21f5", - "duhar;": "\u296f", - "dwangle;": "\u29a6", - "dzcy;": "\u045f", - "dzigrarr;": "\u27ff", - "eDDot;": "\u2a77", - "eDot;": "\u2251", - "eacute": "\xe9", - "eacute;": "\xe9", - "easter;": "\u2a6e", - "ecaron;": "\u011b", - "ecir;": "\u2256", - "ecirc": "\xea", - "ecirc;": "\xea", - "ecolon;": "\u2255", - "ecy;": "\u044d", - "edot;": "\u0117", - "ee;": "\u2147", - "efDot;": "\u2252", - "efr;": "\u{01d522}", - "eg;": "\u2a9a", - "egrave": "\xe8", - "egrave;": "\xe8", - "egs;": "\u2a96", - "egsdot;": "\u2a98", - "el;": "\u2a99", - "elinters;": "\u23e7", - "ell;": "\u2113", - "els;": "\u2a95", - "elsdot;": "\u2a97", - "emacr;": "\u0113", - "empty;": "\u2205", - "emptyset;": "\u2205", - "emptyv;": "\u2205", - "emsp13;": "\u2004", - "emsp14;": "\u2005", - "emsp;": "\u2003", - "eng;": "\u014b", - "ensp;": "\u2002", - "eogon;": "\u0119", - "eopf;": "\u{01d556}", - "epar;": "\u22d5", - "eparsl;": "\u29e3", - "eplus;": "\u2a71", - "epsi;": "\u03b5", - "epsilon;": "\u03b5", - "epsiv;": "\u03f5", - "eqcirc;": "\u2256", - "eqcolon;": "\u2255", - "eqsim;": "\u2242", - "eqslantgtr;": "\u2a96", - "eqslantless;": "\u2a95", - "equals;": "=", - "equest;": "\u225f", - "equiv;": "\u2261", - "equivDD;": "\u2a78", - "eqvparsl;": "\u29e5", - "erDot;": "\u2253", - "erarr;": "\u2971", - "escr;": "\u212f", - "esdot;": "\u2250", - "esim;": "\u2242", - "eta;": "\u03b7", - "eth": "\xf0", - "eth;": "\xf0", - "euml": "\xeb", - "euml;": "\xeb", - "euro;": "\u20ac", - "excl;": "!", - "exist;": "\u2203", - "expectation;": "\u2130", - "exponentiale;": "\u2147", - "fallingdotseq;": "\u2252", - "fcy;": "\u0444", - "female;": "\u2640", - "ffilig;": "\ufb03", - "fflig;": "\ufb00", - "ffllig;": "\ufb04", - "ffr;": "\u{01d523}", - "filig;": "\ufb01", - "fjlig;": "fj", - "flat;": "\u266d", - "fllig;": "\ufb02", - "fltns;": "\u25b1", - "fnof;": "\u0192", - "fopf;": "\u{01d557}", - "forall;": "\u2200", - "fork;": "\u22d4", - "forkv;": "\u2ad9", - "fpartint;": "\u2a0d", - "frac12": "\xbd", - "frac12;": "\xbd", - "frac13;": "\u2153", - "frac14": "\xbc", - "frac14;": "\xbc", - "frac15;": "\u2155", - "frac16;": "\u2159", - "frac18;": "\u215b", - "frac23;": "\u2154", - "frac25;": "\u2156", - "frac34": "\xbe", - "frac34;": "\xbe", - "frac35;": "\u2157", - "frac38;": "\u215c", - "frac45;": "\u2158", - "frac56;": "\u215a", - "frac58;": "\u215d", - "frac78;": "\u215e", - "frasl;": "\u2044", - "frown;": "\u2322", - "fscr;": "\u{01d4bb}", - "gE;": "\u2267", - "gEl;": "\u2a8c", - "gacute;": "\u01f5", - "gamma;": "\u03b3", - "gammad;": "\u03dd", - "gap;": "\u2a86", - "gbreve;": "\u011f", - "gcirc;": "\u011d", - "gcy;": "\u0433", - "gdot;": "\u0121", - "ge;": "\u2265", - "gel;": "\u22db", - "geq;": "\u2265", - "geqq;": "\u2267", - "geqslant;": "\u2a7e", - "ges;": "\u2a7e", - "gescc;": "\u2aa9", - "gesdot;": "\u2a80", - "gesdoto;": "\u2a82", - "gesdotol;": "\u2a84", - "gesl;": "\u22db\ufe00", - "gesles;": "\u2a94", - "gfr;": "\u{01d524}", - "gg;": "\u226b", - "ggg;": "\u22d9", - "gimel;": "\u2137", - "gjcy;": "\u0453", - "gl;": "\u2277", - "glE;": "\u2a92", - "gla;": "\u2aa5", - "glj;": "\u2aa4", - "gnE;": "\u2269", - "gnap;": "\u2a8a", - "gnapprox;": "\u2a8a", - "gne;": "\u2a88", - "gneq;": "\u2a88", - "gneqq;": "\u2269", - "gnsim;": "\u22e7", - "gopf;": "\u{01d558}", - "grave;": "`", - "gscr;": "\u210a", - "gsim;": "\u2273", - "gsime;": "\u2a8e", - "gsiml;": "\u2a90", - "gt": ">", - "gt;": ">", - "gtcc;": "\u2aa7", - "gtcir;": "\u2a7a", - "gtdot;": "\u22d7", - "gtlPar;": "\u2995", - "gtquest;": "\u2a7c", - "gtrapprox;": "\u2a86", - "gtrarr;": "\u2978", - "gtrdot;": "\u22d7", - "gtreqless;": "\u22db", - "gtreqqless;": "\u2a8c", - "gtrless;": "\u2277", - "gtrsim;": "\u2273", - "gvertneqq;": "\u2269\ufe00", - "gvnE;": "\u2269\ufe00", - "hArr;": "\u21d4", - "hairsp;": "\u200a", - "half;": "\xbd", - "hamilt;": "\u210b", - "hardcy;": "\u044a", - "harr;": "\u2194", - "harrcir;": "\u2948", - "harrw;": "\u21ad", - "hbar;": "\u210f", - "hcirc;": "\u0125", - "hearts;": "\u2665", - "heartsuit;": "\u2665", - "hellip;": "\u2026", - "hercon;": "\u22b9", - "hfr;": "\u{01d525}", - "hksearow;": "\u2925", - "hkswarow;": "\u2926", - "hoarr;": "\u21ff", - "homtht;": "\u223b", - "hookleftarrow;": "\u21a9", - "hookrightarrow;": "\u21aa", - "hopf;": "\u{01d559}", - "horbar;": "\u2015", - "hscr;": "\u{01d4bd}", - "hslash;": "\u210f", - "hstrok;": "\u0127", - "hybull;": "\u2043", - "hyphen;": "\u2010", - "iacute": "\xed", - "iacute;": "\xed", - "ic;": "\u2063", - "icirc": "\xee", - "icirc;": "\xee", - "icy;": "\u0438", - "iecy;": "\u0435", - "iexcl": "\xa1", - "iexcl;": "\xa1", - "iff;": "\u21d4", - "ifr;": "\u{01d526}", - "igrave": "\xec", - "igrave;": "\xec", - "ii;": "\u2148", - "iiiint;": "\u2a0c", - "iiint;": "\u222d", - "iinfin;": "\u29dc", - "iiota;": "\u2129", - "ijlig;": "\u0133", - "imacr;": "\u012b", - "image;": "\u2111", - "imagline;": "\u2110", - "imagpart;": "\u2111", - "imath;": "\u0131", - "imof;": "\u22b7", - "imped;": "\u01b5", - "in;": "\u2208", - "incare;": "\u2105", - "infin;": "\u221e", - "infintie;": "\u29dd", - "inodot;": "\u0131", - "int;": "\u222b", - "intcal;": "\u22ba", - "integers;": "\u2124", - "intercal;": "\u22ba", - "intlarhk;": "\u2a17", - "intprod;": "\u2a3c", - "iocy;": "\u0451", - "iogon;": "\u012f", - "iopf;": "\u{01d55a}", - "iota;": "\u03b9", - "iprod;": "\u2a3c", - "iquest": "\xbf", - "iquest;": "\xbf", - "iscr;": "\u{01d4be}", - "isin;": "\u2208", - "isinE;": "\u22f9", - "isindot;": "\u22f5", - "isins;": "\u22f4", - "isinsv;": "\u22f3", - "isinv;": "\u2208", - "it;": "\u2062", - "itilde;": "\u0129", - "iukcy;": "\u0456", - "iuml": "\xef", - "iuml;": "\xef", - "jcirc;": "\u0135", - "jcy;": "\u0439", - "jfr;": "\u{01d527}", - "jmath;": "\u0237", - "jopf;": "\u{01d55b}", - "jscr;": "\u{01d4bf}", - "jsercy;": "\u0458", - "jukcy;": "\u0454", - "kappa;": "\u03ba", - "kappav;": "\u03f0", - "kcedil;": "\u0137", - "kcy;": "\u043a", - "kfr;": "\u{01d528}", - "kgreen;": "\u0138", - "khcy;": "\u0445", - "kjcy;": "\u045c", - "kopf;": "\u{01d55c}", - "kscr;": "\u{01d4c0}", - "lAarr;": "\u21da", - "lArr;": "\u21d0", - "lAtail;": "\u291b", - "lBarr;": "\u290e", - "lE;": "\u2266", - "lEg;": "\u2a8b", - "lHar;": "\u2962", - "lacute;": "\u013a", - "laemptyv;": "\u29b4", - "lagran;": "\u2112", - "lambda;": "\u03bb", - "lang;": "\u27e8", - "langd;": "\u2991", - "langle;": "\u27e8", - "lap;": "\u2a85", - "laquo": "\xab", - "laquo;": "\xab", - "larr;": "\u2190", - "larrb;": "\u21e4", - "larrbfs;": "\u291f", - "larrfs;": "\u291d", - "larrhk;": "\u21a9", - "larrlp;": "\u21ab", - "larrpl;": "\u2939", - "larrsim;": "\u2973", - "larrtl;": "\u21a2", - "lat;": "\u2aab", - "latail;": "\u2919", - "late;": "\u2aad", - "lates;": "\u2aad\ufe00", - "lbarr;": "\u290c", - "lbbrk;": "\u2772", - "lbrace;": "{", - "lbrack;": "[", - "lbrke;": "\u298b", - "lbrksld;": "\u298f", - "lbrkslu;": "\u298d", - "lcaron;": "\u013e", - "lcedil;": "\u013c", - "lceil;": "\u2308", - "lcub;": "{", - "lcy;": "\u043b", - "ldca;": "\u2936", - "ldquo;": "\u201c", - "ldquor;": "\u201e", - "ldrdhar;": "\u2967", - "ldrushar;": "\u294b", - "ldsh;": "\u21b2", - "le;": "\u2264", - "leftarrow;": "\u2190", - "leftarrowtail;": "\u21a2", - "leftharpoondown;": "\u21bd", - "leftharpoonup;": "\u21bc", - "leftleftarrows;": "\u21c7", - "leftrightarrow;": "\u2194", - "leftrightarrows;": "\u21c6", - "leftrightharpoons;": "\u21cb", - "leftrightsquigarrow;": "\u21ad", - "leftthreetimes;": "\u22cb", - "leg;": "\u22da", - "leq;": "\u2264", - "leqq;": "\u2266", - "leqslant;": "\u2a7d", - "les;": "\u2a7d", - "lescc;": "\u2aa8", - "lesdot;": "\u2a7f", - "lesdoto;": "\u2a81", - "lesdotor;": "\u2a83", - "lesg;": "\u22da\ufe00", - "lesges;": "\u2a93", - "lessapprox;": "\u2a85", - "lessdot;": "\u22d6", - "lesseqgtr;": "\u22da", - "lesseqqgtr;": "\u2a8b", - "lessgtr;": "\u2276", - "lesssim;": "\u2272", - "lfisht;": "\u297c", - "lfloor;": "\u230a", - "lfr;": "\u{01d529}", - "lg;": "\u2276", - "lgE;": "\u2a91", - "lhard;": "\u21bd", - "lharu;": "\u21bc", - "lharul;": "\u296a", - "lhblk;": "\u2584", - "ljcy;": "\u0459", - "ll;": "\u226a", - "llarr;": "\u21c7", - "llcorner;": "\u231e", - "llhard;": "\u296b", - "lltri;": "\u25fa", - "lmidot;": "\u0140", - "lmoust;": "\u23b0", - "lmoustache;": "\u23b0", - "lnE;": "\u2268", - "lnap;": "\u2a89", - "lnapprox;": "\u2a89", - "lne;": "\u2a87", - "lneq;": "\u2a87", - "lneqq;": "\u2268", - "lnsim;": "\u22e6", - "loang;": "\u27ec", - "loarr;": "\u21fd", - "lobrk;": "\u27e6", - "longleftarrow;": "\u27f5", - "longleftrightarrow;": "\u27f7", - "longmapsto;": "\u27fc", - "longrightarrow;": "\u27f6", - "looparrowleft;": "\u21ab", - "looparrowright;": "\u21ac", - "lopar;": "\u2985", - "lopf;": "\u{01d55d}", - "loplus;": "\u2a2d", - "lotimes;": "\u2a34", - "lowast;": "\u2217", - "lowbar;": "_", - "loz;": "\u25ca", - "lozenge;": "\u25ca", - "lozf;": "\u29eb", - "lpar;": "(", - "lparlt;": "\u2993", - "lrarr;": "\u21c6", - "lrcorner;": "\u231f", - "lrhar;": "\u21cb", - "lrhard;": "\u296d", - "lrm;": "\u200e", - "lrtri;": "\u22bf", - "lsaquo;": "\u2039", - "lscr;": "\u{01d4c1}", - "lsh;": "\u21b0", - "lsim;": "\u2272", - "lsime;": "\u2a8d", - "lsimg;": "\u2a8f", - "lsqb;": "[", - "lsquo;": "\u2018", - "lsquor;": "\u201a", - "lstrok;": "\u0142", - "lt": "<", - "lt;": "<", - "ltcc;": "\u2aa6", - "ltcir;": "\u2a79", - "ltdot;": "\u22d6", - "lthree;": "\u22cb", - "ltimes;": "\u22c9", - "ltlarr;": "\u2976", - "ltquest;": "\u2a7b", - "ltrPar;": "\u2996", - "ltri;": "\u25c3", - "ltrie;": "\u22b4", - "ltrif;": "\u25c2", - "lurdshar;": "\u294a", - "luruhar;": "\u2966", - "lvertneqq;": "\u2268\ufe00", - "lvnE;": "\u2268\ufe00", - "mDDot;": "\u223a", - "macr": "\xaf", - "macr;": "\xaf", - "male;": "\u2642", - "malt;": "\u2720", - "maltese;": "\u2720", - "map;": "\u21a6", - "mapsto;": "\u21a6", - "mapstodown;": "\u21a7", - "mapstoleft;": "\u21a4", - "mapstoup;": "\u21a5", - "marker;": "\u25ae", - "mcomma;": "\u2a29", - "mcy;": "\u043c", - "mdash;": "\u2014", - "measuredangle;": "\u2221", - "mfr;": "\u{01d52a}", - "mho;": "\u2127", - "micro": "\xb5", - "micro;": "\xb5", - "mid;": "\u2223", - "midast;": "*", - "midcir;": "\u2af0", - "middot": "\xb7", - "middot;": "\xb7", - "minus;": "\u2212", - "minusb;": "\u229f", - "minusd;": "\u2238", - "minusdu;": "\u2a2a", - "mlcp;": "\u2adb", - "mldr;": "\u2026", - "mnplus;": "\u2213", - "models;": "\u22a7", - "mopf;": "\u{01d55e}", - "mp;": "\u2213", - "mscr;": "\u{01d4c2}", - "mstpos;": "\u223e", - "mu;": "\u03bc", - "multimap;": "\u22b8", - "mumap;": "\u22b8", - "nGg;": "\u22d9\u0338", - "nGt;": "\u226b\u20d2", - "nGtv;": "\u226b\u0338", - "nLeftarrow;": "\u21cd", - "nLeftrightarrow;": "\u21ce", - "nLl;": "\u22d8\u0338", - "nLt;": "\u226a\u20d2", - "nLtv;": "\u226a\u0338", - "nRightarrow;": "\u21cf", - "nVDash;": "\u22af", - "nVdash;": "\u22ae", - "nabla;": "\u2207", - "nacute;": "\u0144", - "nang;": "\u2220\u20d2", - "nap;": "\u2249", - "napE;": "\u2a70\u0338", - "napid;": "\u224b\u0338", - "napos;": "\u0149", - "napprox;": "\u2249", - "natur;": "\u266e", - "natural;": "\u266e", - "naturals;": "\u2115", - "nbsp": "\xa0", - "nbsp;": "\xa0", - "nbump;": "\u224e\u0338", - "nbumpe;": "\u224f\u0338", - "ncap;": "\u2a43", - "ncaron;": "\u0148", - "ncedil;": "\u0146", - "ncong;": "\u2247", - "ncongdot;": "\u2a6d\u0338", - "ncup;": "\u2a42", - "ncy;": "\u043d", - "ndash;": "\u2013", - "ne;": "\u2260", - "neArr;": "\u21d7", - "nearhk;": "\u2924", - "nearr;": "\u2197", - "nearrow;": "\u2197", - "nedot;": "\u2250\u0338", - "nequiv;": "\u2262", - "nesear;": "\u2928", - "nesim;": "\u2242\u0338", - "nexist;": "\u2204", - "nexists;": "\u2204", - "nfr;": "\u{01d52b}", - "ngE;": "\u2267\u0338", - "nge;": "\u2271", - "ngeq;": "\u2271", - "ngeqq;": "\u2267\u0338", - "ngeqslant;": "\u2a7e\u0338", - "nges;": "\u2a7e\u0338", - "ngsim;": "\u2275", - "ngt;": "\u226f", - "ngtr;": "\u226f", - "nhArr;": "\u21ce", - "nharr;": "\u21ae", - "nhpar;": "\u2af2", - "ni;": "\u220b", - "nis;": "\u22fc", - "nisd;": "\u22fa", - "niv;": "\u220b", - "njcy;": "\u045a", - "nlArr;": "\u21cd", - "nlE;": "\u2266\u0338", - "nlarr;": "\u219a", - "nldr;": "\u2025", - "nle;": "\u2270", - "nleftarrow;": "\u219a", - "nleftrightarrow;": "\u21ae", - "nleq;": "\u2270", - "nleqq;": "\u2266\u0338", - "nleqslant;": "\u2a7d\u0338", - "nles;": "\u2a7d\u0338", - "nless;": "\u226e", - "nlsim;": "\u2274", - "nlt;": "\u226e", - "nltri;": "\u22ea", - "nltrie;": "\u22ec", - "nmid;": "\u2224", - "nopf;": "\u{01d55f}", - "not": "\xac", - "not;": "\xac", - "notin;": "\u2209", - "notinE;": "\u22f9\u0338", - "notindot;": "\u22f5\u0338", - "notinva;": "\u2209", - "notinvb;": "\u22f7", - "notinvc;": "\u22f6", - "notni;": "\u220c", - "notniva;": "\u220c", - "notnivb;": "\u22fe", - "notnivc;": "\u22fd", - "npar;": "\u2226", - "nparallel;": "\u2226", - "nparsl;": "\u2afd\u20e5", - "npart;": "\u2202\u0338", - "npolint;": "\u2a14", - "npr;": "\u2280", - "nprcue;": "\u22e0", - "npre;": "\u2aaf\u0338", - "nprec;": "\u2280", - "npreceq;": "\u2aaf\u0338", - "nrArr;": "\u21cf", - "nrarr;": "\u219b", - "nrarrc;": "\u2933\u0338", - "nrarrw;": "\u219d\u0338", - "nrightarrow;": "\u219b", - "nrtri;": "\u22eb", - "nrtrie;": "\u22ed", - "nsc;": "\u2281", - "nsccue;": "\u22e1", - "nsce;": "\u2ab0\u0338", - "nscr;": "\u{01d4c3}", - "nshortmid;": "\u2224", - "nshortparallel;": "\u2226", - "nsim;": "\u2241", - "nsime;": "\u2244", - "nsimeq;": "\u2244", - "nsmid;": "\u2224", - "nspar;": "\u2226", - "nsqsube;": "\u22e2", - "nsqsupe;": "\u22e3", - "nsub;": "\u2284", - "nsubE;": "\u2ac5\u0338", - "nsube;": "\u2288", - "nsubset;": "\u2282\u20d2", - "nsubseteq;": "\u2288", - "nsubseteqq;": "\u2ac5\u0338", - "nsucc;": "\u2281", - "nsucceq;": "\u2ab0\u0338", - "nsup;": "\u2285", - "nsupE;": "\u2ac6\u0338", - "nsupe;": "\u2289", - "nsupset;": "\u2283\u20d2", - "nsupseteq;": "\u2289", - "nsupseteqq;": "\u2ac6\u0338", - "ntgl;": "\u2279", - "ntilde": "\xf1", - "ntilde;": "\xf1", - "ntlg;": "\u2278", - "ntriangleleft;": "\u22ea", - "ntrianglelefteq;": "\u22ec", - "ntriangleright;": "\u22eb", - "ntrianglerighteq;": "\u22ed", - "nu;": "\u03bd", - "num;": "#", - "numero;": "\u2116", - "numsp;": "\u2007", - "nvDash;": "\u22ad", - "nvHarr;": "\u2904", - "nvap;": "\u224d\u20d2", - "nvdash;": "\u22ac", - "nvge;": "\u2265\u20d2", - "nvgt;": ">\u20d2", - "nvinfin;": "\u29de", - "nvlArr;": "\u2902", - "nvle;": "\u2264\u20d2", - "nvlt;": "<\u20d2", - "nvltrie;": "\u22b4\u20d2", - "nvrArr;": "\u2903", - "nvrtrie;": "\u22b5\u20d2", - "nvsim;": "\u223c\u20d2", - "nwArr;": "\u21d6", - "nwarhk;": "\u2923", - "nwarr;": "\u2196", - "nwarrow;": "\u2196", - "nwnear;": "\u2927", - "oS;": "\u24c8", - "oacute": "\xf3", - "oacute;": "\xf3", - "oast;": "\u229b", - "ocir;": "\u229a", - "ocirc": "\xf4", - "ocirc;": "\xf4", - "ocy;": "\u043e", - "odash;": "\u229d", - "odblac;": "\u0151", - "odiv;": "\u2a38", - "odot;": "\u2299", - "odsold;": "\u29bc", - "oelig;": "\u0153", - "ofcir;": "\u29bf", - "ofr;": "\u{01d52c}", - "ogon;": "\u02db", - "ograve": "\xf2", - "ograve;": "\xf2", - "ogt;": "\u29c1", - "ohbar;": "\u29b5", - "ohm;": "\u03a9", - "oint;": "\u222e", - "olarr;": "\u21ba", - "olcir;": "\u29be", - "olcross;": "\u29bb", - "oline;": "\u203e", - "olt;": "\u29c0", - "omacr;": "\u014d", - "omega;": "\u03c9", - "omicron;": "\u03bf", - "omid;": "\u29b6", - "ominus;": "\u2296", - "oopf;": "\u{01d560}", - "opar;": "\u29b7", - "operp;": "\u29b9", - "oplus;": "\u2295", - "or;": "\u2228", - "orarr;": "\u21bb", - "ord;": "\u2a5d", - "order;": "\u2134", - "orderof;": "\u2134", - "ordf": "\xaa", - "ordf;": "\xaa", - "ordm": "\xba", - "ordm;": "\xba", - "origof;": "\u22b6", - "oror;": "\u2a56", - "orslope;": "\u2a57", - "orv;": "\u2a5b", - "oscr;": "\u2134", - "oslash": "\xf8", - "oslash;": "\xf8", - "osol;": "\u2298", - "otilde": "\xf5", - "otilde;": "\xf5", - "otimes;": "\u2297", - "otimesas;": "\u2a36", - "ouml": "\xf6", - "ouml;": "\xf6", - "ovbar;": "\u233d", - "par;": "\u2225", - "para": "\xb6", - "para;": "\xb6", - "parallel;": "\u2225", - "parsim;": "\u2af3", - "parsl;": "\u2afd", - "part;": "\u2202", - "pcy;": "\u043f", - "percnt;": "%", - "period;": ".", - "permil;": "\u2030", - "perp;": "\u22a5", - "pertenk;": "\u2031", - "pfr;": "\u{01d52d}", - "phi;": "\u03c6", - "phiv;": "\u03d5", - "phmmat;": "\u2133", - "phone;": "\u260e", - "pi;": "\u03c0", - "pitchfork;": "\u22d4", - "piv;": "\u03d6", - "planck;": "\u210f", - "planckh;": "\u210e", - "plankv;": "\u210f", - "plus;": "+", - "plusacir;": "\u2a23", - "plusb;": "\u229e", - "pluscir;": "\u2a22", - "plusdo;": "\u2214", - "plusdu;": "\u2a25", - "pluse;": "\u2a72", - "plusmn": "\xb1", - "plusmn;": "\xb1", - "plussim;": "\u2a26", - "plustwo;": "\u2a27", - "pm;": "\xb1", - "pointint;": "\u2a15", - "popf;": "\u{01d561}", - "pound": "\xa3", - "pound;": "\xa3", - "pr;": "\u227a", - "prE;": "\u2ab3", - "prap;": "\u2ab7", - "prcue;": "\u227c", - "pre;": "\u2aaf", - "prec;": "\u227a", - "precapprox;": "\u2ab7", - "preccurlyeq;": "\u227c", - "preceq;": "\u2aaf", - "precnapprox;": "\u2ab9", - "precneqq;": "\u2ab5", - "precnsim;": "\u22e8", - "precsim;": "\u227e", - "prime;": "\u2032", - "primes;": "\u2119", - "prnE;": "\u2ab5", - "prnap;": "\u2ab9", - "prnsim;": "\u22e8", - "prod;": "\u220f", - "profalar;": "\u232e", - "profline;": "\u2312", - "profsurf;": "\u2313", - "prop;": "\u221d", - "propto;": "\u221d", - "prsim;": "\u227e", - "prurel;": "\u22b0", - "pscr;": "\u{01d4c5}", - "psi;": "\u03c8", - "puncsp;": "\u2008", - "qfr;": "\u{01d52e}", - "qint;": "\u2a0c", - "qopf;": "\u{01d562}", - "qprime;": "\u2057", - "qscr;": "\u{01d4c6}", - "quaternions;": "\u210d", - "quatint;": "\u2a16", - "quest;": "?", - "questeq;": "\u225f", - "quot": "\"", - "quot;": "\"", - "rAarr;": "\u21db", - "rArr;": "\u21d2", - "rAtail;": "\u291c", - "rBarr;": "\u290f", - "rHar;": "\u2964", - "race;": "\u223d\u0331", - "racute;": "\u0155", - "radic;": "\u221a", - "raemptyv;": "\u29b3", - "rang;": "\u27e9", - "rangd;": "\u2992", - "range;": "\u29a5", - "rangle;": "\u27e9", - "raquo": "\xbb", - "raquo;": "\xbb", - "rarr;": "\u2192", - "rarrap;": "\u2975", - "rarrb;": "\u21e5", - "rarrbfs;": "\u2920", - "rarrc;": "\u2933", - "rarrfs;": "\u291e", - "rarrhk;": "\u21aa", - "rarrlp;": "\u21ac", - "rarrpl;": "\u2945", - "rarrsim;": "\u2974", - "rarrtl;": "\u21a3", - "rarrw;": "\u219d", - "ratail;": "\u291a", - "ratio;": "\u2236", - "rationals;": "\u211a", - "rbarr;": "\u290d", - "rbbrk;": "\u2773", - "rbrace;": "}", - "rbrack;": "]", - "rbrke;": "\u298c", - "rbrksld;": "\u298e", - "rbrkslu;": "\u2990", - "rcaron;": "\u0159", - "rcedil;": "\u0157", - "rceil;": "\u2309", - "rcub;": "}", - "rcy;": "\u0440", - "rdca;": "\u2937", - "rdldhar;": "\u2969", - "rdquo;": "\u201d", - "rdquor;": "\u201d", - "rdsh;": "\u21b3", - "real;": "\u211c", - "realine;": "\u211b", - "realpart;": "\u211c", - "reals;": "\u211d", - "rect;": "\u25ad", - "reg": "\xae", - "reg;": "\xae", - "rfisht;": "\u297d", - "rfloor;": "\u230b", - "rfr;": "\u{01d52f}", - "rhard;": "\u21c1", - "rharu;": "\u21c0", - "rharul;": "\u296c", - "rho;": "\u03c1", - "rhov;": "\u03f1", - "rightarrow;": "\u2192", - "rightarrowtail;": "\u21a3", - "rightharpoondown;": "\u21c1", - "rightharpoonup;": "\u21c0", - "rightleftarrows;": "\u21c4", - "rightleftharpoons;": "\u21cc", - "rightrightarrows;": "\u21c9", - "rightsquigarrow;": "\u219d", - "rightthreetimes;": "\u22cc", - "ring;": "\u02da", - "risingdotseq;": "\u2253", - "rlarr;": "\u21c4", - "rlhar;": "\u21cc", - "rlm;": "\u200f", - "rmoust;": "\u23b1", - "rmoustache;": "\u23b1", - "rnmid;": "\u2aee", - "roang;": "\u27ed", - "roarr;": "\u21fe", - "robrk;": "\u27e7", - "ropar;": "\u2986", - "ropf;": "\u{01d563}", - "roplus;": "\u2a2e", - "rotimes;": "\u2a35", - "rpar;": ")", - "rpargt;": "\u2994", - "rppolint;": "\u2a12", - "rrarr;": "\u21c9", - "rsaquo;": "\u203a", - "rscr;": "\u{01d4c7}", - "rsh;": "\u21b1", - "rsqb;": "]", - "rsquo;": "\u2019", - "rsquor;": "\u2019", - "rthree;": "\u22cc", - "rtimes;": "\u22ca", - "rtri;": "\u25b9", - "rtrie;": "\u22b5", - "rtrif;": "\u25b8", - "rtriltri;": "\u29ce", - "ruluhar;": "\u2968", - "rx;": "\u211e", - "sacute;": "\u015b", - "sbquo;": "\u201a", - "sc;": "\u227b", - "scE;": "\u2ab4", - "scap;": "\u2ab8", - "scaron;": "\u0161", - "sccue;": "\u227d", - "sce;": "\u2ab0", - "scedil;": "\u015f", - "scirc;": "\u015d", - "scnE;": "\u2ab6", - "scnap;": "\u2aba", - "scnsim;": "\u22e9", - "scpolint;": "\u2a13", - "scsim;": "\u227f", - "scy;": "\u0441", - "sdot;": "\u22c5", - "sdotb;": "\u22a1", - "sdote;": "\u2a66", - "seArr;": "\u21d8", - "searhk;": "\u2925", - "searr;": "\u2198", - "searrow;": "\u2198", - "sect": "\xa7", - "sect;": "\xa7", - "semi;": ";", - "seswar;": "\u2929", - "setminus;": "\u2216", - "setmn;": "\u2216", - "sext;": "\u2736", - "sfr;": "\u{01d530}", - "sfrown;": "\u2322", - "sharp;": "\u266f", - "shchcy;": "\u0449", - "shcy;": "\u0448", - "shortmid;": "\u2223", - "shortparallel;": "\u2225", - "shy": "\xad", - "shy;": "\xad", - "sigma;": "\u03c3", - "sigmaf;": "\u03c2", - "sigmav;": "\u03c2", - "sim;": "\u223c", - "simdot;": "\u2a6a", - "sime;": "\u2243", - "simeq;": "\u2243", - "simg;": "\u2a9e", - "simgE;": "\u2aa0", - "siml;": "\u2a9d", - "simlE;": "\u2a9f", - "simne;": "\u2246", - "simplus;": "\u2a24", - "simrarr;": "\u2972", - "slarr;": "\u2190", - "smallsetminus;": "\u2216", - "smashp;": "\u2a33", - "smeparsl;": "\u29e4", - "smid;": "\u2223", - "smile;": "\u2323", - "smt;": "\u2aaa", - "smte;": "\u2aac", - "smtes;": "\u2aac\ufe00", - "softcy;": "\u044c", - "sol;": "/", - "solb;": "\u29c4", - "solbar;": "\u233f", - "sopf;": "\u{01d564}", - "spades;": "\u2660", - "spadesuit;": "\u2660", - "spar;": "\u2225", - "sqcap;": "\u2293", - "sqcaps;": "\u2293\ufe00", - "sqcup;": "\u2294", - "sqcups;": "\u2294\ufe00", - "sqsub;": "\u228f", - "sqsube;": "\u2291", - "sqsubset;": "\u228f", - "sqsubseteq;": "\u2291", - "sqsup;": "\u2290", - "sqsupe;": "\u2292", - "sqsupset;": "\u2290", - "sqsupseteq;": "\u2292", - "squ;": "\u25a1", - "square;": "\u25a1", - "squarf;": "\u25aa", - "squf;": "\u25aa", - "srarr;": "\u2192", - "sscr;": "\u{01d4c8}", - "ssetmn;": "\u2216", - "ssmile;": "\u2323", - "sstarf;": "\u22c6", - "star;": "\u2606", - "starf;": "\u2605", - "straightepsilon;": "\u03f5", - "straightphi;": "\u03d5", - "strns;": "\xaf", - "sub;": "\u2282", - "subE;": "\u2ac5", - "subdot;": "\u2abd", - "sube;": "\u2286", - "subedot;": "\u2ac3", - "submult;": "\u2ac1", - "subnE;": "\u2acb", - "subne;": "\u228a", - "subplus;": "\u2abf", - "subrarr;": "\u2979", - "subset;": "\u2282", - "subseteq;": "\u2286", - "subseteqq;": "\u2ac5", - "subsetneq;": "\u228a", - "subsetneqq;": "\u2acb", - "subsim;": "\u2ac7", - "subsub;": "\u2ad5", - "subsup;": "\u2ad3", - "succ;": "\u227b", - "succapprox;": "\u2ab8", - "succcurlyeq;": "\u227d", - "succeq;": "\u2ab0", - "succnapprox;": "\u2aba", - "succneqq;": "\u2ab6", - "succnsim;": "\u22e9", - "succsim;": "\u227f", - "sum;": "\u2211", - "sung;": "\u266a", - "sup1": "\xb9", - "sup1;": "\xb9", - "sup2": "\xb2", - "sup2;": "\xb2", - "sup3": "\xb3", - "sup3;": "\xb3", - "sup;": "\u2283", - "supE;": "\u2ac6", - "supdot;": "\u2abe", - "supdsub;": "\u2ad8", - "supe;": "\u2287", - "supedot;": "\u2ac4", - "suphsol;": "\u27c9", - "suphsub;": "\u2ad7", - "suplarr;": "\u297b", - "supmult;": "\u2ac2", - "supnE;": "\u2acc", - "supne;": "\u228b", - "supplus;": "\u2ac0", - "supset;": "\u2283", - "supseteq;": "\u2287", - "supseteqq;": "\u2ac6", - "supsetneq;": "\u228b", - "supsetneqq;": "\u2acc", - "supsim;": "\u2ac8", - "supsub;": "\u2ad4", - "supsup;": "\u2ad6", - "swArr;": "\u21d9", - "swarhk;": "\u2926", - "swarr;": "\u2199", - "swarrow;": "\u2199", - "swnwar;": "\u292a", - "szlig": "\xdf", - "szlig;": "\xdf", - "target;": "\u2316", - "tau;": "\u03c4", - "tbrk;": "\u23b4", - "tcaron;": "\u0165", - "tcedil;": "\u0163", - "tcy;": "\u0442", - "tdot;": "\u20db", - "telrec;": "\u2315", - "tfr;": "\u{01d531}", - "there4;": "\u2234", - "therefore;": "\u2234", - "theta;": "\u03b8", - "thetasym;": "\u03d1", - "thetav;": "\u03d1", - "thickapprox;": "\u2248", - "thicksim;": "\u223c", - "thinsp;": "\u2009", - "thkap;": "\u2248", - "thksim;": "\u223c", - "thorn": "\xfe", - "thorn;": "\xfe", - "tilde;": "\u02dc", - "times": "\xd7", - "times;": "\xd7", - "timesb;": "\u22a0", - "timesbar;": "\u2a31", - "timesd;": "\u2a30", - "tint;": "\u222d", - "toea;": "\u2928", - "top;": "\u22a4", - "topbot;": "\u2336", - "topcir;": "\u2af1", - "topf;": "\u{01d565}", - "topfork;": "\u2ada", - "tosa;": "\u2929", - "tprime;": "\u2034", - "trade;": "\u2122", - "triangle;": "\u25b5", - "triangledown;": "\u25bf", - "triangleleft;": "\u25c3", - "trianglelefteq;": "\u22b4", - "triangleq;": "\u225c", - "triangleright;": "\u25b9", - "trianglerighteq;": "\u22b5", - "tridot;": "\u25ec", - "trie;": "\u225c", - "triminus;": "\u2a3a", - "triplus;": "\u2a39", - "trisb;": "\u29cd", - "tritime;": "\u2a3b", - "trpezium;": "\u23e2", - "tscr;": "\u{01d4c9}", - "tscy;": "\u0446", - "tshcy;": "\u045b", - "tstrok;": "\u0167", - "twixt;": "\u226c", - "twoheadleftarrow;": "\u219e", - "twoheadrightarrow;": "\u21a0", - "uArr;": "\u21d1", - "uHar;": "\u2963", - "uacute": "\xfa", - "uacute;": "\xfa", - "uarr;": "\u2191", - "ubrcy;": "\u045e", - "ubreve;": "\u016d", - "ucirc": "\xfb", - "ucirc;": "\xfb", - "ucy;": "\u0443", - "udarr;": "\u21c5", - "udblac;": "\u0171", - "udhar;": "\u296e", - "ufisht;": "\u297e", - "ufr;": "\u{01d532}", - "ugrave": "\xf9", - "ugrave;": "\xf9", - "uharl;": "\u21bf", - "uharr;": "\u21be", - "uhblk;": "\u2580", - "ulcorn;": "\u231c", - "ulcorner;": "\u231c", - "ulcrop;": "\u230f", - "ultri;": "\u25f8", - "umacr;": "\u016b", - "uml": "\xa8", - "uml;": "\xa8", - "uogon;": "\u0173", - "uopf;": "\u{01d566}", - "uparrow;": "\u2191", - "updownarrow;": "\u2195", - "upharpoonleft;": "\u21bf", - "upharpoonright;": "\u21be", - "uplus;": "\u228e", - "upsi;": "\u03c5", - "upsih;": "\u03d2", - "upsilon;": "\u03c5", - "upuparrows;": "\u21c8", - "urcorn;": "\u231d", - "urcorner;": "\u231d", - "urcrop;": "\u230e", - "uring;": "\u016f", - "urtri;": "\u25f9", - "uscr;": "\u{01d4ca}", - "utdot;": "\u22f0", - "utilde;": "\u0169", - "utri;": "\u25b5", - "utrif;": "\u25b4", - "uuarr;": "\u21c8", - "uuml": "\xfc", - "uuml;": "\xfc", - "uwangle;": "\u29a7", - "vArr;": "\u21d5", - "vBar;": "\u2ae8", - "vBarv;": "\u2ae9", - "vDash;": "\u22a8", - "vangrt;": "\u299c", - "varepsilon;": "\u03f5", - "varkappa;": "\u03f0", - "varnothing;": "\u2205", - "varphi;": "\u03d5", - "varpi;": "\u03d6", - "varpropto;": "\u221d", - "varr;": "\u2195", - "varrho;": "\u03f1", - "varsigma;": "\u03c2", - "varsubsetneq;": "\u228a\ufe00", - "varsubsetneqq;": "\u2acb\ufe00", - "varsupsetneq;": "\u228b\ufe00", - "varsupsetneqq;": "\u2acc\ufe00", - "vartheta;": "\u03d1", - "vartriangleleft;": "\u22b2", - "vartriangleright;": "\u22b3", - "vcy;": "\u0432", - "vdash;": "\u22a2", - "vee;": "\u2228", - "veebar;": "\u22bb", - "veeeq;": "\u225a", - "vellip;": "\u22ee", - "verbar;": "|", - "vert;": "|", - "vfr;": "\u{01d533}", - "vltri;": "\u22b2", - "vnsub;": "\u2282\u20d2", - "vnsup;": "\u2283\u20d2", - "vopf;": "\u{01d567}", - "vprop;": "\u221d", - "vrtri;": "\u22b3", - "vscr;": "\u{01d4cb}", - "vsubnE;": "\u2acb\ufe00", - "vsubne;": "\u228a\ufe00", - "vsupnE;": "\u2acc\ufe00", - "vsupne;": "\u228b\ufe00", - "vzigzag;": "\u299a", - "wcirc;": "\u0175", - "wedbar;": "\u2a5f", - "wedge;": "\u2227", - "wedgeq;": "\u2259", - "weierp;": "\u2118", - "wfr;": "\u{01d534}", - "wopf;": "\u{01d568}", - "wp;": "\u2118", - "wr;": "\u2240", - "wreath;": "\u2240", - "wscr;": "\u{01d4cc}", - "xcap;": "\u22c2", - "xcirc;": "\u25ef", - "xcup;": "\u22c3", - "xdtri;": "\u25bd", - "xfr;": "\u{01d535}", - "xhArr;": "\u27fa", - "xharr;": "\u27f7", - "xi;": "\u03be", - "xlArr;": "\u27f8", - "xlarr;": "\u27f5", - "xmap;": "\u27fc", - "xnis;": "\u22fb", - "xodot;": "\u2a00", - "xopf;": "\u{01d569}", - "xoplus;": "\u2a01", - "xotime;": "\u2a02", - "xrArr;": "\u27f9", - "xrarr;": "\u27f6", - "xscr;": "\u{01d4cd}", - "xsqcup;": "\u2a06", - "xuplus;": "\u2a04", - "xutri;": "\u25b3", - "xvee;": "\u22c1", - "xwedge;": "\u22c0", - "yacute": "\xfd", - "yacute;": "\xfd", - "yacy;": "\u044f", - "ycirc;": "\u0177", - "ycy;": "\u044b", - "yen": "\xa5", - "yen;": "\xa5", - "yfr;": "\u{01d536}", - "yicy;": "\u0457", - "yopf;": "\u{01d56a}", - "yscr;": "\u{01d4ce}", - "yucy;": "\u044e", - "yuml": "\xff", - "yuml;": "\xff", - "zacute;": "\u017a", - "zcaron;": "\u017e", - "zcy;": "\u0437", - "zdot;": "\u017c", - "zeetrf;": "\u2128", - "zeta;": "\u03b6", - "zfr;": "\u{01d537}", - "zhcy;": "\u0436", - "zigrarr;": "\u21dd", - "zopf;": "\u{01d56b}", - "zscr;": "\u{01d4cf}", - "zwj;": "\u200d", - "zwnj;": "\u200c", + 'AElig': '\xc6', + 'AElig;': '\xc6', + 'AMP': '&', + 'AMP;': '&', + 'Aacute': '\xc1', + 'Aacute;': '\xc1', + 'Abreve;': '\u0102', + 'Acirc': '\xc2', + 'Acirc;': '\xc2', + 'Acy;': '\u0410', + 'Afr;': '\u{01d504}', + 'Agrave': '\xc0', + 'Agrave;': '\xc0', + 'Alpha;': '\u0391', + 'Amacr;': '\u0100', + 'And;': '\u2a53', + 'Aogon;': '\u0104', + 'Aopf;': '\u{01d538}', + 'ApplyFunction;': '\u2061', + 'Aring': '\xc5', + 'Aring;': '\xc5', + 'Ascr;': '\u{01d49c}', + 'Assign;': '\u2254', + 'Atilde': '\xc3', + 'Atilde;': '\xc3', + 'Auml': '\xc4', + 'Auml;': '\xc4', + 'Backslash;': '\u2216', + 'Barv;': '\u2ae7', + 'Barwed;': '\u2306', + 'Bcy;': '\u0411', + 'Because;': '\u2235', + 'Bernoullis;': '\u212c', + 'Beta;': '\u0392', + 'Bfr;': '\u{01d505}', + 'Bopf;': '\u{01d539}', + 'Breve;': '\u02d8', + 'Bscr;': '\u212c', + 'Bumpeq;': '\u224e', + 'CHcy;': '\u0427', + 'COPY': '\xa9', + 'COPY;': '\xa9', + 'Cacute;': '\u0106', + 'Cap;': '\u22d2', + 'CapitalDifferentialD;': '\u2145', + 'Cayleys;': '\u212d', + 'Ccaron;': '\u010c', + 'Ccedil': '\xc7', + 'Ccedil;': '\xc7', + 'Ccirc;': '\u0108', + 'Cconint;': '\u2230', + 'Cdot;': '\u010a', + 'Cedilla;': '\xb8', + 'CenterDot;': '\xb7', + 'Cfr;': '\u212d', + 'Chi;': '\u03a7', + 'CircleDot;': '\u2299', + 'CircleMinus;': '\u2296', + 'CirclePlus;': '\u2295', + 'CircleTimes;': '\u2297', + 'ClockwiseContourIntegral;': '\u2232', + 'CloseCurlyDoubleQuote;': '\u201d', + 'CloseCurlyQuote;': '\u2019', + 'Colon;': '\u2237', + 'Colone;': '\u2a74', + 'Congruent;': '\u2261', + 'Conint;': '\u222f', + 'ContourIntegral;': '\u222e', + 'Copf;': '\u2102', + 'Coproduct;': '\u2210', + 'CounterClockwiseContourIntegral;': '\u2233', + 'Cross;': '\u2a2f', + 'Cscr;': '\u{01d49e}', + 'Cup;': '\u22d3', + 'CupCap;': '\u224d', + 'DD;': '\u2145', + 'DDotrahd;': '\u2911', + 'DJcy;': '\u0402', + 'DScy;': '\u0405', + 'DZcy;': '\u040f', + 'Dagger;': '\u2021', + 'Darr;': '\u21a1', + 'Dashv;': '\u2ae4', + 'Dcaron;': '\u010e', + 'Dcy;': '\u0414', + 'Del;': '\u2207', + 'Delta;': '\u0394', + 'Dfr;': '\u{01d507}', + 'DiacriticalAcute;': '\xb4', + 'DiacriticalDot;': '\u02d9', + 'DiacriticalDoubleAcute;': '\u02dd', + 'DiacriticalGrave;': '`', + 'DiacriticalTilde;': '\u02dc', + 'Diamond;': '\u22c4', + 'DifferentialD;': '\u2146', + 'Dopf;': '\u{01d53b}', + 'Dot;': '\xa8', + 'DotDot;': '\u20dc', + 'DotEqual;': '\u2250', + 'DoubleContourIntegral;': '\u222f', + 'DoubleDot;': '\xa8', + 'DoubleDownArrow;': '\u21d3', + 'DoubleLeftArrow;': '\u21d0', + 'DoubleLeftRightArrow;': '\u21d4', + 'DoubleLeftTee;': '\u2ae4', + 'DoubleLongLeftArrow;': '\u27f8', + 'DoubleLongLeftRightArrow;': '\u27fa', + 'DoubleLongRightArrow;': '\u27f9', + 'DoubleRightArrow;': '\u21d2', + 'DoubleRightTee;': '\u22a8', + 'DoubleUpArrow;': '\u21d1', + 'DoubleUpDownArrow;': '\u21d5', + 'DoubleVerticalBar;': '\u2225', + 'DownArrow;': '\u2193', + 'DownArrowBar;': '\u2913', + 'DownArrowUpArrow;': '\u21f5', + 'DownBreve;': '\u0311', + 'DownLeftRightVector;': '\u2950', + 'DownLeftTeeVector;': '\u295e', + 'DownLeftVector;': '\u21bd', + 'DownLeftVectorBar;': '\u2956', + 'DownRightTeeVector;': '\u295f', + 'DownRightVector;': '\u21c1', + 'DownRightVectorBar;': '\u2957', + 'DownTee;': '\u22a4', + 'DownTeeArrow;': '\u21a7', + 'Downarrow;': '\u21d3', + 'Dscr;': '\u{01d49f}', + 'Dstrok;': '\u0110', + 'ENG;': '\u014a', + 'ETH': '\xd0', + 'ETH;': '\xd0', + 'Eacute': '\xc9', + 'Eacute;': '\xc9', + 'Ecaron;': '\u011a', + 'Ecirc': '\xca', + 'Ecirc;': '\xca', + 'Ecy;': '\u042d', + 'Edot;': '\u0116', + 'Efr;': '\u{01d508}', + 'Egrave': '\xc8', + 'Egrave;': '\xc8', + 'Element;': '\u2208', + 'Emacr;': '\u0112', + 'EmptySmallSquare;': '\u25fb', + 'EmptyVerySmallSquare;': '\u25ab', + 'Eogon;': '\u0118', + 'Eopf;': '\u{01d53c}', + 'Epsilon;': '\u0395', + 'Equal;': '\u2a75', + 'EqualTilde;': '\u2242', + 'Equilibrium;': '\u21cc', + 'Escr;': '\u2130', + 'Esim;': '\u2a73', + 'Eta;': '\u0397', + 'Euml': '\xcb', + 'Euml;': '\xcb', + 'Exists;': '\u2203', + 'ExponentialE;': '\u2147', + 'Fcy;': '\u0424', + 'Ffr;': '\u{01d509}', + 'FilledSmallSquare;': '\u25fc', + 'FilledVerySmallSquare;': '\u25aa', + 'Fopf;': '\u{01d53d}', + 'ForAll;': '\u2200', + 'Fouriertrf;': '\u2131', + 'Fscr;': '\u2131', + 'GJcy;': '\u0403', + 'GT': '>', + 'GT;': '>', + 'Gamma;': '\u0393', + 'Gammad;': '\u03dc', + 'Gbreve;': '\u011e', + 'Gcedil;': '\u0122', + 'Gcirc;': '\u011c', + 'Gcy;': '\u0413', + 'Gdot;': '\u0120', + 'Gfr;': '\u{01d50a}', + 'Gg;': '\u22d9', + 'Gopf;': '\u{01d53e}', + 'GreaterEqual;': '\u2265', + 'GreaterEqualLess;': '\u22db', + 'GreaterFullEqual;': '\u2267', + 'GreaterGreater;': '\u2aa2', + 'GreaterLess;': '\u2277', + 'GreaterSlantEqual;': '\u2a7e', + 'GreaterTilde;': '\u2273', + 'Gscr;': '\u{01d4a2}', + 'Gt;': '\u226b', + 'HARDcy;': '\u042a', + 'Hacek;': '\u02c7', + 'Hat;': '^', + 'Hcirc;': '\u0124', + 'Hfr;': '\u210c', + 'HilbertSpace;': '\u210b', + 'Hopf;': '\u210d', + 'HorizontalLine;': '\u2500', + 'Hscr;': '\u210b', + 'Hstrok;': '\u0126', + 'HumpDownHump;': '\u224e', + 'HumpEqual;': '\u224f', + 'IEcy;': '\u0415', + 'IJlig;': '\u0132', + 'IOcy;': '\u0401', + 'Iacute': '\xcd', + 'Iacute;': '\xcd', + 'Icirc': '\xce', + 'Icirc;': '\xce', + 'Icy;': '\u0418', + 'Idot;': '\u0130', + 'Ifr;': '\u2111', + 'Igrave': '\xcc', + 'Igrave;': '\xcc', + 'Im;': '\u2111', + 'Imacr;': '\u012a', + 'ImaginaryI;': '\u2148', + 'Implies;': '\u21d2', + 'Int;': '\u222c', + 'Integral;': '\u222b', + 'Intersection;': '\u22c2', + 'InvisibleComma;': '\u2063', + 'InvisibleTimes;': '\u2062', + 'Iogon;': '\u012e', + 'Iopf;': '\u{01d540}', + 'Iota;': '\u0399', + 'Iscr;': '\u2110', + 'Itilde;': '\u0128', + 'Iukcy;': '\u0406', + 'Iuml': '\xcf', + 'Iuml;': '\xcf', + 'Jcirc;': '\u0134', + 'Jcy;': '\u0419', + 'Jfr;': '\u{01d50d}', + 'Jopf;': '\u{01d541}', + 'Jscr;': '\u{01d4a5}', + 'Jsercy;': '\u0408', + 'Jukcy;': '\u0404', + 'KHcy;': '\u0425', + 'KJcy;': '\u040c', + 'Kappa;': '\u039a', + 'Kcedil;': '\u0136', + 'Kcy;': '\u041a', + 'Kfr;': '\u{01d50e}', + 'Kopf;': '\u{01d542}', + 'Kscr;': '\u{01d4a6}', + 'LJcy;': '\u0409', + 'LT': '<', + 'LT;': '<', + 'Lacute;': '\u0139', + 'Lambda;': '\u039b', + 'Lang;': '\u27ea', + 'Laplacetrf;': '\u2112', + 'Larr;': '\u219e', + 'Lcaron;': '\u013d', + 'Lcedil;': '\u013b', + 'Lcy;': '\u041b', + 'LeftAngleBracket;': '\u27e8', + 'LeftArrow;': '\u2190', + 'LeftArrowBar;': '\u21e4', + 'LeftArrowRightArrow;': '\u21c6', + 'LeftCeiling;': '\u2308', + 'LeftDoubleBracket;': '\u27e6', + 'LeftDownTeeVector;': '\u2961', + 'LeftDownVector;': '\u21c3', + 'LeftDownVectorBar;': '\u2959', + 'LeftFloor;': '\u230a', + 'LeftRightArrow;': '\u2194', + 'LeftRightVector;': '\u294e', + 'LeftTee;': '\u22a3', + 'LeftTeeArrow;': '\u21a4', + 'LeftTeeVector;': '\u295a', + 'LeftTriangle;': '\u22b2', + 'LeftTriangleBar;': '\u29cf', + 'LeftTriangleEqual;': '\u22b4', + 'LeftUpDownVector;': '\u2951', + 'LeftUpTeeVector;': '\u2960', + 'LeftUpVector;': '\u21bf', + 'LeftUpVectorBar;': '\u2958', + 'LeftVector;': '\u21bc', + 'LeftVectorBar;': '\u2952', + 'Leftarrow;': '\u21d0', + 'Leftrightarrow;': '\u21d4', + 'LessEqualGreater;': '\u22da', + 'LessFullEqual;': '\u2266', + 'LessGreater;': '\u2276', + 'LessLess;': '\u2aa1', + 'LessSlantEqual;': '\u2a7d', + 'LessTilde;': '\u2272', + 'Lfr;': '\u{01d50f}', + 'Ll;': '\u22d8', + 'Lleftarrow;': '\u21da', + 'Lmidot;': '\u013f', + 'LongLeftArrow;': '\u27f5', + 'LongLeftRightArrow;': '\u27f7', + 'LongRightArrow;': '\u27f6', + 'Longleftarrow;': '\u27f8', + 'Longleftrightarrow;': '\u27fa', + 'Longrightarrow;': '\u27f9', + 'Lopf;': '\u{01d543}', + 'LowerLeftArrow;': '\u2199', + 'LowerRightArrow;': '\u2198', + 'Lscr;': '\u2112', + 'Lsh;': '\u21b0', + 'Lstrok;': '\u0141', + 'Lt;': '\u226a', + 'Map;': '\u2905', + 'Mcy;': '\u041c', + 'MediumSpace;': '\u205f', + 'Mellintrf;': '\u2133', + 'Mfr;': '\u{01d510}', + 'MinusPlus;': '\u2213', + 'Mopf;': '\u{01d544}', + 'Mscr;': '\u2133', + 'Mu;': '\u039c', + 'NJcy;': '\u040a', + 'Nacute;': '\u0143', + 'Ncaron;': '\u0147', + 'Ncedil;': '\u0145', + 'Ncy;': '\u041d', + 'NegativeMediumSpace;': '\u200b', + 'NegativeThickSpace;': '\u200b', + 'NegativeThinSpace;': '\u200b', + 'NegativeVeryThinSpace;': '\u200b', + 'NestedGreaterGreater;': '\u226b', + 'NestedLessLess;': '\u226a', + 'NewLine;': '\n', + 'Nfr;': '\u{01d511}', + 'NoBreak;': '\u2060', + 'NonBreakingSpace;': '\xa0', + 'Nopf;': '\u2115', + 'Not;': '\u2aec', + 'NotCongruent;': '\u2262', + 'NotCupCap;': '\u226d', + 'NotDoubleVerticalBar;': '\u2226', + 'NotElement;': '\u2209', + 'NotEqual;': '\u2260', + 'NotEqualTilde;': '\u2242\u0338', + 'NotExists;': '\u2204', + 'NotGreater;': '\u226f', + 'NotGreaterEqual;': '\u2271', + 'NotGreaterFullEqual;': '\u2267\u0338', + 'NotGreaterGreater;': '\u226b\u0338', + 'NotGreaterLess;': '\u2279', + 'NotGreaterSlantEqual;': '\u2a7e\u0338', + 'NotGreaterTilde;': '\u2275', + 'NotHumpDownHump;': '\u224e\u0338', + 'NotHumpEqual;': '\u224f\u0338', + 'NotLeftTriangle;': '\u22ea', + 'NotLeftTriangleBar;': '\u29cf\u0338', + 'NotLeftTriangleEqual;': '\u22ec', + 'NotLess;': '\u226e', + 'NotLessEqual;': '\u2270', + 'NotLessGreater;': '\u2278', + 'NotLessLess;': '\u226a\u0338', + 'NotLessSlantEqual;': '\u2a7d\u0338', + 'NotLessTilde;': '\u2274', + 'NotNestedGreaterGreater;': '\u2aa2\u0338', + 'NotNestedLessLess;': '\u2aa1\u0338', + 'NotPrecedes;': '\u2280', + 'NotPrecedesEqual;': '\u2aaf\u0338', + 'NotPrecedesSlantEqual;': '\u22e0', + 'NotReverseElement;': '\u220c', + 'NotRightTriangle;': '\u22eb', + 'NotRightTriangleBar;': '\u29d0\u0338', + 'NotRightTriangleEqual;': '\u22ed', + 'NotSquareSubset;': '\u228f\u0338', + 'NotSquareSubsetEqual;': '\u22e2', + 'NotSquareSuperset;': '\u2290\u0338', + 'NotSquareSupersetEqual;': '\u22e3', + 'NotSubset;': '\u2282\u20d2', + 'NotSubsetEqual;': '\u2288', + 'NotSucceeds;': '\u2281', + 'NotSucceedsEqual;': '\u2ab0\u0338', + 'NotSucceedsSlantEqual;': '\u22e1', + 'NotSucceedsTilde;': '\u227f\u0338', + 'NotSuperset;': '\u2283\u20d2', + 'NotSupersetEqual;': '\u2289', + 'NotTilde;': '\u2241', + 'NotTildeEqual;': '\u2244', + 'NotTildeFullEqual;': '\u2247', + 'NotTildeTilde;': '\u2249', + 'NotVerticalBar;': '\u2224', + 'Nscr;': '\u{01d4a9}', + 'Ntilde': '\xd1', + 'Ntilde;': '\xd1', + 'Nu;': '\u039d', + 'OElig;': '\u0152', + 'Oacute': '\xd3', + 'Oacute;': '\xd3', + 'Ocirc': '\xd4', + 'Ocirc;': '\xd4', + 'Ocy;': '\u041e', + 'Odblac;': '\u0150', + 'Ofr;': '\u{01d512}', + 'Ograve': '\xd2', + 'Ograve;': '\xd2', + 'Omacr;': '\u014c', + 'Omega;': '\u03a9', + 'Omicron;': '\u039f', + 'Oopf;': '\u{01d546}', + 'OpenCurlyDoubleQuote;': '\u201c', + 'OpenCurlyQuote;': '\u2018', + 'Or;': '\u2a54', + 'Oscr;': '\u{01d4aa}', + 'Oslash': '\xd8', + 'Oslash;': '\xd8', + 'Otilde': '\xd5', + 'Otilde;': '\xd5', + 'Otimes;': '\u2a37', + 'Ouml': '\xd6', + 'Ouml;': '\xd6', + 'OverBar;': '\u203e', + 'OverBrace;': '\u23de', + 'OverBracket;': '\u23b4', + 'OverParenthesis;': '\u23dc', + 'PartialD;': '\u2202', + 'Pcy;': '\u041f', + 'Pfr;': '\u{01d513}', + 'Phi;': '\u03a6', + 'Pi;': '\u03a0', + 'PlusMinus;': '\xb1', + 'Poincareplane;': '\u210c', + 'Popf;': '\u2119', + 'Pr;': '\u2abb', + 'Precedes;': '\u227a', + 'PrecedesEqual;': '\u2aaf', + 'PrecedesSlantEqual;': '\u227c', + 'PrecedesTilde;': '\u227e', + 'Prime;': '\u2033', + 'Product;': '\u220f', + 'Proportion;': '\u2237', + 'Proportional;': '\u221d', + 'Pscr;': '\u{01d4ab}', + 'Psi;': '\u03a8', + 'QUOT': '"', + 'QUOT;': '"', + 'Qfr;': '\u{01d514}', + 'Qopf;': '\u211a', + 'Qscr;': '\u{01d4ac}', + 'RBarr;': '\u2910', + 'REG': '\xae', + 'REG;': '\xae', + 'Racute;': '\u0154', + 'Rang;': '\u27eb', + 'Rarr;': '\u21a0', + 'Rarrtl;': '\u2916', + 'Rcaron;': '\u0158', + 'Rcedil;': '\u0156', + 'Rcy;': '\u0420', + 'Re;': '\u211c', + 'ReverseElement;': '\u220b', + 'ReverseEquilibrium;': '\u21cb', + 'ReverseUpEquilibrium;': '\u296f', + 'Rfr;': '\u211c', + 'Rho;': '\u03a1', + 'RightAngleBracket;': '\u27e9', + 'RightArrow;': '\u2192', + 'RightArrowBar;': '\u21e5', + 'RightArrowLeftArrow;': '\u21c4', + 'RightCeiling;': '\u2309', + 'RightDoubleBracket;': '\u27e7', + 'RightDownTeeVector;': '\u295d', + 'RightDownVector;': '\u21c2', + 'RightDownVectorBar;': '\u2955', + 'RightFloor;': '\u230b', + 'RightTee;': '\u22a2', + 'RightTeeArrow;': '\u21a6', + 'RightTeeVector;': '\u295b', + 'RightTriangle;': '\u22b3', + 'RightTriangleBar;': '\u29d0', + 'RightTriangleEqual;': '\u22b5', + 'RightUpDownVector;': '\u294f', + 'RightUpTeeVector;': '\u295c', + 'RightUpVector;': '\u21be', + 'RightUpVectorBar;': '\u2954', + 'RightVector;': '\u21c0', + 'RightVectorBar;': '\u2953', + 'Rightarrow;': '\u21d2', + 'Ropf;': '\u211d', + 'RoundImplies;': '\u2970', + 'Rrightarrow;': '\u21db', + 'Rscr;': '\u211b', + 'Rsh;': '\u21b1', + 'RuleDelayed;': '\u29f4', + 'SHCHcy;': '\u0429', + 'SHcy;': '\u0428', + 'SOFTcy;': '\u042c', + 'Sacute;': '\u015a', + 'Sc;': '\u2abc', + 'Scaron;': '\u0160', + 'Scedil;': '\u015e', + 'Scirc;': '\u015c', + 'Scy;': '\u0421', + 'Sfr;': '\u{01d516}', + 'ShortDownArrow;': '\u2193', + 'ShortLeftArrow;': '\u2190', + 'ShortRightArrow;': '\u2192', + 'ShortUpArrow;': '\u2191', + 'Sigma;': '\u03a3', + 'SmallCircle;': '\u2218', + 'Sopf;': '\u{01d54a}', + 'Sqrt;': '\u221a', + 'Square;': '\u25a1', + 'SquareIntersection;': '\u2293', + 'SquareSubset;': '\u228f', + 'SquareSubsetEqual;': '\u2291', + 'SquareSuperset;': '\u2290', + 'SquareSupersetEqual;': '\u2292', + 'SquareUnion;': '\u2294', + 'Sscr;': '\u{01d4ae}', + 'Star;': '\u22c6', + 'Sub;': '\u22d0', + 'Subset;': '\u22d0', + 'SubsetEqual;': '\u2286', + 'Succeeds;': '\u227b', + 'SucceedsEqual;': '\u2ab0', + 'SucceedsSlantEqual;': '\u227d', + 'SucceedsTilde;': '\u227f', + 'SuchThat;': '\u220b', + 'Sum;': '\u2211', + 'Sup;': '\u22d1', + 'Superset;': '\u2283', + 'SupersetEqual;': '\u2287', + 'Supset;': '\u22d1', + 'THORN': '\xde', + 'THORN;': '\xde', + 'TRADE;': '\u2122', + 'TSHcy;': '\u040b', + 'TScy;': '\u0426', + 'Tab;': '\t', + 'Tau;': '\u03a4', + 'Tcaron;': '\u0164', + 'Tcedil;': '\u0162', + 'Tcy;': '\u0422', + 'Tfr;': '\u{01d517}', + 'Therefore;': '\u2234', + 'Theta;': '\u0398', + 'ThickSpace;': '\u205f\u200a', + 'ThinSpace;': '\u2009', + 'Tilde;': '\u223c', + 'TildeEqual;': '\u2243', + 'TildeFullEqual;': '\u2245', + 'TildeTilde;': '\u2248', + 'Topf;': '\u{01d54b}', + 'TripleDot;': '\u20db', + 'Tscr;': '\u{01d4af}', + 'Tstrok;': '\u0166', + 'Uacute': '\xda', + 'Uacute;': '\xda', + 'Uarr;': '\u219f', + 'Uarrocir;': '\u2949', + 'Ubrcy;': '\u040e', + 'Ubreve;': '\u016c', + 'Ucirc': '\xdb', + 'Ucirc;': '\xdb', + 'Ucy;': '\u0423', + 'Udblac;': '\u0170', + 'Ufr;': '\u{01d518}', + 'Ugrave': '\xd9', + 'Ugrave;': '\xd9', + 'Umacr;': '\u016a', + 'UnderBar;': '_', + 'UnderBrace;': '\u23df', + 'UnderBracket;': '\u23b5', + 'UnderParenthesis;': '\u23dd', + 'Union;': '\u22c3', + 'UnionPlus;': '\u228e', + 'Uogon;': '\u0172', + 'Uopf;': '\u{01d54c}', + 'UpArrow;': '\u2191', + 'UpArrowBar;': '\u2912', + 'UpArrowDownArrow;': '\u21c5', + 'UpDownArrow;': '\u2195', + 'UpEquilibrium;': '\u296e', + 'UpTee;': '\u22a5', + 'UpTeeArrow;': '\u21a5', + 'Uparrow;': '\u21d1', + 'Updownarrow;': '\u21d5', + 'UpperLeftArrow;': '\u2196', + 'UpperRightArrow;': '\u2197', + 'Upsi;': '\u03d2', + 'Upsilon;': '\u03a5', + 'Uring;': '\u016e', + 'Uscr;': '\u{01d4b0}', + 'Utilde;': '\u0168', + 'Uuml': '\xdc', + 'Uuml;': '\xdc', + 'VDash;': '\u22ab', + 'Vbar;': '\u2aeb', + 'Vcy;': '\u0412', + 'Vdash;': '\u22a9', + 'Vdashl;': '\u2ae6', + 'Vee;': '\u22c1', + 'Verbar;': '\u2016', + 'Vert;': '\u2016', + 'VerticalBar;': '\u2223', + 'VerticalLine;': '|', + 'VerticalSeparator;': '\u2758', + 'VerticalTilde;': '\u2240', + 'VeryThinSpace;': '\u200a', + 'Vfr;': '\u{01d519}', + 'Vopf;': '\u{01d54d}', + 'Vscr;': '\u{01d4b1}', + 'Vvdash;': '\u22aa', + 'Wcirc;': '\u0174', + 'Wedge;': '\u22c0', + 'Wfr;': '\u{01d51a}', + 'Wopf;': '\u{01d54e}', + 'Wscr;': '\u{01d4b2}', + 'Xfr;': '\u{01d51b}', + 'Xi;': '\u039e', + 'Xopf;': '\u{01d54f}', + 'Xscr;': '\u{01d4b3}', + 'YAcy;': '\u042f', + 'YIcy;': '\u0407', + 'YUcy;': '\u042e', + 'Yacute': '\xdd', + 'Yacute;': '\xdd', + 'Ycirc;': '\u0176', + 'Ycy;': '\u042b', + 'Yfr;': '\u{01d51c}', + 'Yopf;': '\u{01d550}', + 'Yscr;': '\u{01d4b4}', + 'Yuml;': '\u0178', + 'ZHcy;': '\u0416', + 'Zacute;': '\u0179', + 'Zcaron;': '\u017d', + 'Zcy;': '\u0417', + 'Zdot;': '\u017b', + 'ZeroWidthSpace;': '\u200b', + 'Zeta;': '\u0396', + 'Zfr;': '\u2128', + 'Zopf;': '\u2124', + 'Zscr;': '\u{01d4b5}', + 'aacute': '\xe1', + 'aacute;': '\xe1', + 'abreve;': '\u0103', + 'ac;': '\u223e', + 'acE;': '\u223e\u0333', + 'acd;': '\u223f', + 'acirc': '\xe2', + 'acirc;': '\xe2', + 'acute': '\xb4', + 'acute;': '\xb4', + 'acy;': '\u0430', + 'aelig': '\xe6', + 'aelig;': '\xe6', + 'af;': '\u2061', + 'afr;': '\u{01d51e}', + 'agrave': '\xe0', + 'agrave;': '\xe0', + 'alefsym;': '\u2135', + 'aleph;': '\u2135', + 'alpha;': '\u03b1', + 'amacr;': '\u0101', + 'amalg;': '\u2a3f', + 'amp': '&', + 'amp;': '&', + 'and;': '\u2227', + 'andand;': '\u2a55', + 'andd;': '\u2a5c', + 'andslope;': '\u2a58', + 'andv;': '\u2a5a', + 'ang;': '\u2220', + 'ange;': '\u29a4', + 'angle;': '\u2220', + 'angmsd;': '\u2221', + 'angmsdaa;': '\u29a8', + 'angmsdab;': '\u29a9', + 'angmsdac;': '\u29aa', + 'angmsdad;': '\u29ab', + 'angmsdae;': '\u29ac', + 'angmsdaf;': '\u29ad', + 'angmsdag;': '\u29ae', + 'angmsdah;': '\u29af', + 'angrt;': '\u221f', + 'angrtvb;': '\u22be', + 'angrtvbd;': '\u299d', + 'angsph;': '\u2222', + 'angst;': '\xc5', + 'angzarr;': '\u237c', + 'aogon;': '\u0105', + 'aopf;': '\u{01d552}', + 'ap;': '\u2248', + 'apE;': '\u2a70', + 'apacir;': '\u2a6f', + 'ape;': '\u224a', + 'apid;': '\u224b', + 'apos;': "'", + 'approx;': '\u2248', + 'approxeq;': '\u224a', + 'aring': '\xe5', + 'aring;': '\xe5', + 'ascr;': '\u{01d4b6}', + 'ast;': '*', + 'asymp;': '\u2248', + 'asympeq;': '\u224d', + 'atilde': '\xe3', + 'atilde;': '\xe3', + 'auml': '\xe4', + 'auml;': '\xe4', + 'awconint;': '\u2233', + 'awint;': '\u2a11', + 'bNot;': '\u2aed', + 'backcong;': '\u224c', + 'backepsilon;': '\u03f6', + 'backprime;': '\u2035', + 'backsim;': '\u223d', + 'backsimeq;': '\u22cd', + 'barvee;': '\u22bd', + 'barwed;': '\u2305', + 'barwedge;': '\u2305', + 'bbrk;': '\u23b5', + 'bbrktbrk;': '\u23b6', + 'bcong;': '\u224c', + 'bcy;': '\u0431', + 'bdquo;': '\u201e', + 'becaus;': '\u2235', + 'because;': '\u2235', + 'bemptyv;': '\u29b0', + 'bepsi;': '\u03f6', + 'bernou;': '\u212c', + 'beta;': '\u03b2', + 'beth;': '\u2136', + 'between;': '\u226c', + 'bfr;': '\u{01d51f}', + 'bigcap;': '\u22c2', + 'bigcirc;': '\u25ef', + 'bigcup;': '\u22c3', + 'bigodot;': '\u2a00', + 'bigoplus;': '\u2a01', + 'bigotimes;': '\u2a02', + 'bigsqcup;': '\u2a06', + 'bigstar;': '\u2605', + 'bigtriangledown;': '\u25bd', + 'bigtriangleup;': '\u25b3', + 'biguplus;': '\u2a04', + 'bigvee;': '\u22c1', + 'bigwedge;': '\u22c0', + 'bkarow;': '\u290d', + 'blacklozenge;': '\u29eb', + 'blacksquare;': '\u25aa', + 'blacktriangle;': '\u25b4', + 'blacktriangledown;': '\u25be', + 'blacktriangleleft;': '\u25c2', + 'blacktriangleright;': '\u25b8', + 'blank;': '\u2423', + 'blk12;': '\u2592', + 'blk14;': '\u2591', + 'blk34;': '\u2593', + 'block;': '\u2588', + 'bne;': '=\u20e5', + 'bnequiv;': '\u2261\u20e5', + 'bnot;': '\u2310', + 'bopf;': '\u{01d553}', + 'bot;': '\u22a5', + 'bottom;': '\u22a5', + 'bowtie;': '\u22c8', + 'boxDL;': '\u2557', + 'boxDR;': '\u2554', + 'boxDl;': '\u2556', + 'boxDr;': '\u2553', + 'boxH;': '\u2550', + 'boxHD;': '\u2566', + 'boxHU;': '\u2569', + 'boxHd;': '\u2564', + 'boxHu;': '\u2567', + 'boxUL;': '\u255d', + 'boxUR;': '\u255a', + 'boxUl;': '\u255c', + 'boxUr;': '\u2559', + 'boxV;': '\u2551', + 'boxVH;': '\u256c', + 'boxVL;': '\u2563', + 'boxVR;': '\u2560', + 'boxVh;': '\u256b', + 'boxVl;': '\u2562', + 'boxVr;': '\u255f', + 'boxbox;': '\u29c9', + 'boxdL;': '\u2555', + 'boxdR;': '\u2552', + 'boxdl;': '\u2510', + 'boxdr;': '\u250c', + 'boxh;': '\u2500', + 'boxhD;': '\u2565', + 'boxhU;': '\u2568', + 'boxhd;': '\u252c', + 'boxhu;': '\u2534', + 'boxminus;': '\u229f', + 'boxplus;': '\u229e', + 'boxtimes;': '\u22a0', + 'boxuL;': '\u255b', + 'boxuR;': '\u2558', + 'boxul;': '\u2518', + 'boxur;': '\u2514', + 'boxv;': '\u2502', + 'boxvH;': '\u256a', + 'boxvL;': '\u2561', + 'boxvR;': '\u255e', + 'boxvh;': '\u253c', + 'boxvl;': '\u2524', + 'boxvr;': '\u251c', + 'bprime;': '\u2035', + 'breve;': '\u02d8', + 'brvbar': '\xa6', + 'brvbar;': '\xa6', + 'bscr;': '\u{01d4b7}', + 'bsemi;': '\u204f', + 'bsim;': '\u223d', + 'bsime;': '\u22cd', + 'bsol;': '\\', + 'bsolb;': '\u29c5', + 'bsolhsub;': '\u27c8', + 'bull;': '\u2022', + 'bullet;': '\u2022', + 'bump;': '\u224e', + 'bumpE;': '\u2aae', + 'bumpe;': '\u224f', + 'bumpeq;': '\u224f', + 'cacute;': '\u0107', + 'cap;': '\u2229', + 'capand;': '\u2a44', + 'capbrcup;': '\u2a49', + 'capcap;': '\u2a4b', + 'capcup;': '\u2a47', + 'capdot;': '\u2a40', + 'caps;': '\u2229\ufe00', + 'caret;': '\u2041', + 'caron;': '\u02c7', + 'ccaps;': '\u2a4d', + 'ccaron;': '\u010d', + 'ccedil': '\xe7', + 'ccedil;': '\xe7', + 'ccirc;': '\u0109', + 'ccups;': '\u2a4c', + 'ccupssm;': '\u2a50', + 'cdot;': '\u010b', + 'cedil': '\xb8', + 'cedil;': '\xb8', + 'cemptyv;': '\u29b2', + 'cent': '\xa2', + 'cent;': '\xa2', + 'centerdot;': '\xb7', + 'cfr;': '\u{01d520}', + 'chcy;': '\u0447', + 'check;': '\u2713', + 'checkmark;': '\u2713', + 'chi;': '\u03c7', + 'cir;': '\u25cb', + 'cirE;': '\u29c3', + 'circ;': '\u02c6', + 'circeq;': '\u2257', + 'circlearrowleft;': '\u21ba', + 'circlearrowright;': '\u21bb', + 'circledR;': '\xae', + 'circledS;': '\u24c8', + 'circledast;': '\u229b', + 'circledcirc;': '\u229a', + 'circleddash;': '\u229d', + 'cire;': '\u2257', + 'cirfnint;': '\u2a10', + 'cirmid;': '\u2aef', + 'cirscir;': '\u29c2', + 'clubs;': '\u2663', + 'clubsuit;': '\u2663', + 'colon;': ':', + 'colone;': '\u2254', + 'coloneq;': '\u2254', + 'comma;': ',', + 'commat;': '@', + 'comp;': '\u2201', + 'compfn;': '\u2218', + 'complement;': '\u2201', + 'complexes;': '\u2102', + 'cong;': '\u2245', + 'congdot;': '\u2a6d', + 'conint;': '\u222e', + 'copf;': '\u{01d554}', + 'coprod;': '\u2210', + 'copy': '\xa9', + 'copy;': '\xa9', + 'copysr;': '\u2117', + 'crarr;': '\u21b5', + 'cross;': '\u2717', + 'cscr;': '\u{01d4b8}', + 'csub;': '\u2acf', + 'csube;': '\u2ad1', + 'csup;': '\u2ad0', + 'csupe;': '\u2ad2', + 'ctdot;': '\u22ef', + 'cudarrl;': '\u2938', + 'cudarrr;': '\u2935', + 'cuepr;': '\u22de', + 'cuesc;': '\u22df', + 'cularr;': '\u21b6', + 'cularrp;': '\u293d', + 'cup;': '\u222a', + 'cupbrcap;': '\u2a48', + 'cupcap;': '\u2a46', + 'cupcup;': '\u2a4a', + 'cupdot;': '\u228d', + 'cupor;': '\u2a45', + 'cups;': '\u222a\ufe00', + 'curarr;': '\u21b7', + 'curarrm;': '\u293c', + 'curlyeqprec;': '\u22de', + 'curlyeqsucc;': '\u22df', + 'curlyvee;': '\u22ce', + 'curlywedge;': '\u22cf', + 'curren': '\xa4', + 'curren;': '\xa4', + 'curvearrowleft;': '\u21b6', + 'curvearrowright;': '\u21b7', + 'cuvee;': '\u22ce', + 'cuwed;': '\u22cf', + 'cwconint;': '\u2232', + 'cwint;': '\u2231', + 'cylcty;': '\u232d', + 'dArr;': '\u21d3', + 'dHar;': '\u2965', + 'dagger;': '\u2020', + 'daleth;': '\u2138', + 'darr;': '\u2193', + 'dash;': '\u2010', + 'dashv;': '\u22a3', + 'dbkarow;': '\u290f', + 'dblac;': '\u02dd', + 'dcaron;': '\u010f', + 'dcy;': '\u0434', + 'dd;': '\u2146', + 'ddagger;': '\u2021', + 'ddarr;': '\u21ca', + 'ddotseq;': '\u2a77', + 'deg': '\xb0', + 'deg;': '\xb0', + 'delta;': '\u03b4', + 'demptyv;': '\u29b1', + 'dfisht;': '\u297f', + 'dfr;': '\u{01d521}', + 'dharl;': '\u21c3', + 'dharr;': '\u21c2', + 'diam;': '\u22c4', + 'diamond;': '\u22c4', + 'diamondsuit;': '\u2666', + 'diams;': '\u2666', + 'die;': '\xa8', + 'digamma;': '\u03dd', + 'disin;': '\u22f2', + 'div;': '\xf7', + 'divide': '\xf7', + 'divide;': '\xf7', + 'divideontimes;': '\u22c7', + 'divonx;': '\u22c7', + 'djcy;': '\u0452', + 'dlcorn;': '\u231e', + 'dlcrop;': '\u230d', + 'dollar;': '\$', + 'dopf;': '\u{01d555}', + 'dot;': '\u02d9', + 'doteq;': '\u2250', + 'doteqdot;': '\u2251', + 'dotminus;': '\u2238', + 'dotplus;': '\u2214', + 'dotsquare;': '\u22a1', + 'doublebarwedge;': '\u2306', + 'downarrow;': '\u2193', + 'downdownarrows;': '\u21ca', + 'downharpoonleft;': '\u21c3', + 'downharpoonright;': '\u21c2', + 'drbkarow;': '\u2910', + 'drcorn;': '\u231f', + 'drcrop;': '\u230c', + 'dscr;': '\u{01d4b9}', + 'dscy;': '\u0455', + 'dsol;': '\u29f6', + 'dstrok;': '\u0111', + 'dtdot;': '\u22f1', + 'dtri;': '\u25bf', + 'dtrif;': '\u25be', + 'duarr;': '\u21f5', + 'duhar;': '\u296f', + 'dwangle;': '\u29a6', + 'dzcy;': '\u045f', + 'dzigrarr;': '\u27ff', + 'eDDot;': '\u2a77', + 'eDot;': '\u2251', + 'eacute': '\xe9', + 'eacute;': '\xe9', + 'easter;': '\u2a6e', + 'ecaron;': '\u011b', + 'ecir;': '\u2256', + 'ecirc': '\xea', + 'ecirc;': '\xea', + 'ecolon;': '\u2255', + 'ecy;': '\u044d', + 'edot;': '\u0117', + 'ee;': '\u2147', + 'efDot;': '\u2252', + 'efr;': '\u{01d522}', + 'eg;': '\u2a9a', + 'egrave': '\xe8', + 'egrave;': '\xe8', + 'egs;': '\u2a96', + 'egsdot;': '\u2a98', + 'el;': '\u2a99', + 'elinters;': '\u23e7', + 'ell;': '\u2113', + 'els;': '\u2a95', + 'elsdot;': '\u2a97', + 'emacr;': '\u0113', + 'empty;': '\u2205', + 'emptyset;': '\u2205', + 'emptyv;': '\u2205', + 'emsp13;': '\u2004', + 'emsp14;': '\u2005', + 'emsp;': '\u2003', + 'eng;': '\u014b', + 'ensp;': '\u2002', + 'eogon;': '\u0119', + 'eopf;': '\u{01d556}', + 'epar;': '\u22d5', + 'eparsl;': '\u29e3', + 'eplus;': '\u2a71', + 'epsi;': '\u03b5', + 'epsilon;': '\u03b5', + 'epsiv;': '\u03f5', + 'eqcirc;': '\u2256', + 'eqcolon;': '\u2255', + 'eqsim;': '\u2242', + 'eqslantgtr;': '\u2a96', + 'eqslantless;': '\u2a95', + 'equals;': '=', + 'equest;': '\u225f', + 'equiv;': '\u2261', + 'equivDD;': '\u2a78', + 'eqvparsl;': '\u29e5', + 'erDot;': '\u2253', + 'erarr;': '\u2971', + 'escr;': '\u212f', + 'esdot;': '\u2250', + 'esim;': '\u2242', + 'eta;': '\u03b7', + 'eth': '\xf0', + 'eth;': '\xf0', + 'euml': '\xeb', + 'euml;': '\xeb', + 'euro;': '\u20ac', + 'excl;': '!', + 'exist;': '\u2203', + 'expectation;': '\u2130', + 'exponentiale;': '\u2147', + 'fallingdotseq;': '\u2252', + 'fcy;': '\u0444', + 'female;': '\u2640', + 'ffilig;': '\ufb03', + 'fflig;': '\ufb00', + 'ffllig;': '\ufb04', + 'ffr;': '\u{01d523}', + 'filig;': '\ufb01', + 'fjlig;': 'fj', + 'flat;': '\u266d', + 'fllig;': '\ufb02', + 'fltns;': '\u25b1', + 'fnof;': '\u0192', + 'fopf;': '\u{01d557}', + 'forall;': '\u2200', + 'fork;': '\u22d4', + 'forkv;': '\u2ad9', + 'fpartint;': '\u2a0d', + 'frac12': '\xbd', + 'frac12;': '\xbd', + 'frac13;': '\u2153', + 'frac14': '\xbc', + 'frac14;': '\xbc', + 'frac15;': '\u2155', + 'frac16;': '\u2159', + 'frac18;': '\u215b', + 'frac23;': '\u2154', + 'frac25;': '\u2156', + 'frac34': '\xbe', + 'frac34;': '\xbe', + 'frac35;': '\u2157', + 'frac38;': '\u215c', + 'frac45;': '\u2158', + 'frac56;': '\u215a', + 'frac58;': '\u215d', + 'frac78;': '\u215e', + 'frasl;': '\u2044', + 'frown;': '\u2322', + 'fscr;': '\u{01d4bb}', + 'gE;': '\u2267', + 'gEl;': '\u2a8c', + 'gacute;': '\u01f5', + 'gamma;': '\u03b3', + 'gammad;': '\u03dd', + 'gap;': '\u2a86', + 'gbreve;': '\u011f', + 'gcirc;': '\u011d', + 'gcy;': '\u0433', + 'gdot;': '\u0121', + 'ge;': '\u2265', + 'gel;': '\u22db', + 'geq;': '\u2265', + 'geqq;': '\u2267', + 'geqslant;': '\u2a7e', + 'ges;': '\u2a7e', + 'gescc;': '\u2aa9', + 'gesdot;': '\u2a80', + 'gesdoto;': '\u2a82', + 'gesdotol;': '\u2a84', + 'gesl;': '\u22db\ufe00', + 'gesles;': '\u2a94', + 'gfr;': '\u{01d524}', + 'gg;': '\u226b', + 'ggg;': '\u22d9', + 'gimel;': '\u2137', + 'gjcy;': '\u0453', + 'gl;': '\u2277', + 'glE;': '\u2a92', + 'gla;': '\u2aa5', + 'glj;': '\u2aa4', + 'gnE;': '\u2269', + 'gnap;': '\u2a8a', + 'gnapprox;': '\u2a8a', + 'gne;': '\u2a88', + 'gneq;': '\u2a88', + 'gneqq;': '\u2269', + 'gnsim;': '\u22e7', + 'gopf;': '\u{01d558}', + 'grave;': '`', + 'gscr;': '\u210a', + 'gsim;': '\u2273', + 'gsime;': '\u2a8e', + 'gsiml;': '\u2a90', + 'gt': '>', + 'gt;': '>', + 'gtcc;': '\u2aa7', + 'gtcir;': '\u2a7a', + 'gtdot;': '\u22d7', + 'gtlPar;': '\u2995', + 'gtquest;': '\u2a7c', + 'gtrapprox;': '\u2a86', + 'gtrarr;': '\u2978', + 'gtrdot;': '\u22d7', + 'gtreqless;': '\u22db', + 'gtreqqless;': '\u2a8c', + 'gtrless;': '\u2277', + 'gtrsim;': '\u2273', + 'gvertneqq;': '\u2269\ufe00', + 'gvnE;': '\u2269\ufe00', + 'hArr;': '\u21d4', + 'hairsp;': '\u200a', + 'half;': '\xbd', + 'hamilt;': '\u210b', + 'hardcy;': '\u044a', + 'harr;': '\u2194', + 'harrcir;': '\u2948', + 'harrw;': '\u21ad', + 'hbar;': '\u210f', + 'hcirc;': '\u0125', + 'hearts;': '\u2665', + 'heartsuit;': '\u2665', + 'hellip;': '\u2026', + 'hercon;': '\u22b9', + 'hfr;': '\u{01d525}', + 'hksearow;': '\u2925', + 'hkswarow;': '\u2926', + 'hoarr;': '\u21ff', + 'homtht;': '\u223b', + 'hookleftarrow;': '\u21a9', + 'hookrightarrow;': '\u21aa', + 'hopf;': '\u{01d559}', + 'horbar;': '\u2015', + 'hscr;': '\u{01d4bd}', + 'hslash;': '\u210f', + 'hstrok;': '\u0127', + 'hybull;': '\u2043', + 'hyphen;': '\u2010', + 'iacute': '\xed', + 'iacute;': '\xed', + 'ic;': '\u2063', + 'icirc': '\xee', + 'icirc;': '\xee', + 'icy;': '\u0438', + 'iecy;': '\u0435', + 'iexcl': '\xa1', + 'iexcl;': '\xa1', + 'iff;': '\u21d4', + 'ifr;': '\u{01d526}', + 'igrave': '\xec', + 'igrave;': '\xec', + 'ii;': '\u2148', + 'iiiint;': '\u2a0c', + 'iiint;': '\u222d', + 'iinfin;': '\u29dc', + 'iiota;': '\u2129', + 'ijlig;': '\u0133', + 'imacr;': '\u012b', + 'image;': '\u2111', + 'imagline;': '\u2110', + 'imagpart;': '\u2111', + 'imath;': '\u0131', + 'imof;': '\u22b7', + 'imped;': '\u01b5', + 'in;': '\u2208', + 'incare;': '\u2105', + 'infin;': '\u221e', + 'infintie;': '\u29dd', + 'inodot;': '\u0131', + 'int;': '\u222b', + 'intcal;': '\u22ba', + 'integers;': '\u2124', + 'intercal;': '\u22ba', + 'intlarhk;': '\u2a17', + 'intprod;': '\u2a3c', + 'iocy;': '\u0451', + 'iogon;': '\u012f', + 'iopf;': '\u{01d55a}', + 'iota;': '\u03b9', + 'iprod;': '\u2a3c', + 'iquest': '\xbf', + 'iquest;': '\xbf', + 'iscr;': '\u{01d4be}', + 'isin;': '\u2208', + 'isinE;': '\u22f9', + 'isindot;': '\u22f5', + 'isins;': '\u22f4', + 'isinsv;': '\u22f3', + 'isinv;': '\u2208', + 'it;': '\u2062', + 'itilde;': '\u0129', + 'iukcy;': '\u0456', + 'iuml': '\xef', + 'iuml;': '\xef', + 'jcirc;': '\u0135', + 'jcy;': '\u0439', + 'jfr;': '\u{01d527}', + 'jmath;': '\u0237', + 'jopf;': '\u{01d55b}', + 'jscr;': '\u{01d4bf}', + 'jsercy;': '\u0458', + 'jukcy;': '\u0454', + 'kappa;': '\u03ba', + 'kappav;': '\u03f0', + 'kcedil;': '\u0137', + 'kcy;': '\u043a', + 'kfr;': '\u{01d528}', + 'kgreen;': '\u0138', + 'khcy;': '\u0445', + 'kjcy;': '\u045c', + 'kopf;': '\u{01d55c}', + 'kscr;': '\u{01d4c0}', + 'lAarr;': '\u21da', + 'lArr;': '\u21d0', + 'lAtail;': '\u291b', + 'lBarr;': '\u290e', + 'lE;': '\u2266', + 'lEg;': '\u2a8b', + 'lHar;': '\u2962', + 'lacute;': '\u013a', + 'laemptyv;': '\u29b4', + 'lagran;': '\u2112', + 'lambda;': '\u03bb', + 'lang;': '\u27e8', + 'langd;': '\u2991', + 'langle;': '\u27e8', + 'lap;': '\u2a85', + 'laquo': '\xab', + 'laquo;': '\xab', + 'larr;': '\u2190', + 'larrb;': '\u21e4', + 'larrbfs;': '\u291f', + 'larrfs;': '\u291d', + 'larrhk;': '\u21a9', + 'larrlp;': '\u21ab', + 'larrpl;': '\u2939', + 'larrsim;': '\u2973', + 'larrtl;': '\u21a2', + 'lat;': '\u2aab', + 'latail;': '\u2919', + 'late;': '\u2aad', + 'lates;': '\u2aad\ufe00', + 'lbarr;': '\u290c', + 'lbbrk;': '\u2772', + 'lbrace;': '{', + 'lbrack;': '[', + 'lbrke;': '\u298b', + 'lbrksld;': '\u298f', + 'lbrkslu;': '\u298d', + 'lcaron;': '\u013e', + 'lcedil;': '\u013c', + 'lceil;': '\u2308', + 'lcub;': '{', + 'lcy;': '\u043b', + 'ldca;': '\u2936', + 'ldquo;': '\u201c', + 'ldquor;': '\u201e', + 'ldrdhar;': '\u2967', + 'ldrushar;': '\u294b', + 'ldsh;': '\u21b2', + 'le;': '\u2264', + 'leftarrow;': '\u2190', + 'leftarrowtail;': '\u21a2', + 'leftharpoondown;': '\u21bd', + 'leftharpoonup;': '\u21bc', + 'leftleftarrows;': '\u21c7', + 'leftrightarrow;': '\u2194', + 'leftrightarrows;': '\u21c6', + 'leftrightharpoons;': '\u21cb', + 'leftrightsquigarrow;': '\u21ad', + 'leftthreetimes;': '\u22cb', + 'leg;': '\u22da', + 'leq;': '\u2264', + 'leqq;': '\u2266', + 'leqslant;': '\u2a7d', + 'les;': '\u2a7d', + 'lescc;': '\u2aa8', + 'lesdot;': '\u2a7f', + 'lesdoto;': '\u2a81', + 'lesdotor;': '\u2a83', + 'lesg;': '\u22da\ufe00', + 'lesges;': '\u2a93', + 'lessapprox;': '\u2a85', + 'lessdot;': '\u22d6', + 'lesseqgtr;': '\u22da', + 'lesseqqgtr;': '\u2a8b', + 'lessgtr;': '\u2276', + 'lesssim;': '\u2272', + 'lfisht;': '\u297c', + 'lfloor;': '\u230a', + 'lfr;': '\u{01d529}', + 'lg;': '\u2276', + 'lgE;': '\u2a91', + 'lhard;': '\u21bd', + 'lharu;': '\u21bc', + 'lharul;': '\u296a', + 'lhblk;': '\u2584', + 'ljcy;': '\u0459', + 'll;': '\u226a', + 'llarr;': '\u21c7', + 'llcorner;': '\u231e', + 'llhard;': '\u296b', + 'lltri;': '\u25fa', + 'lmidot;': '\u0140', + 'lmoust;': '\u23b0', + 'lmoustache;': '\u23b0', + 'lnE;': '\u2268', + 'lnap;': '\u2a89', + 'lnapprox;': '\u2a89', + 'lne;': '\u2a87', + 'lneq;': '\u2a87', + 'lneqq;': '\u2268', + 'lnsim;': '\u22e6', + 'loang;': '\u27ec', + 'loarr;': '\u21fd', + 'lobrk;': '\u27e6', + 'longleftarrow;': '\u27f5', + 'longleftrightarrow;': '\u27f7', + 'longmapsto;': '\u27fc', + 'longrightarrow;': '\u27f6', + 'looparrowleft;': '\u21ab', + 'looparrowright;': '\u21ac', + 'lopar;': '\u2985', + 'lopf;': '\u{01d55d}', + 'loplus;': '\u2a2d', + 'lotimes;': '\u2a34', + 'lowast;': '\u2217', + 'lowbar;': '_', + 'loz;': '\u25ca', + 'lozenge;': '\u25ca', + 'lozf;': '\u29eb', + 'lpar;': '(', + 'lparlt;': '\u2993', + 'lrarr;': '\u21c6', + 'lrcorner;': '\u231f', + 'lrhar;': '\u21cb', + 'lrhard;': '\u296d', + 'lrm;': '\u200e', + 'lrtri;': '\u22bf', + 'lsaquo;': '\u2039', + 'lscr;': '\u{01d4c1}', + 'lsh;': '\u21b0', + 'lsim;': '\u2272', + 'lsime;': '\u2a8d', + 'lsimg;': '\u2a8f', + 'lsqb;': '[', + 'lsquo;': '\u2018', + 'lsquor;': '\u201a', + 'lstrok;': '\u0142', + 'lt': '<', + 'lt;': '<', + 'ltcc;': '\u2aa6', + 'ltcir;': '\u2a79', + 'ltdot;': '\u22d6', + 'lthree;': '\u22cb', + 'ltimes;': '\u22c9', + 'ltlarr;': '\u2976', + 'ltquest;': '\u2a7b', + 'ltrPar;': '\u2996', + 'ltri;': '\u25c3', + 'ltrie;': '\u22b4', + 'ltrif;': '\u25c2', + 'lurdshar;': '\u294a', + 'luruhar;': '\u2966', + 'lvertneqq;': '\u2268\ufe00', + 'lvnE;': '\u2268\ufe00', + 'mDDot;': '\u223a', + 'macr': '\xaf', + 'macr;': '\xaf', + 'male;': '\u2642', + 'malt;': '\u2720', + 'maltese;': '\u2720', + 'map;': '\u21a6', + 'mapsto;': '\u21a6', + 'mapstodown;': '\u21a7', + 'mapstoleft;': '\u21a4', + 'mapstoup;': '\u21a5', + 'marker;': '\u25ae', + 'mcomma;': '\u2a29', + 'mcy;': '\u043c', + 'mdash;': '\u2014', + 'measuredangle;': '\u2221', + 'mfr;': '\u{01d52a}', + 'mho;': '\u2127', + 'micro': '\xb5', + 'micro;': '\xb5', + 'mid;': '\u2223', + 'midast;': '*', + 'midcir;': '\u2af0', + 'middot': '\xb7', + 'middot;': '\xb7', + 'minus;': '\u2212', + 'minusb;': '\u229f', + 'minusd;': '\u2238', + 'minusdu;': '\u2a2a', + 'mlcp;': '\u2adb', + 'mldr;': '\u2026', + 'mnplus;': '\u2213', + 'models;': '\u22a7', + 'mopf;': '\u{01d55e}', + 'mp;': '\u2213', + 'mscr;': '\u{01d4c2}', + 'mstpos;': '\u223e', + 'mu;': '\u03bc', + 'multimap;': '\u22b8', + 'mumap;': '\u22b8', + 'nGg;': '\u22d9\u0338', + 'nGt;': '\u226b\u20d2', + 'nGtv;': '\u226b\u0338', + 'nLeftarrow;': '\u21cd', + 'nLeftrightarrow;': '\u21ce', + 'nLl;': '\u22d8\u0338', + 'nLt;': '\u226a\u20d2', + 'nLtv;': '\u226a\u0338', + 'nRightarrow;': '\u21cf', + 'nVDash;': '\u22af', + 'nVdash;': '\u22ae', + 'nabla;': '\u2207', + 'nacute;': '\u0144', + 'nang;': '\u2220\u20d2', + 'nap;': '\u2249', + 'napE;': '\u2a70\u0338', + 'napid;': '\u224b\u0338', + 'napos;': '\u0149', + 'napprox;': '\u2249', + 'natur;': '\u266e', + 'natural;': '\u266e', + 'naturals;': '\u2115', + 'nbsp': '\xa0', + 'nbsp;': '\xa0', + 'nbump;': '\u224e\u0338', + 'nbumpe;': '\u224f\u0338', + 'ncap;': '\u2a43', + 'ncaron;': '\u0148', + 'ncedil;': '\u0146', + 'ncong;': '\u2247', + 'ncongdot;': '\u2a6d\u0338', + 'ncup;': '\u2a42', + 'ncy;': '\u043d', + 'ndash;': '\u2013', + 'ne;': '\u2260', + 'neArr;': '\u21d7', + 'nearhk;': '\u2924', + 'nearr;': '\u2197', + 'nearrow;': '\u2197', + 'nedot;': '\u2250\u0338', + 'nequiv;': '\u2262', + 'nesear;': '\u2928', + 'nesim;': '\u2242\u0338', + 'nexist;': '\u2204', + 'nexists;': '\u2204', + 'nfr;': '\u{01d52b}', + 'ngE;': '\u2267\u0338', + 'nge;': '\u2271', + 'ngeq;': '\u2271', + 'ngeqq;': '\u2267\u0338', + 'ngeqslant;': '\u2a7e\u0338', + 'nges;': '\u2a7e\u0338', + 'ngsim;': '\u2275', + 'ngt;': '\u226f', + 'ngtr;': '\u226f', + 'nhArr;': '\u21ce', + 'nharr;': '\u21ae', + 'nhpar;': '\u2af2', + 'ni;': '\u220b', + 'nis;': '\u22fc', + 'nisd;': '\u22fa', + 'niv;': '\u220b', + 'njcy;': '\u045a', + 'nlArr;': '\u21cd', + 'nlE;': '\u2266\u0338', + 'nlarr;': '\u219a', + 'nldr;': '\u2025', + 'nle;': '\u2270', + 'nleftarrow;': '\u219a', + 'nleftrightarrow;': '\u21ae', + 'nleq;': '\u2270', + 'nleqq;': '\u2266\u0338', + 'nleqslant;': '\u2a7d\u0338', + 'nles;': '\u2a7d\u0338', + 'nless;': '\u226e', + 'nlsim;': '\u2274', + 'nlt;': '\u226e', + 'nltri;': '\u22ea', + 'nltrie;': '\u22ec', + 'nmid;': '\u2224', + 'nopf;': '\u{01d55f}', + 'not': '\xac', + 'not;': '\xac', + 'notin;': '\u2209', + 'notinE;': '\u22f9\u0338', + 'notindot;': '\u22f5\u0338', + 'notinva;': '\u2209', + 'notinvb;': '\u22f7', + 'notinvc;': '\u22f6', + 'notni;': '\u220c', + 'notniva;': '\u220c', + 'notnivb;': '\u22fe', + 'notnivc;': '\u22fd', + 'npar;': '\u2226', + 'nparallel;': '\u2226', + 'nparsl;': '\u2afd\u20e5', + 'npart;': '\u2202\u0338', + 'npolint;': '\u2a14', + 'npr;': '\u2280', + 'nprcue;': '\u22e0', + 'npre;': '\u2aaf\u0338', + 'nprec;': '\u2280', + 'npreceq;': '\u2aaf\u0338', + 'nrArr;': '\u21cf', + 'nrarr;': '\u219b', + 'nrarrc;': '\u2933\u0338', + 'nrarrw;': '\u219d\u0338', + 'nrightarrow;': '\u219b', + 'nrtri;': '\u22eb', + 'nrtrie;': '\u22ed', + 'nsc;': '\u2281', + 'nsccue;': '\u22e1', + 'nsce;': '\u2ab0\u0338', + 'nscr;': '\u{01d4c3}', + 'nshortmid;': '\u2224', + 'nshortparallel;': '\u2226', + 'nsim;': '\u2241', + 'nsime;': '\u2244', + 'nsimeq;': '\u2244', + 'nsmid;': '\u2224', + 'nspar;': '\u2226', + 'nsqsube;': '\u22e2', + 'nsqsupe;': '\u22e3', + 'nsub;': '\u2284', + 'nsubE;': '\u2ac5\u0338', + 'nsube;': '\u2288', + 'nsubset;': '\u2282\u20d2', + 'nsubseteq;': '\u2288', + 'nsubseteqq;': '\u2ac5\u0338', + 'nsucc;': '\u2281', + 'nsucceq;': '\u2ab0\u0338', + 'nsup;': '\u2285', + 'nsupE;': '\u2ac6\u0338', + 'nsupe;': '\u2289', + 'nsupset;': '\u2283\u20d2', + 'nsupseteq;': '\u2289', + 'nsupseteqq;': '\u2ac6\u0338', + 'ntgl;': '\u2279', + 'ntilde': '\xf1', + 'ntilde;': '\xf1', + 'ntlg;': '\u2278', + 'ntriangleleft;': '\u22ea', + 'ntrianglelefteq;': '\u22ec', + 'ntriangleright;': '\u22eb', + 'ntrianglerighteq;': '\u22ed', + 'nu;': '\u03bd', + 'num;': '#', + 'numero;': '\u2116', + 'numsp;': '\u2007', + 'nvDash;': '\u22ad', + 'nvHarr;': '\u2904', + 'nvap;': '\u224d\u20d2', + 'nvdash;': '\u22ac', + 'nvge;': '\u2265\u20d2', + 'nvgt;': '>\u20d2', + 'nvinfin;': '\u29de', + 'nvlArr;': '\u2902', + 'nvle;': '\u2264\u20d2', + 'nvlt;': '<\u20d2', + 'nvltrie;': '\u22b4\u20d2', + 'nvrArr;': '\u2903', + 'nvrtrie;': '\u22b5\u20d2', + 'nvsim;': '\u223c\u20d2', + 'nwArr;': '\u21d6', + 'nwarhk;': '\u2923', + 'nwarr;': '\u2196', + 'nwarrow;': '\u2196', + 'nwnear;': '\u2927', + 'oS;': '\u24c8', + 'oacute': '\xf3', + 'oacute;': '\xf3', + 'oast;': '\u229b', + 'ocir;': '\u229a', + 'ocirc': '\xf4', + 'ocirc;': '\xf4', + 'ocy;': '\u043e', + 'odash;': '\u229d', + 'odblac;': '\u0151', + 'odiv;': '\u2a38', + 'odot;': '\u2299', + 'odsold;': '\u29bc', + 'oelig;': '\u0153', + 'ofcir;': '\u29bf', + 'ofr;': '\u{01d52c}', + 'ogon;': '\u02db', + 'ograve': '\xf2', + 'ograve;': '\xf2', + 'ogt;': '\u29c1', + 'ohbar;': '\u29b5', + 'ohm;': '\u03a9', + 'oint;': '\u222e', + 'olarr;': '\u21ba', + 'olcir;': '\u29be', + 'olcross;': '\u29bb', + 'oline;': '\u203e', + 'olt;': '\u29c0', + 'omacr;': '\u014d', + 'omega;': '\u03c9', + 'omicron;': '\u03bf', + 'omid;': '\u29b6', + 'ominus;': '\u2296', + 'oopf;': '\u{01d560}', + 'opar;': '\u29b7', + 'operp;': '\u29b9', + 'oplus;': '\u2295', + 'or;': '\u2228', + 'orarr;': '\u21bb', + 'ord;': '\u2a5d', + 'order;': '\u2134', + 'orderof;': '\u2134', + 'ordf': '\xaa', + 'ordf;': '\xaa', + 'ordm': '\xba', + 'ordm;': '\xba', + 'origof;': '\u22b6', + 'oror;': '\u2a56', + 'orslope;': '\u2a57', + 'orv;': '\u2a5b', + 'oscr;': '\u2134', + 'oslash': '\xf8', + 'oslash;': '\xf8', + 'osol;': '\u2298', + 'otilde': '\xf5', + 'otilde;': '\xf5', + 'otimes;': '\u2297', + 'otimesas;': '\u2a36', + 'ouml': '\xf6', + 'ouml;': '\xf6', + 'ovbar;': '\u233d', + 'par;': '\u2225', + 'para': '\xb6', + 'para;': '\xb6', + 'parallel;': '\u2225', + 'parsim;': '\u2af3', + 'parsl;': '\u2afd', + 'part;': '\u2202', + 'pcy;': '\u043f', + 'percnt;': '%', + 'period;': '.', + 'permil;': '\u2030', + 'perp;': '\u22a5', + 'pertenk;': '\u2031', + 'pfr;': '\u{01d52d}', + 'phi;': '\u03c6', + 'phiv;': '\u03d5', + 'phmmat;': '\u2133', + 'phone;': '\u260e', + 'pi;': '\u03c0', + 'pitchfork;': '\u22d4', + 'piv;': '\u03d6', + 'planck;': '\u210f', + 'planckh;': '\u210e', + 'plankv;': '\u210f', + 'plus;': '+', + 'plusacir;': '\u2a23', + 'plusb;': '\u229e', + 'pluscir;': '\u2a22', + 'plusdo;': '\u2214', + 'plusdu;': '\u2a25', + 'pluse;': '\u2a72', + 'plusmn': '\xb1', + 'plusmn;': '\xb1', + 'plussim;': '\u2a26', + 'plustwo;': '\u2a27', + 'pm;': '\xb1', + 'pointint;': '\u2a15', + 'popf;': '\u{01d561}', + 'pound': '\xa3', + 'pound;': '\xa3', + 'pr;': '\u227a', + 'prE;': '\u2ab3', + 'prap;': '\u2ab7', + 'prcue;': '\u227c', + 'pre;': '\u2aaf', + 'prec;': '\u227a', + 'precapprox;': '\u2ab7', + 'preccurlyeq;': '\u227c', + 'preceq;': '\u2aaf', + 'precnapprox;': '\u2ab9', + 'precneqq;': '\u2ab5', + 'precnsim;': '\u22e8', + 'precsim;': '\u227e', + 'prime;': '\u2032', + 'primes;': '\u2119', + 'prnE;': '\u2ab5', + 'prnap;': '\u2ab9', + 'prnsim;': '\u22e8', + 'prod;': '\u220f', + 'profalar;': '\u232e', + 'profline;': '\u2312', + 'profsurf;': '\u2313', + 'prop;': '\u221d', + 'propto;': '\u221d', + 'prsim;': '\u227e', + 'prurel;': '\u22b0', + 'pscr;': '\u{01d4c5}', + 'psi;': '\u03c8', + 'puncsp;': '\u2008', + 'qfr;': '\u{01d52e}', + 'qint;': '\u2a0c', + 'qopf;': '\u{01d562}', + 'qprime;': '\u2057', + 'qscr;': '\u{01d4c6}', + 'quaternions;': '\u210d', + 'quatint;': '\u2a16', + 'quest;': '?', + 'questeq;': '\u225f', + 'quot': '"', + 'quot;': '"', + 'rAarr;': '\u21db', + 'rArr;': '\u21d2', + 'rAtail;': '\u291c', + 'rBarr;': '\u290f', + 'rHar;': '\u2964', + 'race;': '\u223d\u0331', + 'racute;': '\u0155', + 'radic;': '\u221a', + 'raemptyv;': '\u29b3', + 'rang;': '\u27e9', + 'rangd;': '\u2992', + 'range;': '\u29a5', + 'rangle;': '\u27e9', + 'raquo': '\xbb', + 'raquo;': '\xbb', + 'rarr;': '\u2192', + 'rarrap;': '\u2975', + 'rarrb;': '\u21e5', + 'rarrbfs;': '\u2920', + 'rarrc;': '\u2933', + 'rarrfs;': '\u291e', + 'rarrhk;': '\u21aa', + 'rarrlp;': '\u21ac', + 'rarrpl;': '\u2945', + 'rarrsim;': '\u2974', + 'rarrtl;': '\u21a3', + 'rarrw;': '\u219d', + 'ratail;': '\u291a', + 'ratio;': '\u2236', + 'rationals;': '\u211a', + 'rbarr;': '\u290d', + 'rbbrk;': '\u2773', + 'rbrace;': '}', + 'rbrack;': ']', + 'rbrke;': '\u298c', + 'rbrksld;': '\u298e', + 'rbrkslu;': '\u2990', + 'rcaron;': '\u0159', + 'rcedil;': '\u0157', + 'rceil;': '\u2309', + 'rcub;': '}', + 'rcy;': '\u0440', + 'rdca;': '\u2937', + 'rdldhar;': '\u2969', + 'rdquo;': '\u201d', + 'rdquor;': '\u201d', + 'rdsh;': '\u21b3', + 'real;': '\u211c', + 'realine;': '\u211b', + 'realpart;': '\u211c', + 'reals;': '\u211d', + 'rect;': '\u25ad', + 'reg': '\xae', + 'reg;': '\xae', + 'rfisht;': '\u297d', + 'rfloor;': '\u230b', + 'rfr;': '\u{01d52f}', + 'rhard;': '\u21c1', + 'rharu;': '\u21c0', + 'rharul;': '\u296c', + 'rho;': '\u03c1', + 'rhov;': '\u03f1', + 'rightarrow;': '\u2192', + 'rightarrowtail;': '\u21a3', + 'rightharpoondown;': '\u21c1', + 'rightharpoonup;': '\u21c0', + 'rightleftarrows;': '\u21c4', + 'rightleftharpoons;': '\u21cc', + 'rightrightarrows;': '\u21c9', + 'rightsquigarrow;': '\u219d', + 'rightthreetimes;': '\u22cc', + 'ring;': '\u02da', + 'risingdotseq;': '\u2253', + 'rlarr;': '\u21c4', + 'rlhar;': '\u21cc', + 'rlm;': '\u200f', + 'rmoust;': '\u23b1', + 'rmoustache;': '\u23b1', + 'rnmid;': '\u2aee', + 'roang;': '\u27ed', + 'roarr;': '\u21fe', + 'robrk;': '\u27e7', + 'ropar;': '\u2986', + 'ropf;': '\u{01d563}', + 'roplus;': '\u2a2e', + 'rotimes;': '\u2a35', + 'rpar;': ')', + 'rpargt;': '\u2994', + 'rppolint;': '\u2a12', + 'rrarr;': '\u21c9', + 'rsaquo;': '\u203a', + 'rscr;': '\u{01d4c7}', + 'rsh;': '\u21b1', + 'rsqb;': ']', + 'rsquo;': '\u2019', + 'rsquor;': '\u2019', + 'rthree;': '\u22cc', + 'rtimes;': '\u22ca', + 'rtri;': '\u25b9', + 'rtrie;': '\u22b5', + 'rtrif;': '\u25b8', + 'rtriltri;': '\u29ce', + 'ruluhar;': '\u2968', + 'rx;': '\u211e', + 'sacute;': '\u015b', + 'sbquo;': '\u201a', + 'sc;': '\u227b', + 'scE;': '\u2ab4', + 'scap;': '\u2ab8', + 'scaron;': '\u0161', + 'sccue;': '\u227d', + 'sce;': '\u2ab0', + 'scedil;': '\u015f', + 'scirc;': '\u015d', + 'scnE;': '\u2ab6', + 'scnap;': '\u2aba', + 'scnsim;': '\u22e9', + 'scpolint;': '\u2a13', + 'scsim;': '\u227f', + 'scy;': '\u0441', + 'sdot;': '\u22c5', + 'sdotb;': '\u22a1', + 'sdote;': '\u2a66', + 'seArr;': '\u21d8', + 'searhk;': '\u2925', + 'searr;': '\u2198', + 'searrow;': '\u2198', + 'sect': '\xa7', + 'sect;': '\xa7', + 'semi;': ';', + 'seswar;': '\u2929', + 'setminus;': '\u2216', + 'setmn;': '\u2216', + 'sext;': '\u2736', + 'sfr;': '\u{01d530}', + 'sfrown;': '\u2322', + 'sharp;': '\u266f', + 'shchcy;': '\u0449', + 'shcy;': '\u0448', + 'shortmid;': '\u2223', + 'shortparallel;': '\u2225', + 'shy': '\xad', + 'shy;': '\xad', + 'sigma;': '\u03c3', + 'sigmaf;': '\u03c2', + 'sigmav;': '\u03c2', + 'sim;': '\u223c', + 'simdot;': '\u2a6a', + 'sime;': '\u2243', + 'simeq;': '\u2243', + 'simg;': '\u2a9e', + 'simgE;': '\u2aa0', + 'siml;': '\u2a9d', + 'simlE;': '\u2a9f', + 'simne;': '\u2246', + 'simplus;': '\u2a24', + 'simrarr;': '\u2972', + 'slarr;': '\u2190', + 'smallsetminus;': '\u2216', + 'smashp;': '\u2a33', + 'smeparsl;': '\u29e4', + 'smid;': '\u2223', + 'smile;': '\u2323', + 'smt;': '\u2aaa', + 'smte;': '\u2aac', + 'smtes;': '\u2aac\ufe00', + 'softcy;': '\u044c', + 'sol;': '/', + 'solb;': '\u29c4', + 'solbar;': '\u233f', + 'sopf;': '\u{01d564}', + 'spades;': '\u2660', + 'spadesuit;': '\u2660', + 'spar;': '\u2225', + 'sqcap;': '\u2293', + 'sqcaps;': '\u2293\ufe00', + 'sqcup;': '\u2294', + 'sqcups;': '\u2294\ufe00', + 'sqsub;': '\u228f', + 'sqsube;': '\u2291', + 'sqsubset;': '\u228f', + 'sqsubseteq;': '\u2291', + 'sqsup;': '\u2290', + 'sqsupe;': '\u2292', + 'sqsupset;': '\u2290', + 'sqsupseteq;': '\u2292', + 'squ;': '\u25a1', + 'square;': '\u25a1', + 'squarf;': '\u25aa', + 'squf;': '\u25aa', + 'srarr;': '\u2192', + 'sscr;': '\u{01d4c8}', + 'ssetmn;': '\u2216', + 'ssmile;': '\u2323', + 'sstarf;': '\u22c6', + 'star;': '\u2606', + 'starf;': '\u2605', + 'straightepsilon;': '\u03f5', + 'straightphi;': '\u03d5', + 'strns;': '\xaf', + 'sub;': '\u2282', + 'subE;': '\u2ac5', + 'subdot;': '\u2abd', + 'sube;': '\u2286', + 'subedot;': '\u2ac3', + 'submult;': '\u2ac1', + 'subnE;': '\u2acb', + 'subne;': '\u228a', + 'subplus;': '\u2abf', + 'subrarr;': '\u2979', + 'subset;': '\u2282', + 'subseteq;': '\u2286', + 'subseteqq;': '\u2ac5', + 'subsetneq;': '\u228a', + 'subsetneqq;': '\u2acb', + 'subsim;': '\u2ac7', + 'subsub;': '\u2ad5', + 'subsup;': '\u2ad3', + 'succ;': '\u227b', + 'succapprox;': '\u2ab8', + 'succcurlyeq;': '\u227d', + 'succeq;': '\u2ab0', + 'succnapprox;': '\u2aba', + 'succneqq;': '\u2ab6', + 'succnsim;': '\u22e9', + 'succsim;': '\u227f', + 'sum;': '\u2211', + 'sung;': '\u266a', + 'sup1': '\xb9', + 'sup1;': '\xb9', + 'sup2': '\xb2', + 'sup2;': '\xb2', + 'sup3': '\xb3', + 'sup3;': '\xb3', + 'sup;': '\u2283', + 'supE;': '\u2ac6', + 'supdot;': '\u2abe', + 'supdsub;': '\u2ad8', + 'supe;': '\u2287', + 'supedot;': '\u2ac4', + 'suphsol;': '\u27c9', + 'suphsub;': '\u2ad7', + 'suplarr;': '\u297b', + 'supmult;': '\u2ac2', + 'supnE;': '\u2acc', + 'supne;': '\u228b', + 'supplus;': '\u2ac0', + 'supset;': '\u2283', + 'supseteq;': '\u2287', + 'supseteqq;': '\u2ac6', + 'supsetneq;': '\u228b', + 'supsetneqq;': '\u2acc', + 'supsim;': '\u2ac8', + 'supsub;': '\u2ad4', + 'supsup;': '\u2ad6', + 'swArr;': '\u21d9', + 'swarhk;': '\u2926', + 'swarr;': '\u2199', + 'swarrow;': '\u2199', + 'swnwar;': '\u292a', + 'szlig': '\xdf', + 'szlig;': '\xdf', + 'target;': '\u2316', + 'tau;': '\u03c4', + 'tbrk;': '\u23b4', + 'tcaron;': '\u0165', + 'tcedil;': '\u0163', + 'tcy;': '\u0442', + 'tdot;': '\u20db', + 'telrec;': '\u2315', + 'tfr;': '\u{01d531}', + 'there4;': '\u2234', + 'therefore;': '\u2234', + 'theta;': '\u03b8', + 'thetasym;': '\u03d1', + 'thetav;': '\u03d1', + 'thickapprox;': '\u2248', + 'thicksim;': '\u223c', + 'thinsp;': '\u2009', + 'thkap;': '\u2248', + 'thksim;': '\u223c', + 'thorn': '\xfe', + 'thorn;': '\xfe', + 'tilde;': '\u02dc', + 'times': '\xd7', + 'times;': '\xd7', + 'timesb;': '\u22a0', + 'timesbar;': '\u2a31', + 'timesd;': '\u2a30', + 'tint;': '\u222d', + 'toea;': '\u2928', + 'top;': '\u22a4', + 'topbot;': '\u2336', + 'topcir;': '\u2af1', + 'topf;': '\u{01d565}', + 'topfork;': '\u2ada', + 'tosa;': '\u2929', + 'tprime;': '\u2034', + 'trade;': '\u2122', + 'triangle;': '\u25b5', + 'triangledown;': '\u25bf', + 'triangleleft;': '\u25c3', + 'trianglelefteq;': '\u22b4', + 'triangleq;': '\u225c', + 'triangleright;': '\u25b9', + 'trianglerighteq;': '\u22b5', + 'tridot;': '\u25ec', + 'trie;': '\u225c', + 'triminus;': '\u2a3a', + 'triplus;': '\u2a39', + 'trisb;': '\u29cd', + 'tritime;': '\u2a3b', + 'trpezium;': '\u23e2', + 'tscr;': '\u{01d4c9}', + 'tscy;': '\u0446', + 'tshcy;': '\u045b', + 'tstrok;': '\u0167', + 'twixt;': '\u226c', + 'twoheadleftarrow;': '\u219e', + 'twoheadrightarrow;': '\u21a0', + 'uArr;': '\u21d1', + 'uHar;': '\u2963', + 'uacute': '\xfa', + 'uacute;': '\xfa', + 'uarr;': '\u2191', + 'ubrcy;': '\u045e', + 'ubreve;': '\u016d', + 'ucirc': '\xfb', + 'ucirc;': '\xfb', + 'ucy;': '\u0443', + 'udarr;': '\u21c5', + 'udblac;': '\u0171', + 'udhar;': '\u296e', + 'ufisht;': '\u297e', + 'ufr;': '\u{01d532}', + 'ugrave': '\xf9', + 'ugrave;': '\xf9', + 'uharl;': '\u21bf', + 'uharr;': '\u21be', + 'uhblk;': '\u2580', + 'ulcorn;': '\u231c', + 'ulcorner;': '\u231c', + 'ulcrop;': '\u230f', + 'ultri;': '\u25f8', + 'umacr;': '\u016b', + 'uml': '\xa8', + 'uml;': '\xa8', + 'uogon;': '\u0173', + 'uopf;': '\u{01d566}', + 'uparrow;': '\u2191', + 'updownarrow;': '\u2195', + 'upharpoonleft;': '\u21bf', + 'upharpoonright;': '\u21be', + 'uplus;': '\u228e', + 'upsi;': '\u03c5', + 'upsih;': '\u03d2', + 'upsilon;': '\u03c5', + 'upuparrows;': '\u21c8', + 'urcorn;': '\u231d', + 'urcorner;': '\u231d', + 'urcrop;': '\u230e', + 'uring;': '\u016f', + 'urtri;': '\u25f9', + 'uscr;': '\u{01d4ca}', + 'utdot;': '\u22f0', + 'utilde;': '\u0169', + 'utri;': '\u25b5', + 'utrif;': '\u25b4', + 'uuarr;': '\u21c8', + 'uuml': '\xfc', + 'uuml;': '\xfc', + 'uwangle;': '\u29a7', + 'vArr;': '\u21d5', + 'vBar;': '\u2ae8', + 'vBarv;': '\u2ae9', + 'vDash;': '\u22a8', + 'vangrt;': '\u299c', + 'varepsilon;': '\u03f5', + 'varkappa;': '\u03f0', + 'varnothing;': '\u2205', + 'varphi;': '\u03d5', + 'varpi;': '\u03d6', + 'varpropto;': '\u221d', + 'varr;': '\u2195', + 'varrho;': '\u03f1', + 'varsigma;': '\u03c2', + 'varsubsetneq;': '\u228a\ufe00', + 'varsubsetneqq;': '\u2acb\ufe00', + 'varsupsetneq;': '\u228b\ufe00', + 'varsupsetneqq;': '\u2acc\ufe00', + 'vartheta;': '\u03d1', + 'vartriangleleft;': '\u22b2', + 'vartriangleright;': '\u22b3', + 'vcy;': '\u0432', + 'vdash;': '\u22a2', + 'vee;': '\u2228', + 'veebar;': '\u22bb', + 'veeeq;': '\u225a', + 'vellip;': '\u22ee', + 'verbar;': '|', + 'vert;': '|', + 'vfr;': '\u{01d533}', + 'vltri;': '\u22b2', + 'vnsub;': '\u2282\u20d2', + 'vnsup;': '\u2283\u20d2', + 'vopf;': '\u{01d567}', + 'vprop;': '\u221d', + 'vrtri;': '\u22b3', + 'vscr;': '\u{01d4cb}', + 'vsubnE;': '\u2acb\ufe00', + 'vsubne;': '\u228a\ufe00', + 'vsupnE;': '\u2acc\ufe00', + 'vsupne;': '\u228b\ufe00', + 'vzigzag;': '\u299a', + 'wcirc;': '\u0175', + 'wedbar;': '\u2a5f', + 'wedge;': '\u2227', + 'wedgeq;': '\u2259', + 'weierp;': '\u2118', + 'wfr;': '\u{01d534}', + 'wopf;': '\u{01d568}', + 'wp;': '\u2118', + 'wr;': '\u2240', + 'wreath;': '\u2240', + 'wscr;': '\u{01d4cc}', + 'xcap;': '\u22c2', + 'xcirc;': '\u25ef', + 'xcup;': '\u22c3', + 'xdtri;': '\u25bd', + 'xfr;': '\u{01d535}', + 'xhArr;': '\u27fa', + 'xharr;': '\u27f7', + 'xi;': '\u03be', + 'xlArr;': '\u27f8', + 'xlarr;': '\u27f5', + 'xmap;': '\u27fc', + 'xnis;': '\u22fb', + 'xodot;': '\u2a00', + 'xopf;': '\u{01d569}', + 'xoplus;': '\u2a01', + 'xotime;': '\u2a02', + 'xrArr;': '\u27f9', + 'xrarr;': '\u27f6', + 'xscr;': '\u{01d4cd}', + 'xsqcup;': '\u2a06', + 'xuplus;': '\u2a04', + 'xutri;': '\u25b3', + 'xvee;': '\u22c1', + 'xwedge;': '\u22c0', + 'yacute': '\xfd', + 'yacute;': '\xfd', + 'yacy;': '\u044f', + 'ycirc;': '\u0177', + 'ycy;': '\u044b', + 'yen': '\xa5', + 'yen;': '\xa5', + 'yfr;': '\u{01d536}', + 'yicy;': '\u0457', + 'yopf;': '\u{01d56a}', + 'yscr;': '\u{01d4ce}', + 'yucy;': '\u044e', + 'yuml': '\xff', + 'yuml;': '\xff', + 'zacute;': '\u017a', + 'zcaron;': '\u017e', + 'zcy;': '\u0437', + 'zdot;': '\u017c', + 'zeetrf;': '\u2128', + 'zeta;': '\u03b6', + 'zfr;': '\u{01d537}', + 'zhcy;': '\u0436', + 'zigrarr;': '\u21dd', + 'zopf;': '\u{01d56b}', + 'zscr;': '\u{01d4cf}', + 'zwj;': '\u200d', + 'zwnj;': '\u200c', }; const Map<int, String> replacementCharacters = { - 0x00: "\uFFFD", - 0x0d: "\u000D", - 0x80: "\u20AC", - 0x81: "\u0081", - 0x82: "\u201A", - 0x83: "\u0192", - 0x84: "\u201E", - 0x85: "\u2026", - 0x86: "\u2020", - 0x87: "\u2021", - 0x88: "\u02C6", - 0x89: "\u2030", - 0x8A: "\u0160", - 0x8B: "\u2039", - 0x8C: "\u0152", - 0x8D: "\u008D", - 0x8E: "\u017D", - 0x8F: "\u008F", - 0x90: "\u0090", - 0x91: "\u2018", - 0x92: "\u2019", - 0x93: "\u201C", - 0x94: "\u201D", - 0x95: "\u2022", - 0x96: "\u2013", - 0x97: "\u2014", - 0x98: "\u02DC", - 0x99: "\u2122", - 0x9A: "\u0161", - 0x9B: "\u203A", - 0x9C: "\u0153", - 0x9D: "\u009D", - 0x9E: "\u017E", - 0x9F: "\u0178" + 0x00: '\uFFFD', + 0x0d: '\u000D', + 0x80: '\u20AC', + 0x81: '\u0081', + 0x82: '\u201A', + 0x83: '\u0192', + 0x84: '\u201E', + 0x85: '\u2026', + 0x86: '\u2020', + 0x87: '\u2021', + 0x88: '\u02C6', + 0x89: '\u2030', + 0x8A: '\u0160', + 0x8B: '\u2039', + 0x8C: '\u0152', + 0x8D: '\u008D', + 0x8E: '\u017D', + 0x8F: '\u008F', + 0x90: '\u0090', + 0x91: '\u2018', + 0x92: '\u2019', + 0x93: '\u201C', + 0x94: '\u201D', + 0x95: '\u2022', + 0x96: '\u2013', + 0x97: '\u2014', + 0x98: '\u02DC', + 0x99: '\u2122', + 0x9A: '\u0161', + 0x9B: '\u203A', + 0x9C: '\u0153', + 0x9D: '\u009D', + 0x9E: '\u017E', + 0x9F: '\u0178' }; const Map<String, String> encodings = { diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 939bf41e8..3fa49e012 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -14,12 +14,13 @@ class ElementCssClassSet extends _CssClassSetImpl { ElementCssClassSet(this._element); + @override Set<String> readClasses() { var s = LinkedHashSet<String>(); var classname = _element.className; - for (String name in classname.split(' ')) { - String trimmed = name.trim(); + for (var name in classname.split(' ')) { + var trimmed = name.trim(); if (trimmed.isNotEmpty) { s.add(trimmed); } @@ -27,6 +28,7 @@ class ElementCssClassSet extends _CssClassSetImpl { return s; } + @override void writeClasses(Set<String> s) { _element.className = s.join(' '); } @@ -49,6 +51,7 @@ abstract class CssClassSet implements Set<String> { /// /// This is the Dart equivalent of jQuery's /// [hasClass](http://api.jquery.com/hasClass/). + @override bool contains(Object value); /// Add the class [value] to element. @@ -60,6 +63,7 @@ abstract class CssClassSet implements Set<String> { /// the set, otherwise false. /// /// If this corresponds to many elements, null is always returned. + @override bool add(String value); /// Remove the class [value] from element, and return true on successful @@ -67,18 +71,21 @@ abstract class CssClassSet implements Set<String> { /// /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). + @override bool remove(Object value); /// Add all classes specified in [iterable] to element. /// /// This is the Dart equivalent of jQuery's /// [addClass](http://api.jquery.com/addClass/). + @override void addAll(Iterable<String> iterable); /// Remove all classes specified in [iterable] from element. /// /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). + @override void removeAll(Iterable<Object> iterable); /// Toggles all classes specified in [iterable] on element. @@ -93,6 +100,7 @@ abstract class CssClassSet implements Set<String> { } abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { + @override String toString() { return readClasses().join(' '); } @@ -102,10 +110,11 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// /// If [shouldAdd] is true, then we always add that [value] to the element. If /// [shouldAdd] is false then we always remove [value] from the element. + @override bool toggle(String value, [bool shouldAdd]) { - Set<String> s = readClasses(); - bool result = false; - if (shouldAdd == null) shouldAdd = !s.contains(value); + var s = readClasses(); + var result = false; + shouldAdd ??= !s.contains(value); if (shouldAdd) { s.add(value); result = true; @@ -118,10 +127,13 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// Returns [:true:] if classes cannot be added or removed from this /// [:CssClassSet:]. + @override bool get frozen => false; + @override Iterator<String> get iterator => readClasses().iterator; + @override int get length => readClasses().length; // interface Set - BEGIN @@ -129,17 +141,21 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// /// This is the Dart equivalent of jQuery's /// [hasClass](http://api.jquery.com/hasClass/). + @override bool contains(Object value) => readClasses().contains(value); /// Lookup from the Set interface. Not interesting for a String set. + @override String lookup(Object value) => contains(value) ? value as String : null; + @override Set<String> toSet() => readClasses().toSet(); /// Add the class [value] to element. /// /// This is the Dart equivalent of jQuery's /// [addClass](http://api.jquery.com/addClass/). + @override bool add(String value) { // TODO - figure out if we need to do any validation here // or if the browser natively does enough. @@ -151,10 +167,11 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). + @override bool remove(Object value) { if (value is! String) return false; - Set<String> s = readClasses(); - bool result = s.remove(value); + var s = readClasses(); + var result = s.remove(value); writeClasses(s); return result; } @@ -167,6 +184,7 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// If [shouldAdd] is true, then we always add all the classes in [iterable] /// element. If [shouldAdd] is false then we always remove all the classes in /// [iterable] from the element. + @override void toggleAll(Iterable<String> iterable, [bool shouldAdd]) { iterable.forEach((e) => toggle(e, shouldAdd)); } @@ -178,8 +196,8 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// /// After f returns, the modified set is written to the /// className property of this element. - bool _modify(bool f(Set<String> s)) { - Set<String> s = readClasses(); + bool _modify(bool Function(Set<String>) f) { + var s = readClasses(); var ret = f(s); writeClasses(s); return ret; diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index d0f40d6f9..51766a9d0 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -17,7 +17,7 @@ class EncodingBytes { String _next() { var p = __position = __position + 1; if (p >= _length) { - throw StateError("No more elements"); + throw StateError('No more elements'); } else if (p < 0) { throw RangeError(p); } @@ -27,7 +27,7 @@ class EncodingBytes { String _previous() { var p = __position; if (p >= _length) { - throw StateError("No more elements"); + throw StateError('No more elements'); } else if (p < 0) { throw RangeError(p); } @@ -37,14 +37,14 @@ class EncodingBytes { set _position(int value) { if (__position >= _length) { - throw StateError("No more elements"); + throw StateError('No more elements'); } __position = value; } int get _position { if (__position >= _length) { - throw StateError("No more elements"); + throw StateError('No more elements'); } if (__position >= 0) { return __position; @@ -57,7 +57,7 @@ class EncodingBytes { /// Skip past a list of characters. Defaults to skipping [isWhitespace]. String _skipChars([_CharPredicate skipChars]) { - if (skipChars == null) skipChars = isWhitespace; + skipChars ??= isWhitespace; var p = _position; // use property for the error-checking while (p < _length) { var c = _bytes[p]; @@ -108,12 +108,12 @@ class EncodingBytes { __position = newPosition + bytes.length - 1; return true; } else { - throw StateError("No more elements"); + throw StateError('No more elements'); } } String _slice(int start, [int end]) { - if (end == null) end = _length; + end ??= _length; if (end < 0) end += _length; return _bytes.substring(start, end); } @@ -140,12 +140,12 @@ class EncodingParser { String getEncoding() { final methodDispatch = [ - _DispatchEntry("<!--", _handleComment), - _DispatchEntry("<meta", _handleMeta), - _DispatchEntry("</", _handlePossibleEndTag), - _DispatchEntry("<!", _handleOther), - _DispatchEntry("<?", _handleOther), - _DispatchEntry("<", _handlePossibleStartTag), + _DispatchEntry('<!--', _handleComment), + _DispatchEntry('<meta', _handleMeta), + _DispatchEntry('</', _handlePossibleEndTag), + _DispatchEntry('<!', _handleOther), + _DispatchEntry('<?', _handleOther), + _DispatchEntry('<', _handlePossibleStartTag), ]; try { @@ -169,7 +169,7 @@ class EncodingParser { } /// Skip over comments. - bool _handleComment() => _data._jumpTo("-->"); + bool _handleComment() => _data._jumpTo('-->'); bool _handleMeta() { if (!isWhitespace(_data._currentByte)) { @@ -182,14 +182,14 @@ class EncodingParser { var attr = _getAttribute(); if (attr == null) return true; - if (attr[0] == "charset") { + if (attr[0] == 'charset') { var tentativeEncoding = attr[1]; var codec = codecName(tentativeEncoding); if (codec != null) { _encoding = codec; return false; } - } else if (attr[0] == "content") { + } else if (attr[0] == 'content') { var contentParser = ContentAttrParser(EncodingBytes(attr[1])); var tentativeEncoding = contentParser.parse(); var codec = codecName(tentativeEncoding); @@ -221,7 +221,7 @@ class EncodingParser { } var c = _data._skipUntil(_isSpaceOrAngleBracket); - if (c == "<") { + if (c == '<') { // return to the first step in the overall "two step" algorithm // reprocessing the < byte _data._previous(); @@ -235,15 +235,15 @@ class EncodingParser { return true; } - bool _handleOther() => _data._jumpTo(">"); + bool _handleOther() => _data._jumpTo('>'); /// Return a name,value pair for the next attribute in the stream, /// if one is found, or null List<String> _getAttribute() { // Step 1 (skip chars) - var c = _data._skipChars((x) => x == "/" || isWhitespace(x)); + var c = _data._skipChars((x) => x == '/' || isWhitespace(x)); // Step 2 - if (c == ">" || c == null) { + if (c == '>' || c == null) { return null; } // Step 3 @@ -253,15 +253,15 @@ class EncodingParser { while (true) { if (c == null) { return null; - } else if (c == "=" && attrName.isNotEmpty) { + } else if (c == '=' && attrName.isNotEmpty) { break; } else if (isWhitespace(c)) { // Step 6! c = _data._skipChars(); c = _data._next(); break; - } else if (c == "/" || c == ">") { - return [attrName.join(), ""]; + } else if (c == '/' || c == '>') { + return [attrName.join(), '']; } else if (isLetter(c)) { attrName.add(c.toLowerCase()); } else { @@ -271,9 +271,9 @@ class EncodingParser { c = _data._next(); } // Step 7 - if (c != "=") { + if (c != '=') { _data._previous(); - return [attrName.join(), ""]; + return [attrName.join(), '']; } // Step 8 _data._next(); @@ -298,8 +298,8 @@ class EncodingParser { attrValue.add(c); } } - } else if (c == ">") { - return [attrName.join(), ""]; + } else if (c == '>') { + return [attrName.join(), '']; } else if (c == null) { return null; } else if (isLetter(c)) { @@ -332,10 +332,10 @@ class ContentAttrParser { try { // Check if the attr name is charset // otherwise return - data._jumpTo("charset"); + data._jumpTo('charset'); data._position += 1; data._skipChars(); - if (data._currentByte != "=") { + if (data._currentByte != '=') { // If there is no = sign keep looking for attrs return null; } @@ -369,7 +369,7 @@ class ContentAttrParser { } bool _isSpaceOrAngleBracket(String char) { - return char == ">" || char == "<" || isWhitespace(char); + return char == '>' || char == '<' || isWhitespace(char); } typedef _CharPredicate = bool Function(String char); diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 4590c5d83..0b72da7e6 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -91,14 +91,12 @@ class HtmlInputStream { _lineStarts = <int>[0]; _chars = <int>[]; - if (_rawChars == null) { - _rawChars = _decodeBytes(charEncodingName, _rawBytes); - } + _rawChars ??= _decodeBytes(charEncodingName, _rawBytes); - bool skipNewline = false; - bool wasSurrogatePair = false; - for (int i = 0; i < _rawChars.length; i++) { - int c = _rawChars[i]; + var skipNewline = false; + var wasSurrogatePair = false; + for (var i = 0; i < _rawChars.length; i++) { + var c = _rawChars[i]; if (skipNewline) { skipNewline = false; if (c == NEWLINE) continue; @@ -241,7 +239,7 @@ class HtmlInputStream { /// Returns a string of characters from the stream up to but not /// including any character in 'characters' or EOF. String charsUntil(String characters, [bool opposite = false]) { - int start = _offset; + var start = _offset; String c; while ((c = peekChar()) != null && characters.contains(c) == opposite) { _offset += c.codeUnits.length; @@ -313,7 +311,7 @@ bool _invalidUnicode(int c) { /// string doesn't correspond to a valid encoding. String codecName(String encoding) { final asciiPunctuation = RegExp( - "[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]"); + '[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]'); if (encoding == null) return null; var canonicalName = encoding.replaceAll(asciiPunctuation, '').toLowerCase(); @@ -324,7 +322,7 @@ String codecName(String encoding) { /// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is /// used in HTML to detect the UTF- bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { - int end = length != null ? offset + length : bytes.length; + var end = length != null ? offset + length : bytes.length; return (offset + 3) <= end && bytes[offset] == 0xEF && bytes[offset + 1] == 0xBB && diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 63aeea6ef..ef271abd4 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -7,40 +7,52 @@ abstract class ListProxy<E> extends ListBase<E> { /// The inner [List<T>] with the actual storage. final List<E> _list = <E>[]; + @override bool remove(Object item) => _list.remove(item); + @override int get length => _list.length; // From Iterable + @override Iterator<E> get iterator => _list.iterator; // From List + @override E operator [](int index) => _list[index]; + @override operator []=(int index, E value) { _list[index] = value; } + @override set length(int value) { _list.length = value; } + @override void add(E value) { _list.add(value); } + @override void insert(int index, E item) => _list.insert(index, item); + @override void addAll(Iterable<E> collection) { _list.addAll(collection); } + @override void insertAll(int index, Iterable<E> iterable) { _list.insertAll(index, iterable); } + @override E removeAt(int index) => _list.removeAt(index); + @override void removeRange(int start, int length) { _list.removeRange(start, length); } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 050370796..0c660b7af 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -58,9 +58,11 @@ class SelectorEvaluator extends Visitor { } } + @override bool visitSelectorGroup(SelectorGroup group) => group.selectors.any(visitSelector); + @override bool visitSelector(Selector selector) { var old = _element; var result = true; @@ -123,13 +125,14 @@ class SelectorEvaluator extends Visitor { return result; } - _unimplemented(SimpleSelector selector) => + UnimplementedError _unimplemented(SimpleSelector selector) => UnimplementedError("'$selector' selector of type " - "${selector.runtimeType} is not implemented"); + '${selector.runtimeType} is not implemented'); - _unsupported(selector) => + FormatException _unsupported(selector) => FormatException("'$selector' is not a valid selector"); + @override bool visitPseudoClassSelector(PseudoClassSelector selector) { switch (selector.name) { // http://dev.w3.org/csswg/selectors-4/#structural-pseudos @@ -179,6 +182,7 @@ class SelectorEvaluator extends Visitor { throw _unimplemented(selector); } + @override bool visitPseudoElementSelector(PseudoElementSelector selector) { // :before, :after, :first-letter/line can't match DOM elements. if (_isLegacyPsuedoClass(selector.name)) return false; @@ -198,9 +202,11 @@ class SelectorEvaluator extends Visitor { } } + @override bool visitPseudoElementFunctionSelector(PseudoElementFunctionSelector s) => throw _unimplemented(s); + @override bool visitPseudoClassFunctionSelector(PseudoClassFunctionSelector selector) { switch (selector.name) { // http://dev.w3.org/csswg/selectors-4/#child-index @@ -239,6 +245,7 @@ class SelectorEvaluator extends Visitor { return null; } + @override bool visitNamespaceSelector(NamespaceSelector selector) { // Match element tag name if (!selector.nameAsSimpleSelector.visit(this)) return false; @@ -250,20 +257,25 @@ class SelectorEvaluator extends Visitor { throw _unimplemented(selector); } + @override bool visitElementSelector(ElementSelector selector) => selector.isWildcard || _element.localName == selector.name.toLowerCase(); + @override bool visitIdSelector(IdSelector selector) => _element.id == selector.name; + @override bool visitClassSelector(ClassSelector selector) => _element.classes.contains(selector.name); // TODO(jmesserly): negation should support any selectors in level 4, // not just simple selectors. // http://dev.w3.org/csswg/selectors-4/#negation + @override bool visitNegationSelector(NegationSelector selector) => !selector.negationArg.visit(this); + @override bool visitAttributeSelector(AttributeSelector selector) { // Match name first var value = _element.attributes[selector.name.toLowerCase()]; diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index ea0a855b3..e92ec8e7e 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -39,6 +39,7 @@ class StartTagToken extends TagToken { this.namespace}) : super(name, selfClosing); + @override int get kind => TokenKind.startTag; } @@ -46,6 +47,7 @@ class EndTagToken extends TagToken { EndTagToken(String name, {bool selfClosing = false}) : super(name, selfClosing); + @override int get kind => TokenKind.endTag; } @@ -77,12 +79,14 @@ class ParseErrorToken extends StringToken { ParseErrorToken(String data, {this.messageParams}) : super(data); + @override int get kind => TokenKind.parseError; } class CharactersToken extends StringToken { CharactersToken([String data]) : super(data); + @override int get kind => TokenKind.characters; /// Replaces the token's [data]. This should only be used to wholly replace @@ -96,23 +100,26 @@ class CharactersToken extends StringToken { class SpaceCharactersToken extends StringToken { SpaceCharactersToken([String data]) : super(data); + @override int get kind => TokenKind.spaceCharacters; } class CommentToken extends StringToken { CommentToken([String data]) : super(data); + @override int get kind => TokenKind.comment; } class DoctypeToken extends Token { String publicId; String systemId; - String name = ""; + String name = ''; bool correct; DoctypeToken({this.publicId, this.systemId, this.correct = false}); + @override int get kind => TokenKind.doctype; } diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 638663ec0..cf677443b 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -84,6 +84,7 @@ class HtmlTokenizer implements Iterator<Token> { StringToken get currentStringToken => currentToken; Token _current; + @override Token get current => _current; final StringBuffer _attributeName = StringBuffer(); @@ -107,7 +108,7 @@ class HtmlTokenizer implements Iterator<Token> { void _markAttributeNameEnd(int offset) => _markAttributeEnd(offset); void _addAttribute(String name) { - if (_attributes == null) _attributes = []; + _attributes ??= []; _attributeName.clear(); _attributeName.write(name); _attributeValue.clear(); @@ -121,6 +122,7 @@ class HtmlTokenizer implements Iterator<Token> { /// We do our usually processing through the states and when we have a token /// to return we yield the token which pauses processing until the next token /// is requested. + @override bool moveNext() { // Start processing. When EOF is reached state will return false; // instead of true and the loop will terminate. @@ -154,7 +156,7 @@ class HtmlTokenizer implements Iterator<Token> { /// Adds a token to the queue. Sets the span if needed. void _addToken(Token token) { if (generateSpans && token.span == null) { - int offset = stream.position; + var offset = stream.position; token.span = stream.fileInfo.span(_lastOffset, offset); if (token is! ParseErrorToken) { _lastOffset = offset; @@ -190,13 +192,13 @@ class HtmlTokenizer implements Iterator<Token> { // Certain characters get replaced with others var char = replacementCharacters[charAsInt]; if (char != null) { - _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", - messageParams: {"charAsInt": charAsInt})); + _addToken(ParseErrorToken('illegal-codepoint-for-numeric-entity', + messageParams: {'charAsInt': charAsInt})); } else if ((0xD800 <= charAsInt && charAsInt <= 0xDFFF) || (charAsInt > 0x10FFFF)) { - char = "\uFFFD"; - _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", - messageParams: {"charAsInt": charAsInt})); + char = '\uFFFD'; + _addToken(ParseErrorToken('illegal-codepoint-for-numeric-entity', + messageParams: {'charAsInt': charAsInt})); } else { // Should speed up this check somehow (e.g. move the set to a constant) if ((0x0001 <= charAsInt && charAsInt <= 0x0008) || @@ -240,16 +242,16 @@ class HtmlTokenizer implements Iterator<Token> { 0x10FFFE, 0x10FFFF ].contains(charAsInt)) { - _addToken(ParseErrorToken("illegal-codepoint-for-numeric-entity", - messageParams: {"charAsInt": charAsInt})); + _addToken(ParseErrorToken('illegal-codepoint-for-numeric-entity', + messageParams: {'charAsInt': charAsInt})); } char = String.fromCharCodes([charAsInt]); } // Discard the ; if present. Otherwise, put it back on the queue and // invoke parseError on parser. - if (c != ";") { - _addToken(ParseErrorToken("numeric-entity-without-semicolon")); + if (c != ';') { + _addToken(ParseErrorToken('numeric-entity-without-semicolon')); stream.unget(c); } return char; @@ -257,7 +259,7 @@ class HtmlTokenizer implements Iterator<Token> { void consumeEntity({String allowedChar, bool fromAttribute = false}) { // Initialise to the default output for when no entity is matched - var output = "&"; + var output = '&'; var charStack = [stream.char()]; if (isWhitespace(charStack[0]) || @@ -266,9 +268,9 @@ class HtmlTokenizer implements Iterator<Token> { charStack[0] == eof || allowedChar == charStack[0]) { stream.unget(charStack[0]); - } else if (charStack[0] == "#") { + } else if (charStack[0] == '#') { // Read the next character to see if it's hex or decimal - bool hex = false; + var hex = false; charStack.add(stream.char()); if (charStack.last == 'x' || charStack.last == 'X') { hex = true; @@ -283,9 +285,9 @@ class HtmlTokenizer implements Iterator<Token> { output = consumeNumberEntity(hex); } else { // No digits found - _addToken(ParseErrorToken("expected-numeric-entity")); + _addToken(ParseErrorToken('expected-numeric-entity')); stream.unget(charStack.removeLast()); - output = "&${charStack.join()}"; + output = '&${charStack.join()}'; } } else { // At this point in the process might have named entity. Entities @@ -293,8 +295,7 @@ class HtmlTokenizer implements Iterator<Token> { // // Consume characters and compare to these to a substring of the // entity names in the list until the substring no longer matches. - var filteredEntityList = entitiesByFirstChar[charStack[0]]; - if (filteredEntityList == null) filteredEntityList = const []; + var filteredEntityList = entitiesByFirstChar[charStack[0]] ?? const []; while (charStack.last != eof) { var name = charStack.join(); @@ -325,24 +326,24 @@ class HtmlTokenizer implements Iterator<Token> { if (entityName != null) { var lastChar = entityName[entityName.length - 1]; - if (lastChar != ";") { - _addToken(ParseErrorToken("named-entity-without-semicolon")); + if (lastChar != ';') { + _addToken(ParseErrorToken('named-entity-without-semicolon')); } - if (lastChar != ";" && + if (lastChar != ';' && fromAttribute && (isLetterOrDigit(charStack[entityLen]) || charStack[entityLen] == '=')) { stream.unget(charStack.removeLast()); - output = "&${charStack.join()}"; + output = '&${charStack.join()}'; } else { output = entities[entityName]; stream.unget(charStack.removeLast()); output = '$output${slice(charStack, entityLen).join()}'; } } else { - _addToken(ParseErrorToken("expected-named-entity")); + _addToken(ParseErrorToken('expected-named-entity')); stream.unget(charStack.removeLast()); - output = "&${charStack.join()}"; + output = '&${charStack.join()}'; } } if (fromAttribute) { @@ -375,10 +376,10 @@ class HtmlTokenizer implements Iterator<Token> { } if (token is EndTagToken) { if (_attributes != null) { - _addToken(ParseErrorToken("attributes-in-end-tag")); + _addToken(ParseErrorToken('attributes-in-end-tag')); } if (token.selfClosing) { - _addToken(ParseErrorToken("this-closing-flag-on-end-tag")); + _addToken(ParseErrorToken('this-closing-flag-on-end-tag')); } } else if (token is StartTagToken) { // HTML5 specific normalizations to the token stream. @@ -402,13 +403,13 @@ class HtmlTokenizer implements Iterator<Token> { bool dataState() { var data = stream.char(); - if (data == "&") { + if (data == '&') { state = entityDataState; - } else if (data == "<") { + } else if (data == '<') { state = tagOpenState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\u0000")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\u0000')); } else if (data == eof) { // Tokenization ends. return false; @@ -422,7 +423,7 @@ class HtmlTokenizer implements Iterator<Token> { // have already been appended to lastFourChars and will have broken // any <!-- or --> sequences } else { - var chars = stream.charsUntil("&<\u0000"); + var chars = stream.charsUntil('&<\u0000'); _addToken(CharactersToken('$data$chars')); } return true; @@ -436,16 +437,16 @@ class HtmlTokenizer implements Iterator<Token> { bool rcdataState() { var data = stream.char(); - if (data == "&") { + if (data == '&') { state = characterReferenceInRcdata; - } else if (data == "<") { + } else if (data == '<') { state = rcdataLessThanSignState; } else if (data == eof) { // Tokenization ends. return false; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else if (isWhitespace(data)) { // Directly after emitting a token you switch back to the "data // state". At that point spaceCharacters are important so they are @@ -453,7 +454,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(SpaceCharactersToken( '$data${stream.charsUntil(spaceCharacters, true)}')); } else { - var chars = stream.charsUntil("&<"); + var chars = stream.charsUntil('&<'); _addToken(CharactersToken('$data$chars')); } return true; @@ -467,34 +468,34 @@ class HtmlTokenizer implements Iterator<Token> { bool rawtextState() { var data = stream.char(); - if (data == "<") { + if (data == '<') { state = rawtextLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else if (data == eof) { // Tokenization ends. return false; } else { - var chars = stream.charsUntil("<\u0000"); - _addToken(CharactersToken("$data$chars")); + var chars = stream.charsUntil('<\u0000'); + _addToken(CharactersToken('$data$chars')); } return true; } bool scriptDataState() { var data = stream.char(); - if (data == "<") { + if (data == '<') { state = scriptDataLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else if (data == eof) { // Tokenization ends. return false; } else { - var chars = stream.charsUntil("<\u0000"); - _addToken(CharactersToken("$data$chars")); + var chars = stream.charsUntil('<\u0000'); + _addToken(CharactersToken('$data$chars')); } return true; } @@ -504,9 +505,9 @@ class HtmlTokenizer implements Iterator<Token> { if (data == eof) { // Tokenization ends. return false; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else { _addToken(CharactersToken('$data${stream.charsUntil("\u0000")}')); } @@ -515,29 +516,29 @@ class HtmlTokenizer implements Iterator<Token> { bool tagOpenState() { var data = stream.char(); - if (data == "!") { + if (data == '!') { state = markupDeclarationOpenState; - } else if (data == "/") { + } else if (data == '/') { state = closeTagOpenState; } else if (isLetter(data)) { currentToken = StartTagToken(data); state = tagNameState; - } else if (data == ">") { + } else if (data == '>') { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(ParseErrorToken("expected-tag-name-but-got-right-bracket")); - _addToken(CharactersToken("<>")); + _addToken(ParseErrorToken('expected-tag-name-but-got-right-bracket')); + _addToken(CharactersToken('<>')); state = dataState; - } else if (data == "?") { + } else if (data == '?') { // XXX In theory it could be something besides a tag name. But // do we really care? - _addToken(ParseErrorToken("expected-tag-name-but-got-question-mark")); + _addToken(ParseErrorToken('expected-tag-name-but-got-question-mark')); stream.unget(data); state = bogusCommentState; } else { // XXX - _addToken(ParseErrorToken("expected-tag-name")); - _addToken(CharactersToken("<")); + _addToken(ParseErrorToken('expected-tag-name')); + _addToken(CharactersToken('<')); stream.unget(data); state = dataState; } @@ -549,17 +550,17 @@ class HtmlTokenizer implements Iterator<Token> { if (isLetter(data)) { currentToken = EndTagToken(data); state = tagNameState; - } else if (data == ">") { - _addToken(ParseErrorToken("expected-closing-tag-but-got-right-bracket")); + } else if (data == '>') { + _addToken(ParseErrorToken('expected-closing-tag-but-got-right-bracket')); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-closing-tag-but-got-eof")); - _addToken(CharactersToken("</")); + _addToken(ParseErrorToken('expected-closing-tag-but-got-eof')); + _addToken(CharactersToken('</')); state = dataState; } else { // XXX data can be _'_... - _addToken(ParseErrorToken("expected-closing-tag-but-got-char", - messageParams: {"data": data})); + _addToken(ParseErrorToken('expected-closing-tag-but-got-char', + messageParams: {'data': data})); stream.unget(data); state = bogusCommentState; } @@ -570,15 +571,15 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { state = beforeAttributeNameState; - } else if (data == ">") { + } else if (data == '>') { emitCurrentToken(); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-tag-name")); + _addToken(ParseErrorToken('eof-in-tag-name')); state = dataState; - } else if (data == "/") { + } else if (data == '/') { state = selfClosingStartTagState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentTagToken.name = '${currentTagToken.name}\uFFFD'; } else { currentTagToken.name = '${currentTagToken.name}$data'; @@ -590,11 +591,11 @@ class HtmlTokenizer implements Iterator<Token> { bool rcdataLessThanSignState() { var data = stream.char(); - if (data == "/") { + if (data == '/') { _buffer.clear(); state = rcdataEndTagOpenState; } else { - _addToken(CharactersToken("<")); + _addToken(CharactersToken('<')); stream.unget(data); state = rcdataState; } @@ -607,7 +608,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = rcdataEndTagNameState; } else { - _addToken(CharactersToken("</")); + _addToken(CharactersToken('</')); stream.unget(data); state = rcdataState; } @@ -626,17 +627,17 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; - } else if (data == "/" && appropriate) { + } else if (data == '/' && appropriate) { currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; - } else if (data == ">" && appropriate) { + } else if (data == '>' && appropriate) { currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(CharactersToken("</$_buffer")); + _addToken(CharactersToken('</$_buffer')); stream.unget(data); state = rcdataState; } @@ -645,11 +646,11 @@ class HtmlTokenizer implements Iterator<Token> { bool rawtextLessThanSignState() { var data = stream.char(); - if (data == "/") { + if (data == '/') { _buffer.clear(); state = rawtextEndTagOpenState; } else { - _addToken(CharactersToken("<")); + _addToken(CharactersToken('<')); stream.unget(data); state = rawtextState; } @@ -662,7 +663,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = rawtextEndTagNameState; } else { - _addToken(CharactersToken("</")); + _addToken(CharactersToken('</')); stream.unget(data); state = rawtextState; } @@ -675,17 +676,17 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; - } else if (data == "/" && appropriate) { + } else if (data == '/' && appropriate) { currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; - } else if (data == ">" && appropriate) { + } else if (data == '>' && appropriate) { currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(CharactersToken("</$_buffer")); + _addToken(CharactersToken('</$_buffer')); stream.unget(data); state = rawtextState; } @@ -694,14 +695,14 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataLessThanSignState() { var data = stream.char(); - if (data == "/") { + if (data == '/') { _buffer.clear(); state = scriptDataEndTagOpenState; - } else if (data == "!") { - _addToken(CharactersToken("<!")); + } else if (data == '!') { + _addToken(CharactersToken('<!')); state = scriptDataEscapeStartState; } else { - _addToken(CharactersToken("<")); + _addToken(CharactersToken('<')); stream.unget(data); state = scriptDataState; } @@ -714,7 +715,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = scriptDataEndTagNameState; } else { - _addToken(CharactersToken("</")); + _addToken(CharactersToken('</')); stream.unget(data); state = scriptDataState; } @@ -727,17 +728,17 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; - } else if (data == "/" && appropriate) { + } else if (data == '/' && appropriate) { currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; - } else if (data == ">" && appropriate) { + } else if (data == '>' && appropriate) { currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(CharactersToken("</$_buffer")); + _addToken(CharactersToken('</$_buffer')); stream.unget(data); state = scriptDataState; } @@ -746,8 +747,8 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapeStartState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataEscapeStartDashState; } else { stream.unget(data); @@ -758,8 +759,8 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapeStartDashState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataEscapedDashDashState; } else { stream.unget(data); @@ -770,33 +771,33 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataEscapedDashState; - } else if (data == "<") { + } else if (data == '<') { state = scriptDataEscapedLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else if (data == eof) { state = dataState; } else { - var chars = stream.charsUntil("<-\u0000"); - _addToken(CharactersToken("$data$chars")); + var chars = stream.charsUntil('<-\u0000'); + _addToken(CharactersToken('$data$chars')); } return true; } bool scriptDataEscapedDashState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataEscapedDashDashState; - } else if (data == "<") { + } else if (data == '<') { state = scriptDataEscapedLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); state = scriptDataEscapedState; } else if (data == eof) { state = dataState; @@ -809,16 +810,16 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedDashDashState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); - } else if (data == "<") { + if (data == '-') { + _addToken(CharactersToken('-')); + } else if (data == '<') { state = scriptDataEscapedLessThanSignState; - } else if (data == ">") { - _addToken(CharactersToken(">")); + } else if (data == '>') { + _addToken(CharactersToken('>')); state = scriptDataState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); state = scriptDataEscapedState; } else if (data == eof) { state = dataState; @@ -831,16 +832,16 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataEscapedLessThanSignState() { var data = stream.char(); - if (data == "/") { + if (data == '/') { _buffer.clear(); state = scriptDataEscapedEndTagOpenState; } else if (isLetter(data)) { - _addToken(CharactersToken("<$data")); + _addToken(CharactersToken('<$data')); _buffer.clear(); _buffer.write(data); state = scriptDataDoubleEscapeStartState; } else { - _addToken(CharactersToken("<")); + _addToken(CharactersToken('<')); stream.unget(data); state = scriptDataEscapedState; } @@ -854,7 +855,7 @@ class HtmlTokenizer implements Iterator<Token> { _buffer.write(data); state = scriptDataEscapedEndTagNameState; } else { - _addToken(CharactersToken("</")); + _addToken(CharactersToken('</')); stream.unget(data); state = scriptDataEscapedState; } @@ -867,17 +868,17 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; - } else if (data == "/" && appropriate) { + } else if (data == '/' && appropriate) { currentToken = EndTagToken('$_buffer'); state = selfClosingStartTagState; - } else if (data == ">" && appropriate) { + } else if (data == '>' && appropriate) { currentToken = EndTagToken('$_buffer'); emitCurrentToken(); state = dataState; } else if (isLetter(data)) { _buffer.write(data); } else { - _addToken(CharactersToken("</$_buffer")); + _addToken(CharactersToken('</$_buffer')); stream.unget(data); state = scriptDataEscapedState; } @@ -886,9 +887,9 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapeStartState() { var data = stream.char(); - if (isWhitespace(data) || data == "/" || data == ">") { + if (isWhitespace(data) || data == '/' || data == '>') { _addToken(CharactersToken(data)); - if ('$_buffer'.toLowerCase() == "script") { + if ('$_buffer'.toLowerCase() == 'script') { state = scriptDataDoubleEscapedState; } else { state = scriptDataEscapedState; @@ -905,17 +906,17 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataDoubleEscapedDashState; - } else if (data == "<") { - _addToken(CharactersToken("<")); + } else if (data == '<') { + _addToken(CharactersToken('<')); state = scriptDataDoubleEscapedLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-script-in-script")); + _addToken(ParseErrorToken('eof-in-script-in-script')); state = dataState; } else { _addToken(CharactersToken(data)); @@ -925,18 +926,18 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedDashState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); + if (data == '-') { + _addToken(CharactersToken('-')); state = scriptDataDoubleEscapedDashDashState; - } else if (data == "<") { - _addToken(CharactersToken("<")); + } else if (data == '<') { + _addToken(CharactersToken('<')); state = scriptDataDoubleEscapedLessThanSignState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); state = scriptDataDoubleEscapedState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-script-in-script")); + _addToken(ParseErrorToken('eof-in-script-in-script')); state = dataState; } else { _addToken(CharactersToken(data)); @@ -949,20 +950,20 @@ class HtmlTokenizer implements Iterator<Token> { // (was "Dash" instead of "DashDash") bool scriptDataDoubleEscapedDashDashState() { var data = stream.char(); - if (data == "-") { - _addToken(CharactersToken("-")); - } else if (data == "<") { - _addToken(CharactersToken("<")); + if (data == '-') { + _addToken(CharactersToken('-')); + } else if (data == '<') { + _addToken(CharactersToken('<')); state = scriptDataDoubleEscapedLessThanSignState; - } else if (data == ">") { - _addToken(CharactersToken(">")); + } else if (data == '>') { + _addToken(CharactersToken('>')); state = scriptDataState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addToken(CharactersToken("\uFFFD")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addToken(CharactersToken('\uFFFD')); state = scriptDataDoubleEscapedState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-script-in-script")); + _addToken(ParseErrorToken('eof-in-script-in-script')); state = dataState; } else { _addToken(CharactersToken(data)); @@ -973,8 +974,8 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapedLessThanSignState() { var data = stream.char(); - if (data == "/") { - _addToken(CharactersToken("/")); + if (data == '/') { + _addToken(CharactersToken('/')); _buffer.clear(); state = scriptDataDoubleEscapeEndState; } else { @@ -986,9 +987,9 @@ class HtmlTokenizer implements Iterator<Token> { bool scriptDataDoubleEscapeEndState() { var data = stream.char(); - if (isWhitespace(data) || data == "/" || data == ">") { + if (isWhitespace(data) || data == '/' || data == '>') { _addToken(CharactersToken(data)); - if ('$_buffer'.toLowerCase() == "script") { + if ('$_buffer'.toLowerCase() == 'script') { state = scriptDataEscapedState; } else { state = scriptDataDoubleEscapedState; @@ -1010,20 +1011,20 @@ class HtmlTokenizer implements Iterator<Token> { } else if (isLetter(data)) { _addAttribute(data); state = attributeNameState; - } else if (data == ">") { + } else if (data == '>') { emitCurrentToken(); - } else if (data == "/") { + } else if (data == '/') { state = selfClosingStartTagState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-attribute-name-but-got-eof")); + _addToken(ParseErrorToken('expected-attribute-name-but-got-eof')); state = dataState; } else if ("'\"=<".contains(data)) { - _addToken(ParseErrorToken("invalid-character-in-attribute-name")); + _addToken(ParseErrorToken('invalid-character-in-attribute-name')); _addAttribute(data); state = attributeNameState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addAttribute("\uFFFD"); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addAttribute('\uFFFD'); state = attributeNameState; } else { _addAttribute(data); @@ -1034,32 +1035,32 @@ class HtmlTokenizer implements Iterator<Token> { bool attributeNameState() { var data = stream.char(); - bool leavingThisState = true; - bool emitToken = false; - if (data == "=") { + var leavingThisState = true; + var emitToken = false; + if (data == '=') { state = beforeAttributeValueState; } else if (isLetter(data)) { _attributeName.write(data); _attributeName.write(stream.charsUntil(asciiLetters, true)); leavingThisState = false; - } else if (data == ">") { + } else if (data == '>') { // XXX If we emit here the attributes are converted to a dict // without being checked and when the code below runs we error // because data is a dict not a list emitToken = true; } else if (isWhitespace(data)) { state = afterAttributeNameState; - } else if (data == "/") { + } else if (data == '/') { state = selfClosingStartTagState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); _attributeName.write('\uFFFD'); leavingThisState = false; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-attribute-name")); + _addToken(ParseErrorToken('eof-in-attribute-name')); state = dataState; } else if ("'\"<".contains(data)) { - _addToken(ParseErrorToken("invalid-character-in-attribute-name")); + _addToken(ParseErrorToken('invalid-character-in-attribute-name')); _attributeName.write(data); leavingThisState = false; } else { @@ -1078,9 +1079,9 @@ class HtmlTokenizer implements Iterator<Token> { attrName = asciiUpper2Lower(attrName); } _attributes.last.name = attrName; - if (_attributeNames == null) _attributeNames = Set(); + _attributeNames ??= {}; if (_attributeNames.contains(attrName)) { - _addToken(ParseErrorToken("duplicate-attribute")); + _addToken(ParseErrorToken('duplicate-attribute')); } _attributeNames.add(attrName); @@ -1096,24 +1097,24 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); - } else if (data == "=") { + } else if (data == '=') { state = beforeAttributeValueState; - } else if (data == ">") { + } else if (data == '>') { emitCurrentToken(); } else if (isLetter(data)) { _addAttribute(data); state = attributeNameState; - } else if (data == "/") { + } else if (data == '/') { state = selfClosingStartTagState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - _addAttribute("\uFFFD"); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + _addAttribute('\uFFFD'); state = attributeNameState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-end-of-tag-but-got-eof")); + _addToken(ParseErrorToken('expected-end-of-tag-but-got-eof')); state = dataState; } else if ("'\"<".contains(data)) { - _addToken(ParseErrorToken("invalid-character-after-attribute-name")); + _addToken(ParseErrorToken('invalid-character-after-attribute-name')); _addAttribute(data); state = attributeNameState; } else { @@ -1127,30 +1128,30 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); - } else if (data == "\"") { + } else if (data == '"') { _markAttributeValueStart(0); state = attributeValueDoubleQuotedState; - } else if (data == "&") { + } else if (data == '&') { state = attributeValueUnQuotedState; stream.unget(data); _markAttributeValueStart(0); } else if (data == "'") { _markAttributeValueStart(0); state = attributeValueSingleQuotedState; - } else if (data == ">") { + } else if (data == '>') { _addToken( - ParseErrorToken("expected-attribute-value-but-got-right-bracket")); + ParseErrorToken('expected-attribute-value-but-got-right-bracket')); emitCurrentToken(); - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); _markAttributeValueStart(-1); _attributeValue.write('\uFFFD'); state = attributeValueUnQuotedState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-attribute-value-but-got-eof")); + _addToken(ParseErrorToken('expected-attribute-value-but-got-eof')); state = dataState; - } else if ("=<`".contains(data)) { - _addToken(ParseErrorToken("equals-in-unquoted-attribute-value")); + } else if ('=<`'.contains(data)) { + _addToken(ParseErrorToken('equals-in-unquoted-attribute-value')); _markAttributeValueStart(-1); _attributeValue.write(data); state = attributeValueUnQuotedState; @@ -1164,22 +1165,22 @@ class HtmlTokenizer implements Iterator<Token> { bool attributeValueDoubleQuotedState() { var data = stream.char(); - if (data == "\"") { + if (data == '"') { _markAttributeValueEnd(-1); _markAttributeEnd(0); state = afterAttributeValueState; - } else if (data == "&") { + } else if (data == '&') { processEntityInAttribute('"'); - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); _attributeValue.write('\uFFFD'); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-attribute-value-double-quote")); + _addToken(ParseErrorToken('eof-in-attribute-value-double-quote')); _markAttributeValueEnd(-1); state = dataState; } else { _attributeValue.write(data); - _attributeValue.write(stream.charsUntil("\"&")); + _attributeValue.write(stream.charsUntil('"&')); } return true; } @@ -1190,13 +1191,13 @@ class HtmlTokenizer implements Iterator<Token> { _markAttributeValueEnd(-1); _markAttributeEnd(0); state = afterAttributeValueState; - } else if (data == "&") { + } else if (data == '&') { processEntityInAttribute("'"); - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); _attributeValue.write('\uFFFD'); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-attribute-value-single-quote")); + _addToken(ParseErrorToken('eof-in-attribute-value-single-quote')); _markAttributeValueEnd(-1); state = dataState; } else { @@ -1211,21 +1212,21 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { _markAttributeValueEnd(-1); state = beforeAttributeNameState; - } else if (data == "&") { - processEntityInAttribute(">"); - } else if (data == ">") { + } else if (data == '&') { + processEntityInAttribute('>'); + } else if (data == '>') { _markAttributeValueEnd(-1); emitCurrentToken(); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-attribute-value-no-quotes")); + _addToken(ParseErrorToken('eof-in-attribute-value-no-quotes')); _markAttributeValueEnd(-1); state = dataState; } else if ('"\'=<`'.contains(data)) { _addToken( - ParseErrorToken("unexpected-character-in-unquoted-attribute-value")); + ParseErrorToken('unexpected-character-in-unquoted-attribute-value')); _attributeValue.write(data); - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); _attributeValue.write('\uFFFD'); } else { _attributeValue.write(data); @@ -1238,16 +1239,16 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { state = beforeAttributeNameState; - } else if (data == ">") { + } else if (data == '>') { emitCurrentToken(); - } else if (data == "/") { + } else if (data == '/') { state = selfClosingStartTagState; } else if (data == eof) { - _addToken(ParseErrorToken("unexpected-EOF-after-attribute-value")); + _addToken(ParseErrorToken('unexpected-EOF-after-attribute-value')); stream.unget(data); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-character-after-attribute-value")); + _addToken(ParseErrorToken('unexpected-character-after-attribute-value')); stream.unget(data); state = beforeAttributeNameState; } @@ -1256,15 +1257,15 @@ class HtmlTokenizer implements Iterator<Token> { bool selfClosingStartTagState() { var data = stream.char(); - if (data == ">") { + if (data == '>') { currentTagToken.selfClosing = true; emitCurrentToken(); } else if (data == eof) { - _addToken(ParseErrorToken("unexpected-EOF-after-solidus-in-tag")); + _addToken(ParseErrorToken('unexpected-EOF-after-solidus-in-tag')); stream.unget(data); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-character-after-soldius-in-tag")); + _addToken(ParseErrorToken('unexpected-character-after-soldius-in-tag')); stream.unget(data); state = beforeAttributeNameState; } @@ -1275,8 +1276,8 @@ class HtmlTokenizer implements Iterator<Token> { // Make a new comment token and give it as value all the characters // until the first > or EOF (charsUntil checks for EOF automatically) // and emit it. - var data = stream.charsUntil(">"); - data = data.replaceAll("\u0000", "\uFFFD"); + var data = stream.charsUntil('>'); + data = data.replaceAll('\u0000', '\uFFFD'); _addToken(CommentToken(data)); // Eat the character directly after the bogus comment which is either a @@ -1288,9 +1289,9 @@ class HtmlTokenizer implements Iterator<Token> { bool markupDeclarationOpenState() { var charStack = [stream.char()]; - if (charStack.last == "-") { + if (charStack.last == '-') { charStack.add(stream.char()); - if (charStack.last == "-") { + if (charStack.last == '-') { currentToken = CommentToken(); state = commentStartState; return true; @@ -1310,13 +1311,13 @@ class HtmlTokenizer implements Iterator<Token> { state = doctypeState; return true; } - } else if (charStack.last == "[" && + } else if (charStack.last == '[' && parser != null && parser.tree.openElements.isNotEmpty && parser.tree.openElements.last.namespaceUri != parser.tree.defaultNamespace) { var matched = true; - for (var expected in const ["C", "D", "A", "T", "A", "["]) { + for (var expected in const ['C', 'D', 'A', 'T', 'A', '[']) { charStack.add(stream.char()); if (charStack.last != expected) { matched = false; @@ -1329,7 +1330,7 @@ class HtmlTokenizer implements Iterator<Token> { } } - _addToken(ParseErrorToken("expected-dashes-or-doctype")); + _addToken(ParseErrorToken('expected-dashes-or-doctype')); while (charStack.isNotEmpty) { stream.unget(charStack.removeLast()); @@ -1340,17 +1341,17 @@ class HtmlTokenizer implements Iterator<Token> { bool commentStartState() { var data = stream.char(); - if (data == "-") { + if (data == '-') { state = commentStartDashState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('\uFFFD'); - } else if (data == ">") { - _addToken(ParseErrorToken("incorrect-comment")); + } else if (data == '>') { + _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment")); + _addToken(ParseErrorToken('eof-in-comment')); _addToken(currentToken); state = dataState; } else { @@ -1362,17 +1363,17 @@ class HtmlTokenizer implements Iterator<Token> { bool commentStartDashState() { var data = stream.char(); - if (data == "-") { + if (data == '-') { state = commentEndState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('-\uFFFD'); - } else if (data == ">") { - _addToken(ParseErrorToken("incorrect-comment")); + } else if (data == '>') { + _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment")); + _addToken(ParseErrorToken('eof-in-comment')); _addToken(currentToken); state = dataState; } else { @@ -1384,31 +1385,31 @@ class HtmlTokenizer implements Iterator<Token> { bool commentState() { var data = stream.char(); - if (data == "-") { + if (data == '-') { state = commentEndDashState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('\uFFFD'); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment")); + _addToken(ParseErrorToken('eof-in-comment')); _addToken(currentToken); state = dataState; } else { - currentStringToken.add(data).add(stream.charsUntil("-\u0000")); + currentStringToken.add(data).add(stream.charsUntil('-\u0000')); } return true; } bool commentEndDashState() { var data = stream.char(); - if (data == "-") { + if (data == '-') { state = commentEndState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('-\uFFFD'); state = commentState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment-end-dash")); + _addToken(ParseErrorToken('eof-in-comment-end-dash')); _addToken(currentToken); state = dataState; } else { @@ -1420,28 +1421,28 @@ class HtmlTokenizer implements Iterator<Token> { bool commentEndState() { var data = stream.char(); - if (data == ">") { + if (data == '>') { _addToken(currentToken); state = dataState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('--\uFFFD'); state = commentState; - } else if (data == "!") { + } else if (data == '!') { _addToken( - ParseErrorToken("unexpected-bang-after-double-dash-in-comment")); + ParseErrorToken('unexpected-bang-after-double-dash-in-comment')); state = commentEndBangState; - } else if (data == "-") { + } else if (data == '-') { _addToken( - ParseErrorToken("unexpected-dash-after-double-dash-in-comment")); + ParseErrorToken('unexpected-dash-after-double-dash-in-comment')); currentStringToken.add(data); } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment-double-dash")); + _addToken(ParseErrorToken('eof-in-comment-double-dash')); _addToken(currentToken); state = dataState; } else { // XXX - _addToken(ParseErrorToken("unexpected-char-in-comment")); + _addToken(ParseErrorToken('unexpected-char-in-comment')); currentStringToken.add('--').add(data); state = commentState; } @@ -1450,18 +1451,18 @@ class HtmlTokenizer implements Iterator<Token> { bool commentEndBangState() { var data = stream.char(); - if (data == ">") { + if (data == '>') { _addToken(currentToken); state = dataState; - } else if (data == "-") { + } else if (data == '-') { currentStringToken.add('--!'); state = commentEndDashState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); currentStringToken.add('--!\uFFFD'); state = commentState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-comment-end-bang-state")); + _addToken(ParseErrorToken('eof-in-comment-end-bang-state')); _addToken(currentToken); state = dataState; } else { @@ -1476,12 +1477,12 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypeNameState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-doctype-name-but-got-eof")); + _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("need-space-after-doctype")); + _addToken(ParseErrorToken('need-space-after-doctype')); stream.unget(data); state = beforeDoctypeNameState; } @@ -1492,17 +1493,17 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == ">") { - _addToken(ParseErrorToken("expected-doctype-name-but-got-right-bracket")); + } else if (data == '>') { + _addToken(ParseErrorToken('expected-doctype-name-but-got-right-bracket')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.name = "\uFFFD"; + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.name = '\uFFFD'; state = doctypeNameState; } else if (data == eof) { - _addToken(ParseErrorToken("expected-doctype-name-but-got-eof")); + _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1518,16 +1519,16 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); state = afterDoctypeNameState; - } else if (data == ">") { + } else if (data == '>') { currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); _addToken(currentToken); state = dataState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.name = "${currentDoctypeToken.name}\uFFFD"; + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.name = '${currentDoctypeToken.name}\uFFFD'; state = doctypeNameState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype-name")); + _addToken(ParseErrorToken('eof-in-doctype-name')); currentDoctypeToken.correct = false; currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); _addToken(currentToken); @@ -1542,20 +1543,20 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == ">") { + } else if (data == '>') { _addToken(currentToken); state = dataState; } else if (data == eof) { currentDoctypeToken.correct = false; stream.unget(data); - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); _addToken(currentToken); state = dataState; } else { - if (data == "p" || data == "P") { + if (data == 'p' || data == 'P') { // TODO(jmesserly): would be nice to have a helper for this. var matched = true; - for (var expected in const ["uU", "bB", "lL", "iI", "cC"]) { + for (var expected in const ['uU', 'bB', 'lL', 'iI', 'cC']) { data = stream.char(); if (data == eof || !expected.contains(data)) { matched = false; @@ -1566,9 +1567,9 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypePublicKeywordState; return true; } - } else if (data == "s" || data == "S") { + } else if (data == 's' || data == 'S') { var matched = true; - for (var expected in const ["yY", "sS", "tT", "eE", "mM"]) { + for (var expected in const ['yY', 'sS', 'tT', 'eE', 'mM']) { data = stream.char(); if (data == eof || !expected.contains(data)) { matched = false; @@ -1586,8 +1587,8 @@ class HtmlTokenizer implements Iterator<Token> { // discarded; only the latest character might be '>' or EOF // and needs to be ungetted stream.unget(data); - _addToken(ParseErrorToken("expected-space-or-right-bracket-in-doctype", - messageParams: {"data": data})); + _addToken(ParseErrorToken('expected-space-or-right-bracket-in-doctype', + messageParams: {'data': data})); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1599,11 +1600,11 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypePublicIdentifierState; } else if (data == "'" || data == '"') { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); stream.unget(data); state = beforeDoctypePublicIdentifierState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1618,24 +1619,24 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == "\"") { - currentDoctypeToken.publicId = ""; + } else if (data == '"') { + currentDoctypeToken.publicId = ''; state = doctypePublicIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.publicId = ""; + currentDoctypeToken.publicId = ''; state = doctypePublicIdentifierSingleQuotedState; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-end-of-doctype")); + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1646,16 +1647,16 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (data == '"') { state = afterDoctypePublicIdentifierState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.publicId = "${currentDoctypeToken.publicId}\uFFFD"; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-end-of-doctype")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1669,16 +1670,16 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (data == "'") { state = afterDoctypePublicIdentifierState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.publicId = "${currentDoctypeToken.publicId}\uFFFD"; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-end-of-doctype")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1692,24 +1693,24 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { state = betweenDoctypePublicAndSystemIdentifiersState; - } else if (data == ">") { + } else if (data == '>') { _addToken(currentToken); state = dataState; } else if (data == '"') { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); - currentDoctypeToken.systemId = ""; + _addToken(ParseErrorToken('unexpected-char-in-doctype')); + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); - currentDoctypeToken.systemId = ""; + _addToken(ParseErrorToken('unexpected-char-in-doctype')); + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1720,22 +1721,22 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == ">") { + } else if (data == '>') { _addToken(currentToken); state = dataState; } else if (data == '"') { - currentDoctypeToken.systemId = ""; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.systemId = ""; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1747,11 +1748,11 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = beforeDoctypeSystemIdentifierState; } else if (data == "'" || data == '"') { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); stream.unget(data); state = beforeDoctypeSystemIdentifierState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1766,24 +1767,24 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == "\"") { - currentDoctypeToken.systemId = ""; + } else if (data == '"') { + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.systemId = ""; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; state = bogusDoctypeState; } @@ -1792,18 +1793,18 @@ class HtmlTokenizer implements Iterator<Token> { bool doctypeSystemIdentifierDoubleQuotedState() { var data = stream.char(); - if (data == "\"") { + if (data == '"') { state = afterDoctypeSystemIdentifierState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.systemId = "${currentDoctypeToken.systemId}\uFFFD"; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-end-of-doctype")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1817,16 +1818,16 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (data == "'") { state = afterDoctypeSystemIdentifierState; - } else if (data == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - currentDoctypeToken.systemId = "${currentDoctypeToken.systemId}\uFFFD"; - } else if (data == ">") { - _addToken(ParseErrorToken("unexpected-end-of-doctype")); + } else if (data == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; + } else if (data == '>') { + _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; @@ -1840,16 +1841,16 @@ class HtmlTokenizer implements Iterator<Token> { var data = stream.char(); if (isWhitespace(data)) { return true; - } else if (data == ">") { + } else if (data == '>') { _addToken(currentToken); state = dataState; } else if (data == eof) { - _addToken(ParseErrorToken("eof-in-doctype")); + _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - _addToken(ParseErrorToken("unexpected-char-in-doctype")); + _addToken(ParseErrorToken('unexpected-char-in-doctype')); state = bogusDoctypeState; } return true; @@ -1857,7 +1858,7 @@ class HtmlTokenizer implements Iterator<Token> { bool bogusDoctypeState() { var data = stream.char(); - if (data == ">") { + if (data == '>') { _addToken(currentToken); state = dataState; } else if (data == eof) { @@ -1870,24 +1871,24 @@ class HtmlTokenizer implements Iterator<Token> { } bool cdataSectionState() { - var data = []; - int matchedEnd = 0; + var data = <String>[]; + var matchedEnd = 0; while (true) { var ch = stream.char(); if (ch == eof) { break; } // Deal with null here rather than in the parser - if (ch == "\u0000") { - _addToken(ParseErrorToken("invalid-codepoint")); - ch = "\uFFFD"; + if (ch == '\u0000') { + _addToken(ParseErrorToken('invalid-codepoint')); + ch = '\uFFFD'; } data.add(ch); // TODO(jmesserly): it'd be nice if we had an easier way to match the end, // perhaps with a "peek" API. - if (ch == "]" && matchedEnd < 2) { + if (ch == ']' && matchedEnd < 2) { matchedEnd++; - } else if (ch == ">" && matchedEnd == 2) { + } else if (ch == '>' && matchedEnd == 2) { // Remove "]]>" from the end. data.removeLast(); data.removeLast(); diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index f6db7ad73..e0962141e 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -21,8 +21,9 @@ class ActiveFormattingElements extends ListProxy<Element> { // Override the "add" method. // TODO(jmesserly): I'd rather not override this; can we do this in the // calling code instead? + @override void add(Element node) { - int equalCount = 0; + var equalCount = 0; if (node != Marker) { for (var element in reversed) { if (element == Marker) { @@ -103,32 +104,32 @@ class TreeBuilder { bool elementInScope(target, {String variant}) { //If we pass a node in we match that. if we pass a string //match any node with that name - bool exactNode = target is Node; + var exactNode = target is Node; - List listElements1 = scopingElements; - List listElements2 = const []; - bool invert = false; + var listElements1 = scopingElements; + var listElements2 = const []; + var invert = false; if (variant != null) { switch (variant) { - case "button": - listElements2 = const [Pair(Namespaces.html, "button")]; + case 'button': + listElements2 = const [Pair(Namespaces.html, 'button')]; break; - case "list": + case 'list': listElements2 = const [ - Pair(Namespaces.html, "ol"), - Pair(Namespaces.html, "ul") + Pair(Namespaces.html, 'ol'), + Pair(Namespaces.html, 'ul') ]; break; - case "table": + case 'table': listElements1 = const [ - Pair(Namespaces.html, "html"), - Pair(Namespaces.html, "table") + Pair(Namespaces.html, 'html'), + Pair(Namespaces.html, 'table') ]; break; - case "select": + case 'select': listElements1 = const [ - Pair(Namespaces.html, "optgroup"), - Pair(Namespaces.html, "option") + Pair(Namespaces.html, 'optgroup'), + Pair(Namespaces.html, 'option') ]; invert = true; break; @@ -162,7 +163,7 @@ class TreeBuilder { } // Step 2 and step 3: we start with the last element. So i is -1. - int i = activeFormattingElements.length - 1; + var i = activeFormattingElements.length - 1; var entry = activeFormattingElements[i]; if (entry == Marker || openElements.contains(entry)) { return; @@ -242,17 +243,14 @@ class TreeBuilder { } void insertComment(StringToken token, [Node parent]) { - if (parent == null) { - parent = openElements.last; - } + parent ??= openElements.last; parent.nodes.add(Comment(token.data)..sourceSpan = token.span); } /// Create an element but don't insert it anywhere Element createElement(StartTagToken token) { var name = token.name; - var namespace = token.namespace; - if (namespace == null) namespace = defaultNamespace; + var namespace = token.namespace ?? defaultNamespace; var element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; @@ -266,8 +264,7 @@ class TreeBuilder { Element insertElementNormal(StartTagToken token) { var name = token.name; - var namespace = token.namespace; - if (namespace == null) namespace = defaultNamespace; + var namespace = token.namespace ?? defaultNamespace; var element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; @@ -332,7 +329,7 @@ class TreeBuilder { nodes.add(Text(data)..sourceSpan = span); } } else { - int index = nodes.indexOf(refNode); + var index = nodes.indexOf(refNode); if (index > 0 && nodes[index - 1] is Text) { Text last = nodes[index - 1]; last.appendData(data); @@ -352,7 +349,7 @@ class TreeBuilder { Node fosterParent; Node insertBefore; for (var elm in openElements.reversed) { - if (elm.localName == "table") { + if (elm.localName == 'table') { lastTable = elm; break; } @@ -376,7 +373,7 @@ class TreeBuilder { var name = openElements.last.localName; // XXX td, th and tr are not actually needed if (name != exclude && - const ["dd", "dt", "li", "option", "optgroup", "p", "rp", "rt"] + const ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'] .contains(name)) { openElements.removeLast(); // XXX This is not entirely what the specification says. We should diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 54b578bc7..fec6870e5 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -11,14 +11,16 @@ class Pair<F, S> { const Pair(this.first, this.second); + @override int get hashCode => 37 * first.hashCode + second.hashCode; + @override bool operator ==(other) => other.first == first && other.second == second; } int parseIntRadix(String str, [int radix = 10]) { - int val = 0; - for (int i = 0; i < str.length; i++) { + var val = 0; + for (var i = 0; i < str.length; i++) { var digit = str.codeUnitAt(i); if (digit >= LOWER_A) { digit += 10 - LOWER_A; @@ -45,7 +47,7 @@ bool startsWithAny(String str, List<String> prefixes) { // Like the python [:] operator. List<T> slice<T>(List<T> list, int start, [int end]) { - if (end == null) end = list.length; + end ??= list.length; if (end < 0) end += list.length; // Ensure the indexes are in bounds. @@ -55,7 +57,7 @@ List<T> slice<T>(List<T> list, int start, [int end]) { } bool allWhitespace(String str) { - for (int i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; i++) { if (!isWhitespaceCC(str.codeUnitAt(i))) return false; } return true; @@ -65,7 +67,7 @@ String padWithZeros(String str, int size) { if (str.length == size) return str; var result = StringBuffer(); size -= str.length; - for (int i = 0; i < size; i++) { + for (var i = 0; i < size; i++) { result.write('0'); } result.write(str); @@ -89,7 +91,7 @@ String formatStr(String format, Map data) { result.write(format.substring(last, match)); match += search.length; - int digits = match; + var digits = match; while (isDigit(format[digits])) { digits++; } @@ -112,8 +114,8 @@ String formatStr(String format, Map data) { result.write(padWithZeros(number, numberSize)); break; default: - throw UnsupportedError("formatStr does not support format " - "character ${format[match]}"); + throw UnsupportedError('formatStr does not support format ' + 'character ${format[match]}'); } last = match + 1; diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 1cf912e79..078c3c795 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -5,7 +5,7 @@ import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; -main() { +void main() { group('Element', () { test('classes', () { final barBaz = Element.html('<div class=" bar baz"></div>'); diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 0889f44ce..536f98fb7 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -9,7 +9,7 @@ import 'package:html/src/treebuilder.dart'; import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; -main() { +void main() { _testElementSpans(); test('doctype is cloneable', () { var doc = parse('<!doctype HTML>'); @@ -19,8 +19,8 @@ main() { test('line counter', () { // http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 - var doc = parse("<pre>\nx\n&gt;\n</pre>"); - expect(doc.body.innerHtml, "<pre>x\n&gt;\n</pre>"); + var doc = parse('<pre>\nx\n&gt;\n</pre>'); + expect(doc.body.innerHtml, '<pre>x\n&gt;\n</pre>'); }); test('namespace html elements on', () { @@ -45,7 +45,7 @@ main() { var doc = parser.parse(); expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); - ParseError error = parser.errors[0]; + var error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); // Note: these values are 0-based, but the printed format is 1-based. @@ -75,7 +75,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. var doc = parser.parse(); expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); - ParseError error = parser.errors[0]; + var error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); expect(error.span.start.line, 3); // Note: error position is at the end, not the beginning @@ -317,7 +317,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); group('Encoding pre-parser', () { - getEncoding(String s) => EncodingParser(s.codeUnits).getEncoding(); + String getEncoding(String s) => EncodingParser(s.codeUnits).getEncoding(); test('gets encoding from meta charset', () { expect(getEncoding('<meta charset="utf-16">'), 'utf-16'); @@ -349,8 +349,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); } -_testElementSpans() { - assertSpan(SourceSpan span, int offset, int end, String text) { +void _testElementSpans() { + void assertSpan(SourceSpan span, int offset, int end, String text) { expect(span, isNotNull); expect(span.start.offset, offset); expect(span.end.offset, end); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 1db15868d..21c54d222 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -19,15 +19,15 @@ String namespaceHtml(String expected) { // We can't do regex replace directly =\ // final namespaceExpected = new RegExp(@"^(\s*)<(\S+)>", multiLine: true); // return expected.replaceAll(namespaceExpected, @"$1<html $2>"); - final namespaceExpected = RegExp(r"^(\|\s*)<(\S+)>"); - var lines = expected.split("\n"); - for (int i = 0; i < lines.length; i++) { + final namespaceExpected = RegExp(r'^(\|\s*)<(\S+)>'); + var lines = expected.split('\n'); + for (var i = 0; i < lines.length; i++) { var match = namespaceExpected.firstMatch(lines[i]); if (match != null) { - lines[i] = "${match[1]}<html ${match[2]}>"; + lines[i] = '${match[1]}<html ${match[2]}>'; } } - return lines.join("\n"); + return lines.join('\n'); } void runParserTest( @@ -58,13 +58,13 @@ void runParserTest( expect(output, equals(expected), reason: - "\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output"); + '\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output'); if (checkParseErrors) { expect(parser.errors.length, equals(errors.length), - reason: "\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n" + reason: '\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n' "${errors.join('\n')}\n\n" - "Actual errors (${parser.errors.length}):\n" + 'Actual errors (${parser.errors.length}):\n' "${parser.errors.map((e) => '$e').join('\n')}"); } } @@ -73,7 +73,7 @@ void main() { for (var path in getDataFiles('tree-construction')) { if (!path.endsWith('.dat')) continue; - var tests = TestData(path, "data"); + var tests = TestData(path, 'data'); var testName = pathos.basenameWithoutExtension(path); group(testName, () { @@ -83,7 +83,7 @@ void main() { var innerHTML = testData['document-fragment']; var expected = testData['document']; if (errors != null) { - errors = errors.split("\n"); + errors = errors.split('\n'); } for (var treeCtor in treeTypes.values) { @@ -100,7 +100,7 @@ void main() { } /// Extract the name for the test based on the test input data. -_nameFor(String input) { +dynamic _nameFor(String input) { // Using jsonDecode to unescape other unicode characters var escapeQuote = input .replaceAll(RegExp('\\\\.'), '_') diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 7ed1cc4da..d5defb1d8 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -23,9 +23,9 @@ Document getTestContentDocument() { } var testType = testQsaBaseline; // Only run baseline tests. -var docType = "html"; // Only run tests suitable for HTML +var docType = 'html'; // Only run tests suitable for HTML -main() { +void main() { /* * This test suite tests Selectors API methods in 4 different contexts: * 1. Document node @@ -64,7 +64,7 @@ main() { //doc = frame.contentDocument; // Document Node tests doc = getTestContentDocument(); - var element = doc.getElementById("root"); // In-document Element Node tests + var element = doc.getElementById('root'); // In-document Element Node tests //Setup the namespace tests setupSpecialElements(element); @@ -77,8 +77,8 @@ main() { traverse(outOfScope, (elem) { // Annotate each element as being a clone; used for verifying - elem.attributes["data-clone"] = - ""; // that none of these elements ever match. + elem.attributes['data-clone'] = + ''; // that none of these elements ever match. }); var detached = element.clone(true); // Detached Element Node tests @@ -87,31 +87,31 @@ main() { fragment.append(element.clone(true)); // Setup Tests - interfaceCheck("Document", doc); - interfaceCheck("Detached Element", detached); - interfaceCheck("Fragment", fragment); - interfaceCheck("In-document Element", element); + interfaceCheck('Document', doc); + interfaceCheck('Detached Element', detached); + interfaceCheck('Fragment', fragment); + interfaceCheck('In-document Element', element); - runSpecialSelectorTests("Document", doc); - runSpecialSelectorTests("Detached Element", detached); - runSpecialSelectorTests("Fragment", fragment); - runSpecialSelectorTests("In-document Element", element); + runSpecialSelectorTests('Document', doc); + runSpecialSelectorTests('Detached Element', detached); + runSpecialSelectorTests('Fragment', fragment); + runSpecialSelectorTests('In-document Element', element); - verifyStaticList("Document", doc); - verifyStaticList("Detached Element", detached); - verifyStaticList("Fragment", fragment); - verifyStaticList("In-document Element", element); + verifyStaticList('Document', doc); + verifyStaticList('Detached Element', detached); + verifyStaticList('Fragment', fragment); + verifyStaticList('In-document Element', element); // TODO(jmesserly): fix negative tests - //runInvalidSelectorTest("Document", doc, invalidSelectors); - //runInvalidSelectorTest("Detached Element", detached, invalidSelectors); - //runInvalidSelectorTest("Fragment", fragment, invalidSelectors); - //runInvalidSelectorTest("In-document Element", element, invalidSelectors); + //runInvalidSelectorTest('Document', doc, invalidSelectors); + //runInvalidSelectorTest('Detached Element', detached, invalidSelectors); + //runInvalidSelectorTest('Fragment', fragment, invalidSelectors); + //runInvalidSelectorTest('In-document Element', element, invalidSelectors); - runValidSelectorTest("Document", doc, validSelectors, testType, docType); + runValidSelectorTest('Document', doc, validSelectors, testType, docType); runValidSelectorTest( - "Detached Element", detached, validSelectors, testType, docType); - runValidSelectorTest("Fragment", fragment, validSelectors, testType, docType); + 'Detached Element', detached, validSelectors, testType, docType); + runValidSelectorTest('Fragment', fragment, validSelectors, testType, docType); group('out of scope', () { setUp(() { @@ -122,6 +122,6 @@ main() { outOfScope.remove(); }); runValidSelectorTest( - "In-document Element", element, validSelectors, testType, docType); + 'In-document Element', element, validSelectors, testType, docType); }); } diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index d87c7951a..f97dafc02 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -17,47 +17,47 @@ Document doc; /* * Create and append special elements that cannot be created correctly with HTML markup alone. */ -setupSpecialElements(parent) { +void setupSpecialElements(parent) { // Setup null and undefined tests - parent.append(doc.createElement("null")); - parent.append(doc.createElement("undefined")); + parent.append(doc.createElement('null')); + parent.append(doc.createElement('undefined')); // Setup namespace tests - var anyNS = doc.createElement("div"); - var noNS = doc.createElement("div"); - anyNS.id = "any-namespace"; - noNS.id = "no-namespace"; + var anyNS = doc.createElement('div'); + var noNS = doc.createElement('div'); + anyNS.id = 'any-namespace'; + noNS.id = 'no-namespace'; var div; div = [ - doc.createElement("div"), - doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), - doc.createElementNS("", "div"), - doc.createElementNS("http://www.example.org/ns", "div") + doc.createElement('div'), + doc.createElementNS('http://www.w3.org/1999/xhtml', 'div'), + doc.createElementNS('', 'div'), + doc.createElementNS('http://www.example.org/ns', 'div') ]; - div[0].id = "any-namespace-div1"; - div[1].id = "any-namespace-div2"; - div[2].attributes["id"] = - "any-namespace-div3"; // Non-HTML elements can't use .id property - div[3].attributes["id"] = "any-namespace-div4"; + div[0].id = 'any-namespace-div1'; + div[1].id = 'any-namespace-div2'; + div[2].attributes['id'] = + 'any-namespace-div3'; // Non-HTML elements can't use .id property + div[3].attributes['id'] = 'any-namespace-div4'; for (var i = 0; i < div.length; i++) { anyNS.append(div[i]); } div = [ - doc.createElement("div"), - doc.createElementNS("http://www.w3.org/1999/xhtml", "div"), - doc.createElementNS("", "div"), - doc.createElementNS("http://www.example.org/ns", "div") + doc.createElement('div'), + doc.createElementNS('http://www.w3.org/1999/xhtml', 'div'), + doc.createElementNS('', 'div'), + doc.createElementNS('http://www.example.org/ns', 'div') ]; - div[0].id = "no-namespace-div1"; - div[1].id = "no-namespace-div2"; - div[2].attributes["id"] = - "no-namespace-div3"; // Non-HTML elements can't use .id property - div[3].attributes["id"] = "no-namespace-div4"; + div[0].id = 'no-namespace-div1'; + div[1].id = 'no-namespace-div2'; + div[2].attributes['id'] = + 'no-namespace-div3'; // Non-HTML elements can't use .id property + div[3].attributes['id'] = 'no-namespace-div4'; for (var i = 0; i < div.length; i++) { noNS.append(div[i]); @@ -70,114 +70,114 @@ setupSpecialElements(parent) { /* * Check that the querySelector and querySelectorAll methods exist on the given Node */ -interfaceCheck(type, obj) { +void interfaceCheck(type, obj) { runTest(() { var q = obj.querySelector is Function; - assertTrue(q, type + " supports querySelector."); - }, type + " supports querySelector"); + assertTrue(q, type + ' supports querySelector.'); + }, type + ' supports querySelector'); runTest(() { var qa = obj.querySelectorAll is Function; - assertTrue(qa, type + " supports querySelectorAll."); - }, type + " supports querySelectorAll"); + assertTrue(qa, type + ' supports querySelectorAll.'); + }, type + ' supports querySelectorAll'); runTest(() { - var list = obj.querySelectorAll("div"); + var list = obj.querySelectorAll('div'); // TODO(jmesserly): testing List<Element> for now. It should return an // ElementList which has extra properties. Needed for dart:html compat. assertTrue(list is List<Element>, - "The result should be an instance of a NodeList"); - }, type + ".querySelectorAll returns NodeList instance"); + 'The result should be an instance of a NodeList'); + }, type + '.querySelectorAll returns NodeList instance'); } /* * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after * each call. A static list should not be affected by subsequent changes to the DOM. */ -verifyStaticList(type, root) { +void verifyStaticList(type, root) { var pre, post, preLength; runTest(() { - pre = root.querySelectorAll("div"); + pre = root.querySelectorAll('div'); preLength = pre.length; - var div = doc.createElement("div"); + var div = doc.createElement('div'); (root is Document ? root.body : root).append(div); assertEquals( - pre.length, preLength, "The length of the NodeList should not change."); - }, type + ": static NodeList"); + pre.length, preLength, 'The length of the NodeList should not change.'); + }, type + ': static NodeList'); runTest(() { - post = root.querySelectorAll("div"); + post = root.querySelectorAll('div'); assertEquals(post.length, preLength + 1, - "The length of the new NodeList should be 1 more than the previous list."); - }, type + ": new NodeList"); + 'The length of the new NodeList should be 1 more than the previous list.'); + }, type + ': new NodeList'); } /* * Verify handling of special values for the selector parameter, including stringification of * null and undefined, and the handling of the empty string. */ -runSpecialSelectorTests(type, root) { +void runSpecialSelectorTests(type, root) { // Dart note: changed these tests because we don't have auto conversion to // String like JavaScript does. runTest(() { // 1 assertEquals(root.querySelectorAll('null').length, 1, "This should find one element with the tag name 'NULL'."); - }, type + ".querySelectorAll null"); + }, type + '.querySelectorAll null'); runTest(() { // 2 assertEquals(root.querySelectorAll('undefined').length, 1, "This should find one element with the tag name 'UNDEFINED'."); - }, type + ".querySelectorAll undefined"); + }, type + '.querySelectorAll undefined'); runTest(() { // 3 assertThrows((e) => e is NoSuchMethodError, () { root.querySelectorAll(); - }, "This should throw a TypeError."); - }, type + ".querySelectorAll no parameter"); + }, 'This should throw a TypeError.'); + }, type + '.querySelectorAll no parameter'); runTest(() { // 4 var elm = root.querySelector('null'); - assertNotEquals(elm, null, "This should find an element."); + assertNotEquals(elm, null, 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. assertEquals( - elm.localName.toUpperCase(), "NULL", "The tag name should be 'NULL'."); - }, type + ".querySelector null"); + elm.localName.toUpperCase(), 'NULL', "The tag name should be 'NULL'."); + }, type + '.querySelector null'); runTest(() { // 5 var elm = root.querySelector('undefined'); - assertNotEquals(elm, 'undefined', "This should find an element."); + assertNotEquals(elm, 'undefined', 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assertEquals(elm.localName.toUpperCase(), "UNDEFINED", + assertEquals(elm.localName.toUpperCase(), 'UNDEFINED', "The tag name should be 'UNDEFINED'."); - }, type + ".querySelector undefined"); + }, type + '.querySelector undefined'); runTest(() { // 6 assertThrows((e) => e is NoSuchMethodError, () { root.querySelector(); - }, "This should throw a TypeError."); - }, type + ".querySelector no parameter"); + }, 'This should throw a TypeError.'); + }, type + '.querySelector no parameter'); runTest(() { // 7 - var result = root.querySelectorAll("*"); + var result = root.querySelectorAll('*'); var i = 0; traverse(root, (elem) { if (!identical(elem, root)) { assertEquals( - elem, result[i], "The result in index $i should be in tree order."); + elem, result[i], 'The result in index $i should be in tree order.'); i++; } }); - }, type + ".querySelectorAll tree order"); + }, type + '.querySelectorAll tree order'); } /// Tests containing this string fail for an unknown reason @@ -194,68 +194,68 @@ String _getSkip(String name) { * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() * Only run these tests when results are expected. Don't run for syntax error tests. */ -runValidSelectorTest(String type, root, List<Map<String, dynamic>> selectors, - testType, docType) { - var nodeType = ""; +void runValidSelectorTest(String type, root, + List<Map<String, dynamic>> selectors, testType, docType) { + var nodeType = ''; switch (root.nodeType) { case Node.DOCUMENT_NODE: - nodeType = "document"; + nodeType = 'document'; break; case Node.ELEMENT_NODE: - nodeType = root.parentNode != null ? "element" : "detached"; + nodeType = root.parentNode != null ? 'element' : 'detached'; break; case Node.DOCUMENT_FRAGMENT_NODE: - nodeType = "fragment"; + nodeType = 'fragment'; break; default: - throw StateError("Reached unreachable code path."); + throw StateError('Reached unreachable code path.'); } for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; - var n = s["name"]; + var n = s['name']; var skip = _getSkip(n); - var q = s["selector"]; - var e = s["expect"]; + var q = s['selector']; + var e = s['expect']; - if ((s["exclude"] is! List || - (s["exclude"].indexOf(nodeType) == -1 && - s["exclude"].indexOf(docType) == -1)) && - (s["testType"] & testType != 0)) { + if ((s['exclude'] is! List || + (s['exclude'].indexOf(nodeType) == -1 && + s['exclude'].indexOf(docType) == -1)) && + (s['testType'] & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) var foundall, found; runTest(() { foundall = root.querySelectorAll(q); - assertNotEquals(foundall, null, "The method should not return null."); + assertNotEquals(foundall, null, 'The method should not return null.'); assertEquals(foundall.length, e.length, - "The method should return the expected number of matches."); + 'The method should return the expected number of matches.'); for (var i = 0; i < e.length; i++) { assertNotEquals( - foundall[i], null, "The item in index $i should not be null."); - assertEquals(foundall[i].attributes["id"], e[i], - "The item in index $i should have the expected ID."); - assertFalse(foundall[i].attributes.containsKey("data-clone"), - "This should not be a cloned element."); + foundall[i], null, 'The item in index $i should not be null.'); + assertEquals(foundall[i].attributes['id'], e[i], + 'The item in index $i should have the expected ID.'); + assertFalse(foundall[i].attributes.containsKey('data-clone'), + 'This should not be a cloned element.'); } - }, type + ".querySelectorAll: " + n + ": " + q, skip: skip); + }, type + '.querySelectorAll: ' + n + ': ' + q, skip: skip); runTest(() { found = root.querySelector(q); if (e.isNotEmpty) { - assertNotEquals(found, null, "The method should return a match."); - assertEquals(found.attributes["id"], e[0], - "The method should return the first match."); + assertNotEquals(found, null, 'The method should return a match.'); + assertEquals(found.attributes['id'], e[0], + 'The method should return the first match.'); assertEquals(found, foundall[0], - "The result should match the first item from querySelectorAll."); - assertFalse(found.attributes.containsKey("data-clone"), - "This should not be annotated as a cloned element."); + 'The result should match the first item from querySelectorAll.'); + assertFalse(found.attributes.containsKey('data-clone'), + 'This should not be annotated as a cloned element.'); } else { - assertEquals(found, null, "The method should not match anything."); + assertEquals(found, null, 'The method should not match anything.'); } - }, type + ".querySelector: " + n + ": " + q, skip: skip); + }, type + '.querySelector: ' + n + ': ' + q, skip: skip); } else { //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) } @@ -266,28 +266,28 @@ runValidSelectorTest(String type, root, List<Map<String, dynamic>> selectors, * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() * Only run these tests when errors are expected. Don't run for valid selector tests. */ -runInvalidSelectorTest(String type, root, List selectors) { +void runInvalidSelectorTest(String type, root, List selectors) { for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; - var n = s["name"]; - var q = s["selector"]; + var n = s['name']; + var q = s['selector']; // Dart note: FormatException seems a reasonable mapping of SyntaxError runTest(() { assertThrows((e) => e is FormatException, () { root.querySelector(q); }); - }, type + ".querySelector: " + n + ": " + q); + }, type + '.querySelector: ' + n + ': ' + q); runTest(() { assertThrows((e) => e is FormatException, () { root.querySelectorAll(q); }); - }, type + ".querySelectorAll: " + n + ": " + q); + }, type + '.querySelectorAll: ' + n + ': ' + q); } } -traverse(Node elem, void fn(Node elem)) { +void traverse(Node elem, void Function(Node) fn) { if (elem.nodeType == Node.ELEMENT_NODE) { fn(elem); } @@ -298,19 +298,19 @@ traverse(Node elem, void fn(Node elem)) { } } -runTest(Function body, String name, {String skip}) => +void runTest(Function body, String name, {String skip}) => unittest.test(name, body, skip: skip); -assertTrue(bool value, String reason) => +void assertTrue(bool value, String reason) => unittest.expect(value, unittest.isTrue, reason: reason); -assertFalse(bool value, String reason) => +void assertFalse(bool value, String reason) => unittest.expect(value, unittest.isFalse, reason: reason); -assertEquals(x, y, String reason) => unittest.expect(x, y, reason: reason); +void assertEquals(x, y, String reason) => unittest.expect(x, y, reason: reason); -assertNotEquals(x, y, String reason) => +void assertNotEquals(x, y, String reason) => unittest.expect(x, unittest.isNot(y), reason: reason); -assertThrows(exception, body(), [String reason]) => +void assertThrows(exception, void Function() body, [String reason]) => unittest.expect(body, unittest.throwsA(exception), reason: reason); diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index 9810f5f07..e18f264f6 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -21,41 +21,41 @@ var testMatchAdditional = 0x20; // matches() additional tests * selector: The selector to test */ final invalidSelectors = [ - {'name': "Empty String", 'selector': ""}, - {'name': "Invalid character", 'selector': "["}, - {'name': "Invalid character", 'selector': "]"}, - {'name': "Invalid character", 'selector': "("}, - {'name': "Invalid character", 'selector': ")"}, - {'name': "Invalid character", 'selector': "{"}, - {'name': "Invalid character", 'selector': "}"}, - {'name': "Invalid character", 'selector': "<"}, - {'name': "Invalid character", 'selector': ">"}, - {'name': "Invalid ID", 'selector': "#"}, - {'name': "Invalid group of selectors", 'selector': "div,"}, - {'name': "Invalid class", 'selector': "."}, - {'name': "Invalid class", 'selector': ".5cm"}, - {'name': "Invalid class", 'selector': "..test"}, - {'name': "Invalid class", 'selector': ".foo..quux"}, - {'name': "Invalid class", 'selector': ".bar."}, - {'name': "Invalid combinator", 'selector': "div & address, p"}, - {'name': "Invalid combinator", 'selector': "div >> address, p"}, - {'name': "Invalid combinator", 'selector': "div ++ address, p"}, - {'name': "Invalid combinator", 'selector': "div ~~ address, p"}, - {'name': "Invalid [att=value] selector", 'selector': "[*=test]"}, - {'name': "Invalid [att=value] selector", 'selector': "[*|*=test]"}, - { - 'name': "Invalid [att=value] selector", - 'selector': "[class= space unquoted ]" - }, - {'name': "Unknown pseudo-class", 'selector': "div:example"}, - {'name': "Unknown pseudo-class", 'selector': ":example"}, - {'name': "Unknown pseudo-element", 'selector': "div::example"}, - {'name': "Unknown pseudo-element", 'selector': "::example"}, - {'name': "Invalid pseudo-element", 'selector': ":::before"}, - {'name': "Undeclared namespace", 'selector': "ns|div"}, - {'name': "Undeclared namespace", 'selector': ":not(ns|div)"}, - {'name': "Invalid namespace", 'selector': "^|div"}, - {'name': "Invalid namespace", 'selector': "\$|div"} + {'name': 'Empty String', 'selector': ''}, + {'name': 'Invalid character', 'selector': '['}, + {'name': 'Invalid character', 'selector': ']'}, + {'name': 'Invalid character', 'selector': '('}, + {'name': 'Invalid character', 'selector': ')'}, + {'name': 'Invalid character', 'selector': '{'}, + {'name': 'Invalid character', 'selector': '}'}, + {'name': 'Invalid character', 'selector': '<'}, + {'name': 'Invalid character', 'selector': '>'}, + {'name': 'Invalid ID', 'selector': '#'}, + {'name': 'Invalid group of selectors', 'selector': 'div,'}, + {'name': 'Invalid class', 'selector': '.'}, + {'name': 'Invalid class', 'selector': '.5cm'}, + {'name': 'Invalid class', 'selector': '..test'}, + {'name': 'Invalid class', 'selector': '.foo..quux'}, + {'name': 'Invalid class', 'selector': '.bar.'}, + {'name': 'Invalid combinator', 'selector': 'div & address, p'}, + {'name': 'Invalid combinator', 'selector': 'div >> address, p'}, + {'name': 'Invalid combinator', 'selector': 'div ++ address, p'}, + {'name': 'Invalid combinator', 'selector': 'div ~~ address, p'}, + {'name': 'Invalid [att=value] selector', 'selector': '[*=test]'}, + {'name': 'Invalid [att=value] selector', 'selector': '[*|*=test]'}, + { + 'name': 'Invalid [att=value] selector', + 'selector': '[class= space unquoted ]' + }, + {'name': 'Unknown pseudo-class', 'selector': 'div:example'}, + {'name': 'Unknown pseudo-class', 'selector': ':example'}, + {'name': 'Unknown pseudo-element', 'selector': 'div::example'}, + {'name': 'Unknown pseudo-element', 'selector': '::example'}, + {'name': 'Invalid pseudo-element', 'selector': ':::before'}, + {'name': 'Undeclared namespace', 'selector': 'ns|div'}, + {'name': 'Undeclared namespace', 'selector': ':not(ns|div)'}, + {'name': 'Invalid namespace', 'selector': '^|div'}, + {'name': 'Invalid namespace', 'selector': '\$|div'} ]; /* @@ -77,34 +77,34 @@ final invalidSelectors = [ var validSelectors = [ // Type Selector { - 'name': "Type selector, matching html element", - 'selector': "html", - 'expect': ["html"], - 'exclude': ["element", "fragment", "detached"], + 'name': 'Type selector, matching html element', + 'selector': 'html', + 'expect': ['html'], + 'exclude': ['element', 'fragment', 'detached'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Type selector, matching html element", - 'selector': "html", + 'name': 'Type selector, matching html element', + 'selector': 'html', 'expect': [] /*no matches*/, - 'exclude': ["document"], + 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline }, { - 'name': "Type selector, matching body element", - 'selector': "body", - 'expect': ["body"], - 'exclude': ["element", "fragment", "detached"], + 'name': 'Type selector, matching body element', + 'selector': 'body', + 'expect': ['body'], + 'exclude': ['element', 'fragment', 'detached'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Type selector, matching body element", - 'selector': "body", + 'name': 'Type selector, matching body element', + 'selector': 'body', 'expect': [] /*no matches*/, - 'exclude': ["document"], + 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline }, @@ -113,54 +113,54 @@ var validSelectors = [ // Testing "*" for entire an entire context node is handled separately. { 'name': - "Universal selector, matching all children of element with specified ID", - 'selector': "#universal>*", + 'Universal selector, matching all children of element with specified ID', + 'selector': '#universal>*', 'expect': [ - "universal-p1", - "universal-hr1", - "universal-pre1", - "universal-p2", - "universal-address1" + 'universal-p1', + 'universal-hr1', + 'universal-pre1', + 'universal-p2', + 'universal-address1' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Universal selector, matching all grandchildren of element with specified ID", - 'selector': "#universal>*>*", + 'Universal selector, matching all grandchildren of element with specified ID', + 'selector': '#universal>*>*', 'expect': [ - "universal-code1", - "universal-span1", - "universal-a1", - "universal-code2" + 'universal-code1', + 'universal-span1', + 'universal-a1', + 'universal-code2' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Universal selector, matching all children of empty element with specified ID", - 'selector': "#empty>*", + 'Universal selector, matching all children of empty element with specified ID', + 'selector': '#empty>*', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Universal selector, matching all descendants of element with specified ID", - 'selector': "#universal *", + 'Universal selector, matching all descendants of element with specified ID', + 'selector': '#universal *', 'expect': [ - "universal-p1", - "universal-code1", - "universal-hr1", - "universal-pre1", - "universal-span1", - "universal-p2", - "universal-a1", - "universal-address1", - "universal-code2", - "universal-a2" + 'universal-p1', + 'universal-code1', + 'universal-hr1', + 'universal-pre1', + 'universal-span1', + 'universal-p2', + 'universal-a1', + 'universal-address1', + 'universal-code2', + 'universal-a2' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -169,84 +169,84 @@ var validSelectors = [ // Attribute Selectors // - presence [att] { - 'name': "Attribute presence selector, matching align attribute with value", - 'selector': ".attr-presence-div1[align]", - 'expect': ["attr-presence-div1"], + 'name': 'Attribute presence selector, matching align attribute with value', + 'selector': '.attr-presence-div1[align]', + 'expect': ['attr-presence-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, matching align attribute with empty value", - 'selector': ".attr-presence-div2[align]", - 'expect': ["attr-presence-div2"], + 'Attribute presence selector, matching align attribute with empty value', + 'selector': '.attr-presence-div2[align]', + 'expect': ['attr-presence-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, matching title attribute, case insensitivity", - 'selector': "#attr-presence [TiTlE]", - 'expect': ["attr-presence-a1", "attr-presence-span1"], - 'exclude': ["xhtml"], + 'Attribute presence selector, matching title attribute, case insensitivity', + 'selector': '#attr-presence [TiTlE]', + 'expect': ['attr-presence-a1', 'attr-presence-span1'], + 'exclude': ['xhtml'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, not matching title attribute, case sensitivity", - 'selector': "#attr-presence [TiTlE]", + 'Attribute presence selector, not matching title attribute, case sensitivity', + 'selector': '#attr-presence [TiTlE]', 'expect': [], - 'exclude': ["html"], + 'exclude': ['html'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Attribute presence selector, matching custom data-* attribute", - 'selector': "[data-attr-presence]", - 'expect': ["attr-presence-pre1", "attr-presence-blockquote1"], + 'name': 'Attribute presence selector, matching custom data-* attribute', + 'selector': '[data-attr-presence]', + 'expect': ['attr-presence-pre1', 'attr-presence-blockquote1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, not matching attribute with similar name", - 'selector': ".attr-presence-div3[align], .attr-presence-div4[align]", + 'Attribute presence selector, not matching attribute with similar name', + 'selector': '.attr-presence-div3[align], .attr-presence-div4[align]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute presence selector, matching attribute with non-ASCII characters", - 'selector': "ul[data-中文]", - 'expect': ["attr-presence-ul1"], + 'Attribute presence selector, matching attribute with non-ASCII characters', + 'selector': 'ul[data-中文]', + 'expect': ['attr-presence-ul1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, not matching default option without selected attribute", - 'selector': "#attr-presence-select1 option[selected]", + 'Attribute presence selector, not matching default option without selected attribute', + 'selector': '#attr-presence-select1 option[selected]', 'expect': [] /* no matches */, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute presence selector, matching option with selected attribute", - 'selector': "#attr-presence-select2 option[selected]", - 'expect': ["attr-presence-select2-option4"], + 'Attribute presence selector, matching option with selected attribute', + 'selector': '#attr-presence-select2 option[selected]', + 'expect': ['attr-presence-select2-option4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute presence selector, matching multiple options with selected attributes", - 'selector': "#attr-presence-select3 option[selected]", + 'Attribute presence selector, matching multiple options with selected attributes', + 'selector': '#attr-presence-select3 option[selected]', 'expect': [ - "attr-presence-select3-option2", - "attr-presence-select3-option3" + 'attr-presence-select3-option2', + 'attr-presence-select3-option3' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -254,101 +254,101 @@ var validSelectors = [ // - value [att=val] { - 'name': "Attribute value selector, matching align attribute with value", - 'selector': "#attr-value [align=\"center\"]", - 'expect': ["attr-value-div1"], + 'name': 'Attribute value selector, matching align attribute with value', + 'selector': '#attr-value [align=\"center\"]', + 'expect': ['attr-value-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector, matching align attribute with empty value", - 'selector': "#attr-value [align=\"\"]", - 'expect': ["attr-value-div2"], + 'Attribute value selector, matching align attribute with empty value', + 'selector': '#attr-value [align=\"\"]', + 'expect': ['attr-value-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector, not matching align attribute with partial value", - 'selector': "#attr-value [align=\"c\"]", + 'Attribute value selector, not matching align attribute with partial value', + 'selector': '#attr-value [align=\"c\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute value selector, not matching align attribute with incorrect value", - 'selector': "#attr-value [align=\"centera\"]", + 'Attribute value selector, not matching align attribute with incorrect value', + 'selector': '#attr-value [align=\"centera\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute value selector, matching custom data-* attribute with unicode escaped value", - 'selector': "[data-attr-value=\"\\e9\"]", - 'expect': ["attr-value-div3"], + 'Attribute value selector, matching custom data-* attribute with unicode escaped value', + 'selector': '[data-attr-value=\"\\e9\"]', + 'expect': ['attr-value-div3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector, matching custom data-* attribute with escaped character", - 'selector': "[data-attr-value\_foo=\"\\e9\"]", - 'expect': ["attr-value-div4"], + 'Attribute value selector, matching custom data-* attribute with escaped character', + 'selector': '[data-attr-value\_foo=\"\\e9\"]', + 'expect': ['attr-value-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector with single-quoted value, matching multiple inputs with type attributes", + 'Attribute value selector with single-quoted value, matching multiple inputs with type attributes', 'selector': "#attr-value input[type='hidden'],#attr-value input[type='radio']", 'expect': [ - "attr-value-input3", - "attr-value-input4", - "attr-value-input6", - "attr-value-input8", - "attr-value-input9" + 'attr-value-input3', + 'attr-value-input4', + 'attr-value-input6', + 'attr-value-input8', + 'attr-value-input9' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector with double-quoted value, matching multiple inputs with type attributes", + 'Attribute value selector with double-quoted value, matching multiple inputs with type attributes', 'selector': "#attr-value input[type=\"hidden\"],#attr-value input[type='radio']", 'expect': [ - "attr-value-input3", - "attr-value-input4", - "attr-value-input6", - "attr-value-input8", - "attr-value-input9" + 'attr-value-input3', + 'attr-value-input4', + 'attr-value-input6', + 'attr-value-input8', + 'attr-value-input9' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector with unquoted value, matching multiple inputs with type attributes", - 'selector': "#attr-value input[type=hidden],#attr-value input[type=radio]", + 'Attribute value selector with unquoted value, matching multiple inputs with type attributes', + 'selector': '#attr-value input[type=hidden],#attr-value input[type=radio]', 'expect': [ - "attr-value-input3", - "attr-value-input4", - "attr-value-input6", - "attr-value-input8", - "attr-value-input9" + 'attr-value-input3', + 'attr-value-input4', + 'attr-value-input6', + 'attr-value-input8', + 'attr-value-input9' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute value selector, matching attribute with value using non-ASCII characters", - 'selector': "[data-attr-value=中文]", - 'expect': ["attr-value-div5"], + 'Attribute value selector, matching attribute with value using non-ASCII characters', + 'selector': '[data-attr-value=中文]', + 'expect': ['attr-value-div5'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, @@ -356,102 +356,102 @@ var validSelectors = [ // - whitespace-separated list [att~=val] { 'name': - "Attribute whitespace-separated list selector, matching class attribute with value", - 'selector': "#attr-whitespace [class~=\"div1\"]", - 'expect': ["attr-whitespace-div1"], + 'Attribute whitespace-separated list selector, matching class attribute with value', + 'selector': '#attr-whitespace [class~=\"div1\"]', + 'expect': ['attr-whitespace-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector, not matching class attribute with empty value", - 'selector': "#attr-whitespace [class~=\"\"]", + 'Attribute whitespace-separated list selector, not matching class attribute with empty value', + 'selector': '#attr-whitespace [class~=\"\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute whitespace-separated list selector, not matching class attribute with partial value", - 'selector': "[data-attr-whitespace~=\"div\"]", + 'Attribute whitespace-separated list selector, not matching class attribute with partial value', + 'selector': '[data-attr-whitespace~=\"div\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value", - 'selector': "[data-attr-whitespace~=\"\\0000e9\"]", - 'expect': ["attr-whitespace-div4"], + 'Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value', + 'selector': '[data-attr-whitespace~=\"\\0000e9\"]', + 'expect': ['attr-whitespace-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character", - 'selector': "[data-attr-whitespace\_foo~=\"\\e9\"]", - 'expect': ["attr-whitespace-div5"], + 'Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character', + 'selector': '[data-attr-whitespace\_foo~=\"\\e9\"]', + 'expect': ['attr-whitespace-div5'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes", + 'Attribute whitespace-separated list selector with single-quoted value, matching multiple links with rel attributes', 'selector': "#attr-whitespace a[rel~='bookmark'], #attr-whitespace a[rel~='nofollow']", 'expect': [ - "attr-whitespace-a1", - "attr-whitespace-a2", - "attr-whitespace-a3", - "attr-whitespace-a5", - "attr-whitespace-a7" + 'attr-whitespace-a1', + 'attr-whitespace-a2', + 'attr-whitespace-a3', + 'attr-whitespace-a5', + 'attr-whitespace-a7' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes", + 'Attribute whitespace-separated list selector with double-quoted value, matching multiple links with rel attributes', 'selector': "#attr-whitespace a[rel~=\"bookmark\"],#attr-whitespace a[rel~='nofollow']", 'expect': [ - "attr-whitespace-a1", - "attr-whitespace-a2", - "attr-whitespace-a3", - "attr-whitespace-a5", - "attr-whitespace-a7" + 'attr-whitespace-a1', + 'attr-whitespace-a2', + 'attr-whitespace-a3', + 'attr-whitespace-a5', + 'attr-whitespace-a7' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes", + 'Attribute whitespace-separated list selector with unquoted value, matching multiple links with rel attributes', 'selector': - "#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]", + '#attr-whitespace a[rel~=bookmark], #attr-whitespace a[rel~=nofollow]', 'expect': [ - "attr-whitespace-a1", - "attr-whitespace-a2", - "attr-whitespace-a3", - "attr-whitespace-a5", - "attr-whitespace-a7" + 'attr-whitespace-a1', + 'attr-whitespace-a2', + 'attr-whitespace-a3', + 'attr-whitespace-a5', + 'attr-whitespace-a7' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute whitespace-separated list selector with double-quoted value, not matching value with space", - 'selector': "#attr-whitespace a[rel~=\"book mark\"]", + 'Attribute whitespace-separated list selector with double-quoted value, not matching value with space', + 'selector': '#attr-whitespace a[rel~=\"book mark\"]', 'expect': [] /* no matches */, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters", - 'selector': "#attr-whitespace [title~=中文]", - 'expect': ["attr-whitespace-p1"], + 'Attribute whitespace-separated list selector, matching title attribute with value using non-ASCII characters', + 'selector': '#attr-whitespace [title~=中文]', + 'expect': ['attr-whitespace-p1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, @@ -459,32 +459,32 @@ var validSelectors = [ // - hyphen-separated list [att|=val] { 'name': - "Attribute hyphen-separated list selector, not matching unspecified lang attribute", - 'selector': "#attr-hyphen-div1[lang|=\"en\"]", + 'Attribute hyphen-separated list selector, not matching unspecified lang attribute', + 'selector': '#attr-hyphen-div1[lang|=\"en\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Attribute hyphen-separated list selector, matching lang attribute with exact value", - 'selector': "#attr-hyphen-div2[lang|=\"fr\"]", - 'expect': ["attr-hyphen-div2"], + 'Attribute hyphen-separated list selector, matching lang attribute with exact value', + 'selector': '#attr-hyphen-div2[lang|=\"fr\"]', + 'expect': ['attr-hyphen-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute hyphen-separated list selector, matching lang attribute with partial value", - 'selector': "#attr-hyphen-div3[lang|=\"en\"]", - 'expect': ["attr-hyphen-div3"], + 'Attribute hyphen-separated list selector, matching lang attribute with partial value', + 'selector': '#attr-hyphen-div3[lang|=\"en\"]', + 'expect': ['attr-hyphen-div3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Attribute hyphen-separated list selector, not matching incorrect value", - 'selector': "#attr-hyphen-div4[lang|=\"es-AR\"]", + 'Attribute hyphen-separated list selector, not matching incorrect value', + 'selector': '#attr-hyphen-div4[lang|=\"es-AR\"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -493,48 +493,48 @@ var validSelectors = [ // - substring begins-with [att^=val] (Level 3) { 'name': - "Attribute begins with selector, matching href attributes beginning with specified substring", - 'selector': "#attr-begins a[href^=\"http://www\"]", - 'expect': ["attr-begins-a1", "attr-begins-a3"], + 'Attribute begins with selector, matching href attributes beginning with specified substring', + 'selector': '#attr-begins a[href^=\"http://www\"]', + 'expect': ['attr-begins-a1', 'attr-begins-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute begins with selector, matching lang attributes beginning with specified substring, ", - 'selector': "#attr-begins [lang^=\"en-\"]", - 'expect': ["attr-begins-div2", "attr-begins-div4"], + 'Attribute begins with selector, matching lang attributes beginning with specified substring, ', + 'selector': '#attr-begins [lang^=\"en-\"]', + 'expect': ['attr-begins-div2', 'attr-begins-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute begins with selector, not matching class attribute not beginning with specified substring", - 'selector': "#attr-begins [class^=apple]", + 'Attribute begins with selector, not matching class attribute not beginning with specified substring', + 'selector': '#attr-begins [class^=apple]', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, { 'name': - "Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring", + 'Attribute begins with selector with single-quoted value, matching class attribute beginning with specified substring', 'selector': "#attr-begins [class^=' apple']", - 'expect': ["attr-begins-p1"], + 'expect': ['attr-begins-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring", - 'selector': "#attr-begins [class^=\" apple\"]", - 'expect': ["attr-begins-p1"], + 'Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring', + 'selector': '#attr-begins [class^=\" apple\"]', + 'expect': ['attr-begins-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring", - 'selector': "#attr-begins [class^= apple]", + 'Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring', + 'selector': '#attr-begins [class^= apple]', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -543,48 +543,48 @@ var validSelectors = [ // - substring ends-with [att\$=val] (Level 3) { 'name': - "Attribute ends with selector, matching href attributes ending with specified substring", - 'selector': "#attr-ends a[href\$=\".org\"]", - 'expect': ["attr-ends-a1", "attr-ends-a3"], + 'Attribute ends with selector, matching href attributes ending with specified substring', + 'selector': '#attr-ends a[href\$=\".org\"]', + 'expect': ['attr-ends-a1', 'attr-ends-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute ends with selector, matching lang attributes ending with specified substring, ", - 'selector': "#attr-ends [lang\$=\"-CH\"]", - 'expect': ["attr-ends-div2", "attr-ends-div4"], + 'Attribute ends with selector, matching lang attributes ending with specified substring, ', + 'selector': '#attr-ends [lang\$=\"-CH\"]', + 'expect': ['attr-ends-div2', 'attr-ends-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute ends with selector, not matching class attribute not ending with specified substring", - 'selector': "#attr-ends [class\$=apple]", + 'Attribute ends with selector, not matching class attribute not ending with specified substring', + 'selector': '#attr-ends [class\$=apple]', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, { 'name': - "Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring", + 'Attribute ends with selector with single-quoted value, matching class attribute ending with specified substring', 'selector': "#attr-ends [class\$='apple ']", - 'expect': ["attr-ends-p1"], + 'expect': ['attr-ends-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring", - 'selector': "#attr-ends [class\$=\"apple \"]", - 'expect': ["attr-ends-p1"], + 'Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring', + 'selector': '#attr-ends [class\$=\"apple \"]', + 'expect': ['attr-ends-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring", - 'selector': "#attr-ends [class\$=apple ]", + 'Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring', + 'selector': '#attr-ends [class\$=apple ]', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -593,113 +593,113 @@ var validSelectors = [ // - substring contains [att*=val] (Level 3) { 'name': - "Attribute contains selector, matching href attributes beginning with specified substring", - 'selector': "#attr-contains a[href*=\"http://www\"]", - 'expect': ["attr-contains-a1", "attr-contains-a3"], + 'Attribute contains selector, matching href attributes beginning with specified substring', + 'selector': '#attr-contains a[href*=\"http://www\"]', + 'expect': ['attr-contains-a1', 'attr-contains-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector, matching href attributes ending with specified substring", - 'selector': "#attr-contains a[href*=\".org\"]", - 'expect': ["attr-contains-a1", "attr-contains-a2"], + 'Attribute contains selector, matching href attributes ending with specified substring', + 'selector': '#attr-contains a[href*=\".org\"]', + 'expect': ['attr-contains-a1', 'attr-contains-a2'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector, matching href attributes containing specified substring", - 'selector': "#attr-contains a[href*=\".example.\"]", - 'expect': ["attr-contains-a1", "attr-contains-a3"], + 'Attribute contains selector, matching href attributes containing specified substring', + 'selector': '#attr-contains a[href*=\".example.\"]', + 'expect': ['attr-contains-a1', 'attr-contains-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector, matching lang attributes beginning with specified substring, ", - 'selector': "#attr-contains [lang*=\"en-\"]", - 'expect': ["attr-contains-div2", "attr-contains-div6"], + 'Attribute contains selector, matching lang attributes beginning with specified substring, ', + 'selector': '#attr-contains [lang*=\"en-\"]', + 'expect': ['attr-contains-div2', 'attr-contains-div6'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector, matching lang attributes ending with specified substring, ", - 'selector': "#attr-contains [lang*=\"-CH\"]", - 'expect': ["attr-contains-div3", "attr-contains-div5"], + 'Attribute contains selector, matching lang attributes ending with specified substring, ', + 'selector': '#attr-contains [lang*=\"-CH\"]', + 'expect': ['attr-contains-div3', 'attr-contains-div5'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring", + 'Attribute contains selector with single-quoted value, matching class attribute beginning with specified substring', 'selector': "#attr-contains [class*=' apple']", - 'expect': ["attr-contains-p1"], + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with single-quoted value, matching class attribute ending with specified substring", + 'Attribute contains selector with single-quoted value, matching class attribute ending with specified substring', 'selector': "#attr-contains [class*='orange ']", - 'expect': ["attr-contains-p1"], + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with single-quoted value, matching class attribute containing specified substring", + 'Attribute contains selector with single-quoted value, matching class attribute containing specified substring', 'selector': "#attr-contains [class*='ple banana ora']", - 'expect': ["attr-contains-p1"], + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring", - 'selector': "#attr-contains [class*=\" apple\"]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring', + 'selector': '#attr-contains [class*=\" apple\"]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with double-quoted value, matching class attribute ending with specified substring", - 'selector': "#attr-contains [class*=\"orange \"]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with double-quoted value, matching class attribute ending with specified substring', + 'selector': '#attr-contains [class*=\"orange \"]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with double-quoted value, matching class attribute containing specified substring", - 'selector': "#attr-contains [class*=\"ple banana ora\"]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with double-quoted value, matching class attribute containing specified substring', + 'selector': '#attr-contains [class*=\"ple banana ora\"]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with unquoted value, matching class attribute beginning with specified substring", - 'selector': "#attr-contains [class*= apple]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with unquoted value, matching class attribute beginning with specified substring', + 'selector': '#attr-contains [class*= apple]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with unquoted value, matching class attribute ending with specified substring", - 'selector': "#attr-contains [class*=orange ]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with unquoted value, matching class attribute ending with specified substring', + 'selector': '#attr-contains [class*=orange ]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "Attribute contains selector with unquoted value, matching class attribute containing specified substring", - 'selector': "#attr-contains [class*= banana ]", - 'expect': ["attr-contains-p1"], + 'Attribute contains selector with unquoted value, matching class attribute containing specified substring', + 'selector': '#attr-contains [class*= banana ]', + 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, @@ -707,227 +707,227 @@ var validSelectors = [ // Pseudo-classes // - :root (Level 3) { - 'name': ":root pseudo-class selector, matching document root element", - 'selector': ":root", - 'expect': ["html"], - 'exclude': ["element", "fragment", "detached"], + 'name': ':root pseudo-class selector, matching document root element', + 'selector': ':root', + 'expect': ['html'], + 'exclude': ['element', 'fragment', 'detached'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': ":root pseudo-class selector, not matching document root element", - 'selector': ":root", + 'name': ':root pseudo-class selector, not matching document root element', + 'selector': ':root', 'expect': [] /*no matches*/, - 'exclude': ["document"], + 'exclude': ['document'], 'level': 3, 'testType': testQsaAdditional }, // - :nth-child(n) (Level 3) { - 'name': ":nth-child selector, matching the third child element", - 'selector': "#pseudo-nth-table1 :nth-child(3)", + 'name': ':nth-child selector, matching the third child element', + 'selector': '#pseudo-nth-table1 :nth-child(3)', 'expect': [ - "pseudo-nth-td3", - "pseudo-nth-td9", - "pseudo-nth-tr3", - "pseudo-nth-td15" + 'pseudo-nth-td3', + 'pseudo-nth-td9', + 'pseudo-nth-tr3', + 'pseudo-nth-td15' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': ":nth-child selector, matching every third child element", - 'selector': "#pseudo-nth li:nth-child(3n)", + 'name': ':nth-child selector, matching every third child element', + 'selector': '#pseudo-nth li:nth-child(3n)', 'expect': [ - "pseudo-nth-li3", - "pseudo-nth-li6", - "pseudo-nth-li9", - "pseudo-nth-li12" + 'pseudo-nth-li3', + 'pseudo-nth-li6', + 'pseudo-nth-li9', + 'pseudo-nth-li12' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-child selector, matching every second child element, starting from the fourth", - 'selector': "#pseudo-nth li:nth-child(2n+4)", + ':nth-child selector, matching every second child element, starting from the fourth', + 'selector': '#pseudo-nth li:nth-child(2n+4)', 'expect': [ - "pseudo-nth-li4", - "pseudo-nth-li6", - "pseudo-nth-li8", - "pseudo-nth-li10", - "pseudo-nth-li12" + 'pseudo-nth-li4', + 'pseudo-nth-li6', + 'pseudo-nth-li8', + 'pseudo-nth-li10', + 'pseudo-nth-li12' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-child selector, matching every fourth child element, starting from the third", - 'selector': "#pseudo-nth-p1 :nth-child(4n-1)", - 'expect': ["pseudo-nth-em2", "pseudo-nth-span3"], + ':nth-child selector, matching every fourth child element, starting from the third', + 'selector': '#pseudo-nth-p1 :nth-child(4n-1)', + 'expect': ['pseudo-nth-em2', 'pseudo-nth-span3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-last-child (Level 3) { - 'name': ":nth-last-child selector, matching the third last child element", - 'selector': "#pseudo-nth-table1 :nth-last-child(3)", + 'name': ':nth-last-child selector, matching the third last child element', + 'selector': '#pseudo-nth-table1 :nth-last-child(3)', 'expect': [ - "pseudo-nth-tr1", - "pseudo-nth-td4", - "pseudo-nth-td10", - "pseudo-nth-td16" + 'pseudo-nth-tr1', + 'pseudo-nth-td4', + 'pseudo-nth-td10', + 'pseudo-nth-td16' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-last-child selector, matching every third child element from the end", - 'selector': "#pseudo-nth li:nth-last-child(3n)", + ':nth-last-child selector, matching every third child element from the end', + 'selector': '#pseudo-nth li:nth-last-child(3n)', 'expect': [ - "pseudo-nth-li1", - "pseudo-nth-li4", - "pseudo-nth-li7", - "pseudo-nth-li10" + 'pseudo-nth-li1', + 'pseudo-nth-li4', + 'pseudo-nth-li7', + 'pseudo-nth-li10' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-last-child selector, matching every second child element from the end, starting from the fourth last", - 'selector': "#pseudo-nth li:nth-last-child(2n+4)", + ':nth-last-child selector, matching every second child element from the end, starting from the fourth last', + 'selector': '#pseudo-nth li:nth-last-child(2n+4)', 'expect': [ - "pseudo-nth-li1", - "pseudo-nth-li3", - "pseudo-nth-li5", - "pseudo-nth-li7", - "pseudo-nth-li9" + 'pseudo-nth-li1', + 'pseudo-nth-li3', + 'pseudo-nth-li5', + 'pseudo-nth-li7', + 'pseudo-nth-li9' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-last-child selector, matching every fourth element from the end, starting from the third last", - 'selector': "#pseudo-nth-p1 :nth-last-child(4n-1)", - 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], + ':nth-last-child selector, matching every fourth element from the end, starting from the third last', + 'selector': '#pseudo-nth-p1 :nth-last-child(4n-1)', + 'expect': ['pseudo-nth-span2', 'pseudo-nth-span4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-of-type(n) (Level 3) { - 'name': ":nth-of-type selector, matching the third em element", - 'selector': "#pseudo-nth-p1 em:nth-of-type(3)", - 'expect': ["pseudo-nth-em3"], + 'name': ':nth-of-type selector, matching the third em element', + 'selector': '#pseudo-nth-p1 em:nth-of-type(3)', + 'expect': ['pseudo-nth-em3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-of-type selector, matching every second element of their type", - 'selector': "#pseudo-nth-p1 :nth-of-type(2n)", + ':nth-of-type selector, matching every second element of their type', + 'selector': '#pseudo-nth-p1 :nth-of-type(2n)', 'expect': [ - "pseudo-nth-em2", - "pseudo-nth-span2", - "pseudo-nth-span4", - "pseudo-nth-strong2", - "pseudo-nth-em4" + 'pseudo-nth-em2', + 'pseudo-nth-span2', + 'pseudo-nth-span4', + 'pseudo-nth-strong2', + 'pseudo-nth-em4' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-of-type selector, matching every second elemetn of their type, starting from the first", - 'selector': "#pseudo-nth-p1 span:nth-of-type(2n-1)", - 'expect': ["pseudo-nth-span1", "pseudo-nth-span3"], + ':nth-of-type selector, matching every second elemetn of their type, starting from the first', + 'selector': '#pseudo-nth-p1 span:nth-of-type(2n-1)', + 'expect': ['pseudo-nth-span1', 'pseudo-nth-span3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :nth-last-of-type(n) (Level 3) { - 'name': ":nth-last-of-type selector, matching the thrid last em element", - 'selector': "#pseudo-nth-p1 em:nth-last-of-type(3)", - 'expect': ["pseudo-nth-em2"], + 'name': ':nth-last-of-type selector, matching the thrid last em element', + 'selector': '#pseudo-nth-p1 em:nth-last-of-type(3)', + 'expect': ['pseudo-nth-em2'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-last-of-type selector, matching every second last element of their type", - 'selector': "#pseudo-nth-p1 :nth-last-of-type(2n)", + ':nth-last-of-type selector, matching every second last element of their type', + 'selector': '#pseudo-nth-p1 :nth-last-of-type(2n)', 'expect': [ - "pseudo-nth-span1", - "pseudo-nth-em1", - "pseudo-nth-strong1", - "pseudo-nth-em3", - "pseudo-nth-span3" + 'pseudo-nth-span1', + 'pseudo-nth-em1', + 'pseudo-nth-strong1', + 'pseudo-nth-em3', + 'pseudo-nth-span3' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":nth-last-of-type selector, matching every second last element of their type, starting from the last", - 'selector': "#pseudo-nth-p1 span:nth-last-of-type(2n-1)", - 'expect': ["pseudo-nth-span2", "pseudo-nth-span4"], + ':nth-last-of-type selector, matching every second last element of their type, starting from the last', + 'selector': '#pseudo-nth-p1 span:nth-last-of-type(2n-1)', + 'expect': ['pseudo-nth-span2', 'pseudo-nth-span4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :first-of-type (Level 3) { - 'name': ":first-of-type selector, matching the first em element", - 'selector': "#pseudo-nth-p1 em:first-of-type", - 'expect': ["pseudo-nth-em1"], + 'name': ':first-of-type selector, matching the first em element', + 'selector': '#pseudo-nth-p1 em:first-of-type', + 'expect': ['pseudo-nth-em1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":first-of-type selector, matching the first of every type of element", - 'selector': "#pseudo-nth-p1 :first-of-type", - 'expect': ["pseudo-nth-span1", "pseudo-nth-em1", "pseudo-nth-strong1"], + ':first-of-type selector, matching the first of every type of element', + 'selector': '#pseudo-nth-p1 :first-of-type', + 'expect': ['pseudo-nth-span1', 'pseudo-nth-em1', 'pseudo-nth-strong1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":first-of-type selector, matching the first td element in each table row", - 'selector': "#pseudo-nth-table1 tr :first-of-type", - 'expect': ["pseudo-nth-td1", "pseudo-nth-td7", "pseudo-nth-td13"], + ':first-of-type selector, matching the first td element in each table row', + 'selector': '#pseudo-nth-table1 tr :first-of-type', + 'expect': ['pseudo-nth-td1', 'pseudo-nth-td7', 'pseudo-nth-td13'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :last-of-type (Level 3) { - 'name': ":last-of-type selector, matching the last em elemnet", - 'selector': "#pseudo-nth-p1 em:last-of-type", - 'expect': ["pseudo-nth-em4"], + 'name': ':last-of-type selector, matching the last em elemnet', + 'selector': '#pseudo-nth-p1 em:last-of-type', + 'expect': ['pseudo-nth-em4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":last-of-type selector, matching the last of every type of element", - 'selector': "#pseudo-nth-p1 :last-of-type", - 'expect': ["pseudo-nth-span4", "pseudo-nth-strong2", "pseudo-nth-em4"], + ':last-of-type selector, matching the last of every type of element', + 'selector': '#pseudo-nth-p1 :last-of-type', + 'expect': ['pseudo-nth-span4', 'pseudo-nth-strong2', 'pseudo-nth-em4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":last-of-type selector, matching the last td element in each table row", - 'selector': "#pseudo-nth-table1 tr :last-of-type", - 'expect': ["pseudo-nth-td6", "pseudo-nth-td12", "pseudo-nth-td18"], + ':last-of-type selector, matching the last td element in each table row', + 'selector': '#pseudo-nth-table1 tr :last-of-type', + 'expect': ['pseudo-nth-td6', 'pseudo-nth-td12', 'pseudo-nth-td18'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, @@ -935,9 +935,9 @@ var validSelectors = [ // - :first-child { 'name': - ":first-child pseudo-class selector, matching first child div element", - 'selector': "#pseudo-first-child div:first-child", - 'expect': ["pseudo-first-child-div1"], + ':first-child pseudo-class selector, matching first child div element', + 'selector': '#pseudo-first-child div:first-child', + 'expect': ['pseudo-first-child-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, @@ -945,19 +945,19 @@ var validSelectors = [ 'name': ":first-child pseudo-class selector, doesn't match non-first-child elements", 'selector': - ".pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child", + '.pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - ":first-child pseudo-class selector, matching first-child of multiple elements", - 'selector': "#pseudo-first-child span:first-child", + ':first-child pseudo-class selector, matching first-child of multiple elements', + 'selector': '#pseudo-first-child span:first-child', 'expect': [ - "pseudo-first-child-span1", - "pseudo-first-child-span3", - "pseudo-first-child-span5" + 'pseudo-first-child-span1', + 'pseudo-first-child-span3', + 'pseudo-first-child-span5' ], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -966,9 +966,9 @@ var validSelectors = [ // - :last-child (Level 3) { 'name': - ":last-child pseudo-class selector, matching last child div element", - 'selector': "#pseudo-last-child div:last-child", - 'expect': ["pseudo-last-child-div3"], + ':last-child pseudo-class selector, matching last child div element', + 'selector': '#pseudo-last-child div:last-child', + 'expect': ['pseudo-last-child-div3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, @@ -976,19 +976,19 @@ var validSelectors = [ 'name': ":last-child pseudo-class selector, doesn't match non-last-child elements", 'selector': - ".pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child", + '.pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, { 'name': - ":last-child pseudo-class selector, matching first-child of multiple elements", - 'selector': "#pseudo-last-child span:last-child", + ':last-child pseudo-class selector, matching first-child of multiple elements', + 'selector': '#pseudo-last-child span:last-child', 'expect': [ - "pseudo-last-child-span2", - "pseudo-last-child-span4", - "pseudo-last-child-span6" + 'pseudo-last-child-span2', + 'pseudo-last-child-span4', + 'pseudo-last-child-span6' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -997,16 +997,16 @@ var validSelectors = [ // - :only-child (Level 3) { 'name': - ":pseudo-only-child pseudo-class selector, matching all only-child elements", - 'selector': "#pseudo-only :only-child", - 'expect': ["pseudo-only-span1"], + ':pseudo-only-child pseudo-class selector, matching all only-child elements', + 'selector': '#pseudo-only :only-child', + 'expect': ['pseudo-only-span1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":pseudo-only-child pseudo-class selector, matching only-child em elements", - 'selector': "#pseudo-only em:only-child", + ':pseudo-only-child pseudo-class selector, matching only-child em elements', + 'selector': '#pseudo-only em:only-child', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -1015,33 +1015,33 @@ var validSelectors = [ // - :only-of-type (Level 3) { 'name': - ":pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type", - 'selector': "#pseudo-only :only-of-type", - 'expect': ["pseudo-only-span1", "pseudo-only-em1"], + ':pseudo-only-of-type pseudo-class selector, matching all elements with no siblings of the same type', + 'selector': '#pseudo-only :only-of-type', + 'expect': ['pseudo-only-span1', 'pseudo-only-em1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - ":pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type", - 'selector': "#pseudo-only em:only-of-type", - 'expect': ["pseudo-only-em1"], + ':pseudo-only-of-type pseudo-class selector, matching em elements with no siblings of the same type', + 'selector': '#pseudo-only em:only-of-type', + 'expect': ['pseudo-only-em1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :empty (Level 3) { - 'name': ":empty pseudo-class selector, matching empty p elements", - 'selector': "#pseudo-empty p:empty", - 'expect': ["pseudo-empty-p1", "pseudo-empty-p2"], + 'name': ':empty pseudo-class selector, matching empty p elements', + 'selector': '#pseudo-empty p:empty', + 'expect': ['pseudo-empty-p1', 'pseudo-empty-p2'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': ":empty pseudo-class selector, matching all empty elements", - 'selector': "#pseudo-empty :empty", - 'expect': ["pseudo-empty-p1", "pseudo-empty-p2", "pseudo-empty-span1"], + 'name': ':empty pseudo-class selector, matching all empty elements', + 'selector': '#pseudo-empty :empty', + 'expect': ['pseudo-empty-p1', 'pseudo-empty-p2', 'pseudo-empty-span1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, @@ -1051,36 +1051,36 @@ var validSelectors = [ // The only guarantee is that ":link,:visited" matches the set of all visited and unvisited links and that they are individually mutually exclusive sets. { 'name': - ":link and :visited pseudo-class selectors, matching a and area elements with href attributes", - 'selector': "#pseudo-link :link, #pseudo-link :visited", - 'expect': ["pseudo-link-a1", "pseudo-link-a2", "pseudo-link-area1"], + ':link and :visited pseudo-class selectors, matching a and area elements with href attributes', + 'selector': '#pseudo-link :link, #pseudo-link :visited', + 'expect': ['pseudo-link-a1', 'pseudo-link-a2', 'pseudo-link-area1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - ":link and :visited pseudo-class selectors, matching link elements with href attributes", - 'selector': "#head :link, #head :visited", - 'expect': ["pseudo-link-link1", "pseudo-link-link2"], - 'exclude': ["element", "fragment", "detached"], + ':link and :visited pseudo-class selectors, matching link elements with href attributes', + 'selector': '#head :link, #head :visited', + 'expect': ['pseudo-link-link1', 'pseudo-link-link2'], + 'exclude': ['element', 'fragment', 'detached'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - ":link and :visited pseudo-class selectors, not matching link elements with href attributes", - 'selector': "#head :link, #head :visited", + ':link and :visited pseudo-class selectors, not matching link elements with href attributes', + 'selector': '#head :link, #head :visited', 'expect': [] /*no matches*/, - 'exclude': ["document"], + 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline }, { 'name': - ":link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing", - 'selector': ":link:visited", + ':link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing', + 'selector': ':link:visited', 'expect': [] /*no matches*/, - 'exclude': ["document"], + 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline }, @@ -1088,60 +1088,60 @@ var validSelectors = [ // - :target (Level 3) { 'name': - ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", - 'selector': ":target", + ':target pseudo-class selector, matching the element referenced by the URL fragment identifier', + 'selector': ':target', 'expect': [] /*no matches*/, - 'exclude': ["document", "element"], + 'exclude': ['document', 'element'], 'level': 3, 'testType': testQsaAdditional }, { 'name': - ":target pseudo-class selector, matching the element referenced by the URL fragment identifier", - 'selector': ":target", - 'expect': ["target"], - 'exclude': ["fragment", "detached"], + ':target pseudo-class selector, matching the element referenced by the URL fragment identifier', + 'selector': ':target', + 'expect': ['target'], + 'exclude': ['fragment', 'detached'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // - :lang() { - 'name': ":lang pseudo-class selector, matching inherited language", - 'selector': "#pseudo-lang-div1:lang(en)", - 'expect': ["pseudo-lang-div1"], - 'exclude': ["detached", "fragment"], + 'name': ':lang pseudo-class selector, matching inherited language', + 'selector': '#pseudo-lang-div1:lang(en)', + 'expect': ['pseudo-lang-div1'], + 'exclude': ['detached', 'fragment'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - ":lang pseudo-class selector, not matching element with no inherited language", - 'selector': "#pseudo-lang-div1:lang(en)", + ':lang pseudo-class selector, not matching element with no inherited language', + 'selector': '#pseudo-lang-div1:lang(en)', 'expect': [] /*no matches*/, - 'exclude': ["document", "element"], + 'exclude': ['document', 'element'], 'level': 2, 'testType': testQsaBaseline }, { 'name': - ":lang pseudo-class selector, matching specified language with exact value", - 'selector': "#pseudo-lang-div2:lang(fr)", - 'expect': ["pseudo-lang-div2"], + ':lang pseudo-class selector, matching specified language with exact value', + 'selector': '#pseudo-lang-div2:lang(fr)', + 'expect': ['pseudo-lang-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - ":lang pseudo-class selector, matching specified language with partial value", - 'selector': "#pseudo-lang-div3:lang(en)", - 'expect': ["pseudo-lang-div3"], + ':lang pseudo-class selector, matching specified language with partial value', + 'selector': '#pseudo-lang-div3:lang(en)', + 'expect': ['pseudo-lang-div3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': ":lang pseudo-class selector, not matching incorrect language", - 'selector': "#pseudo-lang-div4:lang(es-AR)", + 'name': ':lang pseudo-class selector, not matching incorrect language', + 'selector': '#pseudo-lang-div4:lang(es-AR)', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -1150,20 +1150,20 @@ var validSelectors = [ // - :enabled (Level 3) { 'name': - ":enabled pseudo-class selector, matching all enabled form controls", - 'selector': "#pseudo-ui :enabled", + ':enabled pseudo-class selector, matching all enabled form controls', + 'selector': '#pseudo-ui :enabled', 'expect': [ - "pseudo-ui-input1", - "pseudo-ui-input2", - "pseudo-ui-input3", - "pseudo-ui-input4", - "pseudo-ui-input5", - "pseudo-ui-input6", - "pseudo-ui-input7", - "pseudo-ui-input8", - "pseudo-ui-input9", - "pseudo-ui-textarea1", - "pseudo-ui-button1" + 'pseudo-ui-input1', + 'pseudo-ui-input2', + 'pseudo-ui-input3', + 'pseudo-ui-input4', + 'pseudo-ui-input5', + 'pseudo-ui-input6', + 'pseudo-ui-input7', + 'pseudo-ui-input8', + 'pseudo-ui-input9', + 'pseudo-ui-textarea1', + 'pseudo-ui-button1' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -1172,20 +1172,20 @@ var validSelectors = [ // - :disabled (Level 3) { 'name': - ":enabled pseudo-class selector, matching all disabled form controls", - 'selector': "#pseudo-ui :disabled", + ':enabled pseudo-class selector, matching all disabled form controls', + 'selector': '#pseudo-ui :disabled', 'expect': [ - "pseudo-ui-input10", - "pseudo-ui-input11", - "pseudo-ui-input12", - "pseudo-ui-input13", - "pseudo-ui-input14", - "pseudo-ui-input15", - "pseudo-ui-input16", - "pseudo-ui-input17", - "pseudo-ui-input18", - "pseudo-ui-textarea2", - "pseudo-ui-button2" + 'pseudo-ui-input10', + 'pseudo-ui-input11', + 'pseudo-ui-input12', + 'pseudo-ui-input13', + 'pseudo-ui-input14', + 'pseudo-ui-input15', + 'pseudo-ui-input16', + 'pseudo-ui-input17', + 'pseudo-ui-input18', + 'pseudo-ui-textarea2', + 'pseudo-ui-button2' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -1194,13 +1194,13 @@ var validSelectors = [ // - :checked (Level 3) { 'name': - ":checked pseudo-class selector, matching checked radio buttons and checkboxes", - 'selector': "#pseudo-ui :checked", + ':checked pseudo-class selector, matching checked radio buttons and checkboxes', + 'selector': '#pseudo-ui :checked', 'expect': [ - "pseudo-ui-input4", - "pseudo-ui-input6", - "pseudo-ui-input13", - "pseudo-ui-input15" + 'pseudo-ui-input4', + 'pseudo-ui-input6', + 'pseudo-ui-input13', + 'pseudo-ui-input15' ], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -1208,29 +1208,29 @@ var validSelectors = [ // - :not(s) (Level 3) { - 'name': ":not pseudo-class selector, matching ", - 'selector': "#not>:not(div)", - 'expect': ["not-p1", "not-p2", "not-p3"], + 'name': ':not pseudo-class selector, matching ', + 'selector': '#not>:not(div)', + 'expect': ['not-p1', 'not-p2', 'not-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': ":not pseudo-class selector, matching ", - 'selector': "#not * :not(:first-child)", - 'expect': ["not-em1", "not-em2", "not-em3"], + 'name': ':not pseudo-class selector, matching ', + 'selector': '#not * :not(:first-child)', + 'expect': ['not-em1', 'not-em2', 'not-em3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': ":not pseudo-class selector, matching nothing", - 'selector': ":not(*)", + 'name': ':not pseudo-class selector, matching nothing', + 'selector': ':not(*)', 'expect': [] /* no matches */, 'level': 3, 'testType': testQsaAdditional }, { - 'name': ":not pseudo-class selector, matching nothing", - 'selector': ":not(*|*)", + 'name': ':not pseudo-class selector, matching nothing', + 'selector': ':not(*|*)', 'expect': [] /* no matches */, 'level': 3, 'testType': testQsaAdditional @@ -1240,16 +1240,16 @@ var validSelectors = [ // - ::first-line { 'name': - ":first-line pseudo-element (one-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element:first-line", + ':first-line pseudo-element (one-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element:first-line', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "::first-line pseudo-element (two-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element::first-line", + '::first-line pseudo-element (two-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element::first-line', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -1258,16 +1258,16 @@ var validSelectors = [ // - ::first-letter { 'name': - ":first-letter pseudo-element (one-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element:first-letter", + ':first-letter pseudo-element (one-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element:first-letter', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "::first-letter pseudo-element (two-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element::first-letter", + '::first-letter pseudo-element (two-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element::first-letter', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -1276,16 +1276,16 @@ var validSelectors = [ // - ::before { 'name': - ":before pseudo-element (one-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element:before", + ':before pseudo-element (one-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element:before', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "::before pseudo-element (two-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element::before", + '::before pseudo-element (two-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element::before', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -1294,16 +1294,16 @@ var validSelectors = [ // - ::after { 'name': - ":after pseudo-element (one-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element:after", + ':after pseudo-element (one-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element:after', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "::after pseudo-element (two-colon syntax) selector, not matching any elements", - 'selector': "#pseudo-element::after", + '::after pseudo-element (two-colon syntax) selector, not matching any elements', + 'selector': '#pseudo-element::after', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional @@ -1311,127 +1311,127 @@ var validSelectors = [ // Class Selectors { - 'name': "Class selector, matching element with specified class", - 'selector': ".class-p", - 'expect': ["class-p1", "class-p2", "class-p3"], + 'name': 'Class selector, matching element with specified class', + 'selector': '.class-p', + 'expect': ['class-p1', 'class-p2', 'class-p3'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Class selector, chained, matching only elements with all specified classes", - 'selector': "#class .apple.orange.banana", + 'Class selector, chained, matching only elements with all specified classes', + 'selector': '#class .apple.orange.banana', 'expect': [ - "class-div1", - "class-div2", - "class-p4", - "class-div3", - "class-p6", - "class-div4" + 'class-div1', + 'class-div2', + 'class-p4', + 'class-div3', + 'class-p6', + 'class-div4' ], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Class Selector, chained, with type selector", - 'selector': "div.apple.banana.orange", - 'expect': ["class-div1", "class-div2", "class-div3", "class-div4"], + 'name': 'Class Selector, chained, with type selector', + 'selector': 'div.apple.banana.orange', + 'expect': ['class-div1', 'class-div2', 'class-div3', 'class-div4'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, // Caution: If copying and pasting the folowing non-ASCII classes, ensure unicode normalisation is not performed in the process. { 'name': - "Class selector, matching element with class value using non-ASCII characters", - 'selector': ".台北Táiběi", - 'expect': ["class-span1"], + 'Class selector, matching element with class value using non-ASCII characters', + 'selector': '.台北Táiběi', + 'expect': ['class-span1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Class selector, matching multiple elements with class value using non-ASCII characters", - 'selector': ".台北", - 'expect': ["class-span1", "class-span2"], + 'Class selector, matching multiple elements with class value using non-ASCII characters', + 'selector': '.台北', + 'expect': ['class-span1', 'class-span2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Class selector, chained, matching element with multiple class values using non-ASCII characters", - 'selector': ".台北Táiběi.台北", - 'expect': ["class-span1"], + 'Class selector, chained, matching element with multiple class values using non-ASCII characters', + 'selector': '.台北Táiběi.台北', + 'expect': ['class-span1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Class selector, matching element with class with escaped character", - 'selector': ".foo\\:bar", - 'expect': ["class-span3"], + 'Class selector, matching element with class with escaped character', + 'selector': '.foo\\:bar', + 'expect': ['class-span3'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Class selector, matching element with class with escaped character", - 'selector': ".test\\.foo\\[5\\]bar", - 'expect': ["class-span4"], + 'Class selector, matching element with class with escaped character', + 'selector': '.test\\.foo\\[5\\]bar', + 'expect': ['class-span4'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, // ID Selectors { - 'name': "ID selector, matching element with specified id", - 'selector': "#id #id-div1", - 'expect': ["id-div1"], + 'name': 'ID selector, matching element with specified id', + 'selector': '#id #id-div1', + 'expect': ['id-div1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID selector, chained, matching element with specified id", - 'selector': "#id-div1, #id-div1", - 'expect': ["id-div1"], + 'name': 'ID selector, chained, matching element with specified id', + 'selector': '#id-div1, #id-div1', + 'expect': ['id-div1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID selector, chained, matching element with specified id", - 'selector': "#id-div1, #id-div2", - 'expect': ["id-div1", "id-div2"], + 'name': 'ID selector, chained, matching element with specified id', + 'selector': '#id-div1, #id-div2', + 'expect': ['id-div1', 'id-div2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID Selector, chained, with type selector", - 'selector': "div#id-div1, div#id-div2", - 'expect': ["id-div1", "id-div2"], + 'name': 'ID Selector, chained, with type selector', + 'selector': 'div#id-div1, div#id-div2', + 'expect': ['id-div1', 'id-div2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID selector, not matching non-existent descendant", - 'selector': "#id #none", + 'name': 'ID selector, not matching non-existent descendant', + 'selector': '#id #none', 'expect': [] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, { - 'name': "ID selector, not matching non-existent ancestor", - 'selector': "#none #id-div1", + 'name': 'ID selector, not matching non-existent ancestor', + 'selector': '#none #id-div1', 'expect': [] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, { - 'name': "ID selector, matching multiple elements with duplicate id", - 'selector': "#id-li-duplicate", + 'name': 'ID selector, matching multiple elements with duplicate id', + 'selector': '#id-li-duplicate', 'expect': [ - "id-li-duplicate", - "id-li-duplicate", - "id-li-duplicate", - "id-li-duplicate" + 'id-li-duplicate', + 'id-li-duplicate', + 'id-li-duplicate', + 'id-li-duplicate' ], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline @@ -1439,39 +1439,39 @@ var validSelectors = [ // Caution: If copying and pasting the folowing non-ASCII IDs, ensure unicode normalisation is not performed in the process. { - 'name': "ID selector, matching id value using non-ASCII characters", - 'selector': "#台北Táiběi", - 'expect': ["台北Táiběi"], + 'name': 'ID selector, matching id value using non-ASCII characters', + 'selector': '#台北Táiběi', + 'expect': ['台北Táiběi'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID selector, matching id value using non-ASCII characters", - 'selector': "#台北", - 'expect': ["台北"], + 'name': 'ID selector, matching id value using non-ASCII characters', + 'selector': '#台北', + 'expect': ['台北'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "ID selector, matching id values using non-ASCII characters", - 'selector': "#台北Táiběi, #台北", - 'expect': ["台北Táiběi", "台北"], + 'name': 'ID selector, matching id values using non-ASCII characters', + 'selector': '#台北Táiběi, #台北', + 'expect': ['台北Táiběi', '台北'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, // XXX runMatchesTest() in level2-lib.js can't handle this because obtaining the expected nodes requires escaping characters when generating the selector from 'expect' values { - 'name': "ID selector, matching element with id with escaped character", - 'selector': "#\\#foo\\:bar", - 'expect': ["#foo:bar"], + 'name': 'ID selector, matching element with id with escaped character', + 'selector': '#\\#foo\\:bar', + 'expect': ['#foo:bar'], 'level': 1, 'testType': testQsaBaseline }, { - 'name': "ID selector, matching element with id with escaped character", - 'selector': "#test\\.foo\\[5\\]bar", - 'expect': ["test.foo[5]bar"], + 'name': 'ID selector, matching element with id with escaped character', + 'selector': '#test\\.foo\\[5\\]bar', + 'expect': ['test.foo[5]bar'], 'level': 1, 'testType': testQsaBaseline }, @@ -1479,28 +1479,28 @@ var validSelectors = [ // Namespaces // XXX runMatchesTest() in level2-lib.js can't handle these because non-HTML elements don't have a recognised id { - 'name': "Namespace selector, matching element with any namespace", - 'selector': "#any-namespace *|div", + 'name': 'Namespace selector, matching element with any namespace', + 'selector': '#any-namespace *|div', 'expect': [ - "any-namespace-div1", - "any-namespace-div2", - "any-namespace-div3", - "any-namespace-div4" + 'any-namespace-div1', + 'any-namespace-div2', + 'any-namespace-div3', + 'any-namespace-div4' ], 'level': 3, 'testType': testQsaBaseline }, { - 'name': "Namespace selector, matching div elements in no namespace only", - 'selector': "#no-namespace |div", - 'expect': ["no-namespace-div3"], + 'name': 'Namespace selector, matching div elements in no namespace only', + 'selector': '#no-namespace |div', + 'expect': ['no-namespace-div3'], 'level': 3, 'testType': testQsaBaseline }, { - 'name': "Namespace selector, matching any elements in no namespace only", - 'selector': "#no-namespace |*", - 'expect': ["no-namespace-div3"], + 'name': 'Namespace selector, matching any elements in no namespace only', + 'selector': '#no-namespace |*', + 'expect': ['no-namespace-div3'], 'level': 3, 'testType': testQsaBaseline }, @@ -1509,70 +1509,70 @@ var validSelectors = [ // - Descendant combinator ' ' { 'name': - "Descendant combinator, matching element that is a descendant of an element with id", - 'selector': "#descendant div", + 'Descendant combinator, matching element that is a descendant of an element with id', + 'selector': '#descendant div', 'expect': [ - "descendant-div1", - "descendant-div2", - "descendant-div3", - "descendant-div4" + 'descendant-div1', + 'descendant-div2', + 'descendant-div3', + 'descendant-div4' ], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, matching element with id that is a descendant of an element", - 'selector': "body #descendant-div1", - 'expect': ["descendant-div1"], - 'exclude': ["detached", "fragment"], + 'Descendant combinator, matching element with id that is a descendant of an element', + 'selector': 'body #descendant-div1', + 'expect': ['descendant-div1'], + 'exclude': ['detached', 'fragment'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, matching element with id that is a descendant of an element", - 'selector': "div #descendant-div1", - 'expect': ["descendant-div1"], + 'Descendant combinator, matching element with id that is a descendant of an element', + 'selector': 'div #descendant-div1', + 'expect': ['descendant-div1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, matching element with id that is a descendant of an element with id", - 'selector': "#descendant #descendant-div2", - 'expect': ["descendant-div2"], + 'Descendant combinator, matching element with id that is a descendant of an element with id', + 'selector': '#descendant #descendant-div2', + 'expect': ['descendant-div2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, matching element with class that is a descendant of an element with id", - 'selector': "#descendant .descendant-div2", - 'expect': ["descendant-div2"], + 'Descendant combinator, matching element with class that is a descendant of an element with id', + 'selector': '#descendant .descendant-div2', + 'expect': ['descendant-div2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, matching element with class that is a descendant of an element with class", - 'selector': ".descendant-div1 .descendant-div3", - 'expect': ["descendant-div3"], + 'Descendant combinator, matching element with class that is a descendant of an element with class', + 'selector': '.descendant-div1 .descendant-div3', + 'expect': ['descendant-div3'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Descendant combinator, not matching element with id that is not a descendant of an element with id", - 'selector': "#descendant-div1 #descendant-div4", + 'Descendant combinator, not matching element with id that is not a descendant of an element with id', + 'selector': '#descendant-div1 #descendant-div4', 'expect': [] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, { - 'name': "Descendant combinator, whitespace characters", - 'selector': "#descendant\t\r\n#descendant-div2", - 'expect': ["descendant-div2"], + 'name': 'Descendant combinator, whitespace characters', + 'selector': '#descendant\t\r\n#descendant-div2', + 'expect': ['descendant-div2'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, @@ -1580,93 +1580,93 @@ var validSelectors = [ // - Child combinator '>' { 'name': - "Child combinator, matching element that is a child of an element with id", - 'selector': "#child>div", - 'expect': ["child-div1", "child-div4"], + 'Child combinator, matching element that is a child of an element with id', + 'selector': '#child>div', + 'expect': ['child-div1', 'child-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Child combinator, matching element with id that is a child of an element", - 'selector': "div>#child-div1", - 'expect': ["child-div1"], + 'Child combinator, matching element with id that is a child of an element', + 'selector': 'div>#child-div1', + 'expect': ['child-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Child combinator, matching element with id that is a child of an element with id", - 'selector': "#child>#child-div1", - 'expect': ["child-div1"], + 'Child combinator, matching element with id that is a child of an element with id', + 'selector': '#child>#child-div1', + 'expect': ['child-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Child combinator, matching element with id that is a child of an element with class", - 'selector': "#child-div1>.child-div2", - 'expect': ["child-div2"], + 'Child combinator, matching element with id that is a child of an element with class', + 'selector': '#child-div1>.child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Child combinator, matching element with class that is a child of an element with class", - 'selector': ".child-div1>.child-div2", - 'expect': ["child-div2"], + 'Child combinator, matching element with class that is a child of an element with class', + 'selector': '.child-div1>.child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Child combinator, not matching element with id that is not a child of an element with id", - 'selector': "#child>#child-div3", + 'Child combinator, not matching element with id that is not a child of an element with id', + 'selector': '#child>#child-div3', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Child combinator, not matching element with id that is not a child of an element with class", - 'selector': "#child-div1>.child-div3", + 'Child combinator, not matching element with id that is not a child of an element with class', + 'selector': '#child-div1>.child-div3', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { 'name': - "Child combinator, not matching element with class that is not a child of an element with class", - 'selector': ".child-div1>.child-div3", + 'Child combinator, not matching element with class that is not a child of an element with class', + 'selector': '.child-div1>.child-div3', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { - 'name': "Child combinator, surrounded by whitespace", - 'selector': "#child-div1\t\r\n>\t\r\n#child-div2", - 'expect': ["child-div2"], + 'name': 'Child combinator, surrounded by whitespace', + 'selector': '#child-div1\t\r\n>\t\r\n#child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Child combinator, whitespace after", - 'selector': "#child-div1>\t\r\n#child-div2", - 'expect': ["child-div2"], + 'name': 'Child combinator, whitespace after', + 'selector': '#child-div1>\t\r\n#child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Child combinator, whitespace before", - 'selector': "#child-div1\t\r\n>#child-div2", - 'expect': ["child-div2"], + 'name': 'Child combinator, whitespace before', + 'selector': '#child-div1\t\r\n>#child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Child combinator, no whitespace", - 'selector': "#child-div1>#child-div2", - 'expect': ["child-div2"], + 'name': 'Child combinator, no whitespace', + 'selector': '#child-div1>#child-div2', + 'expect': ['child-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, @@ -1674,85 +1674,85 @@ var validSelectors = [ // - Adjacent sibling combinator '+' { 'name': - "Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id", - 'selector': "#adjacent-div2+div", - 'expect': ["adjacent-div4"], + 'Adjacent sibling combinator, matching element that is an adjacent sibling of an element with id', + 'selector': '#adjacent-div2+div', + 'expect': ['adjacent-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element", - 'selector': "div+#adjacent-div4", - 'expect': ["adjacent-div4"], + 'Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element', + 'selector': 'div+#adjacent-div4', + 'expect': ['adjacent-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id", - 'selector': "#adjacent-div2+#adjacent-div4", - 'expect': ["adjacent-div4"], + 'Adjacent sibling combinator, matching element with id that is an adjacent sibling of an element with id', + 'selector': '#adjacent-div2+#adjacent-div4', + 'expect': ['adjacent-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id", - 'selector': "#adjacent-div2+.adjacent-div4", - 'expect': ["adjacent-div4"], + 'Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with id', + 'selector': '#adjacent-div2+.adjacent-div4', + 'expect': ['adjacent-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class", - 'selector': ".adjacent-div2+.adjacent-div4", - 'expect': ["adjacent-div4"], + 'Adjacent sibling combinator, matching element with class that is an adjacent sibling of an element with class', + 'selector': '.adjacent-div2+.adjacent-div4', + 'expect': ['adjacent-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element", - 'selector': "#adjacent div+p", - 'expect': ["adjacent-p2"], + 'Adjacent sibling combinator, matching p element that is an adjacent sibling of a div element', + 'selector': '#adjacent div+p', + 'expect': ['adjacent-p2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { 'name': - "Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id", - 'selector': "#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1", + 'Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id', + 'selector': '#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, { - 'name': "Adjacent sibling combinator, surrounded by whitespace", - 'selector': "#adjacent-p2\t\r\n+\t\r\n#adjacent-p3", - 'expect': ["adjacent-p3"], + 'name': 'Adjacent sibling combinator, surrounded by whitespace', + 'selector': '#adjacent-p2\t\r\n+\t\r\n#adjacent-p3', + 'expect': ['adjacent-p3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Adjacent sibling combinator, whitespace after", - 'selector': "#adjacent-p2+\t\r\n#adjacent-p3", - 'expect': ["adjacent-p3"], + 'name': 'Adjacent sibling combinator, whitespace after', + 'selector': '#adjacent-p2+\t\r\n#adjacent-p3', + 'expect': ['adjacent-p3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Adjacent sibling combinator, whitespace before", - 'selector': "#adjacent-p2\t\r\n+#adjacent-p3", - 'expect': ["adjacent-p3"], + 'name': 'Adjacent sibling combinator, whitespace before', + 'selector': '#adjacent-p2\t\r\n+#adjacent-p3', + 'expect': ['adjacent-p3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Adjacent sibling combinator, no whitespace", - 'selector': "#adjacent-p2+#adjacent-p3", - 'expect': ["adjacent-p3"], + 'name': 'Adjacent sibling combinator, no whitespace', + 'selector': '#adjacent-p2+#adjacent-p3', + 'expect': ['adjacent-p3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline }, @@ -1760,115 +1760,115 @@ var validSelectors = [ // - General sibling combinator ~ (Level 3) { 'name': - "General sibling combinator, matching element that is a sibling of an element with id", - 'selector': "#sibling-div2~div", - 'expect': ["sibling-div4", "sibling-div6"], + 'General sibling combinator, matching element that is a sibling of an element with id', + 'selector': '#sibling-div2~div', + 'expect': ['sibling-div4', 'sibling-div6'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "General sibling combinator, matching element with id that is a sibling of an element", - 'selector': "div~#sibling-div4", - 'expect': ["sibling-div4"], + 'General sibling combinator, matching element with id that is a sibling of an element', + 'selector': 'div~#sibling-div4', + 'expect': ['sibling-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "General sibling combinator, matching element with id that is a sibling of an element with id", - 'selector': "#sibling-div2~#sibling-div4", - 'expect': ["sibling-div4"], + 'General sibling combinator, matching element with id that is a sibling of an element with id', + 'selector': '#sibling-div2~#sibling-div4', + 'expect': ['sibling-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "General sibling combinator, matching element with class that is a sibling of an element with id", - 'selector': "#sibling-div2~.sibling-div", - 'expect': ["sibling-div4", "sibling-div6"], + 'General sibling combinator, matching element with class that is a sibling of an element with id', + 'selector': '#sibling-div2~.sibling-div', + 'expect': ['sibling-div4', 'sibling-div6'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "General sibling combinator, matching p element that is a sibling of a div element", - 'selector': "#sibling div~p", - 'expect': ["sibling-p2", "sibling-p3"], + 'General sibling combinator, matching p element that is a sibling of a div element', + 'selector': '#sibling div~p', + 'expect': ['sibling-p2', 'sibling-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { 'name': - "General sibling combinator, not matching element with id that is not a sibling after a p element", - 'selector': "#sibling>p~div", + 'General sibling combinator, not matching element with id that is not a sibling after a p element', + 'selector': '#sibling>p~div', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, { 'name': - "General sibling combinator, not matching element with id that is not a sibling after an element with id", - 'selector': "#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1", + 'General sibling combinator, not matching element with id that is not a sibling after an element with id', + 'selector': '#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1', 'expect': [] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, { - 'name': "General sibling combinator, surrounded by whitespace", - 'selector': "#sibling-p2\t\r\n~\t\r\n#sibling-p3", - 'expect': ["sibling-p3"], + 'name': 'General sibling combinator, surrounded by whitespace', + 'selector': '#sibling-p2\t\r\n~\t\r\n#sibling-p3', + 'expect': ['sibling-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': "General sibling combinator, whitespace after", - 'selector': "#sibling-p2~\t\r\n#sibling-p3", - 'expect': ["sibling-p3"], + 'name': 'General sibling combinator, whitespace after', + 'selector': '#sibling-p2~\t\r\n#sibling-p3', + 'expect': ['sibling-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': "General sibling combinator, whitespace before", - 'selector': "#sibling-p2\t\r\n~#sibling-p3", - 'expect': ["sibling-p3"], + 'name': 'General sibling combinator, whitespace before', + 'selector': '#sibling-p2\t\r\n~#sibling-p3', + 'expect': ['sibling-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, { - 'name': "General sibling combinator, no whitespace", - 'selector': "#sibling-p2~#sibling-p3", - 'expect': ["sibling-p3"], + 'name': 'General sibling combinator, no whitespace', + 'selector': '#sibling-p2~#sibling-p3', + 'expect': ['sibling-p3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline }, // Group of selectors (comma) { - 'name': "Syntax, group of selectors separator, surrounded by whitespace", - 'selector': "#group em\t\r \n,\t\r \n#group strong", - 'expect': ["group-em1", "group-strong1"], + 'name': 'Syntax, group of selectors separator, surrounded by whitespace', + 'selector': '#group em\t\r \n,\t\r \n#group strong', + 'expect': ['group-em1', 'group-strong1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Syntax, group of selectors separator, whitespace after", - 'selector': "#group em,\t\r\n#group strong", - 'expect': ["group-em1", "group-strong1"], + 'name': 'Syntax, group of selectors separator, whitespace after', + 'selector': '#group em,\t\r\n#group strong', + 'expect': ['group-em1', 'group-strong1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Syntax, group of selectors separator, whitespace before", - 'selector': "#group em\t\r\n,#group strong", - 'expect': ["group-em1", "group-strong1"], + 'name': 'Syntax, group of selectors separator, whitespace before', + 'selector': '#group em\t\r\n,#group strong', + 'expect': ['group-em1', 'group-strong1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, { - 'name': "Syntax, group of selectors separator, no whitespace", - 'selector': "#group em,#group strong", - 'expect': ["group-em1", "group-strong1"], + 'name': 'Syntax, group of selectors separator, no whitespace', + 'selector': '#group em,#group strong', + 'expect': ['group-em1', 'group-strong1'], 'level': 1, 'testType': testQsaBaseline | testMatchBaseline }, diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 83e137a91..afcf95263 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -13,10 +13,8 @@ typedef TreeBuilderFactory = TreeBuilder Function(bool namespaceHTMLElements); Map<String, TreeBuilderFactory> _treeTypes; Map<String, TreeBuilderFactory> get treeTypes { - if (_treeTypes == null) { - // TODO(jmesserly): add DOM here once it's implemented - _treeTypes = {"simpletree": (useNs) => TreeBuilder(useNs)}; - } + // TODO(jmesserly): add DOM here once it's implemented + _treeTypes ??= {'simpletree': (useNs) => TreeBuilder(useNs)}; return _treeTypes; } @@ -35,12 +33,13 @@ class TestData extends IterableBase<Map> { final String _text; final String newTestHeading; - TestData(String filename, [this.newTestHeading = "data"]) + TestData(String filename, [this.newTestHeading = 'data']) // Note: can't use readAsLinesSync here because it splits on \r : _text = File(filename).readAsStringSync(); // Note: in Python this was a generator, but since we can't do that in Dart, // it's easier to convert it into an upfront computation. + @override Iterator<Map> get iterator => _getData().iterator; List<Map> _getData() { @@ -62,7 +61,7 @@ class TestData extends IterableBase<Map> { data = <String, String>{}; } key = heading; - data[key] = ""; + data[key] = ''; } else if (key != null) { data[key] = '${data[key]}$line\n'; } @@ -77,13 +76,13 @@ class TestData extends IterableBase<Map> { /// If the current heading is a test section heading return the heading, /// otherwise return null. static String sectionHeading(String line) { - return line.startsWith("#") ? line.substring(1).trim() : null; + return line.startsWith('#') ? line.substring(1).trim() : null; } static Map normaliseOutput(Map data) { // Remove trailing newlines data.forEach((key, value) { - if (value.endsWith("\n")) { + if (value.endsWith('\n')) { data[key] = value.substring(0, value.length - 1); } }); @@ -92,7 +91,7 @@ class TestData extends IterableBase<Map> { } /// Serialize the [document] into the html5 test data format. -testSerializer(document) { +String testSerializer(document) { return (TestSerializer()..visit(document)).toString(); } @@ -104,6 +103,7 @@ class TestSerializer extends TreeVisitor { TestSerializer() : _str = StringBuffer(); + @override String toString() => _str.toString(); int get indent => _indent; @@ -112,7 +112,7 @@ class TestSerializer extends TreeVisitor { if (_indent == value) return; var arr = List<int>(value); - for (int i = 0; i < value; i++) { + for (var i = 0; i < value; i++) { arr[i] = 32; } _spaces = String.fromCharCodes(arr); @@ -124,13 +124,15 @@ class TestSerializer extends TreeVisitor { _str.write('|$_spaces'); } - visitNodeFallback(Node node) { + @override + void visitNodeFallback(Node node) { _newline(); _str.write(node); visitChildren(node); } - visitChildren(Node node) { + @override + void visitChildren(Node node) { indent += 2; for (var child in node.nodes) { visit(child); @@ -138,9 +140,10 @@ class TestSerializer extends TreeVisitor { indent -= 2; } - visitDocument(node) => _visitDocumentOrFragment(node); + @override + void visitDocument(node) => _visitDocumentOrFragment(node); - _visitDocumentOrFragment(node) { + void _visitDocumentOrFragment(node) { indent += 1; for (var child in node.nodes) { visit(child); @@ -148,10 +151,12 @@ class TestSerializer extends TreeVisitor { indent -= 1; } - visitDocumentFragment(DocumentFragment node) => + @override + void visitDocumentFragment(DocumentFragment node) => _visitDocumentOrFragment(node); - visitElement(Element node) { + @override + void visitElement(Element node) { _newline(); _str.write(node); if (node.attributes.isNotEmpty) { @@ -162,7 +167,7 @@ class TestSerializer extends TreeVisitor { var v = node.attributes[key]; if (key is AttributeName) { AttributeName attr = key; - key = "${attr.prefix} ${attr.name}"; + key = '${attr.prefix} ${attr.name}'; } _newline(); _str.write('$key="$v"'); diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 3d2aeb32a..62d5f8ad3 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -73,20 +73,20 @@ class TokenizerTestParser { void processDoctype(DoctypeToken token) { addOutputToken(token, - ["DOCTYPE", token.name, token.publicId, token.systemId, token.correct]); + ['DOCTYPE', token.name, token.publicId, token.systemId, token.correct]); } void processStartTag(StartTagToken token) { addOutputToken( - token, ["StartTag", token.name, token.data, token.selfClosing]); + token, ['StartTag', token.name, token.data, token.selfClosing]); } void processEndTag(EndTagToken token) { - addOutputToken(token, ["EndTag", token.name, token.selfClosing]); + addOutputToken(token, ['EndTag', token.name, token.selfClosing]); } void processComment(StringToken token) { - addOutputToken(token, ["Comment", token.data]); + addOutputToken(token, ['Comment', token.data]); } void processSpaceCharacters(StringToken token) { @@ -94,7 +94,7 @@ class TokenizerTestParser { } void processCharacters(StringToken token) { - addOutputToken(token, ["Character", token.data]); + addOutputToken(token, ['Character', token.data]); } void processEOF(token) {} @@ -103,7 +103,7 @@ class TokenizerTestParser { // TODO(jmesserly): when debugging test failures it can be useful to add // logging here like `print('ParseError $token');`. It would be nice to // use the actual logging library. - addOutputToken(token, ["ParseError", token.data]); + addOutputToken(token, ['ParseError', token.data]); } void addOutputToken(Token token, List array) { @@ -118,10 +118,10 @@ class TokenizerTestParser { List concatenateCharacterTokens(List tokens) { var outputTokens = []; for (var token in tokens) { - if (token.indexOf("ParseError") == -1 && token[0] == "Character") { + if (token.indexOf('ParseError') == -1 && token[0] == 'Character') { if (outputTokens.isNotEmpty && - outputTokens.last.indexOf("ParseError") == -1 && - outputTokens.last[0] == "Character") { + outputTokens.last.indexOf('ParseError') == -1 && + outputTokens.last[0] == 'Character') { outputTokens.last[1] = '${outputTokens.last[1]}${token[1]}'; } else { outputTokens.add(token); @@ -135,7 +135,7 @@ List concatenateCharacterTokens(List tokens) { List normalizeTokens(List tokens) { // TODO: convert tests to reflect arrays - for (int i = 0; i < tokens.length; i++) { + for (var i = 0; i < tokens.length; i++) { var token = tokens[i]; if (token[0] == 'ParseError') { tokens[i] = token[0]; @@ -155,8 +155,8 @@ void expectTokensMatch( // remove it from the received token. var removeSelfClosing = false; for (var token in expectedTokens) { - if (token[0] == "StartTag" && token.length == 3 || - token[0] == "EndTag" && token.length == 2) { + if (token[0] == 'StartTag' && token.length == 3 || + token[0] == 'EndTag' && token.length == 2) { removeSelfClosing = true; break; } @@ -164,7 +164,7 @@ void expectTokensMatch( if (removeSelfClosing) { for (var token in receivedTokens) { - if (token[0] == "StartTag" || token[0] == "EndTag") { + if (token[0] == 'StartTag' || token[0] == 'EndTag') { token.removeLast(); } } @@ -174,13 +174,13 @@ void expectTokensMatch( expect(receivedTokens, equals(expectedTokens), reason: message); } else { // Sort the tokens into two groups; non-parse errors and parse errors - var expectedNonErrors = expectedTokens.where((t) => t != "ParseError"); - var receivedNonErrors = receivedTokens.where((t) => t != "ParseError"); + var expectedNonErrors = expectedTokens.where((t) => t != 'ParseError'); + var receivedNonErrors = receivedTokens.where((t) => t != 'ParseError'); expect(receivedNonErrors, equals(expectedNonErrors), reason: message); if (!ignoreErrors) { - var expectedParseErrors = expectedTokens.where((t) => t == "ParseError"); - var receivedParseErrors = receivedTokens.where((t) => t == "ParseError"); + var expectedParseErrors = expectedTokens.where((t) => t == 'ParseError'); + var receivedParseErrors = receivedTokens.where((t) => t == 'ParseError'); expect(receivedParseErrors, equals(expectedParseErrors), reason: message); } } @@ -203,17 +203,16 @@ void runTokenizerTest(Map testInfo) { tokens = concatenateCharacterTokens(tokens); var received = normalizeTokens(tokens); var errorMsg = [ - "\n\nInitial state:", + '\n\nInitial state:', testInfo['initialState'], - "\nInput:", + '\nInput:', testInfo['input'], - "\nExpected:", + '\nExpected:', expected, - "\nreceived:", + '\nreceived:', tokens ].map((s) => '$s').join('\n'); - var ignoreErrorOrder = testInfo['ignoreErrorOrder']; - if (ignoreErrorOrder == null) ignoreErrorOrder = false; + var ignoreErrorOrder = testInfo['ignoreErrorOrder'] ?? false; expectTokensMatch(expected, received, ignoreErrorOrder, true, errorMsg); } @@ -222,11 +221,11 @@ Map unescape(Map testInfo) { // TODO(sigmundch,jmesserly): we currently use jsonDecode to unescape the // unicode characters in the string, we should use a decoding that works with // any control characters. - decode(inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); + dynamic decode(inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); - testInfo["input"] = decode(testInfo["input"]); - for (var token in testInfo["output"]) { - if (token == "ParseError") { + testInfo['input'] = decode(testInfo['input']); + for (var token in testInfo['output']) { + if (token == 'ParseError') { continue; } else { token[1] = decode(token[1]); @@ -246,7 +245,7 @@ Map unescape(Map testInfo) { String camelCase(String s) { s = s.toLowerCase(); var result = StringBuffer(); - for (var match in RegExp(r"\W+(\w)(\w+)").allMatches(s)) { + for (var match in RegExp(r'\W+(\w)(\w+)').allMatches(s)) { if (result.length == 0) result.write(s.substring(0, match.start)); result.write(match.group(1).toUpperCase()); result.write(match.group(2)); @@ -265,13 +264,13 @@ void main() { if (testList == null) continue; group(testName, () { - for (int index = 0; index < testList.length; index++) { + for (var index = 0; index < testList.length; index++) { final testInfo = testList[index]; - testInfo.putIfAbsent("initialStates", () => ["Data state"]); - for (var initialState in testInfo["initialStates"]) { - test(testInfo["description"], () { - testInfo["initialState"] = camelCase(initialState); + testInfo.putIfAbsent('initialStates', () => ['Data state']); + for (var initialState in testInfo['initialStates']) { + test(testInfo['description'], () { + testInfo['initialState'] = camelCase(initialState); runTokenizerTest(testInfo); }); } From e10757edff9548ad1e7eff4e364aa056d717ac07 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Thu, 11 Jun 2020 16:53:59 -0700 Subject: [PATCH 113/212] Refactor some utilities (dart-lang/html#115) - Drop the `Predicate` typedef, it is unused. - Remove `parseIntRadix`, replace with `int.parse`. - Remove unnecessary `library` directives and a comment that added no information. - Drop unused constants. - Simplify `startsWithAny`. - Remove an ignore that was working around an analyzer bug which is fixed on the latest SDK. Skip lints/hints on older SDKs in travis. --- pkgs/html/.travis.yml | 7 +++++- pkgs/html/lib/src/constants.dart | 40 -------------------------------- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/utils.dart | 35 ++-------------------------- 4 files changed, 9 insertions(+), 75 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 00333322d..3f5bcfbf6 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -7,12 +7,17 @@ dart: dart_task: - test: -p vm - test: -p chrome - - dartanalyzer: --fatal-warnings --fatal-infos . matrix: include: - dart: dev dart_task: dartfmt + - dart: dev + dart_task: + dartanalyzer: --fatal-warnings --fatal-infos . + - dart: 2.3.0 + dart_task: + dartanalyzer: --fatal-warnings . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index e8d0f62a9..313b95273 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -1,5 +1,3 @@ -library constants; - import 'utils.dart'; // TODO(jmesserly): fix up the const lists. For the bigger ones, we need faster @@ -514,44 +512,6 @@ const rcdataElements = [ 'noscript' ]; -const Map<String, List<String>> booleanAttributes = { - '': [ - 'irrelevant', - ], - 'style': [ - 'scoped', - ], - 'img': [ - 'ismap', - ], - 'audio': ['autoplay', 'controls'], - 'video': ['autoplay', 'controls'], - 'script': ['defer', 'async'], - 'details': [ - 'open', - ], - 'datagrid': ['multiple', 'disabled'], - 'command': ['hidden', 'disabled', 'checked', 'default'], - 'hr': ['noshade'], - 'men': [ - 'autosubmit', - ], - 'fieldset': ['disabled', 'readonly'], - 'option': ['disabled', 'readonly', 'selected'], - 'optgroup': ['disabled', 'readonly'], - 'button': ['disabled', 'autofocus'], - 'input': [ - 'disabled', - 'readonly', - 'required', - 'autofocus', - 'checked', - 'ismap' - ], - 'select': ['disabled', 'readonly', 'autofocus', 'multiple'], - 'output': ['disabled', 'readonly'], -}; - // entitiesWindows1252 has to be _ordered_ and needs to have an index. It // therefore can't be a frozenset. const List<int> entitiesWindows1252 = [ diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index cf677443b..b26e8d965 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -187,7 +187,7 @@ class HtmlTokenizer implements Iterator<Token> { } // Convert the set of characters consumed to an int. - var charAsInt = parseIntRadix(charStack.join(), radix); + var charAsInt = int.parse(charStack.join(), radix: radix); // Certain characters get replaced with others var char = replacementCharacters[charAsInt]; diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index fec6870e5..57124c851 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -1,10 +1,5 @@ -/// Misc things that were useful when porting the code from Python. -library utils; - import 'constants.dart'; -typedef Predicate = bool Function(); - class Pair<F, S> { final F first; final S second; @@ -18,32 +13,8 @@ class Pair<F, S> { bool operator ==(other) => other.first == first && other.second == second; } -int parseIntRadix(String str, [int radix = 10]) { - var val = 0; - for (var i = 0; i < str.length; i++) { - var digit = str.codeUnitAt(i); - if (digit >= LOWER_A) { - digit += 10 - LOWER_A; - } else if (digit >= UPPER_A) { - digit += 10 - UPPER_A; - } else { - digit -= ZERO; - } - val = val * radix + digit; - } - return val; -} - -bool any(List<bool> iterable) => iterable.any((f) => f); - -bool startsWithAny(String str, List<String> prefixes) { - for (var prefix in prefixes) { - if (str.startsWith(prefix)) { - return true; - } - } - return false; -} +bool startsWithAny(String str, List<String> prefixes) => + prefixes.any(str.startsWith); // Like the python [:] operator. List<T> slice<T>(List<T> list, int start, [int end]) { @@ -85,8 +56,6 @@ String formatStr(String format, Map data) { var result = StringBuffer(); var search = '%($key)'; int last = 0, match; - // This is a bug in the linter - // ignore: prefer_contains while ((match = format.indexOf(search, last)) >= 0) { result.write(format.substring(last, match)); match += search.length; From b9f59b39f10863f5e43dc0c894ce2474a39ee375 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Fri, 25 Sep 2020 09:43:37 -0700 Subject: [PATCH 114/212] Fix infinite loop with bad button close tag (dart-lang/html#128) Closes dart-lang/html#122 Add 'button' to the tags that are processed with `endTagBlock`. The spec at https://html.spec.whatwg.org/multipage/parsing.html includes 'button' in the list of end tags with this treatment. Add a new `.dat` file for regression test. It include an `#info` field which is new but can be parsed safely to mark the issue for which it is a test. This test loops endlessly before the fix and passes after the fix. Note that since errors are currently untested and tests fail if they are tested the error will be left without content for now. --- pkgs/html/CHANGELOG.md | 5 +++++ pkgs/html/lib/parser.dart | 1 + pkgs/html/pubspec.yaml | 2 +- .../data/tree-construction/regression_tests.dat | 13 +++++++++++++ 4 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 pkgs/html/test/data/tree-construction/regression_tests.dat diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 21fc0411b..53d79703c 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.14.0+4 + +- Fix a bug parsing bad HTML where a 'button' end tag needs to close other + elements. + ## 0.14.0+3 - Fix spans generated for HTML with higher-plane unicode characters diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index c4eafb67f..46702ae61 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1412,6 +1412,7 @@ class InBodyPhase extends Phase { case 'article': case 'aside': case 'blockquote': + case 'button': case 'center': case 'details': case 'dir': diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 71f41db94..e7aa320cd 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.14.0+3 +version: 0.14.0+4 description: APIs for parsing and manipulating HTML content outside the browser. author: Dart Team <misc@dartlang.org> diff --git a/pkgs/html/test/data/tree-construction/regression_tests.dat b/pkgs/html/test/data/tree-construction/regression_tests.dat new file mode 100644 index 000000000..aedb8045b --- /dev/null +++ b/pkgs/html/test/data/tree-construction/regression_tests.dat @@ -0,0 +1,13 @@ +#data +<button><p></button><button></button> +#info +Regression test for https://github.com/dart-lang/html/issues/122 +#errors +Errors are currently untested: https://github.com/dart-lang/html/issues/127 +#document +| <html> +| <head> +| <body> +| <button> +| <p> +| <button> From 3d4d88c0f960716be57915d710d9b784fe267f12 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Mon, 5 Oct 2020 16:30:13 -0700 Subject: [PATCH 115/212] Disable implicit casts (dart-lang/html#130) This will make it easier to migrate to null safety which also disables implicit casts except from dynamic. Also fix the implicit casts from dynamic since this package has a lot of dynamic code that is harder to read with implicit casts. - Add argument types to some signatures that should have had them from the start. - Add explicit casts. - Extract a few new local variables to make some of the casts only need to happen once. - Use `Iterable.whereType` in a loop instead of a type check and `continue` in the loop body. --- pkgs/html/CHANGELOG.md | 2 + pkgs/html/analysis_options.yaml | 2 + pkgs/html/lib/dom.dart | 30 +++++----- pkgs/html/lib/dom_parsing.dart | 12 ++-- pkgs/html/lib/parser.dart | 74 ++++++++++++------------ pkgs/html/lib/src/query_selector.dart | 30 +++++----- pkgs/html/lib/src/token.dart | 4 +- pkgs/html/lib/src/tokenizer.dart | 10 ++-- pkgs/html/lib/src/treebuilder.dart | 14 ++--- pkgs/html/lib/src/utils.dart | 2 +- pkgs/html/pubspec.yaml | 3 +- pkgs/html/test/parser_feature_test.dart | 20 +++---- pkgs/html/test/parser_test.dart | 6 +- pkgs/html/test/selectors/level1_lib.dart | 32 +++++----- pkgs/html/test/support.dart | 24 ++++---- pkgs/html/test/tokenizer_test.dart | 41 +++++++------ 16 files changed, 156 insertions(+), 150 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 53d79703c..615a09fe7 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.15.0-dev + ## 0.14.0+4 - Fix a bug parsing bad HTML where a 'button' end tag needs to close other diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index b8dcf936a..20eba0c64 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,5 +1,7 @@ include: package:pedantic/analysis_options.yaml analyzer: + strong-mode: + implicit-casts: false errors: # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 835d8da92..85e02c4db 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -24,7 +24,7 @@ export 'src/css_class_set.dart' show CssClassSet; // TODO(jmesserly): this needs to be replaced by an AttributeMap for attributes // that exposes namespace info. -class AttributeName implements Comparable { +class AttributeName implements Comparable<Object> { /// The namespace prefix, e.g. `xlink`. final String prefix; @@ -55,14 +55,15 @@ class AttributeName implements Comparable { } @override - int compareTo(other) { + int compareTo(dynamic other) { // Not sure about this sort order if (other is! AttributeName) return 1; - var cmp = (prefix ?? '').compareTo((other.prefix ?? '')); + final otherAttributeName = other as AttributeName; + var cmp = (prefix ?? '').compareTo((otherAttributeName.prefix ?? '')); if (cmp != 0) return cmp; - cmp = name.compareTo(other.name); + cmp = name.compareTo(otherAttributeName.name); if (cmp != 0) return cmp; - return namespace.compareTo(other.namespace); + return namespace.compareTo(otherAttributeName.namespace); } @override @@ -141,7 +142,10 @@ abstract class Node { /// /// Returns null if this node either does not have a parent or its parent is /// not an element. - Element get parent => parentNode is Element ? parentNode : null; + Element get parent { + final parentNode = this.parentNode; + return parentNode is Element ? parentNode : null; + } // TODO(jmesserly): should move to Element. /// A map holding name, value pairs for attributes of the node. @@ -299,7 +303,7 @@ abstract class Node { } } - Node _clone(Node shallowClone, bool deep) { + T _clone<T extends Node>(T shallowClone, bool deep) { if (deep) { for (var child in nodes) { shallowClone.append(child.clone(true)); @@ -442,7 +446,7 @@ class Text extends Node { void appendData(String data) { if (_data is! StringBuffer) _data = StringBuffer(_data); - StringBuffer sb = _data; + final sb = _data as StringBuffer; sb.write(data); } @@ -1054,18 +1058,16 @@ class FilteredElementList extends IterableBase<Element> @override Iterable<Element> getRange(int start, int end) => _filtered.getRange(start, end); - // TODO(sigmund): this should be typed Element, but we currently run into a - // bug where ListMixin<E>.indexOf() expects Object as the argument. @override int indexOf(Object element, [int start = 0]) => - _filtered.indexOf(element, start); + // Cast forced by ListMixin https://github.com/dart-lang/sdk/issues/31311 + _filtered.indexOf(element as Element, start); - // TODO(sigmund): this should be typed Element, but we currently run into a - // bug where ListMixin<E>.lastIndexOf() expects Object as the argument. @override int lastIndexOf(Object element, [int start]) { start ??= length - 1; - return _filtered.lastIndexOf(element, start); + // Cast forced by ListMixin https://github.com/dart-lang/sdk/issues/31311 + return _filtered.lastIndexOf(element as Element, start); } @override diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index f16018c36..3c8774be7 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -10,17 +10,17 @@ class TreeVisitor { void visit(Node node) { switch (node.nodeType) { case Node.ELEMENT_NODE: - return visitElement(node); + return visitElement(node as Element); case Node.TEXT_NODE: - return visitText(node); + return visitText(node as Text); case Node.COMMENT_NODE: - return visitComment(node); + return visitComment(node as Comment); case Node.DOCUMENT_FRAGMENT_NODE: - return visitDocumentFragment(node); + return visitDocumentFragment(node as DocumentFragment); case Node.DOCUMENT_NODE: - return visitDocument(node); + return visitDocument(node as Document); case Node.DOCUMENT_TYPE_NODE: - return visitDocumentType(node); + return visitDocumentType(node as DocumentType); default: throw UnsupportedError('DOM node type ${node.nodeType}'); } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 46702ae61..2a6c43177 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -318,7 +318,7 @@ class HtmlParser { // Note: avoid "is" test here, see http://dartbug.com/4795 if (type == TokenKind.parseError) { - ParseErrorToken error = newToken; + final error = newToken as ParseErrorToken; parseError(error.span, error.data, error.messageParams); newToken = null; } else { @@ -329,22 +329,24 @@ class HtmlParser { switch (type) { case TokenKind.characters: - newToken = localPhase.processCharacters(newToken); + newToken = + localPhase.processCharacters(newToken as CharactersToken); break; case TokenKind.spaceCharacters: - newToken = localPhase.processSpaceCharacters(newToken); + newToken = localPhase + .processSpaceCharacters(newToken as SpaceCharactersToken); break; case TokenKind.startTag: - newToken = localPhase.processStartTag(newToken); + newToken = localPhase.processStartTag(newToken as StartTagToken); break; case TokenKind.endTag: - newToken = localPhase.processEndTag(newToken); + newToken = localPhase.processEndTag(newToken as EndTagToken); break; case TokenKind.comment: - newToken = localPhase.processComment(newToken); + newToken = localPhase.processComment(newToken as CommentToken); break; case TokenKind.doctype: - newToken = localPhase.processDoctype(newToken); + newToken = localPhase.processDoctype(newToken as DoctypeToken); break; } } @@ -571,7 +573,7 @@ class HtmlParser { void parseRCDataRawtext(Token token, String contentType) { assert(contentType == 'RAWTEXT' || contentType == 'RCDATA'); - tree.insertElement(token); + tree.insertElement(token as StartTagToken); if (contentType == 'RAWTEXT') { tokenizer.state = tokenizer.rawtextState; @@ -665,7 +667,7 @@ class Phase { } class InitialPhase extends Phase { - InitialPhase(parser) : super(parser); + InitialPhase(HtmlParser parser) : super(parser); @override Token processSpaceCharacters(SpaceCharactersToken token) { @@ -824,7 +826,7 @@ class InitialPhase extends Phase { } class BeforeHtmlPhase extends Phase { - BeforeHtmlPhase(parser) : super(parser); + BeforeHtmlPhase(HtmlParser parser) : super(parser); // helper methods void insertHtmlElement() { @@ -885,7 +887,7 @@ class BeforeHtmlPhase extends Phase { } class BeforeHeadPhase extends Phase { - BeforeHeadPhase(parser) : super(parser); + BeforeHeadPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -959,7 +961,7 @@ class BeforeHeadPhase extends Phase { } class InHeadPhase extends Phase { - InHeadPhase(parser) : super(parser); + InHeadPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -1106,7 +1108,7 @@ class InHeadPhase extends Phase { // class InHeadNoScriptPhase extends Phase { class AfterHeadPhase extends Phase { - AfterHeadPhase(parser) : super(parser); + AfterHeadPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -1182,7 +1184,7 @@ class AfterHeadPhase extends Phase { void startTagFromHead(StartTagToken token) { parser.parseError(token.span, 'unexpected-start-tag-out-of-my-head', {'name': token.name}); - tree.openElements.add(tree.headPointer); + tree.openElements.add(tree.headPointer as Element); parser._inHeadPhase.processStartTag(token); for (var node in tree.openElements.reversed) { if (node.localName == 'head') { @@ -1225,7 +1227,7 @@ class InBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///parsing-main-inbody // the really-really-really-very crazy mode - InBodyPhase(parser) : super(parser); + InBodyPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -1501,7 +1503,7 @@ class InBodyPhase extends Phase { } // helper - void addFormattingElement(token) { + void addFormattingElement(StartTagToken token) { tree.insertElement(token); var element = tree.openElements.last; @@ -1509,7 +1511,7 @@ class InBodyPhase extends Phase { for (Node node in tree.activeFormattingElements.reversed) { if (node == Marker) { break; - } else if (isMatchingFormattingElement(node, element)) { + } else if (isMatchingFormattingElement(node as Element, element)) { matchingElements.add(node); } } @@ -1816,7 +1818,7 @@ class InBodyPhase extends Phase { if (tree.formPointer != null) { return; } - var formAttrs = <dynamic, String>{}; + var formAttrs = LinkedHashMap<dynamic, String>(); var dataAction = token.data['action']; if (dataAction != null) { formAttrs['action'] = dataAction; @@ -2113,7 +2115,7 @@ class InBodyPhase extends Phase { // Step 2 // Start of the adoption agency algorithm proper var afeIndex = tree.openElements.indexOf(formattingElement); - Node furthestBlock; + Element furthestBlock; for (var element in slice(tree.openElements, afeIndex)) { if (specialElements.contains(getElementNameTuple(element))) { furthestBlock = element; @@ -2270,7 +2272,7 @@ class InBodyPhase extends Phase { } class TextPhase extends Phase { - TextPhase(parser) : super(parser); + TextPhase(HtmlParser parser) : super(parser); // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name @override @@ -2321,7 +2323,7 @@ class TextPhase extends Phase { class InTablePhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table - InTablePhase(parser) : super(parser); + InTablePhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -2622,7 +2624,7 @@ class InTableTextPhase extends Phase { class InCaptionPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-caption - InCaptionPhase(parser) : super(parser); + InCaptionPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -2744,7 +2746,7 @@ class InCaptionPhase extends Phase { class InColumnGroupPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-column - InColumnGroupPhase(parser) : super(parser); + InColumnGroupPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -2832,7 +2834,7 @@ class InColumnGroupPhase extends Phase { class InTableBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table0 - InTableBodyPhase(parser) : super(parser); + InTableBodyPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -2925,7 +2927,7 @@ class InTableBodyPhase extends Phase { return token; } - Token startTagTableOther(token) => endTagTable(token); + Token startTagTableOther(TagToken token) => endTagTable(token); Token startTagOther(StartTagToken token) { return parser._inTablePhase.processStartTag(token); @@ -2971,7 +2973,7 @@ class InTableBodyPhase extends Phase { class InRowPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-row - InRowPhase(parser) : super(parser); + InRowPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3117,7 +3119,7 @@ class InRowPhase extends Phase { class InCellPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-cell - InCellPhase(parser) : super(parser); + InCellPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3241,7 +3243,7 @@ class InCellPhase extends Phase { } class InSelectPhase extends Phase { - InSelectPhase(parser) : super(parser); + InSelectPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3397,7 +3399,7 @@ class InSelectPhase extends Phase { } class InSelectInTablePhase extends Phase { - InSelectInTablePhase(parser) : super(parser); + InSelectInTablePhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3523,7 +3525,7 @@ class InForeignContentPhase extends Phase { 'var' ]; - InForeignContentPhase(parser) : super(parser); + InForeignContentPhase(HtmlParser parser) : super(parser); void adjustSVGTagNames(token) { final replacements = const { @@ -3628,7 +3630,7 @@ class InForeignContentPhase extends Phase { if (asciiUpper2Lower(node.localName) == token.name) { //XXX this isn't in the spec but it seems necessary if (parser.phase == parser._inTableTextPhase) { - InTableTextPhase inTableText = parser.phase; + final inTableText = parser.phase as InTableTextPhase; inTableText.flushCharacters(); parser.phase = inTableText.originalPhase; } @@ -3653,7 +3655,7 @@ class InForeignContentPhase extends Phase { } class AfterBodyPhase extends Phase { - AfterBodyPhase(parser) : super(parser); + AfterBodyPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3725,7 +3727,7 @@ class AfterBodyPhase extends Phase { class InFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-frameset - InFramesetPhase(parser) : super(parser); + InFramesetPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3818,7 +3820,7 @@ class InFramesetPhase extends Phase { class AfterFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///after3 - AfterFramesetPhase(parser) : super(parser); + AfterFramesetPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3875,7 +3877,7 @@ class AfterFramesetPhase extends Phase { } class AfterAfterBodyPhase extends Phase { - AfterAfterBodyPhase(parser) : super(parser); + AfterAfterBodyPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { @@ -3926,7 +3928,7 @@ class AfterAfterBodyPhase extends Phase { } class AfterAfterFramesetPhase extends Phase { - AfterAfterFramesetPhase(parser) : super(parser); + AfterAfterFramesetPhase(HtmlParser parser) : super(parser); @override Token processStartTag(StartTagToken token) { diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 0c660b7af..041c5d824 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -7,7 +7,7 @@ import 'package:csslib/visitor.dart'; // the CSSOM import 'package:html/dom.dart'; import 'package:html/src/constants.dart' show isWhitespaceCC; -bool matches(Node node, String selector) => +bool matches(Element node, String selector) => SelectorEvaluator().matches(node, _parseSelectorList(selector)); Element querySelector(Node node, String selector) => @@ -40,10 +40,9 @@ class SelectorEvaluator extends Visitor { } Element querySelector(Node root, SelectorGroup selector) { - for (var node in root.nodes) { - if (node is! Element) continue; - if (matches(node, selector)) return node; - var result = querySelector(node, selector); + for (var element in root.nodes.whereType<Element>()) { + if (matches(element, selector)) return element; + var result = querySelector(element, selector); if (result != null) return result; } return null; @@ -51,10 +50,9 @@ class SelectorEvaluator extends Visitor { void querySelectorAll( Node root, SelectorGroup selector, List<Element> results) { - for (var node in root.nodes) { - if (node is! Element) continue; - if (matches(node, selector)) results.add(node); - querySelectorAll(node, selector, results); + for (var element in root.nodes.whereType<Element>()) { + if (matches(element, selector)) results.add(element); + querySelectorAll(element, selector, results); } } @@ -71,13 +69,13 @@ class SelectorEvaluator extends Visitor { int combinator; for (var s in selector.simpleSelectorSequences.reversed) { if (combinator == null) { - result = s.simpleSelector.visit(this); + result = s.simpleSelector.visit(this) as bool; } else if (combinator == TokenKind.COMBINATOR_DESCENDANT) { // descendant combinator // http://dev.w3.org/csswg/selectors-4/#descendant-combinators do { _element = _element.parent; - } while (_element != null && !s.simpleSelector.visit(this)); + } while (_element != null && !(s.simpleSelector.visit(this) as bool)); if (_element == null) result = false; } else if (combinator == TokenKind.COMBINATOR_TILDE) { @@ -85,7 +83,7 @@ class SelectorEvaluator extends Visitor { // http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators do { _element = _element.previousElementSibling; - } while (_element != null && !s.simpleSelector.visit(this)); + } while (_element != null && !(s.simpleSelector.visit(this) as bool)); if (_element == null) result = false; } @@ -216,10 +214,10 @@ class SelectorEvaluator extends Visitor { // TODO(jmesserly): support An+B syntax too. var exprs = selector.expression.expressions; if (exprs.length == 1 && exprs[0] is LiteralTerm) { - LiteralTerm literal = exprs[0]; + final literal = exprs[0] as LiteralTerm; var parent = _element.parentNode; return parent != null && - literal.value > 0 && + (literal.value as num) > 0 && parent.nodes.indexOf(_element) == literal.value; } break; @@ -248,7 +246,7 @@ class SelectorEvaluator extends Visitor { @override bool visitNamespaceSelector(NamespaceSelector selector) { // Match element tag name - if (!selector.nameAsSimpleSelector.visit(this)) return false; + if (!(selector.nameAsSimpleSelector.visit(this) as bool)) return false; if (selector.isNamespaceWildcard) return true; @@ -273,7 +271,7 @@ class SelectorEvaluator extends Visitor { // http://dev.w3.org/csswg/selectors-4/#negation @override bool visitNegationSelector(NegationSelector selector) => - !selector.negationArg.visit(this); + !(selector.negationArg.visit(this) as bool); @override bool visitAttributeSelector(AttributeSelector selector) { diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index e92ec8e7e..24c531eb2 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -63,9 +63,7 @@ abstract class StringToken extends Token { return _string; } - StringToken(string) - : _string = string, - _buffer = string == null ? StringBuffer() : null; + StringToken(this._string) : _buffer = _string == null ? StringBuffer() : null; StringToken add(String data) { _buffer.write(data); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index b26e8d965..26b711501 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -51,9 +51,7 @@ class HtmlTokenizer implements Iterator<Token> { Token currentToken; /// Holds a reference to the method to be invoked for the next parser state. - // TODO(jmesserly): the type should be "Predicate" but a dart2js checked mode - // bug prevents us from doing that. See http://dartbug.com/12465 - Function state; + bool Function() state; final StringBuffer _buffer = StringBuffer(); @@ -79,9 +77,9 @@ class HtmlTokenizer implements Iterator<Token> { reset(); } - TagToken get currentTagToken => currentToken; - DoctypeToken get currentDoctypeToken => currentToken; - StringToken get currentStringToken => currentToken; + TagToken get currentTagToken => currentToken as TagToken; + DoctypeToken get currentDoctypeToken => currentToken as DoctypeToken; + StringToken get currentStringToken => currentToken as StringToken; Token _current; @override diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index e0962141e..b60d4a746 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -13,7 +13,7 @@ import 'utils.dart'; // The scope markers are inserted when entering object elements, // marquees, table cells, and table captions, and are used to prevent formatting // from "leaking" into tables, object elements, and marquees. -const Node Marker = null; +const Element Marker = null; // TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt // didn't work. @@ -230,7 +230,7 @@ class TreeBuilder { return null; } - void insertRoot(Token token) { + void insertRoot(StartTagToken token) { var element = createElement(token); openElements.add(element); document.nodes.add(element); @@ -273,7 +273,7 @@ class TreeBuilder { return element; } - Element insertElementTable(token) { + Element insertElementTable(StartTagToken token) { /// Create an element and insert it into the tree var element = createElement(token); if (!tableInsertModeElements.contains(openElements.last.localName)) { @@ -307,7 +307,7 @@ class TreeBuilder { // We should be in the InTable mode. This means we want to do // special magic element rearranging var nodePos = getTableMisnestedNodePosition(); - _insertText(nodePos[0], data, span, nodePos[1]); + _insertText(nodePos[0], data, span, nodePos[1] as Element); } } @@ -318,7 +318,7 @@ class TreeBuilder { var nodes = parent.nodes; if (refNode == null) { if (nodes.isNotEmpty && nodes.last is Text) { - Text last = nodes.last; + final last = nodes.last as Text; last.appendData(data); if (span != null) { @@ -331,7 +331,7 @@ class TreeBuilder { } else { var index = nodes.indexOf(refNode); if (index > 0 && nodes[index - 1] is Text) { - Text last = nodes[index - 1]; + final last = nodes[index - 1] as Text; last.appendData(data); } else { nodes.insert(index, Text(data)..sourceSpan = span); @@ -345,7 +345,7 @@ class TreeBuilder { // The foster parent element is the one which comes before the most // recently opened table element // XXX - this is really inelegant - Node lastTable; + Element lastTable; Node fosterParent; Node insertBefore; for (var elm in openElements.reversed) { diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 57124c851..3eadc2e30 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -79,7 +79,7 @@ String formatStr(String format, Map data) { result.write(padWithZeros(number, numberSize)); break; case 'x': - var number = value.toRadixString(16); + var number = (value as int).toRadixString(16); result.write(padWithZeros(number, numberSize)); break; default: diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index e7aa320cd..2576b05df 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,8 +1,7 @@ name: html -version: 0.14.0+4 +version: 0.15.0-dev description: APIs for parsing and manipulating HTML content outside the browser. -author: Dart Team <misc@dartlang.org> homepage: https://github.com/dart-lang/html environment: diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 536f98fb7..3ed00318a 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -13,7 +13,7 @@ void main() { _testElementSpans(); test('doctype is cloneable', () { var doc = parse('<!doctype HTML>'); - DocumentType doctype = doc.nodes[0]; + final doctype = doc.nodes[0] as DocumentType; expect(doctype.clone(false).toString(), '<!DOCTYPE html>'); }); @@ -86,7 +86,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. var textContent = '\n hello {{name}}'; var html = '<body><div>$textContent</div>'; var doc = parse(html, generateSpans: true); - Text text = doc.body.nodes[0].nodes[0]; + final text = doc.body.nodes[0].nodes[0] as Text; expect(text, const TypeMatcher<Text>()); expect(text.data, textContent); expect(text.sourceSpan.start.offset, html.indexOf(textContent)); @@ -186,35 +186,35 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('escaping Text node in <script>', () { - Element e = parseFragment('<script>a && b</script>').firstChild; + final e = parseFragment('<script>a && b</script>').firstChild as Element; expect(e.outerHtml, '<script>a && b</script>'); }); test('escaping Text node in <span>', () { - Element e = parseFragment('<span>a && b</span>').firstChild; + final e = parseFragment('<span>a && b</span>').firstChild as Element; expect(e.outerHtml, '<span>a &amp;&amp; b</span>'); }); test('Escaping attributes', () { - Element e = parseFragment('<div class="a<b>">').firstChild; + var e = parseFragment('<div class="a<b>">').firstChild as Element; expect(e.outerHtml, '<div class="a<b>"></div>'); - e = parseFragment('<div class=\'a"b\'>').firstChild; + e = parseFragment('<div class=\'a"b\'>').firstChild as Element; expect(e.outerHtml, '<div class="a&quot;b"></div>'); }); test('Escaping non-breaking space', () { var text = '<span>foO\u00A0bar</span>'; expect(text.codeUnitAt(text.indexOf('O') + 1), 0xA0); - Element e = parseFragment(text).firstChild; + var e = parseFragment(text).firstChild as Element; expect(e.outerHtml, '<span>foO&nbsp;bar</span>'); }); test('Newline after <pre>', () { - Element e = parseFragment('<pre>\n\nsome text</span>').firstChild; + var e = parseFragment('<pre>\n\nsome text</span>').firstChild as Element; expect((e.firstChild as Text).data, '\nsome text'); expect(e.outerHtml, '<pre>\n\nsome text</pre>'); - e = parseFragment('<pre>\nsome text</span>').firstChild; + e = parseFragment('<pre>\nsome text</span>').firstChild as Element; expect((e.firstChild as Text).data, 'some text'); expect(e.outerHtml, '<pre>some text</pre>'); }); @@ -278,7 +278,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('Text.text', () { var doc = parseFragment('<div>foo<div>bar</div>baz</div>'); var e = doc.firstChild; - Text text = e.firstChild; + final text = e.firstChild as Text; expect(text.data, 'foo'); expect(text.text, 'foo'); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 21c54d222..232a50f01 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -79,12 +79,10 @@ void main() { group(testName, () { for (var testData in tests) { var input = testData['data']; - var errors = testData['errors']; + final errorString = testData['errors']; + final errors = errorString?.split('\n'); var innerHTML = testData['document-fragment']; var expected = testData['document']; - if (errors != null) { - errors = errors.split('\n'); - } for (var treeCtor in treeTypes.values) { for (var namespaceHTMLElements in const [false, true]) { diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index f97dafc02..721eca6ad 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -28,8 +28,7 @@ void setupSpecialElements(parent) { anyNS.id = 'any-namespace'; noNS.id = 'no-namespace'; - var div; - div = [ + var div = [ doc.createElement('div'), doc.createElementNS('http://www.w3.org/1999/xhtml', 'div'), doc.createElementNS('', 'div'), @@ -70,7 +69,7 @@ void setupSpecialElements(parent) { /* * Check that the querySelector and querySelectorAll methods exist on the given Node */ -void interfaceCheck(type, obj) { +void interfaceCheck(String type, obj) { runTest(() { var q = obj.querySelector is Function; assertTrue(q, type + ' supports querySelector.'); @@ -94,7 +93,7 @@ void interfaceCheck(type, obj) { * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after * each call. A static list should not be affected by subsequent changes to the DOM. */ -void verifyStaticList(type, root) { +void verifyStaticList(String type, root) { var pre, post, preLength; runTest(() { @@ -119,7 +118,7 @@ void verifyStaticList(type, root) { * Verify handling of special values for the selector parameter, including stringification of * null and undefined, and the handling of the empty string. */ -void runSpecialSelectorTests(type, root) { +void runSpecialSelectorTests(String type, root) { // Dart note: changed these tests because we don't have auto conversion to // String like JavaScript does. runTest(() { @@ -170,7 +169,7 @@ void runSpecialSelectorTests(type, root) { // 7 var result = root.querySelectorAll('*'); var i = 0; - traverse(root, (elem) { + traverse(root as Node, (elem) { if (!identical(elem, root)) { assertEquals( elem, result[i], 'The result in index $i should be in tree order.'); @@ -197,7 +196,7 @@ String _getSkip(String name) { void runValidSelectorTest(String type, root, List<Map<String, dynamic>> selectors, testType, docType) { var nodeType = ''; - switch (root.nodeType) { + switch ((root as Node).nodeType) { case Node.DOCUMENT_NODE: nodeType = 'document'; break; @@ -213,20 +212,21 @@ void runValidSelectorTest(String type, root, for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; - var n = s['name']; + var n = s['name'] as String; var skip = _getSkip(n); - var q = s['selector']; - var e = s['expect']; + var q = s['selector'] as String; + var e = s['expect'] as List; if ((s['exclude'] is! List || (s['exclude'].indexOf(nodeType) == -1 && s['exclude'].indexOf(docType) == -1)) && (s['testType'] & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) - var foundall, found; + List<Element> foundall; + Element found; runTest(() { - foundall = root.querySelectorAll(q); + foundall = root.querySelectorAll(q) as List<Element>; assertNotEquals(foundall, null, 'The method should not return null.'); assertEquals(foundall.length, e.length, 'The method should return the expected number of matches.'); @@ -242,7 +242,7 @@ void runValidSelectorTest(String type, root, }, type + '.querySelectorAll: ' + n + ': ' + q, skip: skip); runTest(() { - found = root.querySelector(q); + found = root.querySelector(q) as Element; if (e.isNotEmpty) { assertNotEquals(found, null, 'The method should return a match.'); @@ -269,8 +269,8 @@ void runValidSelectorTest(String type, root, void runInvalidSelectorTest(String type, root, List selectors) { for (var i = 0; i < selectors.length; i++) { var s = selectors[i]; - var n = s['name']; - var q = s['selector']; + var n = s['name'] as String; + var q = s['selector'] as String; // Dart note: FormatException seems a reasonable mapping of SyntaxError runTest(() { @@ -298,7 +298,7 @@ void traverse(Node elem, void Function(Node) fn) { } } -void runTest(Function body, String name, {String skip}) => +void runTest(dynamic Function() body, String name, {String skip}) => unittest.test(name, body, skip: skip); void assertTrue(bool value, String reason) => diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index afcf95263..01995350c 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -29,7 +29,7 @@ Iterable<String> getDataFiles(String subdirectory) { // TODO(jmesserly): make this class simpler. We could probably split on // "\n#" instead of newline and remove a lot of code. -class TestData extends IterableBase<Map> { +class TestData extends IterableBase<Map<String, String>> { final String _text; final String newTestHeading; @@ -40,12 +40,12 @@ class TestData extends IterableBase<Map> { // Note: in Python this was a generator, but since we can't do that in Dart, // it's easier to convert it into an upfront computation. @override - Iterator<Map> get iterator => _getData().iterator; + Iterator<Map<String, String>> get iterator => _getData().iterator; - List<Map> _getData() { + List<Map<String, String>> _getData() { var data = <String, String>{}; String key; - var result = <Map>[]; + var result = <Map<String, String>>[]; var lines = _text.split('\n'); // Remove trailing newline to match Python if (lines.last == '') { @@ -79,7 +79,7 @@ class TestData extends IterableBase<Map> { return line.startsWith('#') ? line.substring(1).trim() : null; } - static Map normaliseOutput(Map data) { + static Map<String, String> normaliseOutput(Map<String, String> data) { // Remove trailing newlines data.forEach((key, value) { if (value.endsWith('\n')) { @@ -91,7 +91,7 @@ class TestData extends IterableBase<Map> { } /// Serialize the [document] into the html5 test data format. -String testSerializer(document) { +String testSerializer(Node document) { return (TestSerializer()..visit(document)).toString(); } @@ -143,7 +143,7 @@ class TestSerializer extends TreeVisitor { @override void visitDocument(node) => _visitDocumentOrFragment(node); - void _visitDocumentOrFragment(node) { + void _visitDocumentOrFragment(Node node) { indent += 1; for (var child in node.nodes) { visit(child); @@ -161,12 +161,16 @@ class TestSerializer extends TreeVisitor { _str.write(node); if (node.attributes.isNotEmpty) { indent += 2; - var keys = List.from(node.attributes.keys); - keys.sort((x, y) => x.compareTo(y)); + var keys = node.attributes.keys.toList(); + keys.sort((x, y) { + if (x is String) return x.compareTo(y as String); + if (x is AttributeName) return x.compareTo(y as AttributeName); + throw StateError('Cannot sort'); + }); for (var key in keys) { var v = node.attributes[key]; if (key is AttributeName) { - AttributeName attr = key; + final attr = key as AttributeName; key = '${attr.prefix} ${attr.name}'; } _newline(); diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 62d5f8ad3..41ae4d551 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -35,7 +35,8 @@ class TokenizerTestParser { // Note: we can't get a closure of the state method. However, we can // create a new closure to invoke it via mirrors. var mtok = reflect(tokenizer); - tokenizer.state = () => mtok.invoke(Symbol(_state), const []).reflectee; + tokenizer.state = + () => mtok.invoke(Symbol(_state), const []).reflectee as bool; if (_lastStartTag != null) { tokenizer.currentToken = StartTagToken(_lastStartTag); @@ -45,25 +46,25 @@ class TokenizerTestParser { var token = tokenizer.current; switch (token.kind) { case TokenKind.characters: - processCharacters(token); + processCharacters(token as CharactersToken); break; case TokenKind.spaceCharacters: - processSpaceCharacters(token); + processSpaceCharacters(token as SpaceCharactersToken); break; case TokenKind.startTag: - processStartTag(token); + processStartTag(token as StartTagToken); break; case TokenKind.endTag: - processEndTag(token); + processEndTag(token as EndTagToken); break; case TokenKind.comment: - processComment(token); + processComment(token as CommentToken); break; case TokenKind.doctype: - processDoctype(token); + processDoctype(token as DoctypeToken); break; case TokenKind.parseError: - processParseError(token); + processParseError(token as ParseErrorToken); break; } } @@ -186,20 +187,22 @@ void expectTokensMatch( } } -void runTokenizerTest(Map testInfo) { +void runTokenizerTest(Map<String, dynamic> testInfo) { // XXX - move this out into the setup function // concatenate all consecutive character tokens into a single token if (testInfo.containsKey('doubleEscaped')) { testInfo = unescape(testInfo); } - var expected = concatenateCharacterTokens(testInfo['output']); + var expected = concatenateCharacterTokens(testInfo['output'] as List); if (!testInfo.containsKey('lastStartTag')) { testInfo['lastStartTag'] = null; } - var parser = TokenizerTestParser(testInfo['initialState'], - testInfo['lastStartTag'], testInfo['generateSpans'] ?? false); - var tokens = parser.parse(testInfo['input']); + var parser = TokenizerTestParser( + testInfo['initialState'] as String, + testInfo['lastStartTag'] as String, + testInfo['generateSpans'] as bool /*?*/ ?? false); + var tokens = parser.parse(testInfo['input'] as String); tokens = concatenateCharacterTokens(tokens); var received = normalizeTokens(tokens); var errorMsg = [ @@ -212,12 +215,12 @@ void runTokenizerTest(Map testInfo) { '\nreceived:', tokens ].map((s) => '$s').join('\n'); - var ignoreErrorOrder = testInfo['ignoreErrorOrder'] ?? false; + var ignoreErrorOrder = testInfo['ignoreErrorOrder'] as bool /*?*/ ?? false; expectTokensMatch(expected, received, ignoreErrorOrder, true, errorMsg); } -Map unescape(Map testInfo) { +Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { // TODO(sigmundch,jmesserly): we currently use jsonDecode to unescape the // unicode characters in the string, we should use a decoding that works with // any control characters. @@ -229,7 +232,7 @@ Map unescape(Map testInfo) { continue; } else { token[1] = decode(token[1]); - if (token.length > 2) { + if ((token as List).length > 2) { for (var pair in token[2]) { var key = pair[0]; var value = pair[1]; @@ -260,17 +263,17 @@ void main() { var text = File(path).readAsStringSync(); var tests = jsonDecode(text); var testName = pathos.basenameWithoutExtension(path); - var testList = tests['tests']; + var testList = tests['tests'] as List; if (testList == null) continue; group(testName, () { for (var index = 0; index < testList.length; index++) { - final testInfo = testList[index]; + final testInfo = testList[index] as Map<String, dynamic>; testInfo.putIfAbsent('initialStates', () => ['Data state']); for (var initialState in testInfo['initialStates']) { test(testInfo['description'], () { - testInfo['initialState'] = camelCase(initialState); + testInfo['initialState'] = camelCase(initialState as String); runTokenizerTest(testInfo); }); } From b3808cfd160fbd53f765df5860883fa2244c8ab6 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Tue, 6 Oct 2020 09:57:42 -0700 Subject: [PATCH 116/212] Enable and fix lint prefer_final_locals (dart-lang/html#131) This package has a number of long methods as well as patterns where the reassignment to local variables is a critical detail. Make it easier to work with by marking locals that don't change with `final`. --- pkgs/html/analysis_options.yaml | 1 + pkgs/html/lib/dom.dart | 42 ++-- pkgs/html/lib/dom_parsing.dart | 6 +- pkgs/html/lib/parser.dart | 142 ++++++------- pkgs/html/lib/src/constants.dart | 6 +- pkgs/html/lib/src/css_class_set.dart | 16 +- pkgs/html/lib/src/encoding_parser.dart | 40 ++-- pkgs/html/lib/src/html_input_stream.dart | 8 +- pkgs/html/lib/src/query_selector.dart | 24 +-- pkgs/html/lib/src/tokenizer.dart | 166 ++++++++-------- pkgs/html/lib/src/treebuilder.dart | 40 ++-- pkgs/html/lib/src/utils.dart | 10 +- pkgs/html/test/dom_test.dart | 28 +-- pkgs/html/test/parser_feature_test.dart | 186 +++++++++--------- pkgs/html/test/parser_test.dart | 22 +-- .../test/selectors/level1_baseline_test.dart | 14 +- pkgs/html/test/selectors/level1_lib.dart | 34 ++-- pkgs/html/test/support.dart | 14 +- pkgs/html/test/tokenizer_test.dart | 46 ++--- 19 files changed, 423 insertions(+), 422 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 20eba0c64..9f2325c88 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -51,6 +51,7 @@ linter: - prefer_const_constructors - prefer_equal_for_default_values - prefer_final_fields + - prefer_final_locals - prefer_initializing_formals #- prefer_interpolation_to_compose_strings #- prefer_single_quotes diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 85e02c4db..fbd2c90b0 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -203,13 +203,13 @@ abstract class Node { // http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface String get _outerHtml { - var str = StringBuffer(); + final str = StringBuffer(); _addOuterHtml(str); return str.toString(); } String get _innerHtml { - var str = StringBuffer(); + final str = StringBuffer(); _addInnerHtml(str); return str.toString(); } @@ -284,16 +284,16 @@ abstract class Node { if (sourceSpan == null) return; - var tokenizer = HtmlTokenizer(sourceSpan.text, + final tokenizer = HtmlTokenizer(sourceSpan.text, generateSpans: true, attributeSpans: true); tokenizer.moveNext(); - var token = tokenizer.current as StartTagToken; + final token = tokenizer.current as StartTagToken; if (token.attributeSpans == null) return; // no attributes for (var attr in token.attributeSpans) { - var offset = sourceSpan.start.offset; + final offset = sourceSpan.start.offset; _attributeSpans[attr.name] = sourceSpan.file.span(offset + attr.start, offset + attr.end); if (attr.startValue != null) { @@ -400,8 +400,8 @@ class DocumentType extends Node { if (publicId != null || systemId != null) { // TODO(jmesserly): the html5 serialization spec does not add these. But // it seems useful, and the parser can handle it, so for now keeping it. - var pid = publicId ?? ''; - var sid = systemId ?? ''; + final pid = publicId ?? ''; + final sid = systemId ?? ''; return '<!DOCTYPE $name "$pid" "$sid">'; } else { return '<!DOCTYPE $name>'; @@ -516,7 +516,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } } - var fragment = parseFragment(html, container: parentTag); + final fragment = parseFragment(html, container: parentTag); Element element; if (fragment.children.length == 1) { element = fragment.children[0]; @@ -537,9 +537,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // TODO(jmesserly): we can make this faster Element get previousElementSibling { if (parentNode == null) return null; - var siblings = parentNode.nodes; + final siblings = parentNode.nodes; for (var i = siblings.indexOf(this) - 1; i >= 0; i--) { - var s = siblings[i]; + final s = siblings[i]; if (s is Element) return s; } return null; @@ -547,9 +547,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { Element get nextElementSibling { if (parentNode == null) return null; - var siblings = parentNode.nodes; + final siblings = parentNode.nodes; for (var i = siblings.indexOf(this) + 1; i < siblings.length; i++) { - var s = siblings[i]; + final s = siblings[i]; if (s is Element) return s; } return null; @@ -557,7 +557,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { @override String toString() { - var prefix = Namespaces.getPrefix(namespaceUri); + final prefix = Namespaces.getPrefix(namespaceUri); return "<${prefix == null ? '' : '$prefix '}$localName>"; } @@ -632,7 +632,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { uri == Namespaces.svg) { return ''; } - var prefix = Namespaces.getPrefix(uri); + final prefix = Namespaces.getPrefix(uri); // TODO(jmesserly): the spec doesn't define "qualified name". // I'm not sure if this is correct, but it should parse reasonably. return prefix == null ? '' : '$prefix:'; @@ -640,14 +640,14 @@ class Element extends Node with _ParentNode, _ElementAndDocument { @override Element clone(bool deep) { - var result = Element._(localName, namespaceUri) + final result = Element._(localName, namespaceUri) ..attributes = LinkedHashMap.from(attributes); return _clone(result, deep); } // http://dom.spec.whatwg.org/#dom-element-id String get id { - var result = attributes['id']; + final result = attributes['id']; return result ?? ''; } @@ -657,7 +657,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // http://dom.spec.whatwg.org/#dom-element-classname String get className { - var result = attributes['class']; + final result = attributes['class']; return result ?? ''; } @@ -741,7 +741,7 @@ class NodeList extends ListProxy<Node> { // 2. we should update parent pointers in reverse order. That way they // are removed from the original NodeList (if any) from the end, which // is faster. - var list = _flattenDocFragments(collection); + final list = _flattenDocFragments(collection); for (var node in list.reversed) { _setParent(node); } @@ -832,7 +832,7 @@ class NodeList extends ListProxy<Node> { @override void insertAll(int index, Iterable<Node> collection) { // Note: we need to be careful how we copy nodes. See note in addAll. - var list = _flattenDocFragments(collection); + final list = _flattenDocFragments(collection); for (var node in list.reversed) { _setParent(node); } @@ -843,7 +843,7 @@ class NodeList extends ListProxy<Node> { // Note: this function serves two purposes: // * it flattens document fragments // * it creates a copy of [collections] when `collection is NodeList`. - var result = <Node>[]; + final result = <Node>[]; for (var node in collection) { if (node is DocumentFragment) { result.addAll(node.nodes); @@ -994,7 +994,7 @@ class FilteredElementList extends IterableBase<Element> bool remove(Object element) { if (element is! Element) return false; for (var i = 0; i < length; i++) { - var indexElement = this[i]; + final indexElement = this[i]; if (identical(indexElement, element)) { indexElement.remove(); return true; diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 3c8774be7..f108b59dd 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -111,7 +111,7 @@ class CodeMarkupVisitor extends TreeVisitor { @override void visitComment(Comment node) { - var data = htmlSerializeEscape(node.data); + final data = htmlSerializeEscape(node.data); _str.write('<code class="markup comment">&lt;!--$data--></code>'); } } @@ -138,7 +138,7 @@ String htmlSerializeEscape(String text, {bool attributeMode = false}) { // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. StringBuffer result; for (var i = 0; i < text.length; i++) { - var ch = text[i]; + final ch = text[i]; String replace; switch (ch) { case '&': @@ -201,7 +201,7 @@ void writeTextNodeAsHtml(StringBuffer str, Text node) { // Don't escape text for certain elements, notably <script>. final parent = node.parentNode; if (parent is Element) { - var tag = parent.localName; + final tag = parent.localName; if (rcdataElements.contains(tag) || tag == 'plaintext') { str.write(node.data); return; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 2a6c43177..5cfd53de5 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -38,7 +38,7 @@ import 'src/utils.dart'; /// extracted from. Document parse(input, {String encoding, bool generateSpans = false, String sourceUrl}) { - var p = HtmlParser(input, + final p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parse(); } @@ -60,7 +60,7 @@ DocumentFragment parseFragment(input, String encoding, bool generateSpans = false, String sourceUrl}) { - var p = HtmlParser(input, + final p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parseFragment(container); } @@ -277,7 +277,7 @@ class HtmlParser { bool inForeignContent(Token token, int type) { if (tree.openElements.isEmpty) return false; - var node = tree.openElements.last; + final node = tree.openElements.last; if (node.namespaceUri == tree.defaultNamespace) return false; if (isMathMLTextIntegrationPoint(node)) { @@ -310,7 +310,7 @@ class HtmlParser { void mainLoop() { while (tokenizer.moveNext()) { - var token = tokenizer.current; + final token = tokenizer.current; var newToken = token; int type; while (newToken != null) { @@ -362,7 +362,7 @@ class HtmlParser { // When the loop finishes it's EOF var reprocess = true; - var reprocessPhases = []; + final reprocessPhases = []; while (reprocess) { reprocessPhases.add(phase); reprocess = phase.processEOF(); @@ -376,7 +376,7 @@ class HtmlParser { /// better. SourceSpan get _lastSpan { if (tokenizer.stream.fileInfo == null) return null; - var pos = tokenizer.stream.position; + final pos = tokenizer.stream.position; return tokenizer.stream.fileInfo.location(pos).pointSpan(); } @@ -386,13 +386,13 @@ class HtmlParser { span = _lastSpan; } - var err = ParseError(errorcode, span, datavars); + final err = ParseError(errorcode, span, datavars); errors.add(err); if (strict) throw err; } void adjustMathMLAttributes(StartTagToken token) { - var orig = token.data.remove('definitionurl'); + final orig = token.data.remove('definitionurl'); if (orig != null) { token.data['definitionURL'] = orig; } @@ -464,7 +464,7 @@ class HtmlParser { 'zoomandpan': 'zoomAndPan' }; for (var originalName in token.data.keys.toList()) { - var svgName = replacements[originalName]; + final svgName = replacements[originalName]; if (svgName != null) { token.data[svgName] = token.data.remove(originalName); } @@ -490,7 +490,7 @@ class HtmlParser { }; for (var originalName in token.data.keys.toList()) { - var foreignName = replacements[originalName]; + final foreignName = replacements[originalName]; if (foreignName != null) { token.data[foreignName] = token.data.remove(originalName); } @@ -502,7 +502,7 @@ class HtmlParser { // specification.) for (var node in tree.openElements.reversed) { var nodeName = node.localName; - var last = node == tree.openElements[0]; + final last = node == tree.openElements[0]; if (last) { assert(innerHTMLMode); nodeName = innerHTML; @@ -655,7 +655,7 @@ class Phase { /// Helper method for popping openElements. void popOpenElementsUntil(EndTagToken token) { - var name = token.name; + final name = token.name; var node = tree.openElements.removeLast(); while (node.localName != name) { node = tree.openElements.removeLast(); @@ -682,10 +682,10 @@ class InitialPhase extends Phase { @override Token processDoctype(DoctypeToken token) { - var name = token.name; + final name = token.name; var publicId = token.publicId; - var systemId = token.systemId; - var correct = token.correct; + final systemId = token.systemId; + final correct = token.correct; if ((name != 'html' || publicId != null || @@ -1046,15 +1046,15 @@ class InHeadPhase extends Phase { tree.openElements.removeLast(); token.selfClosingAcknowledged = true; - var attributes = token.data; + final attributes = token.data; if (!parser.tokenizer.stream.charEncodingCertain) { - var charset = attributes['charset']; - var content = attributes['content']; + final charset = attributes['charset']; + final content = attributes['content']; if (charset != null) { parser.tokenizer.stream.changeEncoding(charset); } else if (content != null) { - var data = EncodingBytes(content); - var codec = ContentAttrParser(data).parse(); + final data = EncodingBytes(content); + final codec = ContentAttrParser(data).parse(); parser.tokenizer.stream.changeEncoding(codec); } } @@ -1082,7 +1082,7 @@ class InHeadPhase extends Phase { } void endTagHead(EndTagToken token) { - var node = parser.tree.openElements.removeLast(); + final node = parser.tree.openElements.removeLast(); assert(node.localName == 'head'); node.endSourceSpan = token.span; parser.phase = parser._afterHeadPhase; @@ -1505,9 +1505,9 @@ class InBodyPhase extends Phase { // helper void addFormattingElement(StartTagToken token) { tree.insertElement(token); - var element = tree.openElements.last; + final element = tree.openElements.last; - var matchingElements = []; + final matchingElements = []; for (Node node in tree.activeFormattingElements.reversed) { if (node == Marker) { break; @@ -1555,7 +1555,7 @@ class InBodyPhase extends Phase { var data = token.data; dropNewline = false; if (data.startsWith('\n')) { - var lastOpen = tree.openElements.last; + final lastOpen = tree.openElements.last; if (const ['pre', 'listing', 'textarea'].contains(lastOpen.localName) && !lastOpen.hasContent()) { data = data.substring(1); @@ -1662,7 +1662,7 @@ class InBodyPhase extends Phase { 'dt': ['dt', 'dd'], 'dd': ['dt', 'dd'] }; - var stopNames = stopNamesMap[token.name]; + final stopNames = stopNamesMap[token.name]; for (var node in tree.openElements.reversed) { if (stopNames.contains(node.localName)) { parser.phase.processEndTag(EndTagToken(node.localName)); @@ -1702,7 +1702,7 @@ class InBodyPhase extends Phase { } void startTagA(StartTagToken token) { - var afeAElement = tree.elementInActiveFormattingElements('a'); + final afeAElement = tree.elementInActiveFormattingElements('a'); if (afeAElement != null) { parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', {'startName': 'a', 'endName': 'a'}); @@ -1781,7 +1781,7 @@ class InBodyPhase extends Phase { } void startTagInput(StartTagToken token) { - var savedFramesetOK = parser.framesetOK; + final savedFramesetOK = parser.framesetOK; startTagVoidFormatting(token); if (asciiUpper2Lower(token.data['type']) == 'hidden') { //input type=hidden doesn't change framesetOK @@ -1818,8 +1818,8 @@ class InBodyPhase extends Phase { if (tree.formPointer != null) { return; } - var formAttrs = LinkedHashMap<dynamic, String>(); - var dataAction = token.data['action']; + final formAttrs = LinkedHashMap<dynamic, String>(); + final dataAction = token.data['action']; if (dataAction != null) { formAttrs['action'] = dataAction; } @@ -1832,7 +1832,7 @@ class InBodyPhase extends Phase { var prompt = token.data['prompt']; prompt ??= 'This is a searchable index. Enter search keywords: '; processCharacters(CharactersToken(prompt)); - var attributes = LinkedHashMap<dynamic, String>.from(token.data); + final attributes = LinkedHashMap<dynamic, String>.from(token.data); attributes.remove('action'); attributes.remove('prompt'); attributes['name'] = 'isindex'; @@ -1889,7 +1889,7 @@ class InBodyPhase extends Phase { void startTagRpRt(StartTagToken token) { if (tree.elementInScope('ruby')) { tree.generateImpliedEndTags(); - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName != 'ruby') { parser.parseError(last.sourceSpan, 'undefined-error'); } @@ -2006,7 +2006,7 @@ class InBodyPhase extends Phase { if (token.name == 'pre') { dropNewline = false; } - var inScope = tree.elementInScope(token.name); + final inScope = tree.elementInScope(token.name); if (inScope) { tree.generateImpliedEndTags(); } @@ -2019,7 +2019,7 @@ class InBodyPhase extends Phase { } void endTagForm(EndTagToken token) { - var node = tree.formPointer; + final node = tree.formPointer; tree.formPointer = null; if (node == null || !tree.elementInScope(node)) { parser.parseError(token.span, 'unexpected-end-tag', {'name': 'form'}); @@ -2090,7 +2090,7 @@ class InBodyPhase extends Phase { outerLoopCounter += 1; // Step 1 paragraph 1 - var formattingElement = + final formattingElement = tree.elementInActiveFormattingElements(token.name); if (formattingElement == null || (tree.openElements.contains(formattingElement) && @@ -2114,7 +2114,7 @@ class InBodyPhase extends Phase { // Step 2 // Start of the adoption agency algorithm proper - var afeIndex = tree.openElements.indexOf(formattingElement); + final afeIndex = tree.openElements.indexOf(formattingElement); Element furthestBlock; for (var element in slice(tree.openElements, afeIndex)) { if (specialElements.contains(getElementNameTuple(element))) { @@ -2135,7 +2135,7 @@ class InBodyPhase extends Phase { return; } - var commonAncestor = tree.openElements[afeIndex - 1]; + final commonAncestor = tree.openElements[afeIndex - 1]; // Step 5 // The bookmark is supposed to help us identify where to reinsert @@ -2170,7 +2170,7 @@ class InBodyPhase extends Phase { } // Step 6.5 //cite = node.parent - var clone = node.clone(false); + final clone = node.clone(false); // Replace node with clone tree.activeFormattingElements[ tree.activeFormattingElements.indexOf(node)] = clone; @@ -2198,14 +2198,14 @@ class InBodyPhase extends Phase { if (const ['table', 'tbody', 'tfoot', 'thead', 'tr'] .contains(commonAncestor.localName)) { - var nodePos = tree.getTableMisnestedNodePosition(); + final nodePos = tree.getTableMisnestedNodePosition(); nodePos[0].insertBefore(lastNode, nodePos[1]); } else { commonAncestor.nodes.add(lastNode); } // Step 8 - var clone = formattingElement.clone(false); + final clone = formattingElement.clone(false); // Step 9 furthestBlock.reparentChildren(clone); @@ -2299,7 +2299,7 @@ class TextPhase extends Phase { @override bool processEOF() { - var last = tree.openElements.last; + final last = tree.openElements.last; parser.parseError(last.sourceSpan, 'expected-named-closing-tag-but-got-eof', {'name': last.localName}); tree.openElements.removeLast(); @@ -2308,7 +2308,7 @@ class TextPhase extends Phase { } void endTagScript(EndTagToken token) { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); assert(node.localName == 'script'); parser.phase = parser.originalPhase; //The rest of this method is all stuff that only happens if @@ -2404,7 +2404,7 @@ class InTablePhase extends Phase { // processing methods @override bool processEOF() { - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName != 'html') { parser.parseError(last.sourceSpan, 'eof-in-table'); } else { @@ -2416,7 +2416,7 @@ class InTablePhase extends Phase { @override Token processSpaceCharacters(SpaceCharactersToken token) { - var originalPhase = parser.phase; + final originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; parser.phase.processSpaceCharacters(token); @@ -2425,7 +2425,7 @@ class InTablePhase extends Phase { @override Token processCharacters(CharactersToken token) { - var originalPhase = parser.phase; + final originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; parser.phase.processCharacters(token); @@ -2517,7 +2517,7 @@ class InTablePhase extends Phase { void endTagTable(EndTagToken token) { if (tree.elementInScope('table', variant: 'table')) { tree.generateImpliedEndTags(); - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName != 'table') { parser.parseError(token.span, 'end-tag-too-early-named', {'gotName': 'table', 'expectedName': last.localName}); @@ -2525,7 +2525,7 @@ class InTablePhase extends Phase { while (tree.openElements.last.localName != 'table') { tree.openElements.removeLast(); } - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; parser.resetInsertionMode(); } else { @@ -2561,7 +2561,7 @@ class InTableTextPhase extends Phase { if (characterTokens.isEmpty) return; // TODO(sigmund,jmesserly): remove '' (dartbug.com/8480) - var data = characterTokens.map((t) => t.data).join(''); + final data = characterTokens.map((t) => t.data).join(''); FileSpan span; if (parser.generateSpans) { @@ -2689,7 +2689,7 @@ class InCaptionPhase extends Phase { Token startTagTableElement(StartTagToken token) { parser.parseError(token.span, 'undefined-error'); //XXX Have to duplicate logic here to find out if the tag is ignored - var ignoreEndTag = ignoreEndTagCaption(); + final ignoreEndTag = ignoreEndTagCaption(); parser.phase.processEndTag(EndTagToken('caption')); if (!ignoreEndTag) { return token; @@ -2714,7 +2714,7 @@ class InCaptionPhase extends Phase { while (tree.openElements.last.localName != 'caption') { tree.openElements.removeLast(); } - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; tree.clearActiveFormattingElements(); parser.phase = parser._inTablePhase; @@ -2727,7 +2727,7 @@ class InCaptionPhase extends Phase { Token endTagTable(EndTagToken token) { parser.parseError(token.span, 'undefined-error'); - var ignoreEndTag = ignoreEndTagCaption(); + final ignoreEndTag = ignoreEndTagCaption(); parser.phase.processEndTag(EndTagToken('caption')); if (!ignoreEndTag) { return token; @@ -2781,7 +2781,7 @@ class InColumnGroupPhase extends Phase { @override bool processEOF() { - var ignoreEndTag = ignoreEndTagColgroup(); + final ignoreEndTag = ignoreEndTagColgroup(); if (ignoreEndTag) { assert(parser.innerHTMLMode); return false; @@ -2793,7 +2793,7 @@ class InColumnGroupPhase extends Phase { @override Token processCharacters(CharactersToken token) { - var ignoreEndTag = ignoreEndTagColgroup(); + final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } @@ -2804,7 +2804,7 @@ class InColumnGroupPhase extends Phase { } Token startTagOther(StartTagToken token) { - var ignoreEndTag = ignoreEndTagColgroup(); + final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } @@ -2815,7 +2815,7 @@ class InColumnGroupPhase extends Phase { assert(parser.innerHTMLMode); parser.parseError(token.span, 'undefined-error'); } else { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; parser.phase = parser._inTablePhase; } @@ -2826,7 +2826,7 @@ class InColumnGroupPhase extends Phase { } Token endTagOther(EndTagToken token) { - var ignoreEndTag = ignoreEndTagColgroup(); + final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; } @@ -2886,7 +2886,7 @@ class InTableBodyPhase extends Phase { // helper methods void clearStackToTableBodyContext() { - var tableTags = const ['tbody', 'tfoot', 'thead', 'html']; + final tableTags = const ['tbody', 'tfoot', 'thead', 'html']; while (!tableTags.contains(tree.openElements.last.localName)) { //XXX parser.parseError(token.span, "unexpected-implied-end-tag-in-table", // {"name": tree.openElements.last.name}) @@ -2936,7 +2936,7 @@ class InTableBodyPhase extends Phase { void endTagTableRowGroup(EndTagToken token) { if (tree.elementInScope(token.name, variant: 'table')) { clearStackToTableBodyContext(); - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; parser.phase = parser._inTablePhase; } else { @@ -3026,7 +3026,7 @@ class InRowPhase extends Phase { // helper methods (XXX unify this with other table helper methods) void clearStackToTableRowContext() { while (true) { - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName == 'tr' || last.localName == 'html') break; parser.parseError( @@ -3066,7 +3066,7 @@ class InRowPhase extends Phase { } Token startTagTableOther(StartTagToken token) { - var ignoreEndTag = ignoreEndTagTr(); + final ignoreEndTag = ignoreEndTagTr(); endTagTr(EndTagToken('tr')); // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; @@ -3079,7 +3079,7 @@ class InRowPhase extends Phase { void endTagTr(EndTagToken token) { if (!ignoreEndTagTr()) { clearStackToTableRowContext(); - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; parser.phase = parser._inTableBodyPhase; } else { @@ -3090,7 +3090,7 @@ class InRowPhase extends Phase { } Token endTagTable(EndTagToken token) { - var ignoreEndTag = ignoreEndTagTr(); + final ignoreEndTag = ignoreEndTagTr(); endTagTr(EndTagToken('tr')); // Reprocess the current tag if the tr end tag was not ignored // XXX how are we sure it's always ignored in the innerHTML case? @@ -3212,7 +3212,7 @@ class InCellPhase extends Phase { token.span, 'unexpected-cell-end-tag', {'name': token.name}); popOpenElementsUntil(token); } else { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; } tree.clearActiveFormattingElements(); @@ -3291,7 +3291,7 @@ class InSelectPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-select @override bool processEOF() { - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName != 'html') { parser.parseError(last.sourceSpan, 'eof-in-select'); } else { @@ -3355,7 +3355,7 @@ class InSelectPhase extends Phase { void endTagOption(EndTagToken token) { if (tree.openElements.last.localName == 'option') { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; } else { parser.parseError( @@ -3372,7 +3372,7 @@ class InSelectPhase extends Phase { } // It also closes </optgroup> if (tree.openElements.last.localName == 'optgroup') { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; // But nothing else } else { @@ -3567,7 +3567,7 @@ class InForeignContentPhase extends Phase { 'textpath': 'textPath' }; - var replace = replacements[token.name]; + final replace = replacements[token.name]; if (replace != null) { token.name = replace; } @@ -3585,7 +3585,7 @@ class InForeignContentPhase extends Phase { @override Token processStartTag(StartTagToken token) { - var currentNode = tree.openElements.last; + final currentNode = tree.openElements.last; if (breakoutElements.contains(token.name) || (token.name == 'font' && (token.data.containsKey('color') || @@ -3761,7 +3761,7 @@ class InFramesetPhase extends Phase { @override bool processEOF() { - var last = tree.openElements.last; + final last = tree.openElements.last; if (last.localName != 'html') { parser.parseError(last.sourceSpan, 'eof-in-frameset'); } else { @@ -3801,7 +3801,7 @@ class InFramesetPhase extends Phase { parser.parseError( token.span, 'unexpected-frameset-in-frameset-innerhtml'); } else { - var node = tree.openElements.removeLast(); + final node = tree.openElements.removeLast(); node.endSourceSpan = token.span; } if (!parser.innerHTMLMode && @@ -4009,13 +4009,13 @@ class ParseError implements SourceSpanException { @override String toString({color}) { - var res = span.message(message, color: color); + final res = span.message(message, color: color); return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; } } /// Convenience function to get the pair of namespace and localName. Pair<String, String> getElementNameTuple(Element e) { - var ns = e.namespaceUri ?? Namespaces.html; + final ns = e.namespaceUri ?? Namespaces.html; return Pair(ns, e.localName); } diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 313b95273..b09fc4853 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -442,13 +442,13 @@ bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char); // Note: this is intentially ASCII only bool isLetter(String char) { if (char == null) return false; - var cc = char.codeUnitAt(0); + final cc = char.codeUnitAt(0); return cc >= LOWER_A && cc <= LOWER_Z || cc >= UPPER_A && cc <= UPPER_Z; } bool isDigit(String char) { if (char == null) return false; - var cc = char.codeUnitAt(0); + final cc = char.codeUnitAt(0); return cc >= ZERO && cc < ZERO + 10; } @@ -486,7 +486,7 @@ bool isHexDigit(String char) { // ASCII chars to.toLowerCase() case, unlike Dart's toLowerCase function. String asciiUpper2Lower(String text) { if (text == null) return null; - var result = List<int>(text.length); + final result = List<int>(text.length); for (var i = 0; i < text.length; i++) { var c = text.codeUnitAt(i); if (c >= UPPER_A && c <= UPPER_Z) { diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 3fa49e012..3f98a336e 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -16,11 +16,11 @@ class ElementCssClassSet extends _CssClassSetImpl { @override Set<String> readClasses() { - var s = LinkedHashSet<String>(); - var classname = _element.className; + final s = LinkedHashSet<String>(); + final classname = _element.className; for (var name in classname.split(' ')) { - var trimmed = name.trim(); + final trimmed = name.trim(); if (trimmed.isNotEmpty) { s.add(trimmed); } @@ -112,7 +112,7 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// [shouldAdd] is false then we always remove [value] from the element. @override bool toggle(String value, [bool shouldAdd]) { - var s = readClasses(); + final s = readClasses(); var result = false; shouldAdd ??= !s.contains(value); if (shouldAdd) { @@ -170,8 +170,8 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { @override bool remove(Object value) { if (value is! String) return false; - var s = readClasses(); - var result = s.remove(value); + final s = readClasses(); + final result = s.remove(value); writeClasses(s); return result; } @@ -197,8 +197,8 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// After f returns, the modified set is written to the /// className property of this element. bool _modify(bool Function(Set<String>) f) { - var s = readClasses(); - var ret = f(s); + final s = readClasses(); + final ret = f(s); writeClasses(s); return ret; } diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 51766a9d0..6fa96c6f3 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -15,7 +15,7 @@ class EncodingBytes { int get _length => _bytes.length; String _next() { - var p = __position = __position + 1; + final p = __position = __position + 1; if (p >= _length) { throw StateError('No more elements'); } else if (p < 0) { @@ -60,7 +60,7 @@ class EncodingBytes { skipChars ??= isWhitespace; var p = _position; // use property for the error-checking while (p < _length) { - var c = _bytes[p]; + final c = _bytes[p]; if (!skipChars(c)) { __position = p; return c; @@ -74,7 +74,7 @@ class EncodingBytes { String _skipUntil(_CharPredicate untilChars) { var p = _position; while (p < _length) { - var c = _bytes[p]; + final c = _bytes[p]; if (untilChars(c)) { __position = p; return c; @@ -88,11 +88,11 @@ class EncodingBytes { /// are found return true and advance the position to the byte after the /// match. Otherwise return false and leave the position alone. bool _matchBytes(String bytes) { - var p = _position; + final p = _position; if (_bytes.length < p + bytes.length) { return false; } - var data = _bytes.substring(p, p + bytes.length); + final data = _bytes.substring(p, p + bytes.length); if (data == bytes) { _position += bytes.length; return true; @@ -103,7 +103,7 @@ class EncodingBytes { /// Look for the next sequence of bytes matching a given sequence. If /// a match is found advance the position to the last byte of the match bool _jumpTo(String bytes) { - var newPosition = _bytes.indexOf(bytes, _position); + final newPosition = _bytes.indexOf(bytes, _position); if (newPosition >= 0) { __position = newPosition + bytes.length - 1; return true; @@ -152,7 +152,7 @@ class EncodingParser { for (;;) { for (var dispatch in methodDispatch) { if (_data._matchBytes(dispatch.pattern)) { - var keepParsing = dispatch.handler(); + final keepParsing = dispatch.handler(); if (keepParsing) break; // We found an encoding. Stop. @@ -179,20 +179,20 @@ class EncodingParser { // We have a valid meta element we want to search for attributes while (true) { // Try to find the next attribute after the current position - var attr = _getAttribute(); + final attr = _getAttribute(); if (attr == null) return true; if (attr[0] == 'charset') { - var tentativeEncoding = attr[1]; - var codec = codecName(tentativeEncoding); + final tentativeEncoding = attr[1]; + final codec = codecName(tentativeEncoding); if (codec != null) { _encoding = codec; return false; } } else if (attr[0] == 'content') { - var contentParser = ContentAttrParser(EncodingBytes(attr[1])); - var tentativeEncoding = contentParser.parse(); - var codec = codecName(tentativeEncoding); + final contentParser = ContentAttrParser(EncodingBytes(attr[1])); + final tentativeEncoding = contentParser.parse(); + final codec = codecName(tentativeEncoding); if (codec != null) { _encoding = codec; return false; @@ -220,7 +220,7 @@ class EncodingParser { return true; } - var c = _data._skipUntil(_isSpaceOrAngleBracket); + final c = _data._skipUntil(_isSpaceOrAngleBracket); if (c == '<') { // return to the first step in the overall "two step" algorithm // reprocessing the < byte @@ -247,8 +247,8 @@ class EncodingParser { return null; } // Step 3 - var attrName = []; - var attrValue = []; + final attrName = []; + final attrValue = []; // Step 4 attribute name while (true) { if (c == null) { @@ -282,7 +282,7 @@ class EncodingParser { // Step 10 if (c == "'" || c == '"') { // 10.1 - var quoteChar = c; + final quoteChar = c; while (true) { // 10.2 c = _data._next(); @@ -343,9 +343,9 @@ class ContentAttrParser { data._skipChars(); // Look for an encoding between matching quote marks if (data._currentByte == '"' || data._currentByte == "'") { - var quoteMark = data._currentByte; + final quoteMark = data._currentByte; data._position += 1; - var oldPosition = data._position; + final oldPosition = data._position; if (data._jumpTo(quoteMark)) { return data._slice(oldPosition, data._position); } else { @@ -353,7 +353,7 @@ class ContentAttrParser { } } else { // Unquoted value - var oldPosition = data._position; + final oldPosition = data._position; try { data._skipUntil(isWhitespace); return data._slice(oldPosition, data._position); diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 0b72da7e6..1a2384eaf 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -193,7 +193,7 @@ class HtmlInputStream { /// Report the encoding declared by the meta element. String detectEncodingMeta() { - var parser = EncodingParser(slice(_rawBytes, 0, numBytesMeta)); + final parser = EncodingParser(slice(_rawBytes, 0, numBytesMeta)); var encoding = parser.getEncoding(); if (const ['utf-16', 'utf-16-be', 'utf-16-le'].contains(encoding)) { @@ -239,7 +239,7 @@ class HtmlInputStream { /// Returns a string of characters from the stream up to but not /// including any character in 'characters' or EOF. String charsUntil(String characters, [bool opposite = false]) { - var start = _offset; + final start = _offset; String c; while ((c = peekChar()) != null && characters.contains(c) == opposite) { _offset += c.codeUnits.length; @@ -314,7 +314,7 @@ String codecName(String encoding) { '[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]'); if (encoding == null) return null; - var canonicalName = encoding.replaceAll(asciiPunctuation, '').toLowerCase(); + final canonicalName = encoding.replaceAll(asciiPunctuation, '').toLowerCase(); return encodings[canonicalName]; } @@ -322,7 +322,7 @@ String codecName(String encoding) { /// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is /// used in HTML to detect the UTF- bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { - var end = length != null ? offset + length : bytes.length; + final end = length != null ? offset + length : bytes.length; return (offset + 3) <= end && bytes[offset] == 0xEF && bytes[offset + 1] == 0xBB && diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 041c5d824..9d0985753 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -14,7 +14,7 @@ Element querySelector(Node node, String selector) => SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); List<Element> querySelectorAll(Node node, String selector) { - var results = <Element>[]; + final results = <Element>[]; SelectorEvaluator() .querySelectorAll(node, _parseSelectorList(selector), results); return results; @@ -22,8 +22,8 @@ List<Element> querySelectorAll(Node node, String selector) { // http://dev.w3.org/csswg/selectors-4/#grouping SelectorGroup _parseSelectorList(String selector) { - var errors = <Message>[]; - var group = css.parseSelectorGroup(selector, errors: errors); + final errors = <Message>[]; + final group = css.parseSelectorGroup(selector, errors: errors); if (group == null || errors.isNotEmpty) { throw FormatException("'$selector' is not a valid selector: $errors"); } @@ -42,7 +42,7 @@ class SelectorEvaluator extends Visitor { Element querySelector(Node root, SelectorGroup selector) { for (var element in root.nodes.whereType<Element>()) { if (matches(element, selector)) return element; - var result = querySelector(element, selector); + final result = querySelector(element, selector); if (result != null) return result; } return null; @@ -62,7 +62,7 @@ class SelectorEvaluator extends Visitor { @override bool visitSelector(Selector selector) { - var old = _element; + final old = _element; var result = true; // Note: evaluate selectors right-to-left as it's more efficient. @@ -212,10 +212,10 @@ class SelectorEvaluator extends Visitor { // http://dev.w3.org/csswg/selectors-4/#the-nth-child-pseudo case 'nth-child': // TODO(jmesserly): support An+B syntax too. - var exprs = selector.expression.expressions; + final exprs = selector.expression.expressions; if (exprs.length == 1 && exprs[0] is LiteralTerm) { final literal = exprs[0] as LiteralTerm; - var parent = _element.parentNode; + final parent = _element.parentNode; return parent != null && (literal.value as num) > 0 && parent.nodes.indexOf(_element) == literal.value; @@ -226,8 +226,8 @@ class SelectorEvaluator extends Visitor { case 'lang': // TODO(jmesserly): shouldn't need to get the raw text here, but csslib // gets confused by the "-" in the expression, such as in "es-AR". - var toMatch = selector.expression.span.text; - var lang = _getInheritedLanguage(_element); + final toMatch = selector.expression.span.text; + final lang = _getInheritedLanguage(_element); // TODO(jmesserly): implement wildcards in level 4 return lang != null && lang.startsWith(toMatch); } @@ -236,7 +236,7 @@ class SelectorEvaluator extends Visitor { static String _getInheritedLanguage(Node node) { while (node != null) { - var lang = node.attributes['lang']; + final lang = node.attributes['lang']; if (lang != null) return lang; node = node.parent; } @@ -276,12 +276,12 @@ class SelectorEvaluator extends Visitor { @override bool visitAttributeSelector(AttributeSelector selector) { // Match name first - var value = _element.attributes[selector.name.toLowerCase()]; + final value = _element.attributes[selector.name.toLowerCase()]; if (value == null) return false; if (selector.operatorKind == TokenKind.NO_MATCH) return true; - var select = '${selector.value}'; + final select = '${selector.value}'; switch (selector.operatorKind) { case TokenKind.EQUALS: return value == select; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 26b711501..7af964829 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -12,7 +12,7 @@ import 'utils.dart'; // TODO(jmesserly): we could use a better data structure here like a trie, if // we had it implemented in Dart. Map<String, List<String>> entitiesByFirstChar = (() { - var result = <String, List<String>>{}; + final result = <String, List<String>>{}; for (var k in entities.keys) { result.putIfAbsent(k[0], () => []).add(k); } @@ -110,7 +110,7 @@ class HtmlTokenizer implements Iterator<Token> { _attributeName.clear(); _attributeName.write(name); _attributeValue.clear(); - var attr = TagAttribute(); + final attr = TagAttribute(); _attributes.add(attr); if (attributeSpans) attr.start = stream.position - name.length; } @@ -154,7 +154,7 @@ class HtmlTokenizer implements Iterator<Token> { /// Adds a token to the queue. Sets the span if needed. void _addToken(Token token) { if (generateSpans && token.span == null) { - var offset = stream.position; + final offset = stream.position; token.span = stream.fileInfo.span(_lastOffset, offset); if (token is! ParseErrorToken) { _lastOffset = offset; @@ -174,7 +174,7 @@ class HtmlTokenizer implements Iterator<Token> { radix = 16; } - var charStack = []; + final charStack = []; // Consume all the characters that are in range while making sure we // don't hit an EOF. @@ -185,7 +185,7 @@ class HtmlTokenizer implements Iterator<Token> { } // Convert the set of characters consumed to an int. - var charAsInt = int.parse(charStack.join(), radix: radix); + final charAsInt = int.parse(charStack.join(), radix: radix); // Certain characters get replaced with others var char = replacementCharacters[charAsInt]; @@ -259,7 +259,7 @@ class HtmlTokenizer implements Iterator<Token> { // Initialise to the default output for when no entity is matched var output = '&'; - var charStack = [stream.char()]; + final charStack = [stream.char()]; if (isWhitespace(charStack[0]) || charStack[0] == '<' || charStack[0] == '&' || @@ -296,7 +296,7 @@ class HtmlTokenizer implements Iterator<Token> { var filteredEntityList = entitiesByFirstChar[charStack[0]] ?? const []; while (charStack.last != eof) { - var name = charStack.join(); + final name = charStack.join(); filteredEntityList = filteredEntityList.where((e) => e.startsWith(name)).toList(); @@ -315,7 +315,7 @@ class HtmlTokenizer implements Iterator<Token> { int entityLen; for (entityLen = charStack.length - 1; entityLen > 1; entityLen--) { - var possibleEntityName = charStack.sublist(0, entityLen).join(); + final possibleEntityName = charStack.sublist(0, entityLen).join(); if (entities.containsKey(possibleEntityName)) { entityName = possibleEntityName; break; @@ -323,7 +323,7 @@ class HtmlTokenizer implements Iterator<Token> { } if (entityName != null) { - var lastChar = entityName[entityName.length - 1]; + final lastChar = entityName[entityName.length - 1]; if (lastChar != ';') { _addToken(ParseErrorToken('named-entity-without-semicolon')); } @@ -366,7 +366,7 @@ class HtmlTokenizer implements Iterator<Token> { /// the state to "data" because that's what's needed after a token has been /// emitted. void emitCurrentToken() { - var token = currentToken; + final token = currentToken; // Add token to the queue to be yielded if (token is TagToken) { if (lowercaseElementName) { @@ -400,7 +400,7 @@ class HtmlTokenizer implements Iterator<Token> { // Below are the various tokenizer states worked out. bool dataState() { - var data = stream.char(); + final data = stream.char(); if (data == '&') { state = entityDataState; } else if (data == '<') { @@ -421,7 +421,7 @@ class HtmlTokenizer implements Iterator<Token> { // have already been appended to lastFourChars and will have broken // any <!-- or --> sequences } else { - var chars = stream.charsUntil('&<\u0000'); + final chars = stream.charsUntil('&<\u0000'); _addToken(CharactersToken('$data$chars')); } return true; @@ -434,7 +434,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rcdataState() { - var data = stream.char(); + final data = stream.char(); if (data == '&') { state = characterReferenceInRcdata; } else if (data == '<') { @@ -452,7 +452,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(SpaceCharactersToken( '$data${stream.charsUntil(spaceCharacters, true)}')); } else { - var chars = stream.charsUntil('&<'); + final chars = stream.charsUntil('&<'); _addToken(CharactersToken('$data$chars')); } return true; @@ -465,7 +465,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rawtextState() { - var data = stream.char(); + final data = stream.char(); if (data == '<') { state = rawtextLessThanSignState; } else if (data == '\u0000') { @@ -475,14 +475,14 @@ class HtmlTokenizer implements Iterator<Token> { // Tokenization ends. return false; } else { - var chars = stream.charsUntil('<\u0000'); + final chars = stream.charsUntil('<\u0000'); _addToken(CharactersToken('$data$chars')); } return true; } bool scriptDataState() { - var data = stream.char(); + final data = stream.char(); if (data == '<') { state = scriptDataLessThanSignState; } else if (data == '\u0000') { @@ -492,14 +492,14 @@ class HtmlTokenizer implements Iterator<Token> { // Tokenization ends. return false; } else { - var chars = stream.charsUntil('<\u0000'); + final chars = stream.charsUntil('<\u0000'); _addToken(CharactersToken('$data$chars')); } return true; } bool plaintextState() { - var data = stream.char(); + final data = stream.char(); if (data == eof) { // Tokenization ends. return false; @@ -513,7 +513,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool tagOpenState() { - var data = stream.char(); + final data = stream.char(); if (data == '!') { state = markupDeclarationOpenState; } else if (data == '/') { @@ -544,7 +544,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool closeTagOpenState() { - var data = stream.char(); + final data = stream.char(); if (isLetter(data)) { currentToken = EndTagToken(data); state = tagNameState; @@ -566,7 +566,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool tagNameState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = beforeAttributeNameState; } else if (data == '>') { @@ -588,7 +588,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rcdataLessThanSignState() { - var data = stream.char(); + final data = stream.char(); if (data == '/') { _buffer.clear(); state = rcdataEndTagOpenState; @@ -601,7 +601,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rcdataEndTagOpenState() { - var data = stream.char(); + final data = stream.char(); if (isLetter(data)) { _buffer.write(data); state = rcdataEndTagNameState; @@ -620,8 +620,8 @@ class HtmlTokenizer implements Iterator<Token> { } bool rcdataEndTagNameState() { - var appropriate = _tokenIsAppropriate(); - var data = stream.char(); + final appropriate = _tokenIsAppropriate(); + final data = stream.char(); if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; @@ -643,7 +643,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rawtextLessThanSignState() { - var data = stream.char(); + final data = stream.char(); if (data == '/') { _buffer.clear(); state = rawtextEndTagOpenState; @@ -656,7 +656,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool rawtextEndTagOpenState() { - var data = stream.char(); + final data = stream.char(); if (isLetter(data)) { _buffer.write(data); state = rawtextEndTagNameState; @@ -669,8 +669,8 @@ class HtmlTokenizer implements Iterator<Token> { } bool rawtextEndTagNameState() { - var appropriate = _tokenIsAppropriate(); - var data = stream.char(); + final appropriate = _tokenIsAppropriate(); + final data = stream.char(); if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; @@ -692,7 +692,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataLessThanSignState() { - var data = stream.char(); + final data = stream.char(); if (data == '/') { _buffer.clear(); state = scriptDataEndTagOpenState; @@ -708,7 +708,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEndTagOpenState() { - var data = stream.char(); + final data = stream.char(); if (isLetter(data)) { _buffer.write(data); state = scriptDataEndTagNameState; @@ -721,8 +721,8 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEndTagNameState() { - var appropriate = _tokenIsAppropriate(); - var data = stream.char(); + final appropriate = _tokenIsAppropriate(); + final data = stream.char(); if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; @@ -744,7 +744,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapeStartState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataEscapeStartDashState; @@ -756,7 +756,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapeStartDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataEscapedDashDashState; @@ -768,7 +768,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapedState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataEscapedDashState; @@ -780,14 +780,14 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { state = dataState; } else { - var chars = stream.charsUntil('<-\u0000'); + final chars = stream.charsUntil('<-\u0000'); _addToken(CharactersToken('$data$chars')); } return true; } bool scriptDataEscapedDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataEscapedDashDashState; @@ -807,7 +807,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapedDashDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); } else if (data == '<') { @@ -829,7 +829,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapedLessThanSignState() { - var data = stream.char(); + final data = stream.char(); if (data == '/') { _buffer.clear(); state = scriptDataEscapedEndTagOpenState; @@ -847,7 +847,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapedEndTagOpenState() { - var data = stream.char(); + final data = stream.char(); if (isLetter(data)) { _buffer.clear(); _buffer.write(data); @@ -861,8 +861,8 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataEscapedEndTagNameState() { - var appropriate = _tokenIsAppropriate(); - var data = stream.char(); + final appropriate = _tokenIsAppropriate(); + final data = stream.char(); if (isWhitespace(data) && appropriate) { currentToken = EndTagToken('$_buffer'); state = beforeAttributeNameState; @@ -884,7 +884,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataDoubleEscapeStartState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data) || data == '/' || data == '>') { _addToken(CharactersToken(data)); if ('$_buffer'.toLowerCase() == 'script') { @@ -903,7 +903,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataDoubleEscapedState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataDoubleEscapedDashState; @@ -923,7 +923,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataDoubleEscapedDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); state = scriptDataDoubleEscapedDashDashState; @@ -947,7 +947,7 @@ class HtmlTokenizer implements Iterator<Token> { // TODO(jmesserly): report bug in original code // (was "Dash" instead of "DashDash") bool scriptDataDoubleEscapedDashDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { _addToken(CharactersToken('-')); } else if (data == '<') { @@ -971,7 +971,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataDoubleEscapedLessThanSignState() { - var data = stream.char(); + final data = stream.char(); if (data == '/') { _addToken(CharactersToken('/')); _buffer.clear(); @@ -984,7 +984,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool scriptDataDoubleEscapeEndState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data) || data == '/' || data == '>') { _addToken(CharactersToken(data)); if ('$_buffer'.toLowerCase() == 'script') { @@ -1003,7 +1003,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool beforeAttributeNameState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); } else if (isLetter(data)) { @@ -1032,7 +1032,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool attributeNameState() { - var data = stream.char(); + final data = stream.char(); var leavingThisState = true; var emitToken = false; if (data == '=') { @@ -1092,7 +1092,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterAttributeNameState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); } else if (data == '=') { @@ -1123,7 +1123,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool beforeAttributeValueState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); } else if (data == '"') { @@ -1162,7 +1162,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool attributeValueDoubleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == '"') { _markAttributeValueEnd(-1); _markAttributeEnd(0); @@ -1184,7 +1184,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool attributeValueSingleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == "'") { _markAttributeValueEnd(-1); _markAttributeEnd(0); @@ -1206,7 +1206,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool attributeValueUnQuotedState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { _markAttributeValueEnd(-1); state = beforeAttributeNameState; @@ -1234,7 +1234,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterAttributeValueState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = beforeAttributeNameState; } else if (data == '>') { @@ -1254,7 +1254,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool selfClosingStartTagState() { - var data = stream.char(); + final data = stream.char(); if (data == '>') { currentTagToken.selfClosing = true; emitCurrentToken(); @@ -1286,7 +1286,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool markupDeclarationOpenState() { - var charStack = [stream.char()]; + final charStack = [stream.char()]; if (charStack.last == '-') { charStack.add(stream.char()); if (charStack.last == '-') { @@ -1297,7 +1297,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (charStack.last == 'd' || charStack.last == 'D') { var matched = true; for (var expected in const ['oO', 'cC', 'tT', 'yY', 'pP', 'eE']) { - var char = stream.char(); + final char = stream.char(); charStack.add(char); if (char == eof || !expected.contains(char)) { matched = false; @@ -1338,7 +1338,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentStartState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { state = commentStartDashState; } else if (data == '\u0000') { @@ -1360,7 +1360,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentStartDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { state = commentEndState; } else if (data == '\u0000') { @@ -1382,7 +1382,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { state = commentEndDashState; } else if (data == '\u0000') { @@ -1399,7 +1399,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentEndDashState() { - var data = stream.char(); + final data = stream.char(); if (data == '-') { state = commentEndState; } else if (data == '\u0000') { @@ -1418,7 +1418,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentEndState() { - var data = stream.char(); + final data = stream.char(); if (data == '>') { _addToken(currentToken); state = dataState; @@ -1448,7 +1448,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool commentEndBangState() { - var data = stream.char(); + final data = stream.char(); if (data == '>') { _addToken(currentToken); state = dataState; @@ -1471,7 +1471,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypeState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = beforeDoctypeNameState; } else if (data == eof) { @@ -1488,7 +1488,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool beforeDoctypeNameState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { return true; } else if (data == '>') { @@ -1513,7 +1513,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypeNameState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); state = afterDoctypeNameState; @@ -1594,7 +1594,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterDoctypePublicKeywordState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = beforeDoctypePublicIdentifierState; } else if (data == "'" || data == '"') { @@ -1614,7 +1614,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool beforeDoctypePublicIdentifierState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { return true; } else if (data == '"') { @@ -1642,7 +1642,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypePublicIdentifierDoubleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == '"') { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { @@ -1665,7 +1665,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypePublicIdentifierSingleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == "'") { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { @@ -1688,7 +1688,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterDoctypePublicIdentifierState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = betweenDoctypePublicAndSystemIdentifiersState; } else if (data == '>') { @@ -1716,7 +1716,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool betweenDoctypePublicAndSystemIdentifiersState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { return true; } else if (data == '>') { @@ -1742,7 +1742,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterDoctypeSystemKeywordState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { state = beforeDoctypeSystemIdentifierState; } else if (data == "'" || data == '"') { @@ -1762,7 +1762,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool beforeDoctypeSystemIdentifierState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { return true; } else if (data == '"') { @@ -1790,7 +1790,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypeSystemIdentifierDoubleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == '"') { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { @@ -1813,7 +1813,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool doctypeSystemIdentifierSingleQuotedState() { - var data = stream.char(); + final data = stream.char(); if (data == "'") { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { @@ -1836,7 +1836,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool afterDoctypeSystemIdentifierState() { - var data = stream.char(); + final data = stream.char(); if (isWhitespace(data)) { return true; } else if (data == '>') { @@ -1855,7 +1855,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool bogusDoctypeState() { - var data = stream.char(); + final data = stream.char(); if (data == '>') { _addToken(currentToken); state = dataState; @@ -1869,7 +1869,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool cdataSectionState() { - var data = <String>[]; + final data = <String>[]; var matchedEnd = 0; while (true) { var ch = stream.char(); diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index b60d4a746..a1f0da1ed 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -48,7 +48,7 @@ bool _mapEquals(Map a, Map b) { if (a.isEmpty) return true; for (var keyA in a.keys) { - var valB = b[keyA]; + final valB = b[keyA]; if (valB == null && !b.containsKey(keyA)) { return false; } @@ -104,7 +104,7 @@ class TreeBuilder { bool elementInScope(target, {String variant}) { //If we pass a node in we match that. if we pass a string //match any node with that name - var exactNode = target is Node; + final exactNode = target is Node; var listElements1 = scopingElements; var listElements2 = const []; @@ -189,13 +189,13 @@ class TreeBuilder { entry = activeFormattingElements[i]; // TODO(jmesserly): optimize this. No need to create a token. - var cloneToken = StartTagToken(entry.localName, + final cloneToken = StartTagToken(entry.localName, namespace: entry.namespaceUri, data: LinkedHashMap.from(entry.attributes)) ..span = entry.sourceSpan; // Step 9 - var element = insertElement(cloneToken); + final element = insertElement(cloneToken); // Step 10 activeFormattingElements[i] = element; @@ -231,13 +231,13 @@ class TreeBuilder { } void insertRoot(StartTagToken token) { - var element = createElement(token); + final element = createElement(token); openElements.add(element); document.nodes.add(element); } void insertDoctype(DoctypeToken token) { - var doctype = DocumentType(token.name, token.publicId, token.systemId) + final doctype = DocumentType(token.name, token.publicId, token.systemId) ..sourceSpan = token.span; document.nodes.add(doctype); } @@ -249,9 +249,9 @@ class TreeBuilder { /// Create an element but don't insert it anywhere Element createElement(StartTagToken token) { - var name = token.name; - var namespace = token.namespace ?? defaultNamespace; - var element = document.createElementNS(namespace, name) + final name = token.name; + final namespace = token.namespace ?? defaultNamespace; + final element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; return element; @@ -263,9 +263,9 @@ class TreeBuilder { } Element insertElementNormal(StartTagToken token) { - var name = token.name; - var namespace = token.namespace ?? defaultNamespace; - var element = document.createElementNS(namespace, name) + final name = token.name; + final namespace = token.namespace ?? defaultNamespace; + final element = document.createElementNS(namespace, name) ..attributes = token.data ..sourceSpan = token.span; openElements.last.nodes.add(element); @@ -275,13 +275,13 @@ class TreeBuilder { Element insertElementTable(StartTagToken token) { /// Create an element and insert it into the tree - var element = createElement(token); + final element = createElement(token); if (!tableInsertModeElements.contains(openElements.last.localName)) { return insertElementNormal(token); } else { // We should be in the InTable mode. This means we want to do // special magic element rearranging - var nodePos = getTableMisnestedNodePosition(); + final nodePos = getTableMisnestedNodePosition(); if (nodePos[1] == null) { // TODO(jmesserly): I don't think this is reachable. If insertFromTable // is true, there will be a <table> element open, and it always has a @@ -297,7 +297,7 @@ class TreeBuilder { /// Insert text data. void insertText(String data, FileSpan span) { - var parent = openElements.last; + final parent = openElements.last; if (!insertFromTable || insertFromTable && @@ -306,7 +306,7 @@ class TreeBuilder { } else { // We should be in the InTable mode. This means we want to do // special magic element rearranging - var nodePos = getTableMisnestedNodePosition(); + final nodePos = getTableMisnestedNodePosition(); _insertText(nodePos[0], data, span, nodePos[1] as Element); } } @@ -315,7 +315,7 @@ class TreeBuilder { /// start of node [refNode] or to the end of the node's text. static void _insertText(Node parent, String data, FileSpan span, [Element refNode]) { - var nodes = parent.nodes; + final nodes = parent.nodes; if (refNode == null) { if (nodes.isNotEmpty && nodes.last is Text) { final last = nodes.last as Text; @@ -329,7 +329,7 @@ class TreeBuilder { nodes.add(Text(data)..sourceSpan = span); } } else { - var index = nodes.indexOf(refNode); + final index = nodes.indexOf(refNode); if (index > 0 && nodes[index - 1] is Text) { final last = nodes[index - 1] as Text; last.appendData(data); @@ -370,7 +370,7 @@ class TreeBuilder { } void generateImpliedEndTags([String exclude]) { - var name = openElements.last.localName; + final name = openElements.last.localName; // XXX td, th and tr are not actually needed if (name != exclude && const ['dd', 'dt', 'li', 'option', 'optgroup', 'p', 'rp', 'rt'] @@ -388,7 +388,7 @@ class TreeBuilder { /// Return the final fragment. DocumentFragment getFragment() { //XXX assert innerHTML - var fragment = DocumentFragment(); + final fragment = DocumentFragment(); openElements[0].reparentChildren(fragment); return fragment; } diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 3eadc2e30..559f6c390 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -36,7 +36,7 @@ bool allWhitespace(String str) { String padWithZeros(String str, int size) { if (str.length == size) return str; - var result = StringBuffer(); + final result = StringBuffer(); size -= str.length; for (var i = 0; i < size; i++) { result.write('0'); @@ -53,8 +53,8 @@ String padWithZeros(String str, int size) { String formatStr(String format, Map data) { if (data == null) return format; data.forEach((key, value) { - var result = StringBuffer(); - var search = '%($key)'; + final result = StringBuffer(); + final search = '%($key)'; int last = 0, match; while ((match = format.indexOf(search, last)) >= 0) { result.write(format.substring(last, match)); @@ -75,11 +75,11 @@ String formatStr(String format, Map data) { result.write(value); break; case 'd': - var number = value.toString(); + final number = value.toString(); result.write(padWithZeros(number, numberSize)); break; case 'x': - var number = (value as int).toRadixString(16); + final number = (value as int).toRadixString(16); result.write(padWithZeros(number, numberSize)); break; default: diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 078c3c795..f9a5cacb7 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -24,8 +24,8 @@ void main() { '<div id=Foo>'); test('getElementById', () { - var foo = doc.body.nodes[0]; - var fooVar = foo.nodes[2]; + final foo = doc.body.nodes[0]; + final fooVar = foo.nodes[2]; expect((foo as Element).id, 'foo'); expect((fooVar as Element).id, 'Foo'); expect(doc.getElementById('foo'), foo); @@ -33,9 +33,9 @@ void main() { }); test('getElementsByClassName', () { - var foo = doc.body.nodes[0]; - var barBaz = foo.nodes[0]; - var quxBaz = foo.nodes[1]; + final foo = doc.body.nodes[0]; + final barBaz = foo.nodes[0]; + final quxBaz = foo.nodes[1]; expect((barBaz as Element).className, ' bar baz'); expect((quxBaz as Element).className, 'qux baz '); expect(doc.getElementsByClassName('baz'), [barBaz, quxBaz]); @@ -45,17 +45,17 @@ void main() { }); test('getElementsByTagName', () { - var foo = doc.body.nodes[0]; - var barBaz = foo.nodes[0]; - var quxBaz = foo.nodes[1]; - var fooVar = foo.nodes[2]; + final foo = doc.body.nodes[0]; + final barBaz = foo.nodes[0]; + final quxBaz = foo.nodes[1]; + final fooVar = foo.nodes[2]; expect(doc.getElementsByTagName('div'), [foo, barBaz, quxBaz, fooVar]); }); }); group('fragments are flattened', () { test('add', () { - var doc = parse('<body>'); + final doc = parse('<body>'); doc.body.nodes.add(parseFragment('<x-foo>')); expect((doc.body.nodes[0] as Element).localName, 'x-foo'); doc.body.nodes.add(parseFragment('<x-bar>')); @@ -63,7 +63,7 @@ void main() { }); test('addLast', () { - var doc = parse('<body>'); + final doc = parse('<body>'); doc.body.nodes.addLast(parseFragment('<x-foo>')); expect((doc.body.nodes[0] as Element).localName, 'x-foo'); doc.body.nodes.addLast(parseFragment('<x-bar>')); @@ -71,7 +71,7 @@ void main() { }); test('addAll', () { - var doc = parse('<body><x-a></x-a>'); + final doc = parse('<body><x-a></x-a>'); doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]); expect((doc.body.nodes[0] as Element).localName, 'x-a'); expect((doc.body.nodes[1] as Element).localName, 'x-b'); @@ -177,8 +177,8 @@ void main() { }); test('replaceWith', () { - var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); - var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); + final fragment = parseFragment('<y-b></y-b><y-c></y-c>'); + final doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); doc.body.nodes[1].replaceWith(fragment); expect((doc.body.nodes[0] as Element).localName, 'x-a'); expect((doc.body.nodes[1] as Element).localName, 'y-b'); diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 3ed00318a..f59df1b61 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -12,29 +12,29 @@ import 'package:test/test.dart'; void main() { _testElementSpans(); test('doctype is cloneable', () { - var doc = parse('<!doctype HTML>'); + final doc = parse('<!doctype HTML>'); final doctype = doc.nodes[0] as DocumentType; expect(doctype.clone(false).toString(), '<!DOCTYPE html>'); }); test('line counter', () { // http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 - var doc = parse('<pre>\nx\n&gt;\n</pre>'); + final doc = parse('<pre>\nx\n&gt;\n</pre>'); expect(doc.body.innerHtml, '<pre>x\n&gt;\n</pre>'); }); test('namespace html elements on', () { - var doc = HtmlParser('', tree: TreeBuilder(true)).parse(); + final doc = HtmlParser('', tree: TreeBuilder(true)).parse(); expect((doc.nodes[0] as Element).namespaceUri, Namespaces.html); }); test('namespace html elements off', () { - var doc = HtmlParser('', tree: TreeBuilder(false)).parse(); + final doc = HtmlParser('', tree: TreeBuilder(false)).parse(); expect((doc.nodes[0] as Element).namespaceUri, null); }); test('parse error spans - full', () { - var parser = HtmlParser(''' + final parser = HtmlParser(''' <!DOCTYPE html> <html> <body> @@ -42,10 +42,10 @@ void main() { </body> </html> ''', generateSpans: true, sourceUrl: 'ParseError'); - var doc = parser.parse(); + final doc = parser.parse(); expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); - var error = parser.errors[0]; + final error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); // Note: these values are 0-based, but the printed format is 1-based. @@ -64,7 +64,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('parse error spans - minimal', () { - var parser = HtmlParser(''' + final parser = HtmlParser(''' <!DOCTYPE html> <html> <body> @@ -72,10 +72,10 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. </body> </html> '''); - var doc = parser.parse(); + final doc = parser.parse(); expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); - var error = parser.errors[0]; + final error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); expect(error.span.start.line, 3); // Note: error position is at the end, not the beginning @@ -83,9 +83,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('text spans should have the correct length', () { - var textContent = '\n hello {{name}}'; - var html = '<body><div>$textContent</div>'; - var doc = parse(html, generateSpans: true); + final textContent = '\n hello {{name}}'; + final html = '<body><div>$textContent</div>'; + final doc = parse(html, generateSpans: true); final text = doc.body.nodes[0].nodes[0] as Text; expect(text, const TypeMatcher<Text>()); expect(text.data, textContent); @@ -94,45 +94,45 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('attribute spans', () { - var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('element'); + final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('element'); expect(elem.sourceSpan.start.offset, 0); expect(elem.sourceSpan.end.offset, text.length); expect(elem.sourceSpan.text, text); expect(elem.attributeSpans['quux'], null); - var span = elem.attributeSpans['extends']; + final span = elem.attributeSpans['extends']; expect(span.start.offset, text.indexOf('extends')); expect(span.text, 'extends="x-bar"'); }); test('attribute value spans', () { - var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('element'); + final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('element'); expect(elem.attributeValueSpans['quux'], null); - var span = elem.attributeValueSpans['extends']; + final span = elem.attributeValueSpans['extends']; expect(span.start.offset, text.indexOf('x-bar')); expect(span.text, 'x-bar'); }); test('attribute spans if no attributes', () { - var text = '<element>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('element'); + final text = '<element>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('element'); expect(elem.attributeSpans['quux'], null); expect(elem.attributeValueSpans['quux'], null); }); test('attribute spans if no attribute value', () { - var text = '<foo template>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('foo'); + final text = '<foo template>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('foo'); expect( elem.attributeSpans['template'].start.offset, text.indexOf('template')); @@ -140,9 +140,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('attribute spans null if code parsed without spans', () { - var text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; - var doc = parse(text); - var elem = doc.querySelector('element'); + final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; + final doc = parse(text); + final elem = doc.querySelector('element'); expect(elem.sourceSpan, null); expect(elem.attributeSpans['quux'], null); expect(elem.attributeSpans['extends'], null); @@ -160,8 +160,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('empty document has html, body, and head', () { - var doc = parse(''); - var html = '<html><head></head><body></body></html>'; + final doc = parse(''); + final html = '<html><head></head><body></body></html>'; expect(doc.outerHtml, html); expect(doc.documentElement.outerHtml, html); expect(doc.head.outerHtml, '<head></head>'); @@ -169,7 +169,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('strange table case', () { - var doc = parse('<table><tbody><foo>').body; + final doc = parse('<table><tbody><foo>').body; expect(doc.innerHtml, '<foo></foo><table><tbody></tbody></table>'); }); @@ -177,7 +177,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('attribute order', () { // Note: the spec only requires a stable order. // However, we preserve the input order via LinkedHashMap - var body = parse('<foo d=1 a=2 c=3 b=4>').body; + final body = parse('<foo d=1 a=2 c=3 b=4>').body; expect(body.innerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); expect(body.querySelector('foo').attributes.remove('a'), '2'); expect(body.innerHtml, '<foo d="1" c="3" b="4"></foo>'); @@ -203,9 +203,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('Escaping non-breaking space', () { - var text = '<span>foO\u00A0bar</span>'; + final text = '<span>foO\u00A0bar</span>'; expect(text.codeUnitAt(text.indexOf('O') + 1), 0xA0); - var e = parseFragment(text).firstChild as Element; + final e = parseFragment(text).firstChild as Element; expect(e.outerHtml, '<span>foO&nbsp;bar</span>'); }); @@ -222,15 +222,15 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('xml namespaces', () { // Note: this is a nonsensical example, but it triggers the behavior // we're looking for with attribute names in foreign content. - var doc = parse(''' + final doc = parse(''' <body> <svg> <desc xlink:type="simple" xlink:href="http://example.com/logo.png" xlink:show="new"></desc> '''); - var n = doc.querySelector('desc'); - var keys = n.attributes.keys.toList(); + final n = doc.querySelector('desc'); + final keys = n.attributes.keys.toList(); expect(keys[0], const TypeMatcher<AttributeName>()); expect(keys[0].prefix, 'xlink'); expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); @@ -244,8 +244,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('error printing without spans', () { - var parser = HtmlParser('foo'); - var doc = parser.parse(); + final parser = HtmlParser('foo'); + final doc = parser.parse(); expect(doc.body.innerHtml, 'foo'); expect(parser.errors.length, 1); expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars'); @@ -262,9 +262,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('Element.text', () { - var doc = parseFragment('<div>foo<div>bar</div>baz</div>'); - var e = doc.firstChild; - var text = e.firstChild; + final doc = parseFragment('<div>foo<div>bar</div>baz</div>'); + final e = doc.firstChild; + final text = e.firstChild; expect((text as Text).data, 'foo'); expect(e.text, 'foobarbaz'); @@ -276,8 +276,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('Text.text', () { - var doc = parseFragment('<div>foo<div>bar</div>baz</div>'); - var e = doc.firstChild; + final doc = parseFragment('<div>foo<div>bar</div>baz</div>'); + final e = doc.firstChild; final text = e.firstChild as Text; expect(text.data, 'foo'); expect(text.text, 'foo'); @@ -289,9 +289,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('Comment.text', () { - var doc = parseFragment('<div><!--foo-->bar</div>'); - var e = doc.firstChild; - var c = e.firstChild; + final doc = parseFragment('<div><!--foo-->bar</div>'); + final e = doc.firstChild; + final c = e.firstChild; expect((c as Comment).data, 'foo'); expect(c.text, 'foo'); expect(e.text, 'bar'); @@ -303,16 +303,16 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. }); test('foreignObject end tag', () { - var p = HtmlParser(''' + final p = HtmlParser(''' <svg width="100%" height="100%" xmlns="http://www.w3.org/2000/svg" version="1.1"> <foreignObject width="320px" height="200px"> <x-flow></x-flow> </foreignObject> </svg>'''); - var doc = p.parseFragment(); + final doc = p.parseFragment(); expect(p.errors, isEmpty); - var svg = doc.querySelector('svg'); + final svg = doc.querySelector('svg'); expect(svg.children[0].children[0].localName, 'x-flow'); }); @@ -359,129 +359,129 @@ void _testElementSpans() { group('element spans', () { test('html and body', () { - var text = '<html><body>123</body></html>'; - var doc = parse(text, generateSpans: true); + final text = '<html><body>123</body></html>'; + final doc = parse(text, generateSpans: true); { - var elem = doc.querySelector('html'); + final elem = doc.querySelector('html'); assertSpan(elem.sourceSpan, 0, 6, '<html>'); assertSpan(elem.endSourceSpan, 22, 29, '</html>'); } { - var elem = doc.querySelector('body'); + final elem = doc.querySelector('body'); assertSpan(elem.sourceSpan, 6, 12, '<body>'); assertSpan(elem.endSourceSpan, 15, 22, '</body>'); } }); test('normal', () { - var text = '<div><element><span></span></element></div>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('element'); + final text = '<div><element><span></span></element></div>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('element'); assertSpan(elem.sourceSpan, 5, 14, '<element>'); assertSpan(elem.endSourceSpan, 27, 37, '</element>'); }); test('block', () { - var text = '<div>123</div>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('div'); + final text = '<div>123</div>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('div'); assertSpan(elem.sourceSpan, 0, 5, '<div>'); assertSpan(elem.endSourceSpan, 8, 14, '</div>'); }); test('form', () { - var text = '<form>123</form>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('form'); + final text = '<form>123</form>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('form'); assertSpan(elem.sourceSpan, 0, 6, '<form>'); assertSpan(elem.endSourceSpan, 9, 16, '</form>'); }); test('p explicit end', () { - var text = '<p>123</p>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('p'); + final text = '<p>123</p>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('p'); assertSpan(elem.sourceSpan, 0, 3, '<p>'); assertSpan(elem.endSourceSpan, 6, 10, '</p>'); }); test('p implicit end', () { - var text = '<div><p>123<p>456</div>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('p'); + final text = '<div><p>123<p>456</div>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('p'); assertSpan(elem.sourceSpan, 5, 8, '<p>'); expect(elem.endSourceSpan, isNull); }); test('li', () { - var text = '<li>123</li>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('li'); + final text = '<li>123</li>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('li'); assertSpan(elem.sourceSpan, 0, 4, '<li>'); assertSpan(elem.endSourceSpan, 7, 12, '</li>'); }); test('heading', () { - var text = '<h1>123</h1>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('h1'); + final text = '<h1>123</h1>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('h1'); assertSpan(elem.sourceSpan, 0, 4, '<h1>'); assertSpan(elem.endSourceSpan, 7, 12, '</h1>'); }); test('formatting', () { - var text = '<b>123</b>'; - var doc = parse(text, generateSpans: true); - var elem = doc.querySelector('b'); + final text = '<b>123</b>'; + final doc = parse(text, generateSpans: true); + final elem = doc.querySelector('b'); assertSpan(elem.sourceSpan, 0, 3, '<b>'); assertSpan(elem.endSourceSpan, 6, 10, '</b>'); }); test('table tbody', () { - var text = '<table><tbody> </tbody></table>'; - var doc = parse(text, generateSpans: true); + final text = '<table><tbody> </tbody></table>'; + final doc = parse(text, generateSpans: true); { - var elem = doc.querySelector('tbody'); + final elem = doc.querySelector('tbody'); assertSpan(elem.sourceSpan, 7, 14, '<tbody>'); assertSpan(elem.endSourceSpan, 16, 24, '</tbody>'); } }); test('table tr td', () { - var text = '<table><tr><td>123</td></tr></table>'; - var doc = parse(text, generateSpans: true); + final text = '<table><tr><td>123</td></tr></table>'; + final doc = parse(text, generateSpans: true); { - var elem = doc.querySelector('table'); + final elem = doc.querySelector('table'); assertSpan(elem.sourceSpan, 0, 7, '<table>'); assertSpan(elem.endSourceSpan, 28, 36, '</table>'); } { - var elem = doc.querySelector('tr'); + final elem = doc.querySelector('tr'); assertSpan(elem.sourceSpan, 7, 11, '<tr>'); assertSpan(elem.endSourceSpan, 23, 28, '</tr>'); } { - var elem = doc.querySelector('td'); + final elem = doc.querySelector('td'); assertSpan(elem.sourceSpan, 11, 15, '<td>'); assertSpan(elem.endSourceSpan, 18, 23, '</td>'); } }); test('select optgroup option', () { - var text = '<select><optgroup><option>123</option></optgroup></select>'; - var doc = parse(text, generateSpans: true); + final text = '<select><optgroup><option>123</option></optgroup></select>'; + final doc = parse(text, generateSpans: true); { - var elem = doc.querySelector('select'); + final elem = doc.querySelector('select'); assertSpan(elem.sourceSpan, 0, 8, '<select>'); assertSpan(elem.endSourceSpan, 49, 58, '</select>'); } { - var elem = doc.querySelector('optgroup'); + final elem = doc.querySelector('optgroup'); assertSpan(elem.sourceSpan, 8, 18, '<optgroup>'); assertSpan(elem.endSourceSpan, 38, 49, '</optgroup>'); } { - var elem = doc.querySelector('option'); + final elem = doc.querySelector('option'); assertSpan(elem.sourceSpan, 18, 26, '<option>'); assertSpan(elem.endSourceSpan, 29, 38, '</option>'); } diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 232a50f01..71730452a 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -20,9 +20,9 @@ String namespaceHtml(String expected) { // final namespaceExpected = new RegExp(@"^(\s*)<(\S+)>", multiLine: true); // return expected.replaceAll(namespaceExpected, @"$1<html $2>"); final namespaceExpected = RegExp(r'^(\|\s*)<(\S+)>'); - var lines = expected.split('\n'); + final lines = expected.split('\n'); for (var i = 0; i < lines.length; i++) { - var match = namespaceExpected.firstMatch(lines[i]); + final match = namespaceExpected.firstMatch(lines[i]); if (match != null) { lines[i] = '${match[1]}<html ${match[2]}>'; } @@ -40,8 +40,8 @@ void runParserTest( bool namespaceHTMLElements) { // XXX - move this out into the setup function // concatenate all consecutive character tokens into a single token - var builder = treeCtor(namespaceHTMLElements); - var parser = HtmlParser(input, tree: builder); + final builder = treeCtor(namespaceHTMLElements); + final parser = HtmlParser(input, tree: builder); Node document; if (innerHTML != null) { @@ -50,7 +50,7 @@ void runParserTest( document = parser.parse(); } - var output = testSerializer(document); + final output = testSerializer(document); if (namespaceHTMLElements) { expected = namespaceHtml(expected); @@ -73,16 +73,16 @@ void main() { for (var path in getDataFiles('tree-construction')) { if (!path.endsWith('.dat')) continue; - var tests = TestData(path, 'data'); - var testName = pathos.basenameWithoutExtension(path); + final tests = TestData(path, 'data'); + final testName = pathos.basenameWithoutExtension(path); group(testName, () { for (var testData in tests) { - var input = testData['data']; + final input = testData['data']; final errorString = testData['errors']; final errors = errorString?.split('\n'); - var innerHTML = testData['document-fragment']; - var expected = testData['document']; + final innerHTML = testData['document-fragment']; + final expected = testData['document']; for (var treeCtor in treeTypes.values) { for (var namespaceHTMLElements in const [false, true]) { @@ -100,7 +100,7 @@ void main() { /// Extract the name for the test based on the test input data. dynamic _nameFor(String input) { // Using jsonDecode to unescape other unicode characters - var escapeQuote = input + final escapeQuote = input .replaceAll(RegExp('\\\\.'), '_') .replaceAll(RegExp('\u0000'), '_') .replaceAll('"', '\\"') diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index d5defb1d8..02d513b4a 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -18,7 +18,7 @@ import 'level1_lib.dart'; import 'selectors.dart'; Document getTestContentDocument() { - var testPath = p.join(testDir, 'selectors', 'level1-content.html'); + final testPath = p.join(testDir, 'selectors', 'level1-content.html'); return parse(File(testPath).readAsStringSync()); } @@ -64,12 +64,12 @@ void main() { //doc = frame.contentDocument; // Document Node tests doc = getTestContentDocument(); - var element = doc.getElementById('root'); // In-document Element Node tests + final element = doc.getElementById('root'); // In-document Element Node tests //Setup the namespace tests setupSpecialElements(element); - var outOfScope = element + final outOfScope = element .clone(true); // Append this to the body before running the in-document // Element tests, but after running the Document tests. This // tests that no elements that are not descendants of element @@ -81,9 +81,9 @@ void main() { ''; // that none of these elements ever match. }); - var detached = element.clone(true); // Detached Element Node tests + final detached = element.clone(true); // Detached Element Node tests - var fragment = doc.createDocumentFragment(); // Fragment Node tests + final fragment = doc.createDocumentFragment(); // Fragment Node tests fragment.append(element.clone(true)); // Setup Tests @@ -118,9 +118,7 @@ void main() { doc.body.append(outOfScope); // Append before in-document Element tests. // None of these elements should match }); - tearDown(() { - outOfScope.remove(); - }); + tearDown(outOfScope.remove); runValidSelectorTest( 'In-document Element', element, validSelectors, testType, docType); }); diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 721eca6ad..388ae0027 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -23,8 +23,8 @@ void setupSpecialElements(parent) { parent.append(doc.createElement('undefined')); // Setup namespace tests - var anyNS = doc.createElement('div'); - var noNS = doc.createElement('div'); + final anyNS = doc.createElement('div'); + final noNS = doc.createElement('div'); anyNS.id = 'any-namespace'; noNS.id = 'no-namespace'; @@ -71,17 +71,17 @@ void setupSpecialElements(parent) { */ void interfaceCheck(String type, obj) { runTest(() { - var q = obj.querySelector is Function; + final q = obj.querySelector is Function; assertTrue(q, type + ' supports querySelector.'); }, type + ' supports querySelector'); runTest(() { - var qa = obj.querySelectorAll is Function; + final qa = obj.querySelectorAll is Function; assertTrue(qa, type + ' supports querySelectorAll.'); }, type + ' supports querySelectorAll'); runTest(() { - var list = obj.querySelectorAll('div'); + final list = obj.querySelectorAll('div'); // TODO(jmesserly): testing List<Element> for now. It should return an // ElementList which has extra properties. Needed for dart:html compat. assertTrue(list is List<Element>, @@ -100,7 +100,7 @@ void verifyStaticList(String type, root) { pre = root.querySelectorAll('div'); preLength = pre.length; - var div = doc.createElement('div'); + final div = doc.createElement('div'); (root is Document ? root.body : root).append(div); assertEquals( @@ -142,7 +142,7 @@ void runSpecialSelectorTests(String type, root) { runTest(() { // 4 - var elm = root.querySelector('null'); + final elm = root.querySelector('null'); assertNotEquals(elm, null, 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. assertEquals( @@ -151,7 +151,7 @@ void runSpecialSelectorTests(String type, root) { runTest(() { // 5 - var elm = root.querySelector('undefined'); + final elm = root.querySelector('undefined'); assertNotEquals(elm, 'undefined', 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. assertEquals(elm.localName.toUpperCase(), 'UNDEFINED', @@ -167,7 +167,7 @@ void runSpecialSelectorTests(String type, root) { runTest(() { // 7 - var result = root.querySelectorAll('*'); + final result = root.querySelectorAll('*'); var i = 0; traverse(root as Node, (elem) { if (!identical(elem, root)) { @@ -211,11 +211,11 @@ void runValidSelectorTest(String type, root, } for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s['name'] as String; - var skip = _getSkip(n); - var q = s['selector'] as String; - var e = s['expect'] as List; + final s = selectors[i]; + final n = s['name'] as String; + final skip = _getSkip(n); + final q = s['selector'] as String; + final e = s['expect'] as List; if ((s['exclude'] is! List || (s['exclude'].indexOf(nodeType) == -1 && @@ -268,9 +268,9 @@ void runValidSelectorTest(String type, root, */ void runInvalidSelectorTest(String type, root, List selectors) { for (var i = 0; i < selectors.length; i++) { - var s = selectors[i]; - var n = s['name'] as String; - var q = s['selector'] as String; + final s = selectors[i]; + final n = s['name'] as String; + final q = s['selector'] as String; // Dart note: FormatException seems a reasonable mapping of SyntaxError runTest(() { diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 01995350c..34fedb2ca 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -23,7 +23,7 @@ final testDir = p.join(p.dirname(p.fromUri(Platform.packageConfig)), 'test'); final testDataDir = p.join(testDir, 'data'); Iterable<String> getDataFiles(String subdirectory) { - var dir = Directory(p.join(testDataDir, subdirectory)); + final dir = Directory(p.join(testDataDir, subdirectory)); return dir.listSync().whereType<File>().map((f) => f.path); } @@ -45,14 +45,14 @@ class TestData extends IterableBase<Map<String, String>> { List<Map<String, String>> _getData() { var data = <String, String>{}; String key; - var result = <Map<String, String>>[]; - var lines = _text.split('\n'); + final result = <Map<String, String>>[]; + final lines = _text.split('\n'); // Remove trailing newline to match Python if (lines.last == '') { lines.removeLast(); } for (var line in lines) { - var heading = sectionHeading(line); + final heading = sectionHeading(line); if (heading != null) { if (data.isNotEmpty && heading == newTestHeading) { // Remove trailing newline @@ -111,7 +111,7 @@ class TestSerializer extends TreeVisitor { set indent(int value) { if (_indent == value) return; - var arr = List<int>(value); + final arr = List<int>(value); for (var i = 0; i < value; i++) { arr[i] = 32; } @@ -161,14 +161,14 @@ class TestSerializer extends TreeVisitor { _str.write(node); if (node.attributes.isNotEmpty) { indent += 2; - var keys = node.attributes.keys.toList(); + final keys = node.attributes.keys.toList(); keys.sort((x, y) { if (x is String) return x.compareTo(y as String); if (x is AttributeName) return x.compareTo(y as AttributeName); throw StateError('Cannot sort'); }); for (var key in keys) { - var v = node.attributes[key]; + final v = node.attributes[key]; if (key is AttributeName) { final attr = key as AttributeName; key = '${attr.prefix} ${attr.name}'; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 41ae4d551..e5a05e9a2 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -27,14 +27,14 @@ class TokenizerTestParser { List parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. - var bytes = utf8.encode(str); - var tokenizer = + final bytes = utf8.encode(str); + final tokenizer = HtmlTokenizer(bytes, encoding: 'utf-8', generateSpans: _generateSpans); outputTokens = []; // Note: we can't get a closure of the state method. However, we can // create a new closure to invoke it via mirrors. - var mtok = reflect(tokenizer); + final mtok = reflect(tokenizer); tokenizer.state = () => mtok.invoke(Symbol(_state), const []).reflectee as bool; @@ -43,7 +43,7 @@ class TokenizerTestParser { } while (tokenizer.moveNext()) { - var token = tokenizer.current; + final token = tokenizer.current; switch (token.kind) { case TokenKind.characters: processCharacters(token as CharactersToken); @@ -117,7 +117,7 @@ class TokenizerTestParser { } List concatenateCharacterTokens(List tokens) { - var outputTokens = []; + final outputTokens = []; for (var token in tokens) { if (token.indexOf('ParseError') == -1 && token[0] == 'Character') { if (outputTokens.isNotEmpty && @@ -137,7 +137,7 @@ List concatenateCharacterTokens(List tokens) { List normalizeTokens(List tokens) { // TODO: convert tests to reflect arrays for (var i = 0; i < tokens.length; i++) { - var token = tokens[i]; + final token = tokens[i]; if (token[0] == 'ParseError') { tokens[i] = token[0]; } @@ -175,13 +175,15 @@ void expectTokensMatch( expect(receivedTokens, equals(expectedTokens), reason: message); } else { // Sort the tokens into two groups; non-parse errors and parse errors - var expectedNonErrors = expectedTokens.where((t) => t != 'ParseError'); - var receivedNonErrors = receivedTokens.where((t) => t != 'ParseError'); + final expectedNonErrors = expectedTokens.where((t) => t != 'ParseError'); + final receivedNonErrors = receivedTokens.where((t) => t != 'ParseError'); expect(receivedNonErrors, equals(expectedNonErrors), reason: message); if (!ignoreErrors) { - var expectedParseErrors = expectedTokens.where((t) => t == 'ParseError'); - var receivedParseErrors = receivedTokens.where((t) => t == 'ParseError'); + final expectedParseErrors = + expectedTokens.where((t) => t == 'ParseError'); + final receivedParseErrors = + receivedTokens.where((t) => t == 'ParseError'); expect(receivedParseErrors, equals(expectedParseErrors), reason: message); } } @@ -194,18 +196,18 @@ void runTokenizerTest(Map<String, dynamic> testInfo) { testInfo = unescape(testInfo); } - var expected = concatenateCharacterTokens(testInfo['output'] as List); + final expected = concatenateCharacterTokens(testInfo['output'] as List); if (!testInfo.containsKey('lastStartTag')) { testInfo['lastStartTag'] = null; } - var parser = TokenizerTestParser( + final parser = TokenizerTestParser( testInfo['initialState'] as String, testInfo['lastStartTag'] as String, testInfo['generateSpans'] as bool /*?*/ ?? false); var tokens = parser.parse(testInfo['input'] as String); tokens = concatenateCharacterTokens(tokens); - var received = normalizeTokens(tokens); - var errorMsg = [ + final received = normalizeTokens(tokens); + final errorMsg = [ '\n\nInitial state:', testInfo['initialState'], '\nInput:', @@ -215,7 +217,7 @@ void runTokenizerTest(Map<String, dynamic> testInfo) { '\nreceived:', tokens ].map((s) => '$s').join('\n'); - var ignoreErrorOrder = testInfo['ignoreErrorOrder'] as bool /*?*/ ?? false; + final ignoreErrorOrder = testInfo['ignoreErrorOrder'] as bool /*?*/ ?? false; expectTokensMatch(expected, received, ignoreErrorOrder, true, errorMsg); } @@ -234,8 +236,8 @@ Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { token[1] = decode(token[1]); if ((token as List).length > 2) { for (var pair in token[2]) { - var key = pair[0]; - var value = pair[1]; + final key = pair[0]; + final value = pair[1]; token[2].remove(key); token[2][decode(key)] = decode(value); } @@ -247,7 +249,7 @@ Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { String camelCase(String s) { s = s.toLowerCase(); - var result = StringBuffer(); + final result = StringBuffer(); for (var match in RegExp(r'\W+(\w)(\w+)').allMatches(s)) { if (result.length == 0) result.write(s.substring(0, match.start)); result.write(match.group(1).toUpperCase()); @@ -260,10 +262,10 @@ void main() { for (var path in getDataFiles('tokenizer')) { if (!path.endsWith('.test')) continue; - var text = File(path).readAsStringSync(); - var tests = jsonDecode(text); - var testName = pathos.basenameWithoutExtension(path); - var testList = tests['tests'] as List; + final text = File(path).readAsStringSync(); + final tests = jsonDecode(text); + final testName = pathos.basenameWithoutExtension(path); + final testList = tests['tests'] as List; if (testList == null) continue; group(testName, () { From 69f402c715816ee828c446e2cc3966e570636562 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 7 Oct 2020 13:25:41 -0700 Subject: [PATCH 117/212] Rewrite asciiUpper2Lower as an extension (dart-lang/html#132) - Switch to an extension method which will work nicer with `?.` instead of needing to handle a null argument and has nicer looking usage. - Rename to `toAsciiLowerCase` for consistency with the similar method in the SDK. - Use `Iterable.map` to avoid needing to create a fixed size list which will not work well with the null safety migration. This method is an internal detail and this is not breaking. --- pkgs/html/.travis.yml | 4 ++-- pkgs/html/lib/parser.dart | 17 ++++++----------- pkgs/html/lib/src/constants.dart | 22 +++++++++------------- pkgs/html/lib/src/tokenizer.dart | 10 +++++----- pkgs/html/pubspec.yaml | 2 +- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 3f5bcfbf6..497fe6887 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -2,7 +2,7 @@ language: dart dart: - dev - - 2.3.0 + - 2.8.1 dart_task: - test: -p vm @@ -15,7 +15,7 @@ matrix: - dart: dev dart_task: dartanalyzer: --fatal-warnings --fatal-infos . - - dart: 2.3.0 + - dart: 2.8.1 dart_task: dartanalyzer: --fatal-warnings . diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 5cfd53de5..ac3d304d8 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -260,8 +260,7 @@ class HtmlParser { bool isHTMLIntegrationPoint(Element element) { if (element.localName == 'annotation-xml' && element.namespaceUri == Namespaces.mathml) { - var enc = element.attributes['encoding']; - if (enc != null) enc = asciiUpper2Lower(enc); + final enc = element.attributes['encoding']?.toAsciiLowerCase(); return enc == 'text/html' || enc == 'application/xhtml+xml'; } else { return htmlIntegrationPointElements @@ -683,7 +682,7 @@ class InitialPhase extends Phase { @override Token processDoctype(DoctypeToken token) { final name = token.name; - var publicId = token.publicId; + var publicId = token.publicId?.toAsciiLowerCase(); final systemId = token.systemId; final correct = token.correct; @@ -697,10 +696,6 @@ class InitialPhase extends Phase { tree.insertDoctype(token); - if (publicId != '') { - publicId = asciiUpper2Lower(publicId); - } - if (!correct || token.name != 'html' || startsWithAny(publicId, const [ @@ -1783,7 +1778,7 @@ class InBodyPhase extends Phase { void startTagInput(StartTagToken token) { final savedFramesetOK = parser.framesetOK; startTagVoidFormatting(token); - if (asciiUpper2Lower(token.data['type']) == 'hidden') { + if (token.data['type']?.toAsciiLowerCase() == 'hidden') { //input type=hidden doesn't change framesetOK parser.framesetOK = savedFramesetOK; } @@ -2486,7 +2481,7 @@ class InTablePhase extends Phase { } void startTagInput(StartTagToken token) { - if (asciiUpper2Lower(token.data['type']) == 'hidden') { + if (token.data['type']?.toAsciiLowerCase() == 'hidden') { parser.parseError(token.span, 'unexpected-hidden-input-in-table'); tree.insertElement(token); // XXX associate with form @@ -3621,13 +3616,13 @@ class InForeignContentPhase extends Phase { Token processEndTag(EndTagToken token) { var nodeIndex = tree.openElements.length - 1; var node = tree.openElements.last; - if (asciiUpper2Lower(node.localName) != token.name) { + if (node.localName?.toAsciiLowerCase() != token.name) { parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } Token newToken; while (true) { - if (asciiUpper2Lower(node.localName) == token.name) { + if (node.localName?.toAsciiLowerCase() == token.name) { //XXX this isn't in the spec but it seems necessary if (parser.phase == parser._inTableTextPhase) { final inTableText = parser.phase as InTableTextPhase; diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index b09fc4853..e1fad5a60 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -482,19 +482,15 @@ bool isHexDigit(String char) { return false; } -// Note: based on the original Python code, I assume we only want to convert -// ASCII chars to.toLowerCase() case, unlike Dart's toLowerCase function. -String asciiUpper2Lower(String text) { - if (text == null) return null; - final result = List<int>(text.length); - for (var i = 0; i < text.length; i++) { - var c = text.codeUnitAt(i); - if (c >= UPPER_A && c <= UPPER_Z) { - c += LOWER_A - UPPER_A; - } - result[i] = c; - } - return String.fromCharCodes(result); +extension AsciiUpperToLower on String { + /// Converts ASCII characters to lowercase. + /// + /// Unlike [String.toLowerCase] does not touch non-ASCII characters. + String toAsciiLowerCase() => + String.fromCharCodes(codeUnits.map(_asciiToLower)); + + static int _asciiToLower(int c) => + (c >= UPPER_A && c <= UPPER_Z) ? c + LOWER_A - UPPER_A : c; } // Heading elements need to be ordered diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 7af964829..2737a7e81 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -370,7 +370,7 @@ class HtmlTokenizer implements Iterator<Token> { // Add token to the queue to be yielded if (token is TagToken) { if (lowercaseElementName) { - token.name = asciiUpper2Lower(token.name); + token.name = token.name?.toAsciiLowerCase(); } if (token is EndTagToken) { if (_attributes != null) { @@ -1074,7 +1074,7 @@ class HtmlTokenizer implements Iterator<Token> { // to attributes, but we do want to report the parse error in time. var attrName = _attributeName.toString(); if (lowercaseAttrName) { - attrName = asciiUpper2Lower(attrName); + attrName = attrName.toAsciiLowerCase(); } _attributes.last.name = attrName; _attributeNames ??= {}; @@ -1515,10 +1515,10 @@ class HtmlTokenizer implements Iterator<Token> { bool doctypeNameState() { final data = stream.char(); if (isWhitespace(data)) { - currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); state = afterDoctypeNameState; } else if (data == '>') { - currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else if (data == '\u0000') { @@ -1528,7 +1528,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype-name')); currentDoctypeToken.correct = false; - currentDoctypeToken.name = asciiUpper2Lower(currentDoctypeToken.name); + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else { diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 2576b05df..a8fcab3a0 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -5,7 +5,7 @@ description: APIs for parsing and manipulating HTML content outside the browser. homepage: https://github.com/dart-lang/html environment: - sdk: '>=2.3.0 <3.0.0' + sdk: '>=2.8.0 <3.0.0' dependencies: csslib: '>=0.13.2 <0.17.0' From e03bc6b59b618c2b1f02fa233b9a7857636c91e1 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 7 Oct 2020 13:41:43 -0700 Subject: [PATCH 118/212] Remove unused field _lineStarts (dart-lang/html#133) The usage of this field was removed in https://github.com/dart-lang/html/commit/e1714e6deac83b6e72436d4709a8361cfd0ca997 --- pkgs/html/lib/src/html_input_stream.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 1a2384eaf..76499738e 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -39,8 +39,6 @@ class HtmlInputStream { SourceFile fileInfo; - List<int> _lineStarts; - List<int> _chars; int _offset; @@ -88,7 +86,6 @@ class HtmlInputStream { errors = Queue<String>(); _offset = 0; - _lineStarts = <int>[0]; _chars = <int>[]; _rawChars ??= _decodeBytes(charEncodingName, _rawBytes); @@ -120,7 +117,6 @@ class HtmlInputStream { } _chars.add(c); - if (c == NEWLINE) _lineStarts.add(_chars.length); } // Free decoded characters if they aren't needed anymore. From ee9b3e05aae2704da15e4d61fd4fe8a4c83e75b2 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 7 Oct 2020 15:11:33 -0700 Subject: [PATCH 119/212] Use Object in place of dynamic (dart-lang/html#134) Replace fields and Map keys with `Object` where they were previously `dynamic`. --- pkgs/html/lib/dom.dart | 18 ++++++------- pkgs/html/lib/parser.dart | 35 +++++++++++-------------- pkgs/html/lib/src/token.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 11 +++++--- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index fbd2c90b0..c3d2e5d16 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -55,7 +55,7 @@ class AttributeName implements Comparable<Object> { } @override - int compareTo(dynamic other) { + int compareTo(Object other) { // Not sure about this sort order if (other is! AttributeName) return 1; final otherAttributeName = other as AttributeName; @@ -152,7 +152,7 @@ abstract class Node { /// /// Note that attribute order needs to be stable for serialization, so we use /// a LinkedHashMap. Each key is a [String] or [AttributeName]. - LinkedHashMap<dynamic, String> attributes = LinkedHashMap(); + LinkedHashMap<Object, String> attributes = LinkedHashMap(); /// A list of child nodes of the current node. This must /// include all elements but not necessarily other node types. @@ -166,8 +166,8 @@ abstract class Node { FileSpan sourceSpan; /// The attribute spans if requested. Otherwise null. - LinkedHashMap<dynamic, FileSpan> _attributeSpans; - LinkedHashMap<dynamic, FileSpan> _attributeValueSpans; + LinkedHashMap<Object, FileSpan> _attributeSpans; + LinkedHashMap<Object, FileSpan> _attributeValueSpans; Node._() { nodes._parent = this; @@ -177,7 +177,7 @@ abstract class Node { /// The span of an attribute is the entire attribute, including the name and /// quotes (if any). For example, the span of "attr" in `<a attr="value">` /// would be the text `attr="value"`. - LinkedHashMap<dynamic, FileSpan> get attributeSpans { + LinkedHashMap<Object, FileSpan> get attributeSpans { _ensureAttributeSpans(); return _attributeSpans; } @@ -186,7 +186,7 @@ abstract class Node { /// value. Unlike [attributeSpans], this span will inlcude only the value. /// For example, the value span of "attr" in `<a attr="value">` would be the /// text `value`. - LinkedHashMap<dynamic, FileSpan> get attributeValueSpans { + LinkedHashMap<Object, FileSpan> get attributeValueSpans { _ensureAttributeSpans(); return _attributeValueSpans; } @@ -279,8 +279,8 @@ abstract class Node { void _ensureAttributeSpans() { if (_attributeSpans != null) return; - _attributeSpans = LinkedHashMap<dynamic, FileSpan>(); - _attributeValueSpans = LinkedHashMap<dynamic, FileSpan>(); + _attributeSpans = LinkedHashMap<Object, FileSpan>(); + _attributeValueSpans = LinkedHashMap<Object, FileSpan>(); if (sourceSpan == null) return; @@ -421,7 +421,7 @@ class Text extends Node { /// The text node's data, stored as either a String or StringBuffer. /// We support storing a StringBuffer here to support fast [appendData]. /// It will flatten back to a String on read. - dynamic _data; + Object _data; Text(String data) : _data = data ?? '', diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index ac3d304d8..940753ce1 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -826,7 +826,7 @@ class BeforeHtmlPhase extends Phase { // helper methods void insertHtmlElement() { tree.insertRoot( - StartTagToken('html', data: LinkedHashMap<dynamic, String>())); + StartTagToken('html', data: LinkedHashMap<Object, String>())); parser.phase = parser._beforeHeadPhase; } @@ -913,7 +913,7 @@ class BeforeHeadPhase extends Phase { @override bool processEOF() { - startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>())); return true; } @@ -924,7 +924,7 @@ class BeforeHeadPhase extends Phase { @override Token processCharacters(CharactersToken token) { - startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>())); return token; } @@ -940,12 +940,12 @@ class BeforeHeadPhase extends Phase { } Token startTagOther(StartTagToken token) { - startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>())); return token; } Token endTagImplyHead(EndTagToken token) { - startTagHead(StartTagToken('head', data: LinkedHashMap<dynamic, String>())); + startTagHead(StartTagToken('head', data: LinkedHashMap<Object, String>())); return token; } @@ -1209,7 +1209,7 @@ class AfterHeadPhase extends Phase { void anythingElse() { tree.insertElement( - StartTagToken('body', data: LinkedHashMap<dynamic, String>())); + StartTagToken('body', data: LinkedHashMap<Object, String>())); parser.phase = parser._inBodyPhase; parser.framesetOK = true; } @@ -1813,29 +1813,27 @@ class InBodyPhase extends Phase { if (tree.formPointer != null) { return; } - final formAttrs = LinkedHashMap<dynamic, String>(); + final formAttrs = LinkedHashMap<Object, String>(); final dataAction = token.data['action']; if (dataAction != null) { formAttrs['action'] = dataAction; } processStartTag(StartTagToken('form', data: formAttrs)); + processStartTag(StartTagToken('hr', data: LinkedHashMap<Object, String>())); processStartTag( - StartTagToken('hr', data: LinkedHashMap<dynamic, String>())); - processStartTag( - StartTagToken('label', data: LinkedHashMap<dynamic, String>())); + StartTagToken('label', data: LinkedHashMap<Object, String>())); // XXX Localization ... var prompt = token.data['prompt']; prompt ??= 'This is a searchable index. Enter search keywords: '; processCharacters(CharactersToken(prompt)); - final attributes = LinkedHashMap<dynamic, String>.from(token.data); + final attributes = LinkedHashMap<Object, String>.from(token.data); attributes.remove('action'); attributes.remove('prompt'); attributes['name'] = 'isindex'; processStartTag(StartTagToken('input', data: attributes, selfClosing: token.selfClosing)); processEndTag(EndTagToken('label')); - processStartTag( - StartTagToken('hr', data: LinkedHashMap<dynamic, String>())); + processStartTag(StartTagToken('hr', data: LinkedHashMap<Object, String>())); processEndTag(EndTagToken('form')); } @@ -1938,8 +1936,7 @@ class InBodyPhase extends Phase { void endTagP(EndTagToken token) { if (!tree.elementInScope('p', variant: 'button')) { - startTagCloseP( - StartTagToken('p', data: LinkedHashMap<dynamic, String>())); + startTagCloseP(StartTagToken('p', data: LinkedHashMap<Object, String>())); parser.parseError(token.span, 'unexpected-end-tag', {'name': 'p'}); endTagP(EndTagToken('p')); } else { @@ -2238,7 +2235,7 @@ class InBodyPhase extends Phase { {'originalName': 'br', 'newName': 'br element'}); tree.reconstructActiveFormattingElements(); tree.insertElement( - StartTagToken('br', data: LinkedHashMap<dynamic, String>())); + StartTagToken('br', data: LinkedHashMap<Object, String>())); tree.openElements.removeLast(); } @@ -2450,7 +2447,7 @@ class InTablePhase extends Phase { Token startTagCol(StartTagToken token) { startTagColgroup( - StartTagToken('colgroup', data: LinkedHashMap<dynamic, String>())); + StartTagToken('colgroup', data: LinkedHashMap<Object, String>())); return token; } @@ -2462,7 +2459,7 @@ class InTablePhase extends Phase { Token startTagImplyTbody(StartTagToken token) { startTagRowGroup( - StartTagToken('tbody', data: LinkedHashMap<dynamic, String>())); + StartTagToken('tbody', data: LinkedHashMap<Object, String>())); return token; } @@ -2918,7 +2915,7 @@ class InTableBodyPhase extends Phase { Token startTagTableCell(StartTagToken token) { parser.parseError( token.span, 'unexpected-cell-in-table-body', {'name': token.name}); - startTagTr(StartTagToken('tr', data: LinkedHashMap<dynamic, String>())); + startTagTr(StartTagToken('tr', data: LinkedHashMap<Object, String>())); return token; } diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 24c531eb2..05fe58dce 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -22,7 +22,7 @@ abstract class TagToken extends Token { class StartTagToken extends TagToken { /// The tag's attributes. A map from the name to the value, where the name /// can be a [String] or [AttributeName]. - LinkedHashMap<dynamic, String> data; + LinkedHashMap<Object, String> data; /// The attribute spans if requested. Otherwise null. List<TagAttribute> attributeSpans; diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index f59df1b61..0237172a9 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -231,10 +231,13 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. '''); final n = doc.querySelector('desc'); final keys = n.attributes.keys.toList(); - expect(keys[0], const TypeMatcher<AttributeName>()); - expect(keys[0].prefix, 'xlink'); - expect(keys[0].namespace, 'http://www.w3.org/1999/xlink'); - expect(keys[0].name, 'type'); + expect( + keys.first, + isA<AttributeName>() + .having((n) => n.prefix, 'prefix', 'xlink') + .having((n) => n.namespace, 'namespace', + 'http://www.w3.org/1999/xlink') + .having((n) => n.name, 'name', 'type')); expect( n.outerHtml, From 72bf9fd0806f7d72680008341ee09b5379687ec1 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Mon, 12 Oct 2020 16:43:53 -0700 Subject: [PATCH 120/212] Remove Marker as a name for null (dart-lang/html#136) The checks against `== Marker` won't upgrade a nullable variable to non-nullable like `== null` would. - Replace `Marker` with `null`. Remove the field. - Add a doc comment on the class to link to the parsing spec and describe the usage of `null`. - Add a doc comment on `add` to describe it's difference from the normal `List.add`. - Add some comments and a link to an issue filed about a likely bug in this method. --- pkgs/html/lib/parser.dart | 8 +++---- pkgs/html/lib/src/treebuilder.dart | 38 +++++++++++++++++------------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 940753ce1..363aa233d 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -1504,7 +1504,7 @@ class InBodyPhase extends Phase { final matchingElements = []; for (Node node in tree.activeFormattingElements.reversed) { - if (node == Marker) { + if (node == null) { break; } else if (isMatchingFormattingElement(node as Element, element)) { matchingElements.add(node); @@ -1743,7 +1743,7 @@ class InBodyPhase extends Phase { void startTagAppletMarqueeObject(StartTagToken token) { tree.reconstructActiveFormattingElements(); tree.insertElement(token); - tree.activeFormattingElements.add(Marker); + tree.activeFormattingElements.add(null); parser.framesetOK = false; } @@ -2434,7 +2434,7 @@ class InTablePhase extends Phase { void startTagCaption(StartTagToken token) { clearStackToTableContext(); - tree.activeFormattingElements.add(Marker); + tree.activeFormattingElements.add(null); tree.insertElement(token); parser.phase = parser._inCaptionPhase; } @@ -3054,7 +3054,7 @@ class InRowPhase extends Phase { clearStackToTableRowContext(); tree.insertElement(token); parser.phase = parser._inCellPhase; - tree.activeFormattingElements.add(Marker); + tree.activeFormattingElements.add(null); } Token startTagTableOther(StartTagToken token) { diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index a1f0da1ed..36874641b 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -10,29 +10,33 @@ import 'list_proxy.dart'; import 'token.dart'; import 'utils.dart'; -// The scope markers are inserted when entering object elements, -// marquees, table cells, and table captions, and are used to prevent formatting -// from "leaking" into tables, object elements, and marquees. -const Element Marker = null; - -// TODO(jmesserly): this should extend ListBase<Element>, but my simple attempt -// didn't work. -class ActiveFormattingElements extends ListProxy<Element> { - // Override the "add" method. - // TODO(jmesserly): I'd rather not override this; can we do this in the - // calling code instead? +/// Open elements in the formatting category, most recent element last. +/// +/// `null` is used as the "marker" entry to prevent style from leaking when +/// entering some elements. +/// +/// https://html.spec.whatwg.org/multipage/parsing.html#list-of-active-formatting-elements +class ActiveFormattingElements extends ListProxy<Element /*?*/ > { + /// Push an element into the active formatting elements. + /// + /// Prevents equivalent elements from appearing more than 3 times following + /// the last `null` marker. If adding [node] would cause there to be more than + /// 3 equivalent elements the earliest identical element is removed. + // TODO - Earliest equivalent following a marker, as opposed to earliest + // identical regardless of marker position, should be removed. @override void add(Element node) { var equalCount = 0; - if (node != Marker) { + if (node != null) { for (var element in reversed) { - if (element == Marker) { + if (element == null) { break; } if (_nodesEqual(element, node)) { equalCount += 1; } if (equalCount == 3) { + // TODO - https://github.com/dart-lang/html/issues/135 remove(element); break; } @@ -165,12 +169,12 @@ class TreeBuilder { // Step 2 and step 3: we start with the last element. So i is -1. var i = activeFormattingElements.length - 1; var entry = activeFormattingElements[i]; - if (entry == Marker || openElements.contains(entry)) { + if (entry == null || openElements.contains(entry)) { return; } // Step 6 - while (entry != Marker && !openElements.contains(entry)) { + while (entry != null && !openElements.contains(entry)) { if (i == 0) { //This will be reset to 0 below i = -1; @@ -209,7 +213,7 @@ class TreeBuilder { void clearActiveFormattingElements() { var entry = activeFormattingElements.removeLast(); - while (activeFormattingElements.isNotEmpty && entry != Marker) { + while (activeFormattingElements.isNotEmpty && entry != null) { entry = activeFormattingElements.removeLast(); } } @@ -221,7 +225,7 @@ class TreeBuilder { for (var item in activeFormattingElements.reversed) { // Check for Marker first because if it's a Marker it doesn't have a // name attribute. - if (item == Marker) { + if (item == null) { break; } else if (item.localName == name) { return item; From 79e6e860f2af36730b541affd868a0d7aa537b10 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 14 Oct 2020 14:07:53 -0700 Subject: [PATCH 121/212] Drop unused lastPhase and beforeRcDataPhase fields (dart-lang/html#137) These fields are unused in both this library and the python library from which it was transliterated. The `lastPhase` was later named to `originalPhase` but not all references were cleaned up which leaves one remaining assignment to null. `beforeRcDataPhase` was unused in the commit which introduced it and never assigned an interesting value or read the field. --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/lib/parser.dart | 6 ------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 615a09fe7..e294c419f 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,5 +1,8 @@ ## 0.15.0-dev +- Drop `HtmlParser.lastPhase` and `HtmlParser.beforeRcDataPhase`. These fields + never had a value other than `null`. + ## 0.14.0+4 - Fix a bug parsing bad HTML where a 'button' end tag needs to close other diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 363aa233d..00c15629e 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -93,12 +93,8 @@ class HtmlParser { Phase phase; - Phase lastPhase; - Phase originalPhase; - Phase beforeRCDataPhase; - bool framesetOK; // These fields hold the different phase singletons. At any given time one @@ -252,8 +248,6 @@ class HtmlParser { phase = _initialPhase; } - lastPhase = null; - beforeRCDataPhase = null; framesetOK = true; } From 14949e4d658cf8495f4f0f855f8ce35f20cc017e Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Wed, 14 Oct 2020 15:32:07 -0700 Subject: [PATCH 122/212] Remove a fixed size list creation (dart-lang/html#138) The dart idiom for a repeated string is `operator *`. Remove an unnecessary intermediate list and `String.fromCharCodes`. --- pkgs/html/test/support.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 34fedb2ca..ee2557a17 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -110,12 +110,7 @@ class TestSerializer extends TreeVisitor { set indent(int value) { if (_indent == value) return; - - final arr = List<int>(value); - for (var i = 0; i < value; i++) { - arr[i] = 32; - } - _spaces = String.fromCharCodes(arr); + _spaces = ' ' * value; _indent = value; } From a7c1435963815a33e115f489560f079d56882536 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Wed, 7 Oct 2020 10:42:49 -0700 Subject: [PATCH 123/212] Migrate to null safety - Append `-nullsafety` to version. - Set min SDK to `2.11.0-0`, add `publish_to:none` since this package is not in the allow list. - Use late field initialization over constructor assignment to clean up the handling of backreferences in the different "phases". - Remove some conditional branches that are impossible to hit. --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/analysis_options.yaml | 2 + pkgs/html/lib/dom.dart | 138 +++--- pkgs/html/lib/dom_parsing.dart | 8 +- pkgs/html/lib/parser.dart | 425 ++++++++---------- pkgs/html/lib/src/constants.dart | 14 +- pkgs/html/lib/src/css_class_set.dart | 20 +- pkgs/html/lib/src/encoding_parser.dart | 16 +- pkgs/html/lib/src/html_input_stream.dart | 52 +-- pkgs/html/lib/src/list_proxy.dart | 2 +- pkgs/html/lib/src/query_selector.dart | 50 +-- pkgs/html/lib/src/token.dart | 51 +-- pkgs/html/lib/src/tokenizer.dart | 226 +++++----- pkgs/html/lib/src/treebuilder.dart | 46 +- pkgs/html/lib/src/utils.dart | 13 +- pkgs/html/pubspec.yaml | 20 +- pkgs/html/test/parser_feature_test.dart | 176 ++++---- pkgs/html/test/parser_test.dart | 16 +- .../test/selectors/level1_baseline_test.dart | 2 +- pkgs/html/test/selectors/level1_lib.dart | 30 +- pkgs/html/test/support.dart | 20 +- pkgs/html/test/tokenizer_test.dart | 36 +- 22 files changed, 669 insertions(+), 696 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index e294c419f..2269d1fec 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.15.0-dev +## 0.15.0-nullsafety-dev - Drop `HtmlParser.lastPhase` and `HtmlParser.beforeRcDataPhase`. These fields never had a value other than `null`. diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 9f2325c88..cbca1a7dd 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -9,6 +9,8 @@ analyzer: unused_import: error unused_local_variable: error dead_code: error + enable-experiment: + - non-nullable linter: rules: #- annotate_overrides diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index c3d2e5d16..bdbfb09ca 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -26,7 +26,7 @@ export 'src/css_class_set.dart' show CssClassSet; // that exposes namespace info. class AttributeName implements Comparable<Object> { /// The namespace prefix, e.g. `xlink`. - final String prefix; + final String? prefix; /// The attribute name, e.g. `title`. final String name; @@ -58,7 +58,7 @@ class AttributeName implements Comparable<Object> { int compareTo(Object other) { // Not sure about this sort order if (other is! AttributeName) return 1; - final otherAttributeName = other as AttributeName; + final otherAttributeName = other; var cmp = (prefix ?? '').compareTo((otherAttributeName.prefix ?? '')); if (cmp != 0) return cmp; cmp = name.compareTo(otherAttributeName.name); @@ -85,7 +85,7 @@ abstract class _ParentNode implements Node { /// are implemented. For example, nth-child does not implement An+B syntax /// and *-of-type is not implemented. If a selector is not implemented this /// method will throw [UniplmentedError]. - Element querySelector(String selector) => query.querySelector(this, selector); + Element? querySelector(String selector) => query.querySelector(this, selector); /// Returns all descendant nodes matching the given selectors, using a /// preorder traversal. @@ -102,7 +102,7 @@ abstract class _ParentNode implements Node { // http://dom.spec.whatwg.org/#interface-nonelementparentnode abstract class _NonElementParentNode implements _ParentNode { // TODO(jmesserly): could be faster, should throw on invalid id. - Element getElementById(String id) => querySelector('#$id'); + Element? getElementById(String id) => querySelector('#$id'); } // This doesn't exist as an interface in the spec, but it's useful to merge @@ -136,13 +136,13 @@ abstract class Node { static const int TEXT_NODE = 3; /// The parent of the current node (or null for the document node). - Node parentNode; + Node? parentNode; /// The parent element of this node. /// /// Returns null if this node either does not have a parent or its parent is /// not an element. - Element get parent { + Element? get parent { final parentNode = this.parentNode; return parentNode is Element ? parentNode : null; } @@ -158,16 +158,16 @@ abstract class Node { /// include all elements but not necessarily other node types. final NodeList nodes = NodeList._(); - List<Element> _elements; + List<Element>? _elements; // TODO(jmesserly): consider using an Expando for this, and put it in // dom_parsing. Need to check the performance affect. /// The source span of this node, if it was created by the [HtmlParser]. - FileSpan sourceSpan; + FileSpan? sourceSpan; /// The attribute spans if requested. Otherwise null. - LinkedHashMap<Object, FileSpan> _attributeSpans; - LinkedHashMap<Object, FileSpan> _attributeValueSpans; + LinkedHashMap<Object?, FileSpan>? _attributeSpans; + LinkedHashMap<Object?, FileSpan>? _attributeValueSpans; Node._() { nodes._parent = this; @@ -177,7 +177,7 @@ abstract class Node { /// The span of an attribute is the entire attribute, including the name and /// quotes (if any). For example, the span of "attr" in `<a attr="value">` /// would be the text `attr="value"`. - LinkedHashMap<Object, FileSpan> get attributeSpans { + LinkedHashMap<Object?, FileSpan>? get attributeSpans { _ensureAttributeSpans(); return _attributeSpans; } @@ -186,7 +186,7 @@ abstract class Node { /// value. Unlike [attributeSpans], this span will inlcude only the value. /// For example, the value span of "attr" in `<a attr="value">` would be the /// text `value`. - LinkedHashMap<Object, FileSpan> get attributeValueSpans { + LinkedHashMap<Object?, FileSpan>? get attributeValueSpans { _ensureAttributeSpans(); return _attributeValueSpans; } @@ -215,12 +215,12 @@ abstract class Node { } // Implemented per: http://dom.spec.whatwg.org/#dom-node-textcontent - String get text => null; - set text(String value) {} + String? get text => null; + set text(String? value) {} void append(Node node) => nodes.add(node); - Node get firstChild => nodes.isNotEmpty ? nodes[0] : null; + Node? get firstChild => nodes.isNotEmpty ? nodes[0] : null; void _addOuterHtml(StringBuffer str); @@ -232,9 +232,7 @@ abstract class Node { Node remove() { // TODO(jmesserly): is parent == null an error? - if (parentNode != null) { - parentNode.nodes.remove(this); - } + parentNode?.nodes.remove(this); return this; } @@ -242,7 +240,7 @@ abstract class Node { /// list of child nodes. Raises [UnsupportedOperationException] if [refNode] /// is not a child of the current node. If refNode is null, this adds to the /// end of the list. - void insertBefore(Node node, Node refNode) { + void insertBefore(Node node, Node? refNode) { if (refNode == null) { nodes.add(node); } else { @@ -255,7 +253,7 @@ abstract class Node { if (parentNode == null) { throw UnsupportedError('Node must have a parent to replace it.'); } - parentNode.nodes[parentNode.nodes.indexOf(this)] = otherNode; + parentNode!.nodes[parentNode!.nodes.indexOf(this)] = otherNode; return this; } @@ -279,12 +277,12 @@ abstract class Node { void _ensureAttributeSpans() { if (_attributeSpans != null) return; - _attributeSpans = LinkedHashMap<Object, FileSpan>(); - _attributeValueSpans = LinkedHashMap<Object, FileSpan>(); + _attributeSpans = LinkedHashMap<Object?, FileSpan>(); + _attributeValueSpans = LinkedHashMap<Object?, FileSpan>(); if (sourceSpan == null) return; - final tokenizer = HtmlTokenizer(sourceSpan.text, + final tokenizer = HtmlTokenizer(sourceSpan!.text, generateSpans: true, attributeSpans: true); tokenizer.moveNext(); @@ -292,13 +290,13 @@ abstract class Node { if (token.attributeSpans == null) return; // no attributes - for (var attr in token.attributeSpans) { - final offset = sourceSpan.start.offset; - _attributeSpans[attr.name] = - sourceSpan.file.span(offset + attr.start, offset + attr.end); + for (var attr in token.attributeSpans!) { + final offset = sourceSpan!.start.offset; + _attributeSpans![attr.name] = + sourceSpan!.file.span(offset + attr.start, offset + attr.end); if (attr.startValue != null) { - _attributeValueSpans[attr.name] = sourceSpan.file - .span(offset + attr.startValue, offset + attr.endValue); + _attributeValueSpans![attr.name] = sourceSpan!.file + .span(offset + attr.startValue!, offset + attr.endValue); } } } @@ -322,9 +320,9 @@ class Document extends Node int get nodeType => Node.DOCUMENT_NODE; // TODO(jmesserly): optmize this if needed - Element get documentElement => querySelector('html'); - Element get head => documentElement.querySelector('head'); - Element get body => documentElement.querySelector('body'); + Element get documentElement => querySelector('html')!; + Element get head => documentElement.querySelector('head')!; + Element get body => documentElement.querySelector('body')!; /// Returns a fragment of HTML or XML that represents the element and its /// contents. @@ -347,7 +345,7 @@ class Document extends Node // TODO(jmesserly): this is only a partial implementation of: // http://dom.spec.whatwg.org/#dom-document-createelementns - Element createElementNS(String namespaceUri, String tag) { + Element createElementNS(String? namespaceUri, String? tag) { if (namespaceUri == '') namespaceUri = null; return Element._(tag, namespaceUri); } @@ -382,13 +380,13 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { @override String get text => _getText(this); @override - set text(String value) => _setText(this, value); + set text(String? value) => _setText(this, value); } class DocumentType extends Node { - final String name; - final String publicId; - final String systemId; + final String? name; + final String? publicId; + final String? systemId; DocumentType(this.name, this.publicId, this.systemId) : super._(); @@ -423,7 +421,7 @@ class Text extends Node { /// It will flatten back to a String on read. Object _data; - Text(String data) + Text(String? data) : _data = data ?? '', super._(); @@ -431,7 +429,7 @@ class Text extends Node { int get nodeType => Node.TEXT_NODE; String get data => _data = _data.toString(); - set data(String value) { + set data(String? value) { _data = value ?? ''; } @@ -453,24 +451,24 @@ class Text extends Node { @override String get text => data; @override - set text(String value) { + set text(String? value) { data = value; } } // TODO(jmesserly): Elements should have a pointer back to their document class Element extends Node with _ParentNode, _ElementAndDocument { - final String namespaceUri; + final String? namespaceUri; /// The [local name](http://dom.spec.whatwg.org/#concept-element-local-name) /// of this element. - final String localName; + final String? localName; // TODO(jmesserly): consider using an Expando for this, and put it in // dom_parsing. Need to check the performance affect. /// The source span of the end tag this element, if it was created by the /// [HtmlParser]. May be `null` if does not have an implicit end tag. - FileSpan endSourceSpan; + FileSpan? endSourceSpan; Element._(this.localName, [this.namespaceUri]) : super._(); @@ -507,12 +505,12 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // 3) Verify that the html does not contain both <head> and <body> tags. // 4) Detatch the created element from its dummy parent. var parentTag = 'div'; - String tag; + String? tag; final match = _startTagRegexp.firstMatch(html); if (match != null) { - tag = match.group(1).toLowerCase(); + tag = match.group(1)!.toLowerCase(); if (_customParentTagMap.containsKey(tag)) { - parentTag = _customParentTagMap[tag]; + parentTag = _customParentTagMap[tag]!; } } @@ -535,9 +533,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { int get nodeType => Node.ELEMENT_NODE; // TODO(jmesserly): we can make this faster - Element get previousElementSibling { + Element? get previousElementSibling { if (parentNode == null) return null; - final siblings = parentNode.nodes; + final siblings = parentNode!.nodes; for (var i = siblings.indexOf(this) - 1; i >= 0; i--) { final s = siblings[i]; if (s is Element) return s; @@ -545,9 +543,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { return null; } - Element get nextElementSibling { + Element? get nextElementSibling { if (parentNode == null) return null; - final siblings = parentNode.nodes; + final siblings = parentNode!.nodes; for (var i = siblings.indexOf(this) + 1; i < siblings.length; i++) { final s = siblings[i]; if (s is Element) return s; @@ -564,7 +562,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { @override String get text => _getText(this); @override - set text(String value) => _setText(this, value); + set text(String? value) => _setText(this, value); /// Returns a fragment of HTML or XML that represents the element and its /// contents. @@ -625,7 +623,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { if (!isVoidElement(localName)) str.write('</$localName>'); } - static String _getSerializationPrefix(String uri) { + static String _getSerializationPrefix(String? uri) { if (uri == null || uri == Namespaces.html || uri == Namespaces.mathml || @@ -677,7 +675,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } class Comment extends Node { - String data; + String? data; Comment(this.data) : super._(); @@ -696,9 +694,9 @@ class Comment extends Node { Comment clone(bool deep) => Comment(data); @override - String get text => data; + String? get text => data; @override - set text(String value) { + set text(String? value) { data = value; } } @@ -709,7 +707,7 @@ class Comment extends Node { class NodeList extends ListProxy<Node> { // Note: this is conceptually final, but because of circular reference // between Node and NodeList we initialize it after construction. - Node _parent; + Node? _parent; NodeList._(); @@ -917,7 +915,7 @@ class FilteredElementList extends IterableBase<Element> } @override - bool contains(Object element) { + bool contains(Object? element) { return element is Element && _childNodes.contains(element); } @@ -925,7 +923,7 @@ class FilteredElementList extends IterableBase<Element> Iterable<Element> get reversed => _filtered.reversed; @override - void sort([int Function(Element, Element) compare]) { + void sort([int Function(Element, Element)? compare]) { throw UnsupportedError('TODO(jacobr): should we impl?'); } @@ -936,7 +934,7 @@ class FilteredElementList extends IterableBase<Element> } @override - void fillRange(int start, int end, [Element fillValue]) { + void fillRange(int start, int end, [Element? fillValue]) { throw UnimplementedError(); } @@ -959,11 +957,7 @@ class FilteredElementList extends IterableBase<Element> @override Element removeLast() { - final result = last; - if (result != null) { - result.remove(); - } - return result; + return last..remove(); } @override @@ -991,7 +985,7 @@ class FilteredElementList extends IterableBase<Element> } @override - bool remove(Object element) { + bool remove(Object? element) { if (element is! Element) return false; for (var i = 0; i < length; i++) { final indexElement = this[i]; @@ -1024,18 +1018,18 @@ class FilteredElementList extends IterableBase<Element> @override Set<Element> toSet() => Set<Element>.from(this); @override - Element firstWhere(bool Function(Element) test, {Element Function() orElse}) { + Element firstWhere(bool Function(Element) test, {Element Function()? orElse}) { return _filtered.firstWhere(test, orElse: orElse); } @override - Element lastWhere(bool Function(Element) test, {Element Function() orElse}) { + Element lastWhere(bool Function(Element) test, {Element Function()? orElse}) { return _filtered.lastWhere(test, orElse: orElse); } @override Element singleWhere(bool Function(Element) test, - {Element Function() orElse}) { + {Element Function()? orElse}) { if (orElse != null) throw UnimplementedError('orElse'); return _filtered.singleWhere(test); } @@ -1054,17 +1048,17 @@ class FilteredElementList extends IterableBase<Element> @override Iterator<Element> get iterator => _filtered.iterator; @override - List<Element> sublist(int start, [int end]) => _filtered.sublist(start, end); + List<Element> sublist(int start, [int? end]) => _filtered.sublist(start, end); @override Iterable<Element> getRange(int start, int end) => _filtered.getRange(start, end); @override - int indexOf(Object element, [int start = 0]) => + int indexOf(Object? element, [int start = 0]) => // Cast forced by ListMixin https://github.com/dart-lang/sdk/issues/31311 _filtered.indexOf(element as Element, start); @override - int lastIndexOf(Object element, [int start]) { + int lastIndexOf(Object? element, [int? start]) { start ??= length - 1; // Cast forced by ListMixin https://github.com/dart-lang/sdk/issues/31311 return _filtered.lastIndexOf(element as Element, start); @@ -1084,7 +1078,7 @@ class FilteredElementList extends IterableBase<Element> // For Element and DocumentFragment String _getText(Node node) => (_ConcatTextVisitor()..visit(node)).toString(); -void _setText(Node node, String value) { +void _setText(Node node, String? value) { node.nodes.clear(); node.append(Text(value)); } diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index f108b59dd..142222ebc 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -111,7 +111,7 @@ class CodeMarkupVisitor extends TreeVisitor { @override void visitComment(Comment node) { - final data = htmlSerializeEscape(node.data); + final data = htmlSerializeEscape(node.data!); _str.write('<code class="markup comment">&lt;!--$data--></code>'); } } @@ -136,10 +136,10 @@ class CodeMarkupVisitor extends TreeVisitor { String htmlSerializeEscape(String text, {bool attributeMode = false}) { // TODO(jmesserly): is it faster to build up a list of codepoints? // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. - StringBuffer result; + StringBuffer? result; for (var i = 0; i < text.length; i++) { final ch = text[i]; - String replace; + String? replace; switch (ch) { case '&': replace = '&amp;'; @@ -172,7 +172,7 @@ String htmlSerializeEscape(String text, {bool attributeMode = false}) { /// This method is useful to a pretty printer, because void elements must not /// have an end tag. /// See also: <http://dev.w3.org/html5/markup/syntax.html#void-elements>. -bool isVoidElement(String tagName) { +bool isVoidElement(String? tagName) { switch (tagName) { case 'area': case 'base': diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 00c15629e..1b8a58e04 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -37,7 +37,7 @@ import 'src/utils.dart'; /// can additionally pass [sourceUrl] to indicate where the [input] was /// extracted from. Document parse(input, - {String encoding, bool generateSpans = false, String sourceUrl}) { + {String? encoding, bool generateSpans = false, String? sourceUrl}) { final p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parse(); @@ -56,10 +56,10 @@ Document parse(input, /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. DocumentFragment parseFragment(input, - {String container = 'div', - String encoding, + {String? container = 'div', + String? encoding, bool generateSpans = false, - String sourceUrl}) { + String? sourceUrl}) { final p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); return p.parseFragment(container); @@ -80,7 +80,7 @@ class HtmlParser { final List<ParseError> errors = <ParseError>[]; - String container; + String? container; bool firstStartTag = false; @@ -89,38 +89,43 @@ class HtmlParser { String compatMode = 'no quirks'; /// innerHTML container when parsing document fragment. - String innerHTML; + String? innerHTML; - Phase phase; + late Phase phase = _initialPhase; - Phase originalPhase; + Phase? originalPhase; - bool framesetOK; + var framesetOK = true; // These fields hold the different phase singletons. At any given time one // of them will be active. - InitialPhase _initialPhase; - BeforeHtmlPhase _beforeHtmlPhase; - BeforeHeadPhase _beforeHeadPhase; - InHeadPhase _inHeadPhase; - AfterHeadPhase _afterHeadPhase; - InBodyPhase _inBodyPhase; - TextPhase _textPhase; - InTablePhase _inTablePhase; - InTableTextPhase _inTableTextPhase; - InCaptionPhase _inCaptionPhase; - InColumnGroupPhase _inColumnGroupPhase; - InTableBodyPhase _inTableBodyPhase; - InRowPhase _inRowPhase; - InCellPhase _inCellPhase; - InSelectPhase _inSelectPhase; - InSelectInTablePhase _inSelectInTablePhase; - InForeignContentPhase _inForeignContentPhase; - AfterBodyPhase _afterBodyPhase; - InFramesetPhase _inFramesetPhase; - AfterFramesetPhase _afterFramesetPhase; - AfterAfterBodyPhase _afterAfterBodyPhase; - AfterAfterFramesetPhase _afterAfterFramesetPhase; + late final _initialPhase = InitialPhase(this); + late final _beforeHtmlPhase = BeforeHtmlPhase(this); + late final _beforeHeadPhase = BeforeHeadPhase(this); + late final _inHeadPhase = InHeadPhase(this); + // TODO: html5lib did not implement the no script parsing mode + // More information here: + // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#scripting-flag + // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inheadnoscript + // late final _inHeadNoscript = InHeadNoScriptPhase(this); + late final _afterHeadPhase = AfterHeadPhase(this); + late final _inBodyPhase = InBodyPhase(this); + late final _textPhase = TextPhase(this); + late final _inTablePhase = InTablePhase(this); + late final _inTableTextPhase = InTableTextPhase(this); + late final _inCaptionPhase = InCaptionPhase(this); + late final _inColumnGroupPhase = InColumnGroupPhase(this); + late final _inTableBodyPhase = InTableBodyPhase(this); + late final _inRowPhase = InRowPhase(this); + late final _inCellPhase = InCellPhase(this); + late final _inSelectPhase = InSelectPhase(this); + late final _inSelectInTablePhase = InSelectInTablePhase(this); + late final _inForeignContentPhase = InForeignContentPhase(this); + late final _afterBodyPhase = AfterBodyPhase(this); + late final _inFramesetPhase = InFramesetPhase(this); + late final _afterFramesetPhase = AfterFramesetPhase(this); + late final _afterAfterBodyPhase = AfterAfterBodyPhase(this); + late final _afterAfterFramesetPhase = AfterAfterFramesetPhase(this); /// Create an HtmlParser and configure the [tree] builder and [strict] mode. /// The [input] can be a [String], [List<int>] of bytes or an [HtmlTokenizer]. @@ -138,14 +143,14 @@ class HtmlParser { /// that standard way to parse HTML is to lowercase, which is what the browser /// DOM will do if you request [Node.outerHTML], for example. HtmlParser(input, - {String encoding, + {String? encoding, bool parseMeta = true, bool lowercaseElementName = true, bool lowercaseAttrName = true, this.strict = false, this.generateSpans = false, - String sourceUrl, - TreeBuilder tree}) + String? sourceUrl, + TreeBuilder? tree}) : tree = tree ?? TreeBuilder(true), tokenizer = (input is HtmlTokenizer ? input @@ -157,33 +162,6 @@ class HtmlParser { generateSpans: generateSpans, sourceUrl: sourceUrl)) { tokenizer.parser = this; - _initialPhase = InitialPhase(this); - _beforeHtmlPhase = BeforeHtmlPhase(this); - _beforeHeadPhase = BeforeHeadPhase(this); - _inHeadPhase = InHeadPhase(this); - // TODO(jmesserly): html5lib did not implement the no script parsing mode - // More information here: - // http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#scripting-flag - // http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#parsing-main-inheadnoscript - // "inHeadNoscript": new InHeadNoScriptPhase(this); - _afterHeadPhase = AfterHeadPhase(this); - _inBodyPhase = InBodyPhase(this); - _textPhase = TextPhase(this); - _inTablePhase = InTablePhase(this); - _inTableTextPhase = InTableTextPhase(this); - _inCaptionPhase = InCaptionPhase(this); - _inColumnGroupPhase = InColumnGroupPhase(this); - _inTableBodyPhase = InTableBodyPhase(this); - _inRowPhase = InRowPhase(this); - _inCellPhase = InCellPhase(this); - _inSelectPhase = InSelectPhase(this); - _inSelectInTablePhase = InSelectInTablePhase(this); - _inForeignContentPhase = InForeignContentPhase(this); - _afterBodyPhase = AfterBodyPhase(this); - _inFramesetPhase = InFramesetPhase(this); - _afterFramesetPhase = AfterFramesetPhase(this); - _afterAfterBodyPhase = AfterAfterBodyPhase(this); - _afterAfterFramesetPhase = AfterAfterFramesetPhase(this); } bool get innerHTMLMode => innerHTML != null; @@ -199,7 +177,7 @@ class HtmlParser { /// Parse an html5 document fragment into a tree. /// Pass a [container] to change the type of the containing element. /// After parsing, [errors] will be populated with parse errors, if any. - DocumentFragment parseFragment([String container = 'div']) { + DocumentFragment parseFragment([String? container = 'div']) { if (container == null) throw ArgumentError('container'); innerHTML = container.toLowerCase(); _parse(); @@ -276,7 +254,7 @@ class HtmlParser { if (isMathMLTextIntegrationPoint(node)) { if (type == TokenKind.startTag && (token as StartTagToken).name != 'mglyph' && - (token as StartTagToken).name != 'malignmark') { + token.name != 'malignmark') { return false; } if (type == TokenKind.characters || type == TokenKind.spaceCharacters) { @@ -304,7 +282,7 @@ class HtmlParser { void mainLoop() { while (tokenizer.moveNext()) { final token = tokenizer.current; - var newToken = token; + Token? newToken = token; int type; while (newToken != null) { type = newToken.kind; @@ -367,14 +345,14 @@ class HtmlParser { /// The last span available. Used for EOF errors if we don't have something /// better. - SourceSpan get _lastSpan { + SourceSpan? get _lastSpan { if (tokenizer.stream.fileInfo == null) return null; final pos = tokenizer.stream.position; - return tokenizer.stream.fileInfo.location(pos).pointSpan(); + return tokenizer.stream.fileInfo!.location(pos).pointSpan(); } - void parseError(SourceSpan span, String errorcode, - [Map datavars = const {}]) { + void parseError(SourceSpan? span, String errorcode, + [Map? datavars = const {}]) { if (!generateSpans && span == null) { span = _lastSpan; } @@ -457,9 +435,9 @@ class HtmlParser { 'zoomandpan': 'zoomAndPan' }; for (var originalName in token.data.keys.toList()) { - final svgName = replacements[originalName]; + final svgName = replacements[originalName as String]; if (svgName != null) { - token.data[svgName] = token.data.remove(originalName); + token.data[svgName] = token.data.remove(originalName)!; } } } @@ -483,9 +461,9 @@ class HtmlParser { }; for (var originalName in token.data.keys.toList()) { - final foreignName = replacements[originalName]; + final foreignName = replacements[originalName as String]; if (foreignName != null) { - token.data[foreignName] = token.data.remove(originalName); + token.data[foreignName] = token.data.remove(originalName)!; } } } @@ -602,33 +580,33 @@ class Phase { throw UnimplementedError(); } - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { // For most phases the following is correct. Where it's not it will be // overridden. tree.insertComment(token, tree.openElements.last); return null; } - Token processDoctype(DoctypeToken token) { + Token? processDoctype(DoctypeToken token) { parser.parseError(token.span, 'unexpected-doctype'); return null; } - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { tree.insertText(token.data, token.span); return null; } - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { tree.insertText(token.data, token.span); return null; } - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { throw UnimplementedError(); } - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { if (parser.firstStartTag == false && token.name == 'html') { parser.parseError(token.span, 'non-html-root'); } @@ -642,7 +620,7 @@ class Phase { return null; } - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { throw UnimplementedError(); } @@ -653,9 +631,7 @@ class Phase { while (node.localName != name) { node = tree.openElements.removeLast(); } - if (node != null) { - node.endSourceSpan = token.span; - } + node.endSourceSpan = token.span; } } @@ -663,18 +639,18 @@ class InitialPhase extends Phase { InitialPhase(HtmlParser parser) : super(parser); @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return null; } @override - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } @override - Token processDoctype(DoctypeToken token) { + Token? processDoctype(DoctypeToken token) { final name = token.name; var publicId = token.publicId?.toAsciiLowerCase(); final systemId = token.systemId; @@ -832,13 +808,13 @@ class BeforeHtmlPhase extends Phase { } @override - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return null; } @@ -859,7 +835,7 @@ class BeforeHtmlPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'head': case 'body': @@ -879,7 +855,7 @@ class BeforeHeadPhase extends Phase { BeforeHeadPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -892,7 +868,7 @@ class BeforeHeadPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'head': case 'body': @@ -912,7 +888,7 @@ class BeforeHeadPhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return null; } @@ -923,7 +899,7 @@ class BeforeHeadPhase extends Phase { } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -953,7 +929,7 @@ class InHeadPhase extends Phase { InHeadPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -987,7 +963,7 @@ class InHeadPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'head': endTagHead(token); @@ -1016,7 +992,7 @@ class InHeadPhase extends Phase { } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -1100,7 +1076,7 @@ class AfterHeadPhase extends Phase { AfterHeadPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -1130,7 +1106,7 @@ class AfterHeadPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'body': case 'html': @@ -1155,7 +1131,7 @@ class AfterHeadPhase extends Phase { } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -1219,7 +1195,7 @@ class InBodyPhase extends Phase { InBodyPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -1392,7 +1368,7 @@ class InBodyPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'body': endTagBody(token); @@ -1497,7 +1473,7 @@ class InBodyPhase extends Phase { final element = tree.openElements.last; final matchingElements = []; - for (Node node in tree.activeFormattingElements.reversed) { + for (Node? node in tree.activeFormattingElements.reversed) { if (node == null) { break; } else if (isMatchingFormattingElement(node as Element, element)) { @@ -1557,7 +1533,7 @@ class InBodyPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { if (token.data == '\u0000') { //The tokenizer should always emit null on its own return null; @@ -1571,7 +1547,7 @@ class InBodyPhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { if (dropNewline) { processSpaceCharactersDropNewline(token); } else { @@ -1581,7 +1557,7 @@ class InBodyPhase extends Phase { return null; } - Token startTagProcessInHead(StartTagToken token) { + Token? startTagProcessInHead(StartTagToken token) { return parser._inHeadPhase.processStartTag(token); } @@ -1605,7 +1581,7 @@ class InBodyPhase extends Phase { assert(parser.innerHTMLMode); } else if (parser.framesetOK) { if (tree.openElements[1].parentNode != null) { - tree.openElements[1].parentNode.nodes.remove(tree.openElements[1]); + tree.openElements[1].parentNode!.nodes.remove(tree.openElements[1]); } while (tree.openElements.last.localName != 'html') { tree.openElements.removeLast(); @@ -1651,7 +1627,7 @@ class InBodyPhase extends Phase { 'dt': ['dt', 'dd'], 'dd': ['dt', 'dd'] }; - final stopNames = stopNamesMap[token.name]; + final stopNames = stopNamesMap[token.name!]!; for (var node in tree.openElements.reversed) { if (stopNames.contains(node.localName)) { parser.phase.processEndTag(EndTagToken(node.localName)); @@ -1720,7 +1696,7 @@ class InBodyPhase extends Phase { addFormattingElement(token); } - Token startTagButton(StartTagToken token) { + Token? startTagButton(StartTagToken token) { if (tree.elementInScope('button')) { parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', {'startName': 'button', 'endName': 'button'}); @@ -1922,7 +1898,7 @@ class InBodyPhase extends Phase { token.span, 'unexpected-start-tag-ignored', {'name': token.name}); } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { tree.reconstructActiveFormattingElements(); tree.insertElement(token); return null; @@ -1978,7 +1954,7 @@ class InBodyPhase extends Phase { parser.phase = parser._afterBodyPhase; } - Token endTagHtml(EndTagToken token) { + Token? endTagHtml(EndTagToken token) { //We repeat the test for the body end tag token being ignored here if (tree.elementInScope('body')) { endTagBody(EndTagToken('body')); @@ -2021,7 +1997,7 @@ class InBodyPhase extends Phase { } void endTagListItem(EndTagToken token) { - String variant; + String? variant; if (token.name == 'li') { variant = 'list'; } else { @@ -2056,9 +2032,7 @@ class InBodyPhase extends Phase { while (!headingElements.contains(node.localName)) { node = tree.openElements.removeLast(); } - if (node != null) { - node.endSourceSpan = token.span; - } + node.endSourceSpan = token.span; break; } } @@ -2101,7 +2075,7 @@ class InBodyPhase extends Phase { // Step 2 // Start of the adoption agency algorithm proper final afeIndex = tree.openElements.indexOf(formattingElement); - Element furthestBlock; + Element? furthestBlock; for (var element in slice(tree.openElements, afeIndex)) { if (specialElements.contains(getElementNameTuple(element))) { furthestBlock = element; @@ -2114,9 +2088,7 @@ class InBodyPhase extends Phase { while (element != formattingElement) { element = tree.openElements.removeLast(); } - if (element != null) { - element.endSourceSpan = token.span; - } + element.endSourceSpan = token.span; tree.activeFormattingElements.remove(element); return; } @@ -2166,7 +2138,7 @@ class InBodyPhase extends Phase { // Step 6.6 // Remove lastNode from its parents, if any if (lastNode.parentNode != null) { - lastNode.parentNode.nodes.remove(lastNode); + lastNode.parentNode!.nodes.remove(lastNode); } node.nodes.add(lastNode); // Step 7.7 @@ -2179,13 +2151,13 @@ class InBodyPhase extends Phase { // table, tbody, tfoot, thead, or tr we need to foster parent the // lastNode if (lastNode.parentNode != null) { - lastNode.parentNode.nodes.remove(lastNode); + lastNode.parentNode!.nodes.remove(lastNode); } if (const ['table', 'tbody', 'tfoot', 'thead', 'tr'] .contains(commonAncestor.localName)) { final nodePos = tree.getTableMisnestedNodePosition(); - nodePos[0].insertBefore(lastNode, nodePos[1]); + nodePos[0]!.insertBefore(lastNode, nodePos[1]); } else { commonAncestor.nodes.add(lastNode); } @@ -2262,13 +2234,12 @@ class TextPhase extends Phase { // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name @override - // ignore: missing_return Token processStartTag(StartTagToken token) { - assert(false); + throw StateError('Cannot process start stag in text phase'); } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { if (token.name == 'script') { endTagScript(token); return null; @@ -2278,7 +2249,7 @@ class TextPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { tree.insertText(token.data, token.span); return null; } @@ -2289,21 +2260,21 @@ class TextPhase extends Phase { parser.parseError(last.sourceSpan, 'expected-named-closing-tag-but-got-eof', {'name': last.localName}); tree.openElements.removeLast(); - parser.phase = parser.originalPhase; + parser.phase = parser.originalPhase!; return true; } void endTagScript(EndTagToken token) { final node = tree.openElements.removeLast(); assert(node.localName == 'script'); - parser.phase = parser.originalPhase; + parser.phase = parser.originalPhase!; //The rest of this method is all stuff that only happens if //document.write works } void endTagOther(EndTagToken token) { tree.openElements.removeLast(); - parser.phase = parser.originalPhase; + parser.phase = parser.originalPhase!; } } @@ -2312,7 +2283,7 @@ class InTablePhase extends Phase { InTablePhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -2351,7 +2322,7 @@ class InTablePhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'table': endTagTable(token); @@ -2401,7 +2372,7 @@ class InTablePhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { final originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; @@ -2410,7 +2381,7 @@ class InTablePhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { final originalPhase = parser.phase; parser.phase = parser._inTableTextPhase; parser._inTableTextPhase.originalPhase = originalPhase; @@ -2457,7 +2428,7 @@ class InTablePhase extends Phase { return token; } - Token startTagTable(StartTagToken token) { + Token? startTagTable(StartTagToken token) { parser.parseError(token.span, 'unexpected-start-tag-implies-end-tag', {'startName': 'table', 'endName': 'table'}); parser.phase.processEndTag(EndTagToken('table')); @@ -2467,7 +2438,7 @@ class InTablePhase extends Phase { return null; } - Token startTagStyleScript(StartTagToken token) { + Token? startTagStyleScript(StartTagToken token) { return parser._inHeadPhase.processStartTag(token); } @@ -2536,7 +2507,7 @@ class InTablePhase extends Phase { } class InTableTextPhase extends Phase { - Phase originalPhase; + Phase? originalPhase; List<StringToken> characterTokens; InTableTextPhase(HtmlParser parser) @@ -2548,10 +2519,10 @@ class InTableTextPhase extends Phase { // TODO(sigmund,jmesserly): remove '' (dartbug.com/8480) final data = characterTokens.map((t) => t.data).join(''); - FileSpan span; + FileSpan? span; if (parser.generateSpans) { - span = characterTokens[0].span.expand(characterTokens.last.span); + span = characterTokens[0].span!.expand(characterTokens.last.span!); } if (!allWhitespace(data)) { @@ -2565,19 +2536,19 @@ class InTableTextPhase extends Phase { @override Token processComment(CommentToken token) { flushCharacters(); - parser.phase = originalPhase; + parser.phase = originalPhase!; return token; } @override bool processEOF() { flushCharacters(); - parser.phase = originalPhase; + parser.phase = originalPhase!; return true; } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { if (token.data == '\u0000') { return null; } @@ -2586,7 +2557,7 @@ class InTableTextPhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { //pretty sure we should never reach here characterTokens.add(token); // XXX assert(false); @@ -2596,14 +2567,14 @@ class InTableTextPhase extends Phase { @override Token processStartTag(StartTagToken token) { flushCharacters(); - parser.phase = originalPhase; + parser.phase = originalPhase!; return token; } @override Token processEndTag(EndTagToken token) { flushCharacters(); - parser.phase = originalPhase; + parser.phase = originalPhase!; return token; } } @@ -2613,7 +2584,7 @@ class InCaptionPhase extends Phase { InCaptionPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -2633,7 +2604,7 @@ class InCaptionPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'caption': endTagCaption(token); @@ -2668,11 +2639,11 @@ class InCaptionPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { return parser._inBodyPhase.processCharacters(token); } - Token startTagTableElement(StartTagToken token) { + Token? startTagTableElement(StartTagToken token) { parser.parseError(token.span, 'undefined-error'); //XXX Have to duplicate logic here to find out if the tag is ignored final ignoreEndTag = ignoreEndTagCaption(); @@ -2683,7 +2654,7 @@ class InCaptionPhase extends Phase { return null; } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -2711,7 +2682,7 @@ class InCaptionPhase extends Phase { } } - Token endTagTable(EndTagToken token) { + Token? endTagTable(EndTagToken token) { parser.parseError(token.span, 'undefined-error'); final ignoreEndTag = ignoreEndTagCaption(); parser.phase.processEndTag(EndTagToken('caption')); @@ -2725,7 +2696,7 @@ class InCaptionPhase extends Phase { parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { return parser._inBodyPhase.processEndTag(token); } } @@ -2735,7 +2706,7 @@ class InColumnGroupPhase extends Phase { InColumnGroupPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -2748,7 +2719,7 @@ class InColumnGroupPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'colgroup': endTagColgroup(token); @@ -2778,7 +2749,7 @@ class InColumnGroupPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; @@ -2789,7 +2760,7 @@ class InColumnGroupPhase extends Phase { tree.openElements.removeLast(); } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; @@ -2811,7 +2782,7 @@ class InColumnGroupPhase extends Phase { parser.parseError(token.span, 'no-end-tag', {'name': 'col'}); } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { final ignoreEndTag = ignoreEndTagColgroup(); endTagColgroup(EndTagToken('colgroup')); return ignoreEndTag ? null : token; @@ -2823,7 +2794,7 @@ class InTableBodyPhase extends Phase { InTableBodyPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -2846,7 +2817,7 @@ class InTableBodyPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'tbody': case 'tfoot': @@ -2891,12 +2862,12 @@ class InTableBodyPhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return parser._inTablePhase.processSpaceCharacters(token); } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { return parser._inTablePhase.processCharacters(token); } @@ -2913,9 +2884,9 @@ class InTableBodyPhase extends Phase { return token; } - Token startTagTableOther(TagToken token) => endTagTable(token); + Token? startTagTableOther(TagToken token) => endTagTable(token); - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { return parser._inTablePhase.processStartTag(token); } @@ -2931,7 +2902,7 @@ class InTableBodyPhase extends Phase { } } - Token endTagTable(TagToken token) { + Token? endTagTable(TagToken token) { // XXX AT Any ideas on how to share this with endTagTable? if (tree.elementInScope('tbody', variant: 'table') || tree.elementInScope('thead', variant: 'table') || @@ -2952,7 +2923,7 @@ class InTableBodyPhase extends Phase { token.span, 'unexpected-end-tag-in-table-body', {'name': token.name}); } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { return parser._inTablePhase.processEndTag(token); } } @@ -2962,7 +2933,7 @@ class InRowPhase extends Phase { InRowPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -2984,7 +2955,7 @@ class InRowPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'tr': endTagTr(token); @@ -3035,12 +3006,12 @@ class InRowPhase extends Phase { } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return parser._inTablePhase.processSpaceCharacters(token); } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { return parser._inTablePhase.processCharacters(token); } @@ -3051,14 +3022,14 @@ class InRowPhase extends Phase { tree.activeFormattingElements.add(null); } - Token startTagTableOther(StartTagToken token) { + Token? startTagTableOther(StartTagToken token) { final ignoreEndTag = ignoreEndTagTr(); endTagTr(EndTagToken('tr')); // XXX how are we sure it's always ignored in the innerHTML case? return ignoreEndTag ? null : token; } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { return parser._inTablePhase.processStartTag(token); } @@ -3075,7 +3046,7 @@ class InRowPhase extends Phase { } } - Token endTagTable(EndTagToken token) { + Token? endTagTable(EndTagToken token) { final ignoreEndTag = ignoreEndTagTr(); endTagTr(EndTagToken('tr')); // Reprocess the current tag if the tr end tag was not ignored @@ -3083,7 +3054,7 @@ class InRowPhase extends Phase { return ignoreEndTag ? null : token; } - Token endTagTableRowGroup(EndTagToken token) { + Token? endTagTableRowGroup(EndTagToken token) { if (tree.elementInScope(token.name, variant: 'table')) { endTagTr(EndTagToken('tr')); return token; @@ -3098,7 +3069,7 @@ class InRowPhase extends Phase { token.span, 'unexpected-end-tag-in-table-row', {'name': token.name}); } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { return parser._inTablePhase.processEndTag(token); } } @@ -3108,7 +3079,7 @@ class InCellPhase extends Phase { InCellPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -3128,7 +3099,7 @@ class InCellPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'td': case 'th': @@ -3169,11 +3140,11 @@ class InCellPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { return parser._inBodyPhase.processCharacters(token); } - Token startTagTableOther(StartTagToken token) { + Token? startTagTableOther(StartTagToken token) { if (tree.elementInScope('td', variant: 'table') || tree.elementInScope('th', variant: 'table')) { closeCell(); @@ -3186,7 +3157,7 @@ class InCellPhase extends Phase { } } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -3212,7 +3183,7 @@ class InCellPhase extends Phase { parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } - Token endTagImply(EndTagToken token) { + Token? endTagImply(EndTagToken token) { if (tree.elementInScope(token.name, variant: 'table')) { closeCell(); return token; @@ -3223,7 +3194,7 @@ class InCellPhase extends Phase { return null; } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { return parser._inBodyPhase.processEndTag(token); } } @@ -3232,7 +3203,7 @@ class InSelectPhase extends Phase { InSelectPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -3257,7 +3228,7 @@ class InSelectPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'option': endTagOption(token); @@ -3287,7 +3258,7 @@ class InSelectPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { if (token.data == '\u0000') { return null; } @@ -3318,7 +3289,7 @@ class InSelectPhase extends Phase { endTagSelect(EndTagToken('select')); } - Token startTagInput(StartTagToken token) { + Token? startTagInput(StartTagToken token) { parser.parseError(token.span, 'unexpected-input-in-select'); if (tree.elementInScope('select', variant: 'select')) { endTagSelect(EndTagToken('select')); @@ -3329,11 +3300,11 @@ class InSelectPhase extends Phase { return null; } - Token startTagScript(StartTagToken token) { + Token? startTagScript(StartTagToken token) { return parser._inHeadPhase.processStartTag(token); } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { parser.parseError( token.span, 'unexpected-start-tag-in-select', {'name': token.name}); return null; @@ -3388,7 +3359,7 @@ class InSelectInTablePhase extends Phase { InSelectInTablePhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'caption': case 'table': @@ -3405,7 +3376,7 @@ class InSelectInTablePhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'caption': case 'table': @@ -3428,7 +3399,7 @@ class InSelectInTablePhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { return parser._inSelectPhase.processCharacters(token); } @@ -3441,11 +3412,11 @@ class InSelectInTablePhase extends Phase { return token; } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { return parser._inSelectPhase.processStartTag(token); } - Token endTagTable(EndTagToken token) { + Token? endTagTable(EndTagToken token) { parser.parseError( token.span, 'unexpected-table-element-end-tag-in-select-in-table', @@ -3457,7 +3428,7 @@ class InSelectInTablePhase extends Phase { return null; } - Token endTagOther(EndTagToken token) { + Token? endTagOther(EndTagToken token) { return parser._inSelectPhase.processEndTag(token); } } @@ -3560,7 +3531,7 @@ class InForeignContentPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { if (token.data == '\u0000') { token.replaceData('\uFFFD'); } else if (parser.framesetOK && !allWhitespace(token.data)) { @@ -3570,7 +3541,7 @@ class InForeignContentPhase extends Phase { } @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { final currentNode = tree.openElements.last; if (breakoutElements.contains(token.name) || (token.name == 'font' && @@ -3604,21 +3575,21 @@ class InForeignContentPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { var nodeIndex = tree.openElements.length - 1; var node = tree.openElements.last; if (node.localName?.toAsciiLowerCase() != token.name) { parser.parseError(token.span, 'unexpected-end-tag', {'name': token.name}); } - Token newToken; + Token? newToken; while (true) { if (node.localName?.toAsciiLowerCase() == token.name) { //XXX this isn't in the spec but it seems necessary if (parser.phase == parser._inTableTextPhase) { final inTableText = parser.phase as InTableTextPhase; inTableText.flushCharacters(); - parser.phase = inTableText.originalPhase; + parser.phase = inTableText.originalPhase!; } while (tree.openElements.removeLast() != node) { assert(tree.openElements.isNotEmpty); @@ -3644,13 +3615,13 @@ class AfterBodyPhase extends Phase { AfterBodyPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { if (token.name == 'html') return startTagHtml(token); return startTagOther(token); } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { if (token.name == 'html') { endTagHtml(token); return null; @@ -3663,7 +3634,7 @@ class AfterBodyPhase extends Phase { bool processEOF() => false; @override - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { // This is needed because data is to be appended to the <html> element // here and not to whatever is currently open. tree.insertComment(token, tree.openElements[0]); @@ -3678,7 +3649,7 @@ class AfterBodyPhase extends Phase { } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -3716,7 +3687,7 @@ class InFramesetPhase extends Phase { InFramesetPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -3734,7 +3705,7 @@ class InFramesetPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'frameset': endTagFrameset(token); @@ -3757,7 +3728,7 @@ class InFramesetPhase extends Phase { } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { parser.parseError(token.span, 'unexpected-char-in-frameset'); return null; } @@ -3771,11 +3742,11 @@ class InFramesetPhase extends Phase { tree.openElements.removeLast(); } - Token startTagNoframes(StartTagToken token) { + Token? startTagNoframes(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } - Token startTagOther(StartTagToken token) { + Token? startTagOther(StartTagToken token) { parser.parseError( token.span, 'unexpected-start-tag-in-frameset', {'name': token.name}); return null; @@ -3809,7 +3780,7 @@ class AfterFramesetPhase extends Phase { AfterFramesetPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -3822,7 +3793,7 @@ class AfterFramesetPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { switch (token.name) { case 'html': endTagHtml(token); @@ -3838,12 +3809,12 @@ class AfterFramesetPhase extends Phase { bool processEOF() => false; @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { parser.parseError(token.span, 'unexpected-char-after-frameset'); return null; } - Token startTagNoframes(StartTagToken token) { + Token? startTagNoframes(StartTagToken token) { return parser._inHeadPhase.processStartTag(token); } @@ -3866,7 +3837,7 @@ class AfterAfterBodyPhase extends Phase { AfterAfterBodyPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { if (token.name == 'html') return startTagHtml(token); return startTagOther(token); } @@ -3875,13 +3846,13 @@ class AfterAfterBodyPhase extends Phase { bool processEOF() => false; @override - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return parser._inBodyPhase.processSpaceCharacters(token); } @@ -3893,7 +3864,7 @@ class AfterAfterBodyPhase extends Phase { } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } @@ -3917,7 +3888,7 @@ class AfterAfterFramesetPhase extends Phase { AfterAfterFramesetPhase(HtmlParser parser) : super(parser); @override - Token processStartTag(StartTagToken token) { + Token? processStartTag(StartTagToken token) { switch (token.name) { case 'html': return startTagHtml(token); @@ -3933,28 +3904,28 @@ class AfterAfterFramesetPhase extends Phase { bool processEOF() => false; @override - Token processComment(CommentToken token) { + Token? processComment(CommentToken token) { tree.insertComment(token, tree.document); return null; } @override - Token processSpaceCharacters(SpaceCharactersToken token) { + Token? processSpaceCharacters(SpaceCharactersToken token) { return parser._inBodyPhase.processSpaceCharacters(token); } @override - Token processCharacters(CharactersToken token) { + Token? processCharacters(CharactersToken token) { parser.parseError(token.span, 'expected-eof-but-got-char'); return null; } @override - Token startTagHtml(StartTagToken token) { + Token? startTagHtml(StartTagToken token) { return parser._inBodyPhase.processStartTag(token); } - Token startTagNoFrames(StartTagToken token) { + Token? startTagNoFrames(StartTagToken token) { return parser._inHeadPhase.processStartTag(token); } @@ -3964,7 +3935,7 @@ class AfterAfterFramesetPhase extends Phase { } @override - Token processEndTag(EndTagToken token) { + Token? processEndTag(EndTagToken token) { parser.parseError( token.span, 'expected-eof-but-got-end-tag', {'name': token.name}); return null; @@ -3975,14 +3946,14 @@ class AfterAfterFramesetPhase extends Phase { class ParseError implements SourceSpanException { final String errorCode; @override - final SourceSpan span; - final Map data; + final SourceSpan? span; + final Map? data; ParseError(this.errorCode, this.span, this.data); - int get line => span.start.line; + int get line => span!.start.line; - int get column => span.start.column; + int get column => span!.start.column; /// Gets the human readable error message for this error. Use /// [span.getLocationMessage] or [toString] to get a message including span @@ -3991,17 +3962,17 @@ class ParseError implements SourceSpanException { /// [span.getLocationMessage] will not show any source url information, but /// [toString] will include 'ParserError:' as a prefix. @override - String get message => formatStr(errorMessages[errorCode], data); + String get message => formatStr(errorMessages[errorCode]!, data); @override String toString({color}) { - final res = span.message(message, color: color); - return span.sourceUrl == null ? 'ParserError on $res' : 'On $res'; + final res = span!.message(message, color: color); + return span!.sourceUrl == null ? 'ParserError on $res' : 'On $res'; } } /// Convenience function to get the pair of namespace and localName. -Pair<String, String> getElementNameTuple(Element e) { +Pair<String, String?> getElementNameTuple(Element e) { final ns = e.namespaceUri ?? Namespaces.html; return Pair(ns, e.localName); } diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index e1fad5a60..52c08d79d 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -4,7 +4,7 @@ import 'utils.dart'; // lookup than linear search "contains". In the Python code they were // frozensets. -final String eof = null; +final String? eof = null; class ReparseException implements Exception { final String message; @@ -243,7 +243,7 @@ class Namespaces { static const xmlns = 'http://www.w3.org/2000/xmlns/'; Namespaces._(); - static String getPrefix(String url) { + static String? getPrefix(String? url) { switch (url) { case html: return 'html'; @@ -403,7 +403,7 @@ const spaceCharacters = ' \n\r\t\u000C'; const int NEWLINE = 10; const int RETURN = 13; -bool isWhitespace(String char) { +bool isWhitespace(String? char) { if (char == null) return false; return isWhitespaceCC(char.codeUnitAt(0)); } @@ -437,22 +437,22 @@ const LOWER_Z = 122; const UPPER_A = 65; const UPPER_Z = 90; -bool isLetterOrDigit(String char) => isLetter(char) || isDigit(char); +bool isLetterOrDigit(String? char) => isLetter(char) || isDigit(char); // Note: this is intentially ASCII only -bool isLetter(String char) { +bool isLetter(String? char) { if (char == null) return false; final cc = char.codeUnitAt(0); return cc >= LOWER_A && cc <= LOWER_Z || cc >= UPPER_A && cc <= UPPER_Z; } -bool isDigit(String char) { +bool isDigit(String? char) { if (char == null) return false; final cc = char.codeUnitAt(0); return cc >= ZERO && cc < ZERO + 10; } -bool isHexDigit(String char) { +bool isHexDigit(String? char) { if (char == null) return false; switch (char.codeUnitAt(0)) { case 48: diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 3f98a336e..166d30dfc 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -41,7 +41,7 @@ abstract class CssClassSet implements Set<String> { /// /// If [shouldAdd] is true, then we always add that [value] to the element. If /// [shouldAdd] is false then we always remove [value] from the element. - bool toggle(String value, [bool shouldAdd]); + bool toggle(String value, [bool? shouldAdd]); /// Returns [:true:] if classes cannot be added or removed from this /// [:CssClassSet:]. @@ -52,7 +52,7 @@ abstract class CssClassSet implements Set<String> { /// This is the Dart equivalent of jQuery's /// [hasClass](http://api.jquery.com/hasClass/). @override - bool contains(Object value); + bool contains(Object? value); /// Add the class [value] to element. /// @@ -72,7 +72,7 @@ abstract class CssClassSet implements Set<String> { /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). @override - bool remove(Object value); + bool remove(Object? value); /// Add all classes specified in [iterable] to element. /// @@ -86,7 +86,7 @@ abstract class CssClassSet implements Set<String> { /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). @override - void removeAll(Iterable<Object> iterable); + void removeAll(Iterable<Object?> iterable); /// Toggles all classes specified in [iterable] on element. /// @@ -96,7 +96,7 @@ abstract class CssClassSet implements Set<String> { /// If [shouldAdd] is true, then we always add all the classes in [iterable] /// element. If [shouldAdd] is false then we always remove all the classes in /// [iterable] from the element. - void toggleAll(Iterable<String> iterable, [bool shouldAdd]); + void toggleAll(Iterable<String> iterable, [bool? shouldAdd]); } abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { @@ -111,7 +111,7 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// If [shouldAdd] is true, then we always add that [value] to the element. If /// [shouldAdd] is false then we always remove [value] from the element. @override - bool toggle(String value, [bool shouldAdd]) { + bool toggle(String value, [bool? shouldAdd]) { final s = readClasses(); var result = false; shouldAdd ??= !s.contains(value); @@ -142,11 +142,11 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// This is the Dart equivalent of jQuery's /// [hasClass](http://api.jquery.com/hasClass/). @override - bool contains(Object value) => readClasses().contains(value); + bool contains(Object? value) => readClasses().contains(value); /// Lookup from the Set interface. Not interesting for a String set. @override - String lookup(Object value) => contains(value) ? value as String : null; + String? lookup(Object? value) => contains(value) ? value as String? : null; @override Set<String> toSet() => readClasses().toSet(); @@ -168,7 +168,7 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// This is the Dart equivalent of jQuery's /// [removeClass](http://api.jquery.com/removeClass/). @override - bool remove(Object value) { + bool remove(Object? value) { if (value is! String) return false; final s = readClasses(); final result = s.remove(value); @@ -185,7 +185,7 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// element. If [shouldAdd] is false then we always remove all the classes in /// [iterable] from the element. @override - void toggleAll(Iterable<String> iterable, [bool shouldAdd]) { + void toggleAll(Iterable<String> iterable, [bool? shouldAdd]) { iterable.forEach((e) => toggle(e, shouldAdd)); } diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index 6fa96c6f3..e41735170 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -56,7 +56,7 @@ class EncodingBytes { String get _currentByte => _bytes[_position]; /// Skip past a list of characters. Defaults to skipping [isWhitespace]. - String _skipChars([_CharPredicate skipChars]) { + String? _skipChars([_CharPredicate? skipChars]) { skipChars ??= isWhitespace; var p = _position; // use property for the error-checking while (p < _length) { @@ -71,7 +71,7 @@ class EncodingBytes { return null; } - String _skipUntil(_CharPredicate untilChars) { + String? _skipUntil(_CharPredicate untilChars) { var p = _position; while (p < _length) { final c = _bytes[p]; @@ -112,7 +112,7 @@ class EncodingBytes { } } - String _slice(int start, [int end]) { + String _slice(int start, [int? end]) { end ??= _length; if (end < 0) end += _length; return _bytes.substring(start, end); @@ -131,14 +131,14 @@ class _DispatchEntry { /// Mini parser for detecting character encoding from meta elements. class EncodingParser { final EncodingBytes _data; - String _encoding; + String? _encoding; /// [bytes] - the data to work on for encoding detection. EncodingParser(List<int> bytes) // Note: this is intentionally interpreting bytes as codepoints. : _data = EncodingBytes(String.fromCharCodes(bytes).toLowerCase()); - String getEncoding() { + String? getEncoding() { final methodDispatch = [ _DispatchEntry('<!--', _handleComment), _DispatchEntry('<meta', _handleMeta), @@ -239,7 +239,7 @@ class EncodingParser { /// Return a name,value pair for the next attribute in the stream, /// if one is found, or null - List<String> _getAttribute() { + List<String>? _getAttribute() { // Step 1 (skip chars) var c = _data._skipChars((x) => x == '/' || isWhitespace(x)); // Step 2 @@ -312,8 +312,6 @@ class EncodingParser { c = _data._next(); if (_isSpaceOrAngleBracket(c)) { return [attrName.join(), attrValue.join()]; - } else if (c == null) { - return null; } else if (isLetter(c)) { attrValue.add(c.toLowerCase()); } else { @@ -328,7 +326,7 @@ class ContentAttrParser { ContentAttrParser(this.data); - String parse() { + String? parse() { try { // Check if the attr name is charset // otherwise return diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 76499738e..c4e03b56e 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -20,7 +20,7 @@ class HtmlInputStream { static const String defaultEncoding = 'utf-8'; /// The name of the character encoding. - String charEncodingName; + String? charEncodingName; /// True if we are certain about [charEncodingName], false for tenative. bool charEncodingCertain = true; @@ -28,20 +28,20 @@ class HtmlInputStream { final bool generateSpans; /// Location where the contents of the stream were found. - final String sourceUrl; + final String? sourceUrl; - List<int> _rawBytes; + List<int>? _rawBytes; /// Raw UTF-16 codes, used if a Dart String is passed in. - List<int> _rawChars; + List<int>? _rawChars; - Queue<String> errors; + var errors = Queue<String>(); - SourceFile fileInfo; + SourceFile? fileInfo; - List<int> _chars; + var _chars = <int>[]; - int _offset; + var _offset = 0; /// Initialises the HtmlInputStream. /// @@ -58,7 +58,7 @@ class HtmlInputStream { /// /// [parseMeta] - Look for a <meta> element containing encoding information HtmlInputStream(source, - [String encoding, + [String? encoding, bool parseMeta = true, this.generateSpans = false, this.sourceUrl]) @@ -88,18 +88,18 @@ class HtmlInputStream { _offset = 0; _chars = <int>[]; - _rawChars ??= _decodeBytes(charEncodingName, _rawBytes); + final rawChars = _rawChars ??= _decodeBytes(charEncodingName!, _rawBytes!); var skipNewline = false; var wasSurrogatePair = false; - for (var i = 0; i < _rawChars.length; i++) { - var c = _rawChars[i]; + for (var i = 0; i < rawChars.length; i++) { + var c = rawChars[i]; if (skipNewline) { skipNewline = false; if (c == NEWLINE) continue; } - final isSurrogatePair = _isSurrogatePair(_rawChars, i); + final isSurrogatePair = _isSurrogatePair(rawChars, i); if (!isSurrogatePair && !wasSurrogatePair) { if (_invalidUnicode(c)) { errors.add('invalid-codepoint'); @@ -146,12 +146,12 @@ class HtmlInputStream { } // Substitute for equivalent encodings: - if (charEncodingName.toLowerCase() == 'iso-8859-1') { + if (charEncodingName!.toLowerCase() == 'iso-8859-1') { charEncodingName = 'windows-1252'; } } - void changeEncoding(String newEncoding) { + void changeEncoding(String? newEncoding) { if (_rawBytes == null) { // We should never get here -- if encoding is certain we won't try to // change it. @@ -179,17 +179,17 @@ class HtmlInputStream { /// Attempts to detect at BOM at the start of the stream. If /// an encoding can be determined from the BOM return the name of the /// encoding otherwise return null. - String detectBOM() { + String? detectBOM() { // Try detecting the BOM using bytes from the string - if (_hasUtf8Bom(_rawBytes)) { + if (_hasUtf8Bom(_rawBytes!)) { return 'utf-8'; } return null; } /// Report the encoding declared by the meta element. - String detectEncodingMeta() { - final parser = EncodingParser(slice(_rawBytes, 0, numBytesMeta)); + String? detectEncodingMeta() { + final parser = EncodingParser(slice(_rawBytes!, 0, numBytesMeta)); var encoding = parser.getEncoding(); if (const ['utf-16', 'utf-16-be', 'utf-16-le'].contains(encoding)) { @@ -205,14 +205,14 @@ class HtmlInputStream { /// Read one character from the stream or queue if available. Return /// EOF when EOF is reached. - String char() { + String? char() { if (_offset >= _chars.length) return eof; return _isSurrogatePair(_chars, _offset) ? String.fromCharCodes([_chars[_offset++], _chars[_offset++]]) : String.fromCharCodes([_chars[_offset++]]); } - String peekChar() { + String? peekChar() { if (_offset >= _chars.length) return eof; return _isSurrogatePair(_chars, _offset) ? String.fromCharCodes([_chars[_offset], _chars[_offset + 1]]) @@ -236,15 +236,15 @@ class HtmlInputStream { /// including any character in 'characters' or EOF. String charsUntil(String characters, [bool opposite = false]) { final start = _offset; - String c; - while ((c = peekChar()) != null && characters.contains(c) == opposite) { + String? c; + while ((c = peekChar()) != null && characters.contains(c!) == opposite) { _offset += c.codeUnits.length; } return String.fromCharCodes(_chars.sublist(start, _offset)); } - void unget(String ch) { + void unget(String? ch) { // Only one character is allowed to be ungotten at once - it must // be consumed again before any further call to unget if (ch != null) { @@ -305,7 +305,7 @@ bool _invalidUnicode(int c) { /// Return the python codec name corresponding to an encoding or null if the /// string doesn't correspond to a valid encoding. -String codecName(String encoding) { +String? codecName(String? encoding) { final asciiPunctuation = RegExp( '[\u0009-\u000D\u0020-\u002F\u003A-\u0040\u005B-\u0060\u007B-\u007E]'); @@ -317,7 +317,7 @@ String codecName(String encoding) { /// Returns true if the [bytes] starts with a UTF-8 byte order mark. /// Since UTF-8 doesn't have byte order, it's somewhat of a misnomer, but it is /// used in HTML to detect the UTF- -bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int length]) { +bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int? length]) { final end = length != null ? offset + length : bytes.length; return (offset + 3) <= end && bytes[offset] == 0xEF && diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index ef271abd4..61784c7b9 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -8,7 +8,7 @@ abstract class ListProxy<E> extends ListBase<E> { final List<E> _list = <E>[]; @override - bool remove(Object item) => _list.remove(item); + bool remove(Object? item) => _list.remove(item); @override int get length => _list.length; diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 9d0985753..8880cfe7e 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -10,7 +10,7 @@ import 'package:html/src/constants.dart' show isWhitespaceCC; bool matches(Element node, String selector) => SelectorEvaluator().matches(node, _parseSelectorList(selector)); -Element querySelector(Node node, String selector) => +Element? querySelector(Node node, String selector) => SelectorEvaluator().querySelector(node, _parseSelectorList(selector)); List<Element> querySelectorAll(Node node, String selector) { @@ -32,14 +32,14 @@ SelectorGroup _parseSelectorList(String selector) { class SelectorEvaluator extends Visitor { /// The current HTML element to match against. - Element _element; + Element? _element; bool matches(Element element, SelectorGroup selector) { _element = element; return visitSelectorGroup(selector); } - Element querySelector(Node root, SelectorGroup selector) { + Element? querySelector(Node root, SelectorGroup selector) { for (var element in root.nodes.whereType<Element>()) { if (matches(element, selector)) return element; final result = querySelector(element, selector); @@ -66,7 +66,7 @@ class SelectorEvaluator extends Visitor { var result = true; // Note: evaluate selectors right-to-left as it's more efficient. - int combinator; + int? combinator; for (var s in selector.simpleSelectorSequences.reversed) { if (combinator == null) { result = s.simpleSelector.visit(this) as bool; @@ -74,7 +74,7 @@ class SelectorEvaluator extends Visitor { // descendant combinator // http://dev.w3.org/csswg/selectors-4/#descendant-combinators do { - _element = _element.parent; + _element = _element!.parent; } while (_element != null && !(s.simpleSelector.visit(this) as bool)); if (_element == null) result = false; @@ -82,7 +82,7 @@ class SelectorEvaluator extends Visitor { // Following-sibling combinator // http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators do { - _element = _element.previousElementSibling; + _element = _element!.previousElementSibling; } while (_element != null && !(s.simpleSelector.visit(this) as bool)); if (_element == null) result = false; @@ -94,12 +94,12 @@ class SelectorEvaluator extends Visitor { case TokenKind.COMBINATOR_PLUS: // Next-sibling combinator // http://dev.w3.org/csswg/selectors-4/#adjacent-sibling-combinators - _element = _element.previousElementSibling; + _element = _element!.previousElementSibling; break; case TokenKind.COMBINATOR_GREATER: // Child combinator // http://dev.w3.org/csswg/selectors-4/#child-combinators - _element = _element.parent; + _element = _element!.parent; break; case TokenKind.COMBINATOR_DESCENDANT: case TokenKind.COMBINATOR_TILDE: @@ -139,34 +139,34 @@ class SelectorEvaluator extends Visitor { case 'root': // TODO(jmesserly): fix when we have a .ownerDocument pointer // return _element == _element.ownerDocument.rootElement; - return _element.localName == 'html' && _element.parentNode == null; + return _element!.localName == 'html' && _element!.parentNode == null; // http://dev.w3.org/csswg/selectors-4/#the-empty-pseudo case 'empty': - return _element.nodes + return _element!.nodes .any((n) => !(n is Element || n is Text && n.text.isNotEmpty)); // http://dev.w3.org/csswg/selectors-4/#the-blank-pseudo case 'blank': - return _element.nodes.any((n) => !(n is Element || + return _element!.nodes.any((n) => !(n is Element || n is Text && n.text.runes.any((r) => !isWhitespaceCC(r)))); // http://dev.w3.org/csswg/selectors-4/#the-first-child-pseudo case 'first-child': - return _element.previousElementSibling == null; + return _element!.previousElementSibling == null; // http://dev.w3.org/csswg/selectors-4/#the-last-child-pseudo case 'last-child': - return _element.nextElementSibling == null; + return _element!.nextElementSibling == null; // http://dev.w3.org/csswg/selectors-4/#the-only-child-pseudo case 'only-child': - return _element.previousElementSibling == null && - _element.nextElementSibling == null; + return _element!.previousElementSibling == null && + _element!.nextElementSibling == null; // http://dev.w3.org/csswg/selectors-4/#link case 'link': - return _element.attributes['href'] != null; + return _element!.attributes['href'] != null; case 'visited': // Always return false since we aren't a browser. This is allowed per: @@ -215,7 +215,7 @@ class SelectorEvaluator extends Visitor { final exprs = selector.expression.expressions; if (exprs.length == 1 && exprs[0] is LiteralTerm) { final literal = exprs[0] as LiteralTerm; - final parent = _element.parentNode; + final parent = _element!.parentNode; return parent != null && (literal.value as num) > 0 && parent.nodes.indexOf(_element) == literal.value; @@ -234,7 +234,7 @@ class SelectorEvaluator extends Visitor { throw _unimplemented(selector); } - static String _getInheritedLanguage(Node node) { + static String? _getInheritedLanguage(Node? node) { while (node != null) { final lang = node.attributes['lang']; if (lang != null) return lang; @@ -246,37 +246,37 @@ class SelectorEvaluator extends Visitor { @override bool visitNamespaceSelector(NamespaceSelector selector) { // Match element tag name - if (!(selector.nameAsSimpleSelector.visit(this) as bool)) return false; + if (!(selector.nameAsSimpleSelector!.visit(this) as bool)) return false; if (selector.isNamespaceWildcard) return true; - if (selector.namespace == '') return _element.namespaceUri == null; + if (selector.namespace == '') return _element!.namespaceUri == null; throw _unimplemented(selector); } @override bool visitElementSelector(ElementSelector selector) => - selector.isWildcard || _element.localName == selector.name.toLowerCase(); + selector.isWildcard || _element!.localName == selector.name.toLowerCase(); @override - bool visitIdSelector(IdSelector selector) => _element.id == selector.name; + bool visitIdSelector(IdSelector selector) => _element!.id == selector.name; @override bool visitClassSelector(ClassSelector selector) => - _element.classes.contains(selector.name); + _element!.classes.contains(selector.name); // TODO(jmesserly): negation should support any selectors in level 4, // not just simple selectors. // http://dev.w3.org/csswg/selectors-4/#negation @override bool visitNegationSelector(NegationSelector selector) => - !(selector.negationArg.visit(this) as bool); + !(selector.negationArg!.visit(this) as bool); @override bool visitAttributeSelector(AttributeSelector selector) { // Match name first - final value = _element.attributes[selector.name.toLowerCase()]; + final value = _element!.attributes[selector.name.toLowerCase()]; if (value == null) return false; if (selector.operatorKind == TokenKind.NO_MATCH) return true; diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 05fe58dce..8d995bcc1 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -6,13 +6,13 @@ import 'package:source_span/source_span.dart'; /// An html5 token. abstract class Token { - FileSpan span; + FileSpan? span; int get kind; } abstract class TagToken extends Token { - String name; + String? name; bool selfClosing; @@ -25,26 +25,27 @@ class StartTagToken extends TagToken { LinkedHashMap<Object, String> data; /// The attribute spans if requested. Otherwise null. - List<TagAttribute> attributeSpans; + List<TagAttribute>? attributeSpans; bool selfClosingAcknowledged; /// The namespace. This is filled in later during tree building. - String namespace; + String? namespace; - StartTagToken(String name, - {this.data, + StartTagToken(String? name, + {LinkedHashMap<Object, String>? data, bool selfClosing = false, this.selfClosingAcknowledged = false, this.namespace}) - : super(name, selfClosing); + : data = data ?? LinkedHashMap(), + super(name, selfClosing); @override int get kind => TokenKind.startTag; } class EndTagToken extends TagToken { - EndTagToken(String name, {bool selfClosing = false}) + EndTagToken(String? name, {bool selfClosing = false}) : super(name, selfClosing); @override @@ -52,28 +53,28 @@ class EndTagToken extends TagToken { } abstract class StringToken extends Token { - StringBuffer _buffer; + StringBuffer? _buffer; - String _string; + String? _string; String get data { if (_string == null) { _string = _buffer.toString(); _buffer = null; } - return _string; + return _string!; } StringToken(this._string) : _buffer = _string == null ? StringBuffer() : null; StringToken add(String data) { - _buffer.write(data); + _buffer!.write(data); return this; } } class ParseErrorToken extends StringToken { /// Extra information that goes along with the error message. - Map messageParams; + Map? messageParams; ParseErrorToken(String data, {this.messageParams}) : super(data); @@ -82,7 +83,7 @@ class ParseErrorToken extends StringToken { } class CharactersToken extends StringToken { - CharactersToken([String data]) : super(data); + CharactersToken([String? data]) : super(data); @override int get kind => TokenKind.characters; @@ -96,23 +97,23 @@ class CharactersToken extends StringToken { } class SpaceCharactersToken extends StringToken { - SpaceCharactersToken([String data]) : super(data); + SpaceCharactersToken([String? data]) : super(data); @override int get kind => TokenKind.spaceCharacters; } class CommentToken extends StringToken { - CommentToken([String data]) : super(data); + CommentToken([String? data]) : super(data); @override int get kind => TokenKind.comment; } class DoctypeToken extends Token { - String publicId; - String systemId; - String name = ''; + String? publicId; + String? systemId; + String? name = ''; bool correct; DoctypeToken({this.publicId, this.systemId, this.correct = false}); @@ -125,15 +126,15 @@ class DoctypeToken extends Token { /// They're also used by [StartTagToken.attributeSpans] if attribute spans are /// requested. class TagAttribute { - String name; - String value; + String? name; + late String value; // The spans of the attribute. This is not used unless we are computing an // attribute span on demand. - int start; - int end; - int startValue; - int endValue; + late int start; + late int end; + int? startValue; + late int endValue; TagAttribute(); } diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 2737a7e81..acd388fd0 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -43,33 +43,33 @@ class HtmlTokenizer implements Iterator<Token> { /// This reference to the parser is used for correct CDATA handling. /// The [HtmlParser] will set this at construction time. - HtmlParser parser; + HtmlParser? parser; - final Queue<Token> tokenQueue; + final Queue<Token?> tokenQueue; /// Holds the token that is currently being processed. - Token currentToken; + Token? currentToken; /// Holds a reference to the method to be invoked for the next parser state. - bool Function() state; + late bool Function() state; final StringBuffer _buffer = StringBuffer(); - int _lastOffset; + late int _lastOffset; // TODO(jmesserly): ideally this would be a LinkedHashMap and we wouldn't add // an item until it's ready. But the code doesn't have a clear notion of when // it's "done" with the attribute. - List<TagAttribute> _attributes; - Set<String> _attributeNames; + List<TagAttribute>? _attributes; + Set<String>? _attributeNames; HtmlTokenizer(doc, - {String encoding, + {String? encoding, bool parseMeta = true, this.lowercaseElementName = true, this.lowercaseAttrName = true, this.generateSpans = false, - String sourceUrl, + String? sourceUrl, this.attributeSpans = false}) : stream = HtmlInputStream(doc, encoding, parseMeta, generateSpans, sourceUrl), @@ -77,42 +77,42 @@ class HtmlTokenizer implements Iterator<Token> { reset(); } - TagToken get currentTagToken => currentToken as TagToken; - DoctypeToken get currentDoctypeToken => currentToken as DoctypeToken; - StringToken get currentStringToken => currentToken as StringToken; + TagToken? get currentTagToken => currentToken as TagToken?; + DoctypeToken? get currentDoctypeToken => currentToken as DoctypeToken?; + StringToken? get currentStringToken => currentToken as StringToken?; - Token _current; + Token? _current; @override - Token get current => _current; + Token get current => _current!; final StringBuffer _attributeName = StringBuffer(); final StringBuffer _attributeValue = StringBuffer(); void _markAttributeEnd(int offset) { - _attributes.last.value = '$_attributeValue'; - if (attributeSpans) _attributes.last.end = stream.position + offset; + _attributes!.last.value = '$_attributeValue'; + if (attributeSpans) _attributes!.last.end = stream.position + offset; } void _markAttributeValueStart(int offset) { - if (attributeSpans) _attributes.last.startValue = stream.position + offset; + if (attributeSpans) _attributes!.last.startValue = stream.position + offset; } void _markAttributeValueEnd(int offset) { - if (attributeSpans) _attributes.last.endValue = stream.position + offset; + if (attributeSpans) _attributes!.last.endValue = stream.position + offset; _markAttributeEnd(offset); } // Note: we could track the name span here, if we need it. void _markAttributeNameEnd(int offset) => _markAttributeEnd(offset); - void _addAttribute(String name) { + void _addAttribute(String? name) { _attributes ??= []; _attributeName.clear(); _attributeName.write(name); _attributeValue.clear(); final attr = TagAttribute(); - _attributes.add(attr); - if (attributeSpans) attr.start = stream.position - name.length; + _attributes!.add(attr); + if (attributeSpans) attr.start = stream.position - name!.length; } /// This is where the magic happens. @@ -152,10 +152,10 @@ class HtmlTokenizer implements Iterator<Token> { } /// Adds a token to the queue. Sets the span if needed. - void _addToken(Token token) { - if (generateSpans && token.span == null) { + void _addToken(Token? token) { + if (generateSpans && token!.span == null) { final offset = stream.position; - token.span = stream.fileInfo.span(_lastOffset, offset); + token.span = stream.fileInfo!.span(_lastOffset, offset); if (token is! ParseErrorToken) { _lastOffset = offset; } @@ -255,9 +255,9 @@ class HtmlTokenizer implements Iterator<Token> { return char; } - void consumeEntity({String allowedChar, bool fromAttribute = false}) { + void consumeEntity({String? allowedChar, bool fromAttribute = false}) { // Initialise to the default output for when no entity is matched - var output = '&'; + String? output = '&'; final charStack = [stream.char()]; if (isWhitespace(charStack[0]) || @@ -293,7 +293,7 @@ class HtmlTokenizer implements Iterator<Token> { // // Consume characters and compare to these to a substring of the // entity names in the list until the substring no longer matches. - var filteredEntityList = entitiesByFirstChar[charStack[0]] ?? const []; + var filteredEntityList = entitiesByFirstChar[charStack[0]!] ?? const []; while (charStack.last != eof) { final name = charStack.join(); @@ -308,7 +308,7 @@ class HtmlTokenizer implements Iterator<Token> { // At this point we have a string that starts with some characters // that may match an entity - String entityName; + String? entityName; // Try to find the longest entity the string will match to take care // of &noti for instance. @@ -384,8 +384,8 @@ class HtmlTokenizer implements Iterator<Token> { // Convert the list into a map where first key wins. token.data = LinkedHashMap<Object, String>(); if (_attributes != null) { - for (var attr in _attributes) { - token.data.putIfAbsent(attr.name, () => attr.value); + for (var attr in _attributes!) { + token.data.putIfAbsent(attr.name!, () => attr.value); } if (attributeSpans) token.attributeSpans = _attributes; } @@ -578,9 +578,9 @@ class HtmlTokenizer implements Iterator<Token> { state = selfClosingStartTagState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentTagToken.name = '${currentTagToken.name}\uFFFD'; + currentTagToken!.name = '${currentTagToken!.name}\uFFFD'; } else { - currentTagToken.name = '${currentTagToken.name}$data'; + currentTagToken!.name = '${currentTagToken!.name}$data'; // (Don't use charsUntil here, because tag names are // very short and it's faster to not do anything fancy) } @@ -616,7 +616,7 @@ class HtmlTokenizer implements Iterator<Token> { bool _tokenIsAppropriate() { // TODO(jmesserly): this should use case insensitive compare instead. return currentToken is TagToken && - currentTagToken.name.toLowerCase() == '$_buffer'.toLowerCase(); + currentTagToken!.name!.toLowerCase() == '$_buffer'.toLowerCase(); } bool rcdataEndTagNameState() { @@ -1016,7 +1016,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('expected-attribute-name-but-got-eof')); state = dataState; - } else if ("'\"=<".contains(data)) { + } else if ("'\"=<".contains(data!)) { _addToken(ParseErrorToken('invalid-character-in-attribute-name')); _addAttribute(data); state = attributeNameState; @@ -1057,7 +1057,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-attribute-name')); state = dataState; - } else if ("'\"<".contains(data)) { + } else if ("'\"<".contains(data!)) { _addToken(ParseErrorToken('invalid-character-in-attribute-name')); _attributeName.write(data); leavingThisState = false; @@ -1076,12 +1076,12 @@ class HtmlTokenizer implements Iterator<Token> { if (lowercaseAttrName) { attrName = attrName.toAsciiLowerCase(); } - _attributes.last.name = attrName; + _attributes!.last.name = attrName; _attributeNames ??= {}; - if (_attributeNames.contains(attrName)) { + if (_attributeNames!.contains(attrName)) { _addToken(ParseErrorToken('duplicate-attribute')); } - _attributeNames.add(attrName); + _attributeNames!.add(attrName); // XXX Fix for above XXX if (emitToken) { @@ -1111,7 +1111,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('expected-end-of-tag-but-got-eof')); state = dataState; - } else if ("'\"<".contains(data)) { + } else if ("'\"<".contains(data!)) { _addToken(ParseErrorToken('invalid-character-after-attribute-name')); _addAttribute(data); state = attributeNameState; @@ -1148,7 +1148,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('expected-attribute-value-but-got-eof')); state = dataState; - } else if ('=<`'.contains(data)) { + } else if ('=<`'.contains(data!)) { _addToken(ParseErrorToken('equals-in-unquoted-attribute-value')); _markAttributeValueStart(-1); _attributeValue.write(data); @@ -1219,7 +1219,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(ParseErrorToken('eof-in-attribute-value-no-quotes')); _markAttributeValueEnd(-1); state = dataState; - } else if ('"\'=<`'.contains(data)) { + } else if ('"\'=<`'.contains(data!)) { _addToken( ParseErrorToken('unexpected-character-in-unquoted-attribute-value')); _attributeValue.write(data); @@ -1256,7 +1256,7 @@ class HtmlTokenizer implements Iterator<Token> { bool selfClosingStartTagState() { final data = stream.char(); if (data == '>') { - currentTagToken.selfClosing = true; + currentTagToken!.selfClosing = true; emitCurrentToken(); } else if (data == eof) { _addToken(ParseErrorToken('unexpected-EOF-after-solidus-in-tag')); @@ -1299,7 +1299,7 @@ class HtmlTokenizer implements Iterator<Token> { for (var expected in const ['oO', 'cC', 'tT', 'yY', 'pP', 'eE']) { final char = stream.char(); charStack.add(char); - if (char == eof || !expected.contains(char)) { + if (char == eof || !expected.contains(char!)) { matched = false; break; } @@ -1311,9 +1311,9 @@ class HtmlTokenizer implements Iterator<Token> { } } else if (charStack.last == '[' && parser != null && - parser.tree.openElements.isNotEmpty && - parser.tree.openElements.last.namespaceUri != - parser.tree.defaultNamespace) { + parser!.tree.openElements.isNotEmpty && + parser!.tree.openElements.last.namespaceUri != + parser!.tree.defaultNamespace) { var matched = true; for (var expected in const ['C', 'D', 'A', 'T', 'A', '[']) { charStack.add(stream.char()); @@ -1343,7 +1343,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentStartDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('\uFFFD'); + currentStringToken!.add('\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); @@ -1353,7 +1353,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken.add(data); + currentStringToken!.add(data!); state = commentState; } return true; @@ -1365,7 +1365,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('-\uFFFD'); + currentStringToken!.add('-\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); @@ -1375,7 +1375,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken.add('-').add(data); + currentStringToken!.add('-').add(data!); state = commentState; } return true; @@ -1387,13 +1387,13 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('\uFFFD'); + currentStringToken!.add('\uFFFD'); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment')); _addToken(currentToken); state = dataState; } else { - currentStringToken.add(data).add(stream.charsUntil('-\u0000')); + currentStringToken!.add(data!).add(stream.charsUntil('-\u0000')); } return true; } @@ -1404,14 +1404,14 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('-\uFFFD'); + currentStringToken!.add('-\uFFFD'); state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-dash')); _addToken(currentToken); state = dataState; } else { - currentStringToken.add('-').add(data); + currentStringToken!.add('-').add(data!); state = commentState; } return true; @@ -1424,7 +1424,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('--\uFFFD'); + currentStringToken!.add('--\uFFFD'); state = commentState; } else if (data == '!') { _addToken( @@ -1433,7 +1433,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '-') { _addToken( ParseErrorToken('unexpected-dash-after-double-dash-in-comment')); - currentStringToken.add(data); + currentStringToken!.add(data!); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-double-dash')); _addToken(currentToken); @@ -1441,7 +1441,7 @@ class HtmlTokenizer implements Iterator<Token> { } else { // XXX _addToken(ParseErrorToken('unexpected-char-in-comment')); - currentStringToken.add('--').add(data); + currentStringToken!.add('--').add(data!); state = commentState; } return true; @@ -1453,18 +1453,18 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == '-') { - currentStringToken.add('--!'); + currentStringToken!.add('--!'); state = commentEndDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken.add('--!\uFFFD'); + currentStringToken!.add('--!\uFFFD'); state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-bang-state')); _addToken(currentToken); state = dataState; } else { - currentStringToken.add('--!').add(data); + currentStringToken!.add('--!').add(data!); state = commentState; } return true; @@ -1476,7 +1476,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1493,20 +1493,20 @@ class HtmlTokenizer implements Iterator<Token> { return true; } else if (data == '>') { _addToken(ParseErrorToken('expected-doctype-name-but-got-right-bracket')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.name = '\uFFFD'; + currentDoctypeToken!.name = '\uFFFD'; state = doctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.name = data; + currentDoctypeToken!.name = data; state = doctypeNameState; } return true; @@ -1515,24 +1515,24 @@ class HtmlTokenizer implements Iterator<Token> { bool doctypeNameState() { final data = stream.char(); if (isWhitespace(data)) { - currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); + currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); state = afterDoctypeNameState; } else if (data == '>') { - currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); + currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.name = '${currentDoctypeToken.name}\uFFFD'; + currentDoctypeToken!.name = '${currentDoctypeToken!.name}\uFFFD'; state = doctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype-name')); - currentDoctypeToken.correct = false; - currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); + currentDoctypeToken!.correct = false; + currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.name = '${currentDoctypeToken.name}$data'; + currentDoctypeToken!.name = '${currentDoctypeToken!.name}$data'; } return true; } @@ -1545,7 +1545,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == eof) { - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; stream.unget(data); _addToken(ParseErrorToken('eof-in-doctype')); _addToken(currentToken); @@ -1556,7 +1556,7 @@ class HtmlTokenizer implements Iterator<Token> { var matched = true; for (var expected in const ['uU', 'bB', 'lL', 'iI', 'cC']) { data = stream.char(); - if (data == eof || !expected.contains(data)) { + if (data == eof || !expected.contains(data!)) { matched = false; break; } @@ -1569,7 +1569,7 @@ class HtmlTokenizer implements Iterator<Token> { var matched = true; for (var expected in const ['yY', 'sS', 'tT', 'eE', 'mM']) { data = stream.char(); - if (data == eof || !expected.contains(data)) { + if (data == eof || !expected.contains(data!)) { matched = false; break; } @@ -1587,7 +1587,7 @@ class HtmlTokenizer implements Iterator<Token> { stream.unget(data); _addToken(ParseErrorToken('expected-space-or-right-bracket-in-doctype', messageParams: {'data': data})); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; state = bogusDoctypeState; } return true; @@ -1603,7 +1603,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypePublicIdentifierState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1618,24 +1618,24 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '"') { - currentDoctypeToken.publicId = ''; + currentDoctypeToken!.publicId = ''; state = doctypePublicIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.publicId = ''; + currentDoctypeToken!.publicId = ''; state = doctypePublicIdentifierSingleQuotedState; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; state = bogusDoctypeState; } return true; @@ -1647,19 +1647,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; + currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; + currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}$data'; } return true; } @@ -1670,19 +1670,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; + currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; + currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}$data'; } return true; } @@ -1696,20 +1696,20 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == '"') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; state = bogusDoctypeState; } return true; @@ -1723,19 +1723,19 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == '"') { - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; state = bogusDoctypeState; } return true; @@ -1751,7 +1751,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypeSystemIdentifierState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1766,24 +1766,24 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '"') { - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken.systemId = ''; + currentDoctypeToken!.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; state = bogusDoctypeState; } return true; @@ -1795,19 +1795,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; + currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; + currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}$data'; } return true; } @@ -1818,19 +1818,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; + currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; + currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}$data'; } return true; } @@ -1844,7 +1844,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken.correct = false; + currentDoctypeToken!.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1869,7 +1869,7 @@ class HtmlTokenizer implements Iterator<Token> { } bool cdataSectionState() { - final data = <String>[]; + final data = <String?>[]; var matchedEnd = 0; while (true) { var ch = stream.char(); diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 36874641b..04c3a193d 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -16,7 +16,7 @@ import 'utils.dart'; /// entering some elements. /// /// https://html.spec.whatwg.org/multipage/parsing.html#list-of-active-formatting-elements -class ActiveFormattingElements extends ListProxy<Element /*?*/ > { +class ActiveFormattingElements extends ListProxy<Element?> { /// Push an element into the active formatting elements. /// /// Prevents equivalent elements from appearing more than 3 times following @@ -25,7 +25,7 @@ class ActiveFormattingElements extends ListProxy<Element /*?*/ > { // TODO - Earliest equivalent following a marker, as opposed to earliest // identical regardless of marker position, should be removed. @override - void add(Element node) { + void add(Element? node) { var equalCount = 0; if (node != null) { for (var element in reversed) { @@ -71,21 +71,21 @@ bool _nodesEqual(Element node1, Element node2) { /// Basic treebuilder implementation. class TreeBuilder { - final String defaultNamespace; + final String? defaultNamespace; - Document document; + var document = Document(); final List<Element> openElements = <Element>[]; final activeFormattingElements = ActiveFormattingElements(); - Node headPointer; + Node? headPointer; - Element formPointer; + Element? formPointer; /// Switch the function used to insert an element from the /// normal one to the misnested table one and back again - bool insertFromTable; + var insertFromTable = false; TreeBuilder(bool namespaceHTMLElements) : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null { @@ -105,7 +105,7 @@ class TreeBuilder { document = Document(); } - bool elementInScope(target, {String variant}) { + bool elementInScope(target, {String? variant}) { //If we pass a node in we match that. if we pass a string //match any node with that name final exactNode = target is Node; @@ -193,7 +193,7 @@ class TreeBuilder { entry = activeFormattingElements[i]; // TODO(jmesserly): optimize this. No need to create a token. - final cloneToken = StartTagToken(entry.localName, + final cloneToken = StartTagToken(entry!.localName, namespace: entry.namespaceUri, data: LinkedHashMap.from(entry.attributes)) ..span = entry.sourceSpan; @@ -221,7 +221,7 @@ class TreeBuilder { /// Check if an element exists between the end of the active /// formatting elements and the last marker. If it does, return it, else /// return null. - Element elementInActiveFormattingElements(String name) { + Element? elementInActiveFormattingElements(String? name) { for (var item in activeFormattingElements.reversed) { // Check for Marker first because if it's a Marker it doesn't have a // name attribute. @@ -246,7 +246,7 @@ class TreeBuilder { document.nodes.add(doctype); } - void insertComment(StringToken token, [Node parent]) { + void insertComment(StringToken token, [Node? parent]) { parent ??= openElements.last; parent.nodes.add(Comment(token.data)..sourceSpan = token.span); } @@ -290,9 +290,9 @@ class TreeBuilder { // TODO(jmesserly): I don't think this is reachable. If insertFromTable // is true, there will be a <table> element open, and it always has a // parent pointer. - nodePos[0].nodes.add(element); + nodePos[0]!.nodes.add(element); } else { - nodePos[0].insertBefore(element, nodePos[1]); + nodePos[0]!.insertBefore(element, nodePos[1]); } openElements.add(element); } @@ -300,7 +300,7 @@ class TreeBuilder { } /// Insert text data. - void insertText(String data, FileSpan span) { + void insertText(String data, FileSpan? span) { final parent = openElements.last; if (!insertFromTable || @@ -311,14 +311,14 @@ class TreeBuilder { // We should be in the InTable mode. This means we want to do // special magic element rearranging final nodePos = getTableMisnestedNodePosition(); - _insertText(nodePos[0], data, span, nodePos[1] as Element); + _insertText(nodePos[0]!, data, span, nodePos[1] as Element?); } } /// Insert [data] as text in the current node, positioned before the /// start of node [refNode] or to the end of the node's text. - static void _insertText(Node parent, String data, FileSpan span, - [Element refNode]) { + static void _insertText(Node parent, String data, FileSpan? span, + [Element? refNode]) { final nodes = parent.nodes; if (refNode == null) { if (nodes.isNotEmpty && nodes.last is Text) { @@ -327,7 +327,7 @@ class TreeBuilder { if (span != null) { last.sourceSpan = - span.file.span(last.sourceSpan.start.offset, span.end.offset); + span.file.span(last.sourceSpan!.start.offset, span.end.offset); } } else { nodes.add(Text(data)..sourceSpan = span); @@ -345,13 +345,13 @@ class TreeBuilder { /// Get the foster parent element, and sibling to insert before /// (or null) when inserting a misnested table node - List<Node> getTableMisnestedNodePosition() { + List<Node?> getTableMisnestedNodePosition() { // The foster parent element is the one which comes before the most // recently opened table element // XXX - this is really inelegant - Element lastTable; - Node fosterParent; - Node insertBefore; + Element? lastTable; + Node? fosterParent; + Node? insertBefore; for (var elm in openElements.reversed) { if (elm.localName == 'table') { lastTable = elm; @@ -373,7 +373,7 @@ class TreeBuilder { return [fosterParent, insertBefore]; } - void generateImpliedEndTags([String exclude]) { + void generateImpliedEndTags([String? exclude]) { final name = openElements.last.localName; // XXX td, th and tr are not actually needed if (name != exclude && diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 559f6c390..6480ea3ef 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -10,14 +10,15 @@ class Pair<F, S> { int get hashCode => 37 * first.hashCode + second.hashCode; @override - bool operator ==(other) => other.first == first && other.second == second; + bool operator ==(Object other) => + other is Pair && other.first == first && other.second == second; } bool startsWithAny(String str, List<String> prefixes) => prefixes.any(str.startsWith); // Like the python [:] operator. -List<T> slice<T>(List<T> list, int start, [int end]) { +List<T> slice<T>(List<T> list, int start, [int? end]) { end ??= list.length; if (end < 0) end += list.length; @@ -50,7 +51,7 @@ String padWithZeros(String str, int size) { /// Format a string like Python's % string format operator. Right now this only /// supports a [data] dictionary used with %s or %08x. Those were the only /// things needed for [errorMessages]. -String formatStr(String format, Map data) { +String formatStr(String format, Map? data) { if (data == null) return format; data.forEach((key, value) { final result = StringBuffer(); @@ -64,7 +65,7 @@ String formatStr(String format, Map data) { while (isDigit(format[digits])) { digits++; } - int numberSize; + int? numberSize; if (digits > match) { numberSize = int.parse(format.substring(match, digits)); match = digits; @@ -76,11 +77,11 @@ String formatStr(String format, Map data) { break; case 'd': final number = value.toString(); - result.write(padWithZeros(number, numberSize)); + result.write(padWithZeros(number, numberSize!)); break; case 'x': final number = (value as int).toRadixString(16); - result.write(padWithZeros(number, numberSize)); + result.write(padWithZeros(number, numberSize!)); break; default: throw UnsupportedError('formatStr does not support format ' diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index a8fcab3a0..44658d03f 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,17 +1,23 @@ name: html -version: 0.15.0-dev +version: 0.15.0-nullsafety-dev description: APIs for parsing and manipulating HTML content outside the browser. homepage: https://github.com/dart-lang/html +publish_to: none + environment: - sdk: '>=2.8.0 <3.0.0' + sdk: ">=2.11.0-0 <3.0.0" dependencies: - csslib: '>=0.13.2 <0.17.0' - source_span: '>=1.0.0 <2.0.0' + csslib: ^0.17.0 + source_span: ^1.8.0-nullsafety dev_dependencies: - path: ^1.6.2 - pedantic: ^1.3.0 - test: ^1.3.0 + path: ^1.8.0-nullsafety + pedantic: ^1.10.0-nullsafety + test: ^1.16.0-nullsafety + +dependency_overrides: + csslib: + git: git://github.com/dart-lang/csslib.git diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 0237172a9..5f755555e 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -49,11 +49,11 @@ void main() { expect(error.errorCode, 'unexpected-doctype'); // Note: these values are 0-based, but the printed format is 1-based. - expect(error.span.start.line, 3); - expect(error.span.end.line, 3); - expect(error.span.start.column, 2); - expect(error.span.end.column, 17); - expect(error.span.text, '<!DOCTYPE html>'); + expect(error.span!.start.line, 3); + expect(error.span!.end.line, 3); + expect(error.span!.start.column, 2); + expect(error.span!.end.column, 17); + expect(error.span!.text, '<!DOCTYPE html>'); expect(error.toString(), ''' On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. @@ -77,9 +77,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. expect(parser.errors.length, 1); final error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); - expect(error.span.start.line, 3); + expect(error.span!.start.line, 3); // Note: error position is at the end, not the beginning - expect(error.span.start.column, 17); + expect(error.span!.start.column, 17); }); test('text spans should have the correct length', () { @@ -89,21 +89,21 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. final text = doc.body.nodes[0].nodes[0] as Text; expect(text, const TypeMatcher<Text>()); expect(text.data, textContent); - expect(text.sourceSpan.start.offset, html.indexOf(textContent)); - expect(text.sourceSpan.length, textContent.length); + expect(text.sourceSpan!.start.offset, html.indexOf(textContent)); + expect(text.sourceSpan!.length, textContent.length); }); test('attribute spans', () { final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('element'); - expect(elem.sourceSpan.start.offset, 0); - expect(elem.sourceSpan.end.offset, text.length); - expect(elem.sourceSpan.text, text); + final elem = doc.querySelector('element')!; + expect(elem.sourceSpan!.start.offset, 0); + expect(elem.sourceSpan!.end.offset, text.length); + expect(elem.sourceSpan!.text, text); - expect(elem.attributeSpans['quux'], null); + expect(elem.attributeSpans!['quux'], null); - final span = elem.attributeSpans['extends']; + final span = elem.attributeSpans!['extends']!; expect(span.start.offset, text.indexOf('extends')); expect(span.text, 'extends="x-bar"'); }); @@ -111,11 +111,11 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('attribute value spans', () { final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('element'); + final elem = doc.querySelector('element')!; - expect(elem.attributeValueSpans['quux'], null); + expect(elem.attributeValueSpans!['quux'], null); - final span = elem.attributeValueSpans['extends']; + final span = elem.attributeValueSpans!['extends']!; expect(span.start.offset, text.indexOf('x-bar')); expect(span.text, 'x-bar'); }); @@ -123,29 +123,29 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('attribute spans if no attributes', () { final text = '<element>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('element'); + final elem = doc.querySelector('element')!; - expect(elem.attributeSpans['quux'], null); - expect(elem.attributeValueSpans['quux'], null); + expect(elem.attributeSpans!['quux'], null); + expect(elem.attributeValueSpans!['quux'], null); }); test('attribute spans if no attribute value', () { final text = '<foo template>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('foo'); + final elem = doc.querySelector('foo')!; expect( - elem.attributeSpans['template'].start.offset, text.indexOf('template')); - expect(elem.attributeValueSpans.containsKey('template'), false); + elem.attributeSpans!['template']!.start.offset, text.indexOf('template')); + expect(elem.attributeValueSpans!.containsKey('template'), false); }); test('attribute spans null if code parsed without spans', () { final text = '<element name="x-foo" extends="x-bar" constructor="Foo">'; final doc = parse(text); - final elem = doc.querySelector('element'); + final elem = doc.querySelector('element')!; expect(elem.sourceSpan, null); - expect(elem.attributeSpans['quux'], null); - expect(elem.attributeSpans['extends'], null); + expect(elem.attributeSpans!['quux'], null); + expect(elem.attributeSpans!['extends'], null); }); test('void element innerHTML', () { @@ -179,9 +179,9 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. // However, we preserve the input order via LinkedHashMap final body = parse('<foo d=1 a=2 c=3 b=4>').body; expect(body.innerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); - expect(body.querySelector('foo').attributes.remove('a'), '2'); + expect(body.querySelector('foo')!.attributes.remove('a'), '2'); expect(body.innerHtml, '<foo d="1" c="3" b="4"></foo>'); - body.querySelector('foo').attributes['a'] = '0'; + body.querySelector('foo')!.attributes['a'] = '0'; expect(body.innerHtml, '<foo d="1" c="3" b="4" a="0"></foo>'); }); @@ -229,7 +229,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. xlink:href="http://example.com/logo.png" xlink:show="new"></desc> '''); - final n = doc.querySelector('desc'); + final n = doc.querySelector('desc')!; final keys = n.attributes.keys.toList(); expect( keys.first, @@ -266,8 +266,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('Element.text', () { final doc = parseFragment('<div>foo<div>bar</div>baz</div>'); - final e = doc.firstChild; - final text = e.firstChild; + final e = doc.firstChild!; + final text = e.firstChild!; expect((text as Text).data, 'foo'); expect(e.text, 'foobarbaz'); @@ -280,7 +280,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('Text.text', () { final doc = parseFragment('<div>foo<div>bar</div>baz</div>'); - final e = doc.firstChild; + final e = doc.firstChild!; final text = e.firstChild as Text; expect(text.data, 'foo'); expect(text.text, 'foo'); @@ -293,14 +293,14 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('Comment.text', () { final doc = parseFragment('<div><!--foo-->bar</div>'); - final e = doc.firstChild; - final c = e.firstChild; + final e = doc.firstChild!; + final c = e.firstChild!; expect((c as Comment).data, 'foo'); expect(c.text, 'foo'); expect(e.text, 'bar'); c.text = 'qux'; - expect((c as Comment).data, 'qux'); + expect(c.data, 'qux'); expect(c.text, 'qux'); expect(e.text, 'bar'); }); @@ -315,12 +315,12 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. </svg>'''); final doc = p.parseFragment(); expect(p.errors, isEmpty); - final svg = doc.querySelector('svg'); + final svg = doc.querySelector('svg')!; expect(svg.children[0].children[0].localName, 'x-flow'); }); group('Encoding pre-parser', () { - String getEncoding(String s) => EncodingParser(s.codeUnits).getEncoding(); + String? getEncoding(String s) => EncodingParser(s.codeUnits).getEncoding(); test('gets encoding from meta charset', () { expect(getEncoding('<meta charset="utf-16">'), 'utf-16'); @@ -365,88 +365,88 @@ void _testElementSpans() { final text = '<html><body>123</body></html>'; final doc = parse(text, generateSpans: true); { - final elem = doc.querySelector('html'); - assertSpan(elem.sourceSpan, 0, 6, '<html>'); - assertSpan(elem.endSourceSpan, 22, 29, '</html>'); + final elem = doc.querySelector('html')!; + assertSpan(elem.sourceSpan!, 0, 6, '<html>'); + assertSpan(elem.endSourceSpan!, 22, 29, '</html>'); } { - final elem = doc.querySelector('body'); - assertSpan(elem.sourceSpan, 6, 12, '<body>'); - assertSpan(elem.endSourceSpan, 15, 22, '</body>'); + final elem = doc.querySelector('body')!; + assertSpan(elem.sourceSpan!, 6, 12, '<body>'); + assertSpan(elem.endSourceSpan!, 15, 22, '</body>'); } }); test('normal', () { final text = '<div><element><span></span></element></div>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('element'); - assertSpan(elem.sourceSpan, 5, 14, '<element>'); - assertSpan(elem.endSourceSpan, 27, 37, '</element>'); + final elem = doc.querySelector('element')!; + assertSpan(elem.sourceSpan!, 5, 14, '<element>'); + assertSpan(elem.endSourceSpan!, 27, 37, '</element>'); }); test('block', () { final text = '<div>123</div>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('div'); - assertSpan(elem.sourceSpan, 0, 5, '<div>'); - assertSpan(elem.endSourceSpan, 8, 14, '</div>'); + final elem = doc.querySelector('div')!; + assertSpan(elem.sourceSpan!, 0, 5, '<div>'); + assertSpan(elem.endSourceSpan!, 8, 14, '</div>'); }); test('form', () { final text = '<form>123</form>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('form'); - assertSpan(elem.sourceSpan, 0, 6, '<form>'); - assertSpan(elem.endSourceSpan, 9, 16, '</form>'); + final elem = doc.querySelector('form')!; + assertSpan(elem.sourceSpan!, 0, 6, '<form>'); + assertSpan(elem.endSourceSpan!, 9, 16, '</form>'); }); test('p explicit end', () { final text = '<p>123</p>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('p'); - assertSpan(elem.sourceSpan, 0, 3, '<p>'); - assertSpan(elem.endSourceSpan, 6, 10, '</p>'); + final elem = doc.querySelector('p')!; + assertSpan(elem.sourceSpan!, 0, 3, '<p>'); + assertSpan(elem.endSourceSpan!, 6, 10, '</p>'); }); test('p implicit end', () { final text = '<div><p>123<p>456</div>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('p'); - assertSpan(elem.sourceSpan, 5, 8, '<p>'); + final elem = doc.querySelector('p')!; + assertSpan(elem.sourceSpan!, 5, 8, '<p>'); expect(elem.endSourceSpan, isNull); }); test('li', () { final text = '<li>123</li>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('li'); - assertSpan(elem.sourceSpan, 0, 4, '<li>'); - assertSpan(elem.endSourceSpan, 7, 12, '</li>'); + final elem = doc.querySelector('li')!; + assertSpan(elem.sourceSpan!, 0, 4, '<li>'); + assertSpan(elem.endSourceSpan!, 7, 12, '</li>'); }); test('heading', () { final text = '<h1>123</h1>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('h1'); - assertSpan(elem.sourceSpan, 0, 4, '<h1>'); - assertSpan(elem.endSourceSpan, 7, 12, '</h1>'); + final elem = doc.querySelector('h1')!; + assertSpan(elem.sourceSpan!, 0, 4, '<h1>'); + assertSpan(elem.endSourceSpan!, 7, 12, '</h1>'); }); test('formatting', () { final text = '<b>123</b>'; final doc = parse(text, generateSpans: true); - final elem = doc.querySelector('b'); - assertSpan(elem.sourceSpan, 0, 3, '<b>'); - assertSpan(elem.endSourceSpan, 6, 10, '</b>'); + final elem = doc.querySelector('b')!; + assertSpan(elem.sourceSpan!, 0, 3, '<b>'); + assertSpan(elem.endSourceSpan!, 6, 10, '</b>'); }); test('table tbody', () { final text = '<table><tbody> </tbody></table>'; final doc = parse(text, generateSpans: true); { - final elem = doc.querySelector('tbody'); - assertSpan(elem.sourceSpan, 7, 14, '<tbody>'); - assertSpan(elem.endSourceSpan, 16, 24, '</tbody>'); + final elem = doc.querySelector('tbody')!; + assertSpan(elem.sourceSpan!, 7, 14, '<tbody>'); + assertSpan(elem.endSourceSpan!, 16, 24, '</tbody>'); } }); @@ -454,19 +454,19 @@ void _testElementSpans() { final text = '<table><tr><td>123</td></tr></table>'; final doc = parse(text, generateSpans: true); { - final elem = doc.querySelector('table'); - assertSpan(elem.sourceSpan, 0, 7, '<table>'); - assertSpan(elem.endSourceSpan, 28, 36, '</table>'); + final elem = doc.querySelector('table')!; + assertSpan(elem.sourceSpan!, 0, 7, '<table>'); + assertSpan(elem.endSourceSpan!, 28, 36, '</table>'); } { - final elem = doc.querySelector('tr'); - assertSpan(elem.sourceSpan, 7, 11, '<tr>'); - assertSpan(elem.endSourceSpan, 23, 28, '</tr>'); + final elem = doc.querySelector('tr')!; + assertSpan(elem.sourceSpan!, 7, 11, '<tr>'); + assertSpan(elem.endSourceSpan!, 23, 28, '</tr>'); } { - final elem = doc.querySelector('td'); - assertSpan(elem.sourceSpan, 11, 15, '<td>'); - assertSpan(elem.endSourceSpan, 18, 23, '</td>'); + final elem = doc.querySelector('td')!; + assertSpan(elem.sourceSpan!, 11, 15, '<td>'); + assertSpan(elem.endSourceSpan!, 18, 23, '</td>'); } }); @@ -474,19 +474,19 @@ void _testElementSpans() { final text = '<select><optgroup><option>123</option></optgroup></select>'; final doc = parse(text, generateSpans: true); { - final elem = doc.querySelector('select'); - assertSpan(elem.sourceSpan, 0, 8, '<select>'); - assertSpan(elem.endSourceSpan, 49, 58, '</select>'); + final elem = doc.querySelector('select')!; + assertSpan(elem.sourceSpan!, 0, 8, '<select>'); + assertSpan(elem.endSourceSpan!, 49, 58, '</select>'); } { - final elem = doc.querySelector('optgroup'); - assertSpan(elem.sourceSpan, 8, 18, '<optgroup>'); - assertSpan(elem.endSourceSpan, 38, 49, '</optgroup>'); + final elem = doc.querySelector('optgroup')!; + assertSpan(elem.sourceSpan!, 8, 18, '<optgroup>'); + assertSpan(elem.endSourceSpan!, 38, 49, '</optgroup>'); } { - final elem = doc.querySelector('option'); - assertSpan(elem.sourceSpan, 18, 26, '<option>'); - assertSpan(elem.endSourceSpan, 29, 38, '</option>'); + final elem = doc.querySelector('option')!; + assertSpan(elem.sourceSpan!, 18, 26, '<option>'); + assertSpan(elem.endSourceSpan!, 29, 38, '</option>'); } }); }); diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 71730452a..1e35916bc 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -32,10 +32,10 @@ String namespaceHtml(String expected) { void runParserTest( String groupName, - String innerHTML, - String input, - String expected, - List errors, + String? innerHTML, + String? input, + String? expected, + List? errors, TreeBuilderFactory treeCtor, bool namespaceHTMLElements) { // XXX - move this out into the setup function @@ -53,7 +53,7 @@ void runParserTest( final output = testSerializer(document); if (namespaceHTMLElements) { - expected = namespaceHtml(expected); + expected = namespaceHtml(expected!); } expect(output, equals(expected), @@ -61,7 +61,7 @@ void runParserTest( '\n\nInput:\n$input\n\nExpected:\n$expected\n\nReceived:\n$output'); if (checkParseErrors) { - expect(parser.errors.length, equals(errors.length), + expect(parser.errors.length, equals(errors!.length), reason: '\n\nInput:\n$input\n\nExpected errors (${errors.length}):\n' "${errors.join('\n')}\n\n" 'Actual errors (${parser.errors.length}):\n' @@ -84,9 +84,9 @@ void main() { final innerHTML = testData['document-fragment']; final expected = testData['document']; - for (var treeCtor in treeTypes.values) { + for (var treeCtor in treeTypes!.values) { for (var namespaceHTMLElements in const [false, true]) { - test(_nameFor(input), () { + test(_nameFor(input!), () { runParserTest(testName, innerHTML, input, expected, errors, treeCtor, namespaceHTMLElements); }); diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 02d513b4a..a97f1305a 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -64,7 +64,7 @@ void main() { //doc = frame.contentDocument; // Document Node tests doc = getTestContentDocument(); - final element = doc.getElementById('root'); // In-document Element Node tests + final element = doc.getElementById('root')!; // In-document Element Node tests //Setup the namespace tests setupSpecialElements(element); diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 388ae0027..f05d9cc6f 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -12,7 +12,7 @@ library html.test.selectors.level1_lib; import 'package:html/dom.dart'; import 'package:test/test.dart' as unittest; -Document doc; +late Document doc; /* * Create and append special elements that cannot be created correctly with HTML markup alone. @@ -182,7 +182,7 @@ void runSpecialSelectorTests(String type, root) { /// Tests containing this string fail for an unknown reason final _failureName = 'matching custom data-* attribute with'; -String _getSkip(String name) { +String? _getSkip(String name) { if (name.contains(_failureName)) { return 'Tests related to `$_failureName` fail for an unknown reason.'; } @@ -193,10 +193,10 @@ String _getSkip(String name) { * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() * Only run these tests when results are expected. Don't run for syntax error tests. */ -void runValidSelectorTest(String type, root, +void runValidSelectorTest(String type, Node root, List<Map<String, dynamic>> selectors, testType, docType) { var nodeType = ''; - switch ((root as Node).nodeType) { + switch (root.nodeType) { case Node.DOCUMENT_NODE: nodeType = 'document'; break; @@ -215,20 +215,20 @@ void runValidSelectorTest(String type, root, final n = s['name'] as String; final skip = _getSkip(n); final q = s['selector'] as String; - final e = s['expect'] as List; + final e = s['expect'] as List?; if ((s['exclude'] is! List || (s['exclude'].indexOf(nodeType) == -1 && s['exclude'].indexOf(docType) == -1)) && (s['testType'] & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) - List<Element> foundall; - Element found; + late List<Element> foundall; + Element? found; runTest(() { - foundall = root.querySelectorAll(q) as List<Element>; + foundall = (root as dynamic).querySelectorAll(q) as List<Element>; assertNotEquals(foundall, null, 'The method should not return null.'); - assertEquals(foundall.length, e.length, + assertEquals(foundall.length, e!.length, 'The method should return the expected number of matches.'); for (var i = 0; i < e.length; i++) { @@ -242,15 +242,15 @@ void runValidSelectorTest(String type, root, }, type + '.querySelectorAll: ' + n + ': ' + q, skip: skip); runTest(() { - found = root.querySelector(q) as Element; + found = (root as dynamic).querySelector(q) as Element?; - if (e.isNotEmpty) { + if (e!.isNotEmpty) { assertNotEquals(found, null, 'The method should return a match.'); - assertEquals(found.attributes['id'], e[0], + assertEquals(found!.attributes['id'], e[0], 'The method should return the first match.'); assertEquals(found, foundall[0], 'The result should match the first item from querySelectorAll.'); - assertFalse(found.attributes.containsKey('data-clone'), + assertFalse(found!.attributes.containsKey('data-clone'), 'This should not be annotated as a cloned element.'); } else { assertEquals(found, null, 'The method should not match anything.'); @@ -298,7 +298,7 @@ void traverse(Node elem, void Function(Node) fn) { } } -void runTest(dynamic Function() body, String name, {String skip}) => +void runTest(dynamic Function() body, String name, {String? skip}) => unittest.test(name, body, skip: skip); void assertTrue(bool value, String reason) => @@ -312,5 +312,5 @@ void assertEquals(x, y, String reason) => unittest.expect(x, y, reason: reason); void assertNotEquals(x, y, String reason) => unittest.expect(x, unittest.isNot(y), reason: reason); -void assertThrows(exception, void Function() body, [String reason]) => +void assertThrows(exception, void Function() body, [String? reason]) => unittest.expect(body, unittest.throwsA(exception), reason: reason); diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index ee2557a17..34fb8a045 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -11,8 +11,8 @@ import 'package:html/dom_parsing.dart'; typedef TreeBuilderFactory = TreeBuilder Function(bool namespaceHTMLElements); -Map<String, TreeBuilderFactory> _treeTypes; -Map<String, TreeBuilderFactory> get treeTypes { +Map<String, TreeBuilderFactory>? _treeTypes; +Map<String, TreeBuilderFactory>? get treeTypes { // TODO(jmesserly): add DOM here once it's implemented _treeTypes ??= {'simpletree': (useNs) => TreeBuilder(useNs)}; return _treeTypes; @@ -29,7 +29,7 @@ Iterable<String> getDataFiles(String subdirectory) { // TODO(jmesserly): make this class simpler. We could probably split on // "\n#" instead of newline and remove a lot of code. -class TestData extends IterableBase<Map<String, String>> { +class TestData extends IterableBase<Map<String?, String>> { final String _text; final String newTestHeading; @@ -40,12 +40,12 @@ class TestData extends IterableBase<Map<String, String>> { // Note: in Python this was a generator, but since we can't do that in Dart, // it's easier to convert it into an upfront computation. @override - Iterator<Map<String, String>> get iterator => _getData().iterator; + Iterator<Map<String?, String>> get iterator => _getData().iterator; - List<Map<String, String>> _getData() { + List<Map<String?, String>> _getData() { var data = <String, String>{}; - String key; - final result = <Map<String, String>>[]; + String? key; + final List<Map<String?, String>> result = <Map<String, String>>[]; final lines = _text.split('\n'); // Remove trailing newline to match Python if (lines.last == '') { @@ -56,7 +56,7 @@ class TestData extends IterableBase<Map<String, String>> { if (heading != null) { if (data.isNotEmpty && heading == newTestHeading) { // Remove trailing newline - data[key] = data[key].substring(0, data[key].length - 1); + data[key!] = data[key]!.substring(0, data[key]!.length - 1); result.add(normaliseOutput(data)); data = <String, String>{}; } @@ -75,7 +75,7 @@ class TestData extends IterableBase<Map<String, String>> { /// If the current heading is a test section heading return the heading, /// otherwise return null. - static String sectionHeading(String line) { + static String? sectionHeading(String line) { return line.startsWith('#') ? line.substring(1).trim() : null; } @@ -165,7 +165,7 @@ class TestSerializer extends TreeVisitor { for (var key in keys) { final v = node.attributes[key]; if (key is AttributeName) { - final attr = key as AttributeName; + final attr = key; key = '${attr.prefix} ${attr.name}'; } _newline(); diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index e5a05e9a2..e0700a2de 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -14,18 +14,18 @@ import 'package:test/test.dart'; import 'support.dart'; class TokenizerTestParser { - final String _state; - final String _lastStartTag; + final String? _state; + final String? _lastStartTag; final bool _generateSpans; - List outputTokens; + List? outputTokens; - TokenizerTestParser(String initialState, - [String lastStartTag, bool generateSpans = false]) + TokenizerTestParser(String? initialState, + [String? lastStartTag, bool generateSpans = false]) : _state = initialState, _lastStartTag = lastStartTag, _generateSpans = generateSpans; - List parse(String str) { + List? parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. final bytes = utf8.encode(str); final tokenizer = @@ -36,7 +36,7 @@ class TokenizerTestParser { // create a new closure to invoke it via mirrors. final mtok = reflect(tokenizer); tokenizer.state = - () => mtok.invoke(Symbol(_state), const []).reflectee as bool; + () => mtok.invoke(Symbol(_state!), const []).reflectee as bool; if (_lastStartTag != null) { tokenizer.currentToken = StartTagToken(_lastStartTag); @@ -108,10 +108,10 @@ class TokenizerTestParser { } void addOutputToken(Token token, List array) { - outputTokens.add([ + outputTokens!.add([ ...array, - if (token.span != null && _generateSpans) token.span.start.offset, - if (token.span != null && _generateSpans) token.span.end.offset, + if (token.span != null && _generateSpans) token.span!.start.offset, + if (token.span != null && _generateSpans) token.span!.end.offset, ]); } } @@ -151,7 +151,7 @@ List normalizeTokens(List tokens) { /// positions of parse errors and non parse errors. void expectTokensMatch( List expectedTokens, List receivedTokens, bool ignoreErrorOrder, - [bool ignoreErrors = false, String message]) { + [bool ignoreErrors = false, String? message]) { // If the 'selfClosing' attribute is not included in the expected test tokens, // remove it from the received token. var removeSelfClosing = false; @@ -201,10 +201,10 @@ void runTokenizerTest(Map<String, dynamic> testInfo) { testInfo['lastStartTag'] = null; } final parser = TokenizerTestParser( - testInfo['initialState'] as String, - testInfo['lastStartTag'] as String, - testInfo['generateSpans'] as bool /*?*/ ?? false); - var tokens = parser.parse(testInfo['input'] as String); + testInfo['initialState'] as String?, + testInfo['lastStartTag'] as String?, + testInfo['generateSpans'] as bool? ?? false); + var tokens = parser.parse(testInfo['input'] as String)!; tokens = concatenateCharacterTokens(tokens); final received = normalizeTokens(tokens); final errorMsg = [ @@ -217,7 +217,7 @@ void runTokenizerTest(Map<String, dynamic> testInfo) { '\nreceived:', tokens ].map((s) => '$s').join('\n'); - final ignoreErrorOrder = testInfo['ignoreErrorOrder'] as bool /*?*/ ?? false; + final ignoreErrorOrder = testInfo['ignoreErrorOrder'] as bool? ?? false; expectTokensMatch(expected, received, ignoreErrorOrder, true, errorMsg); } @@ -252,7 +252,7 @@ String camelCase(String s) { final result = StringBuffer(); for (var match in RegExp(r'\W+(\w)(\w+)').allMatches(s)) { if (result.length == 0) result.write(s.substring(0, match.start)); - result.write(match.group(1).toUpperCase()); + result.write(match.group(1)!.toUpperCase()); result.write(match.group(2)); } return result.toString(); @@ -265,7 +265,7 @@ void main() { final text = File(path).readAsStringSync(); final tests = jsonDecode(text); final testName = pathos.basenameWithoutExtension(path); - final testList = tests['tests'] as List; + final testList = tests['tests'] as List?; if (testList == null) continue; group(testName, () { From a83fd60f1463d3c1e306955fc837c3f3cefb0c94 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 14 Oct 2020 20:09:39 -0700 Subject: [PATCH 124/212] fixes --- pkgs/html/.travis.yml | 13 ++++--------- pkgs/html/lib/dom.dart | 6 ++++-- pkgs/html/test/parser_feature_test.dart | 4 ++-- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 497fe6887..d41d3c2a0 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -2,7 +2,6 @@ language: dart dart: - dev - - 2.8.1 dart_task: - test: -p vm @@ -10,14 +9,10 @@ dart_task: matrix: include: - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-warnings --fatal-infos . - - dart: 2.8.1 - dart_task: - dartanalyzer: --fatal-warnings . + - script: pub run --enable-experiment=non-nullable test -p vm,chrome + - dart_task: dartfmt + - dart_task: + dartanalyzer: --enable-experiment=non-nullable --fatal-warnings --fatal-infos . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index bdbfb09ca..bcc535d51 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -85,7 +85,8 @@ abstract class _ParentNode implements Node { /// are implemented. For example, nth-child does not implement An+B syntax /// and *-of-type is not implemented. If a selector is not implemented this /// method will throw [UniplmentedError]. - Element? querySelector(String selector) => query.querySelector(this, selector); + Element? querySelector(String selector) => + query.querySelector(this, selector); /// Returns all descendant nodes matching the given selectors, using a /// preorder traversal. @@ -1018,7 +1019,8 @@ class FilteredElementList extends IterableBase<Element> @override Set<Element> toSet() => Set<Element>.from(this); @override - Element firstWhere(bool Function(Element) test, {Element Function()? orElse}) { + Element firstWhere(bool Function(Element) test, + {Element Function()? orElse}) { return _filtered.firstWhere(test, orElse: orElse); } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 5f755555e..7825a23f7 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -134,8 +134,8 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. final doc = parse(text, generateSpans: true); final elem = doc.querySelector('foo')!; - expect( - elem.attributeSpans!['template']!.start.offset, text.indexOf('template')); + expect(elem.attributeSpans!['template']!.start.offset, + text.indexOf('template')); expect(elem.attributeValueSpans!.containsKey('template'), false); }); From 04123ecb6b0e1b92b66fbe6546d467e848ad25d0 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 14 Oct 2020 20:12:30 -0700 Subject: [PATCH 125/212] enable test --- pkgs/html/.travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index d41d3c2a0..822a88e94 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -16,7 +16,7 @@ matrix: # Only building master means that we don't run two builds for each pull request. branches: - only: [master] + only: [master, null_safety] cache: directories: From ecb4ce134dcdc9521630eba42aa6de1ad51d0377 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Wed, 14 Oct 2020 20:13:04 -0700 Subject: [PATCH 126/212] oops2 --- pkgs/html/.travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 822a88e94..038c3da42 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -3,10 +3,6 @@ language: dart dart: - dev -dart_task: - - test: -p vm - - test: -p chrome - matrix: include: - script: pub run --enable-experiment=non-nullable test -p vm,chrome From 8ebbb618698b82489dec0d706b5ebc091a2606dd Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Tue, 20 Oct 2020 16:49:27 -0700 Subject: [PATCH 127/212] Review comments - Make Text.data consistently non nullable for getter and setter. - Add a local variable to avoid double null check for a field. - Make the `container` argument non-nullable in multiple places. - Remove unused `container` field. - Use `?.` over null check then `!`. --- pkgs/html/lib/dom.dart | 11 ++++++----- pkgs/html/lib/parser.dart | 16 ++++++---------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index bcc535d51..f8a992e12 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -430,8 +430,8 @@ class Text extends Node { int get nodeType => Node.TEXT_NODE; String get data => _data = _data.toString(); - set data(String? value) { - _data = value ?? ''; + set data(String value) { + _data = identical(value, null) ? '' : value; } @override @@ -453,7 +453,7 @@ class Text extends Node { String get text => data; @override set text(String? value) { - data = value; + data = value ?? ''; } } @@ -545,8 +545,9 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } Element? get nextElementSibling { + final parentNode = this.parentNode; if (parentNode == null) return null; - final siblings = parentNode!.nodes; + final siblings = parentNode.nodes; for (var i = siblings.indexOf(this) + 1; i < siblings.length; i++) { final s = siblings[i]; if (s is Element) return s; @@ -579,7 +580,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { nodes.clear(); // TODO(jmesserly): should be able to get the same effect by adding the // fragment directly. - nodes.addAll(parseFragment(value, container: localName).nodes); + nodes.addAll(parseFragment(value, container: localName!).nodes); } @override diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 1b8a58e04..c085e08e6 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -56,7 +56,7 @@ Document parse(input, /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. DocumentFragment parseFragment(input, - {String? container = 'div', + {String container = 'div', String? encoding, bool generateSpans = false, String? sourceUrl}) { @@ -80,8 +80,6 @@ class HtmlParser { final List<ParseError> errors = <ParseError>[]; - String? container; - bool firstStartTag = false; // TODO(jmesserly): use enum? @@ -177,8 +175,8 @@ class HtmlParser { /// Parse an html5 document fragment into a tree. /// Pass a [container] to change the type of the containing element. /// After parsing, [errors] will be populated with parse errors, if any. - DocumentFragment parseFragment([String? container = 'div']) { - if (container == null) throw ArgumentError('container'); + DocumentFragment parseFragment([String container = 'div']) { + ArgumentError.checkNotNull(container, 'container'); innerHTML = container.toLowerCase(); _parse(); return tree.getFragment(); @@ -345,11 +343,9 @@ class HtmlParser { /// The last span available. Used for EOF errors if we don't have something /// better. - SourceSpan? get _lastSpan { - if (tokenizer.stream.fileInfo == null) return null; - final pos = tokenizer.stream.position; - return tokenizer.stream.fileInfo!.location(pos).pointSpan(); - } + SourceSpan? get _lastSpan => tokenizer.stream.fileInfo + ?.location(tokenizer.stream.position) + .pointSpan(); void parseError(SourceSpan? span, String errorcode, [Map? datavars = const {}]) { From ec95a23354db130b84a5bce048432eb30e99128b Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Tue, 20 Oct 2020 17:26:39 -0700 Subject: [PATCH 128/212] Make current*Token getters non-nullable --- pkgs/html/lib/src/tokenizer.dart | 142 +++++++++++++++---------------- 1 file changed, 71 insertions(+), 71 deletions(-) diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index acd388fd0..0a7f66033 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -77,9 +77,9 @@ class HtmlTokenizer implements Iterator<Token> { reset(); } - TagToken? get currentTagToken => currentToken as TagToken?; - DoctypeToken? get currentDoctypeToken => currentToken as DoctypeToken?; - StringToken? get currentStringToken => currentToken as StringToken?; + TagToken get currentTagToken => currentToken as TagToken; + DoctypeToken get currentDoctypeToken => currentToken as DoctypeToken; + StringToken get currentStringToken => currentToken as StringToken; Token? _current; @override @@ -578,9 +578,9 @@ class HtmlTokenizer implements Iterator<Token> { state = selfClosingStartTagState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentTagToken!.name = '${currentTagToken!.name}\uFFFD'; + currentTagToken.name = '${currentTagToken.name}\uFFFD'; } else { - currentTagToken!.name = '${currentTagToken!.name}$data'; + currentTagToken.name = '${currentTagToken.name}$data'; // (Don't use charsUntil here, because tag names are // very short and it's faster to not do anything fancy) } @@ -616,7 +616,7 @@ class HtmlTokenizer implements Iterator<Token> { bool _tokenIsAppropriate() { // TODO(jmesserly): this should use case insensitive compare instead. return currentToken is TagToken && - currentTagToken!.name!.toLowerCase() == '$_buffer'.toLowerCase(); + currentTagToken.name!.toLowerCase() == '$_buffer'.toLowerCase(); } bool rcdataEndTagNameState() { @@ -1256,7 +1256,7 @@ class HtmlTokenizer implements Iterator<Token> { bool selfClosingStartTagState() { final data = stream.char(); if (data == '>') { - currentTagToken!.selfClosing = true; + currentTagToken.selfClosing = true; emitCurrentToken(); } else if (data == eof) { _addToken(ParseErrorToken('unexpected-EOF-after-solidus-in-tag')); @@ -1343,7 +1343,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentStartDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('\uFFFD'); + currentStringToken.add('\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); @@ -1353,7 +1353,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken!.add(data!); + currentStringToken.add(data!); state = commentState; } return true; @@ -1365,7 +1365,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('-\uFFFD'); + currentStringToken.add('-\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); _addToken(currentToken); @@ -1375,7 +1375,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else { - currentStringToken!.add('-').add(data!); + currentStringToken.add('-').add(data!); state = commentState; } return true; @@ -1387,13 +1387,13 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('\uFFFD'); + currentStringToken.add('\uFFFD'); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment')); _addToken(currentToken); state = dataState; } else { - currentStringToken!.add(data!).add(stream.charsUntil('-\u0000')); + currentStringToken.add(data!).add(stream.charsUntil('-\u0000')); } return true; } @@ -1404,14 +1404,14 @@ class HtmlTokenizer implements Iterator<Token> { state = commentEndState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('-\uFFFD'); + currentStringToken.add('-\uFFFD'); state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-dash')); _addToken(currentToken); state = dataState; } else { - currentStringToken!.add('-').add(data!); + currentStringToken.add('-').add(data!); state = commentState; } return true; @@ -1424,7 +1424,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('--\uFFFD'); + currentStringToken.add('--\uFFFD'); state = commentState; } else if (data == '!') { _addToken( @@ -1433,7 +1433,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '-') { _addToken( ParseErrorToken('unexpected-dash-after-double-dash-in-comment')); - currentStringToken!.add(data!); + currentStringToken.add(data!); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-double-dash')); _addToken(currentToken); @@ -1441,7 +1441,7 @@ class HtmlTokenizer implements Iterator<Token> { } else { // XXX _addToken(ParseErrorToken('unexpected-char-in-comment')); - currentStringToken!.add('--').add(data!); + currentStringToken.add('--').add(data!); state = commentState; } return true; @@ -1453,18 +1453,18 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == '-') { - currentStringToken!.add('--!'); + currentStringToken.add('--!'); state = commentEndDashState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentStringToken!.add('--!\uFFFD'); + currentStringToken.add('--!\uFFFD'); state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-bang-state')); _addToken(currentToken); state = dataState; } else { - currentStringToken!.add('--!').add(data!); + currentStringToken.add('--!').add(data!); state = commentState; } return true; @@ -1476,7 +1476,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1493,20 +1493,20 @@ class HtmlTokenizer implements Iterator<Token> { return true; } else if (data == '>') { _addToken(ParseErrorToken('expected-doctype-name-but-got-right-bracket')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.name = '\uFFFD'; + currentDoctypeToken.name = '\uFFFD'; state = doctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.name = data; + currentDoctypeToken.name = data; state = doctypeNameState; } return true; @@ -1515,24 +1515,24 @@ class HtmlTokenizer implements Iterator<Token> { bool doctypeNameState() { final data = stream.char(); if (isWhitespace(data)) { - currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); state = afterDoctypeNameState; } else if (data == '>') { - currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.name = '${currentDoctypeToken!.name}\uFFFD'; + currentDoctypeToken.name = '${currentDoctypeToken.name}\uFFFD'; state = doctypeNameState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype-name')); - currentDoctypeToken!.correct = false; - currentDoctypeToken!.name = currentDoctypeToken!.name?.toAsciiLowerCase(); + currentDoctypeToken.correct = false; + currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.name = '${currentDoctypeToken!.name}$data'; + currentDoctypeToken.name = '${currentDoctypeToken.name}$data'; } return true; } @@ -1545,7 +1545,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == eof) { - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; stream.unget(data); _addToken(ParseErrorToken('eof-in-doctype')); _addToken(currentToken); @@ -1587,7 +1587,7 @@ class HtmlTokenizer implements Iterator<Token> { stream.unget(data); _addToken(ParseErrorToken('expected-space-or-right-bracket-in-doctype', messageParams: {'data': data})); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; state = bogusDoctypeState; } return true; @@ -1603,7 +1603,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypePublicIdentifierState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1618,24 +1618,24 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '"') { - currentDoctypeToken!.publicId = ''; + currentDoctypeToken.publicId = ''; state = doctypePublicIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken!.publicId = ''; + currentDoctypeToken.publicId = ''; state = doctypePublicIdentifierSingleQuotedState; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; state = bogusDoctypeState; } return true; @@ -1647,19 +1647,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}\uFFFD'; + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}$data'; + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; } return true; } @@ -1670,19 +1670,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypePublicIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}\uFFFD'; + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.publicId = '${currentDoctypeToken!.publicId}$data'; + currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; } return true; } @@ -1696,20 +1696,20 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == '"') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; state = bogusDoctypeState; } return true; @@ -1723,19 +1723,19 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(currentToken); state = dataState; } else if (data == '"') { - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; state = bogusDoctypeState; } return true; @@ -1751,7 +1751,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeDoctypeSystemIdentifierState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { @@ -1766,24 +1766,24 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '"') { - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierDoubleQuotedState; } else if (data == "'") { - currentDoctypeToken!.systemId = ''; + currentDoctypeToken.systemId = ''; state = doctypeSystemIdentifierSingleQuotedState; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; state = bogusDoctypeState; } return true; @@ -1795,19 +1795,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}\uFFFD'; + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}$data'; + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; } return true; } @@ -1818,19 +1818,19 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypeSystemIdentifierState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); - currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}\uFFFD'; + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}\uFFFD'; } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { - currentDoctypeToken!.systemId = '${currentDoctypeToken!.systemId}$data'; + currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; } return true; } @@ -1844,7 +1844,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); - currentDoctypeToken!.correct = false; + currentDoctypeToken.correct = false; _addToken(currentToken); state = dataState; } else { From f978c19e2b2d9ca9baf0e60ca5116fb0fec7b472 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Tue, 20 Oct 2020 17:29:10 -0700 Subject: [PATCH 129/212] Make more arguments non-nullable --- pkgs/html/lib/src/tokenizer.dart | 92 ++++++++++++++++---------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 0a7f66033..86c569997 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -105,14 +105,14 @@ class HtmlTokenizer implements Iterator<Token> { // Note: we could track the name span here, if we need it. void _markAttributeNameEnd(int offset) => _markAttributeEnd(offset); - void _addAttribute(String? name) { + void _addAttribute(String name) { _attributes ??= []; _attributeName.clear(); _attributeName.write(name); _attributeValue.clear(); final attr = TagAttribute(); _attributes!.add(attr); - if (attributeSpans) attr.start = stream.position - name!.length; + if (attributeSpans) attr.start = stream.position - name.length; } /// This is where the magic happens. @@ -152,8 +152,8 @@ class HtmlTokenizer implements Iterator<Token> { } /// Adds a token to the queue. Sets the span if needed. - void _addToken(Token? token) { - if (generateSpans && token!.span == null) { + void _addToken(Token token) { + if (generateSpans && token.span == null) { final offset = stream.position; token.span = stream.fileInfo!.span(_lastOffset, offset); if (token is! ParseErrorToken) { @@ -366,7 +366,7 @@ class HtmlTokenizer implements Iterator<Token> { /// the state to "data" because that's what's needed after a token has been /// emitted. void emitCurrentToken() { - final token = currentToken; + final token = currentToken!; // Add token to the queue to be yielded if (token is TagToken) { if (lowercaseElementName) { @@ -1006,7 +1006,7 @@ class HtmlTokenizer implements Iterator<Token> { final data = stream.char(); if (isWhitespace(data)) { stream.charsUntil(spaceCharacters, true); - } else if (isLetter(data)) { + } else if (data != null && isLetter(data)) { _addAttribute(data); state = attributeNameState; } else if (data == '>') { @@ -1099,7 +1099,7 @@ class HtmlTokenizer implements Iterator<Token> { state = beforeAttributeValueState; } else if (data == '>') { emitCurrentToken(); - } else if (isLetter(data)) { + } else if (data != null && isLetter(data)) { _addAttribute(data); state = attributeNameState; } else if (data == '/') { @@ -1346,11 +1346,11 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.add('\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentStringToken.add(data!); @@ -1368,11 +1368,11 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.add('-\uFFFD'); } else if (data == '>') { _addToken(ParseErrorToken('incorrect-comment')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentStringToken.add('-').add(data!); @@ -1390,7 +1390,7 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.add('\uFFFD'); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentStringToken.add(data!).add(stream.charsUntil('-\u0000')); @@ -1408,7 +1408,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-dash')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentStringToken.add('-').add(data!); @@ -1420,7 +1420,7 @@ class HtmlTokenizer implements Iterator<Token> { bool commentEndState() { final data = stream.char(); if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); @@ -1436,7 +1436,7 @@ class HtmlTokenizer implements Iterator<Token> { currentStringToken.add(data!); } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-double-dash')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { // XXX @@ -1450,7 +1450,7 @@ class HtmlTokenizer implements Iterator<Token> { bool commentEndBangState() { final data = stream.char(); if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '-') { currentStringToken.add('--!'); @@ -1461,7 +1461,7 @@ class HtmlTokenizer implements Iterator<Token> { state = commentState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-comment-end-bang-state')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentStringToken.add('--!').add(data!); @@ -1477,7 +1477,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('need-space-after-doctype')); @@ -1494,7 +1494,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('expected-doctype-name-but-got-right-bracket')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); @@ -1503,7 +1503,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('expected-doctype-name-but-got-eof')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.name = data; @@ -1519,7 +1519,7 @@ class HtmlTokenizer implements Iterator<Token> { state = afterDoctypeNameState; } else if (data == '>') { currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '\u0000') { _addToken(ParseErrorToken('invalid-codepoint')); @@ -1529,7 +1529,7 @@ class HtmlTokenizer implements Iterator<Token> { _addToken(ParseErrorToken('eof-in-doctype-name')); currentDoctypeToken.correct = false; currentDoctypeToken.name = currentDoctypeToken.name?.toAsciiLowerCase(); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.name = '${currentDoctypeToken.name}$data'; @@ -1542,13 +1542,13 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { currentDoctypeToken.correct = false; stream.unget(data); _addToken(ParseErrorToken('eof-in-doctype')); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { if (data == 'p' || data == 'P') { @@ -1604,7 +1604,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { stream.unget(data); @@ -1626,12 +1626,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1651,12 +1651,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; @@ -1674,12 +1674,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.publicId = '${currentDoctypeToken.publicId}$data'; @@ -1692,7 +1692,7 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { state = betweenDoctypePublicAndSystemIdentifiersState; } else if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '"') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1705,7 +1705,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1720,7 +1720,7 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == '"') { currentDoctypeToken.systemId = ''; @@ -1731,7 +1731,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1752,7 +1752,7 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { stream.unget(data); @@ -1774,12 +1774,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-char-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1799,12 +1799,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; @@ -1822,12 +1822,12 @@ class HtmlTokenizer implements Iterator<Token> { } else if (data == '>') { _addToken(ParseErrorToken('unexpected-end-of-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { currentDoctypeToken.systemId = '${currentDoctypeToken.systemId}$data'; @@ -1840,12 +1840,12 @@ class HtmlTokenizer implements Iterator<Token> { if (isWhitespace(data)) { return true; } else if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { _addToken(ParseErrorToken('eof-in-doctype')); currentDoctypeToken.correct = false; - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else { _addToken(ParseErrorToken('unexpected-char-in-doctype')); @@ -1857,12 +1857,12 @@ class HtmlTokenizer implements Iterator<Token> { bool bogusDoctypeState() { final data = stream.char(); if (data == '>') { - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } else if (data == eof) { // XXX EMIT stream.unget(data); - _addToken(currentToken); + _addToken(currentToken!); state = dataState; } return true; From eb5353be30a82160d1efdf0bd48b1cf05030e907 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Tue, 20 Oct 2020 17:36:37 -0700 Subject: [PATCH 130/212] Remove a comparison against eof to get flow analysis --- pkgs/html/lib/src/tokenizer.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 86c569997..4ee70fcc9 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1869,11 +1869,11 @@ class HtmlTokenizer implements Iterator<Token> { } bool cdataSectionState() { - final data = <String?>[]; + final data = <String>[]; var matchedEnd = 0; while (true) { var ch = stream.char(); - if (ch == eof) { + if (ch == null) { break; } // Deal with null here rather than in the parser From 42d0986241ed7b0e74c36f797f6cfd52cd6e2f88 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Tue, 20 Oct 2020 17:38:58 -0700 Subject: [PATCH 131/212] Initialize to avoid nullable local --- pkgs/html/lib/src/utils.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 6480ea3ef..001c706ae 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -65,7 +65,7 @@ String formatStr(String format, Map? data) { while (isDigit(format[digits])) { digits++; } - int? numberSize; + var numberSize = 0; if (digits > match) { numberSize = int.parse(format.substring(match, digits)); match = digits; @@ -77,11 +77,11 @@ String formatStr(String format, Map? data) { break; case 'd': final number = value.toString(); - result.write(padWithZeros(number, numberSize!)); + result.write(padWithZeros(number, numberSize)); break; case 'x': final number = (value as int).toRadixString(16); - result.write(padWithZeros(number, numberSize!)); + result.write(padWithZeros(number, numberSize)); break; default: throw UnsupportedError('formatStr does not support format ' From a3ed63e3e9e40a1969b369276fff71ce552ddad6 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch1@gmail.com> Date: Mon, 26 Oct 2020 13:47:49 -0700 Subject: [PATCH 132/212] Avoid extra list for single character strings (dart-lang/html#141) When we know the length to be 1, use `String.fromCharCode` instead of `String.fromCharCodes`. Read length from a String directly. --- pkgs/html/lib/src/html_input_stream.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 76499738e..51d73bc57 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -209,14 +209,14 @@ class HtmlInputStream { if (_offset >= _chars.length) return eof; return _isSurrogatePair(_chars, _offset) ? String.fromCharCodes([_chars[_offset++], _chars[_offset++]]) - : String.fromCharCodes([_chars[_offset++]]); + : String.fromCharCode(_chars[_offset++]); } String peekChar() { if (_offset >= _chars.length) return eof; return _isSurrogatePair(_chars, _offset) ? String.fromCharCodes([_chars[_offset], _chars[_offset + 1]]) - : String.fromCharCodes([_chars[_offset]]); + : String.fromCharCode(_chars[_offset]); } // Whether the current and next chars indicate a surrogate pair. @@ -248,7 +248,7 @@ class HtmlInputStream { // Only one character is allowed to be ungotten at once - it must // be consumed again before any further call to unget if (ch != null) { - _offset -= ch.codeUnits.length; + _offset -= ch.length; assert(peekChar() == ch); } } From 1254bbe96e77a6f42abbc3abbd79e9d88ae49851 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 30 Oct 2020 17:22:16 -0700 Subject: [PATCH 133/212] cleanup and fix lints (dart-lang/html#143) --- pkgs/html/analysis_options.yaml | 32 ++--------------- pkgs/html/lib/src/css_class_set.dart | 4 ++- pkgs/html/test/selectors/level1_lib.dart | 46 ++++++++++++------------ 3 files changed, 30 insertions(+), 52 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 9f2325c88..e608f4c59 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -11,12 +11,7 @@ analyzer: dead_code: error linter: rules: - #- annotate_overrides - #- avoid_function_literals_in_foreach_calls - - avoid_empty_else - - avoid_init_to_null - - avoid_null_checks_in_equality_operators - - avoid_relative_lib_imports + - avoid_function_literals_in_foreach_calls - avoid_returning_null - avoid_unused_constructor_parameters - await_only_futures @@ -27,49 +22,28 @@ linter: #- constant_identifier_names - control_flow_in_finally - directives_ordering - - empty_catches - - empty_constructor_bodies - empty_statements - hash_and_equals - implementation_imports #- invariant_booleans - iterable_contains_unrelated_type - - library_names - - library_prefixes - list_remove_unrelated_type - no_adjacent_strings_in_list - non_constant_identifier_names - #- omit_local_variable_types - only_throw_errors - overridden_fields - package_api_docs - package_names - package_prefixed_library_names - - prefer_adjacent_string_concatenation - #- prefer_collection_literals - #- prefer_conditional_assignment - prefer_const_constructors - - prefer_equal_for_default_values - - prefer_final_fields - prefer_final_locals - prefer_initializing_formals - #- prefer_interpolation_to_compose_strings - #- prefer_single_quotes - #- prefer_typing_uninitialized_variables - - prefer_generic_function_type_aliases - - prefer_is_not_empty - - slash_for_doc_comments + - prefer_interpolation_to_compose_strings + - prefer_typing_uninitialized_variables - test_types_in_equals - throw_in_finally - - type_init_formals - #- unnecessary_brace_in_string_interps - unnecessary_brace_in_string_interps - - unnecessary_const - unnecessary_getters_setters - unnecessary_lambdas - - unnecessary_new - unnecessary_null_aware_assignments - unnecessary_statements - - unnecessary_this - - unrelated_type_equality_checks - - valid_regexps diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 3f98a336e..e57c48799 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -186,7 +186,9 @@ abstract class _CssClassSetImpl extends SetBase<String> implements CssClassSet { /// [iterable] from the element. @override void toggleAll(Iterable<String> iterable, [bool shouldAdd]) { - iterable.forEach((e) => toggle(e, shouldAdd)); + for (var e in iterable) { + toggle(e, shouldAdd); + } } /// Helper method used to modify the set of css classes on this element. diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 388ae0027..e22f9c450 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -72,13 +72,13 @@ void setupSpecialElements(parent) { void interfaceCheck(String type, obj) { runTest(() { final q = obj.querySelector is Function; - assertTrue(q, type + ' supports querySelector.'); - }, type + ' supports querySelector'); + assertTrue(q, '$type supports querySelector.'); + }, '$type supports querySelector'); runTest(() { final qa = obj.querySelectorAll is Function; - assertTrue(qa, type + ' supports querySelectorAll.'); - }, type + ' supports querySelectorAll'); + assertTrue(qa, '$type supports querySelectorAll.'); + }, '$type supports querySelectorAll'); runTest(() { final list = obj.querySelectorAll('div'); @@ -86,18 +86,20 @@ void interfaceCheck(String type, obj) { // ElementList which has extra properties. Needed for dart:html compat. assertTrue(list is List<Element>, 'The result should be an instance of a NodeList'); - }, type + '.querySelectorAll returns NodeList instance'); + }, '$type.querySelectorAll returns NodeList instance'); } /* * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after * each call. A static list should not be affected by subsequent changes to the DOM. */ -void verifyStaticList(String type, root) { - var pre, post, preLength; +void verifyStaticList(String type, dynamic root) { + List pre; + List post; + int preLength; runTest(() { - pre = root.querySelectorAll('div'); + pre = root.querySelectorAll('div') as List; preLength = pre.length; final div = doc.createElement('div'); @@ -105,13 +107,13 @@ void verifyStaticList(String type, root) { assertEquals( pre.length, preLength, 'The length of the NodeList should not change.'); - }, type + ': static NodeList'); + }, '$type: static NodeList'); runTest(() { - post = root.querySelectorAll('div'); + post = root.querySelectorAll('div') as List; assertEquals(post.length, preLength + 1, 'The length of the new NodeList should be 1 more than the previous list.'); - }, type + ': new NodeList'); + }, '$type: new NodeList'); } /* @@ -125,20 +127,20 @@ void runSpecialSelectorTests(String type, root) { // 1 assertEquals(root.querySelectorAll('null').length, 1, "This should find one element with the tag name 'NULL'."); - }, type + '.querySelectorAll null'); + }, '$type.querySelectorAll null'); runTest(() { // 2 assertEquals(root.querySelectorAll('undefined').length, 1, "This should find one element with the tag name 'UNDEFINED'."); - }, type + '.querySelectorAll undefined'); + }, '$type.querySelectorAll undefined'); runTest(() { // 3 assertThrows((e) => e is NoSuchMethodError, () { root.querySelectorAll(); }, 'This should throw a TypeError.'); - }, type + '.querySelectorAll no parameter'); + }, '$type.querySelectorAll no parameter'); runTest(() { // 4 @@ -147,7 +149,7 @@ void runSpecialSelectorTests(String type, root) { // TODO(jmesserly): change "localName" back to "tagName" once implemented. assertEquals( elm.localName.toUpperCase(), 'NULL', "The tag name should be 'NULL'."); - }, type + '.querySelector null'); + }, '$type.querySelector null'); runTest(() { // 5 @@ -156,14 +158,14 @@ void runSpecialSelectorTests(String type, root) { // TODO(jmesserly): change "localName" back to "tagName" once implemented. assertEquals(elm.localName.toUpperCase(), 'UNDEFINED', "The tag name should be 'UNDEFINED'."); - }, type + '.querySelector undefined'); + }, '$type.querySelector undefined'); runTest(() { // 6 assertThrows((e) => e is NoSuchMethodError, () { root.querySelector(); }, 'This should throw a TypeError.'); - }, type + '.querySelector no parameter'); + }, '$type.querySelector no parameter'); runTest(() { // 7 @@ -176,7 +178,7 @@ void runSpecialSelectorTests(String type, root) { i++; } }); - }, type + '.querySelectorAll tree order'); + }, '$type.querySelectorAll tree order'); } /// Tests containing this string fail for an unknown reason @@ -239,7 +241,7 @@ void runValidSelectorTest(String type, root, assertFalse(foundall[i].attributes.containsKey('data-clone'), 'This should not be a cloned element.'); } - }, type + '.querySelectorAll: ' + n + ': ' + q, skip: skip); + }, '$type.querySelectorAll: $n:$q', skip: skip); runTest(() { found = root.querySelector(q) as Element; @@ -255,7 +257,7 @@ void runValidSelectorTest(String type, root, } else { assertEquals(found, null, 'The method should not match anything.'); } - }, type + '.querySelector: ' + n + ': ' + q, skip: skip); + }, '$type.querySelector: $n : $q', skip: skip); } else { //console.log("Excluding for " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) } @@ -277,13 +279,13 @@ void runInvalidSelectorTest(String type, root, List selectors) { assertThrows((e) => e is FormatException, () { root.querySelector(q); }); - }, type + '.querySelector: ' + n + ': ' + q); + }, '$type.querySelector: $n:$q'); runTest(() { assertThrows((e) => e is FormatException, () { root.querySelectorAll(q); }); - }, type + '.querySelectorAll: ' + n + ': ' + q); + }, '$type.querySelectorAll: $n:$q'); } } From 47599c58f85b44fa84101c0870189b3a531fe7e0 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 30 Oct 2020 17:34:22 -0700 Subject: [PATCH 134/212] Remove unused link in readme (dart-lang/html#142) --- pkgs/html/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 9706dacd0..ca847c2d0 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -20,5 +20,3 @@ main() { You can pass a String or list of bytes to `parse`. There's also `parseFragment` for parsing a document fragment, and `HtmlParser` if you want more low level control. - -[html5parse]: http://dev.w3.org/html5/spec/parsing.html From 26cf956a6cfe481275aa2595bb16420f5a14c4b6 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 12:51:21 -0800 Subject: [PATCH 135/212] Update SDK constraint for 2.12 --- pkgs/html/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 44658d03f..5dc06eb0c 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://github.com/dart-lang/html publish_to: none environment: - sdk: ">=2.11.0-0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dependencies: csslib: ^0.17.0 From 72fcdc0a793c501f03592bd672d798e3e6a40b5f Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 12:51:48 -0800 Subject: [PATCH 136/212] Remove references to experiment --- pkgs/html/.travis.yml | 4 ++-- pkgs/html/analysis_options.yaml | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml index 038c3da42..9865545b5 100644 --- a/pkgs/html/.travis.yml +++ b/pkgs/html/.travis.yml @@ -5,10 +5,10 @@ dart: matrix: include: - - script: pub run --enable-experiment=non-nullable test -p vm,chrome + - script: pub run test -p vm,chrome - dart_task: dartfmt - dart_task: - dartanalyzer: --enable-experiment=non-nullable --fatal-warnings --fatal-infos . + dartanalyzer: --fatal-warnings --fatal-infos . # Only building master means that we don't run two builds for each pull request. branches: diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index ef12dec88..e608f4c59 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -9,8 +9,6 @@ analyzer: unused_import: error unused_local_variable: error dead_code: error - enable-experiment: - - non-nullable linter: rules: - avoid_function_literals_in_foreach_calls From 0c3cc1f0db38f02d1c6c777be8a5f55c61870875 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 12:53:58 -0800 Subject: [PATCH 137/212] Fix a missed static error --- pkgs/html/test/selectors/level1_lib.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 2e2babbb7..65f1468f2 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -96,7 +96,7 @@ void interfaceCheck(String type, obj) { void verifyStaticList(String type, dynamic root) { List pre; List post; - int preLength; + late int preLength; runTest(() { pre = root.querySelectorAll('div') as List; From 19d0738bf631c5b9af213cbe882d0bfd76988be6 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 12:56:20 -0800 Subject: [PATCH 138/212] Non-null map keys --- pkgs/html/lib/dom.dart | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index f8a992e12..de78f26ab 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -167,8 +167,8 @@ abstract class Node { FileSpan? sourceSpan; /// The attribute spans if requested. Otherwise null. - LinkedHashMap<Object?, FileSpan>? _attributeSpans; - LinkedHashMap<Object?, FileSpan>? _attributeValueSpans; + LinkedHashMap<Object, FileSpan>? _attributeSpans; + LinkedHashMap<Object, FileSpan>? _attributeValueSpans; Node._() { nodes._parent = this; @@ -178,7 +178,7 @@ abstract class Node { /// The span of an attribute is the entire attribute, including the name and /// quotes (if any). For example, the span of "attr" in `<a attr="value">` /// would be the text `attr="value"`. - LinkedHashMap<Object?, FileSpan>? get attributeSpans { + LinkedHashMap<Object, FileSpan>? get attributeSpans { _ensureAttributeSpans(); return _attributeSpans; } @@ -187,7 +187,7 @@ abstract class Node { /// value. Unlike [attributeSpans], this span will inlcude only the value. /// For example, the value span of "attr" in `<a attr="value">` would be the /// text `value`. - LinkedHashMap<Object?, FileSpan>? get attributeValueSpans { + LinkedHashMap<Object, FileSpan>? get attributeValueSpans { _ensureAttributeSpans(); return _attributeValueSpans; } @@ -278,8 +278,9 @@ abstract class Node { void _ensureAttributeSpans() { if (_attributeSpans != null) return; - _attributeSpans = LinkedHashMap<Object?, FileSpan>(); - _attributeValueSpans = LinkedHashMap<Object?, FileSpan>(); + final attributeSpans = _attributeSpans = LinkedHashMap<Object, FileSpan>(); + final attributeValueSpans = + _attributeValueSpans = LinkedHashMap<Object, FileSpan>(); if (sourceSpan == null) return; @@ -293,10 +294,11 @@ abstract class Node { for (var attr in token.attributeSpans!) { final offset = sourceSpan!.start.offset; - _attributeSpans![attr.name] = + final name = attr.name!; + attributeSpans[name] = sourceSpan!.file.span(offset + attr.start, offset + attr.end); if (attr.startValue != null) { - _attributeValueSpans![attr.name] = sourceSpan!.file + attributeValueSpans[name] = sourceSpan!.file .span(offset + attr.startValue!, offset + attr.endValue); } } From 0242a477c3e30b40d87bd12824b83317cee7e84b Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 13:07:55 -0800 Subject: [PATCH 139/212] Late final for relationshipt between Node and NodeList --- pkgs/html/lib/dom.dart | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index de78f26ab..b9d0f01f9 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -157,7 +157,7 @@ abstract class Node { /// A list of child nodes of the current node. This must /// include all elements but not necessarily other node types. - final NodeList nodes = NodeList._(); + late final nodes = NodeList._(this); List<Element>? _elements; @@ -170,9 +170,7 @@ abstract class Node { LinkedHashMap<Object, FileSpan>? _attributeSpans; LinkedHashMap<Object, FileSpan>? _attributeValueSpans; - Node._() { - nodes._parent = this; - } + Node._(); /// If [sourceSpan] is available, this contains the spans of each attribute. /// The span of an attribute is the entire attribute, including the name and @@ -709,11 +707,9 @@ class Comment extends Node { // (The requirement to remove the node from the old node list makes it tricky.) // TODO(jmesserly): is there any way to share code with the _NodeListImpl? class NodeList extends ListProxy<Node> { - // Note: this is conceptually final, but because of circular reference - // between Node and NodeList we initialize it after construction. - Node? _parent; + final Node _parent; - NodeList._(); + NodeList._(this._parent); Node _setParent(Node node) { // Note: we need to remove the node from its previous parent node, if any, From 59f4686d2b3fd5ed30ae49ace965e05c56997aad Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Fri, 6 Nov 2020 14:01:12 -0800 Subject: [PATCH 140/212] Enable and fix lint comment_references (dart-lang/html#144) Fix some typos and reference to deleted or renamed members. Rephrase some docs that were not following best practices. Fix some other spelling mistakes in docs. --- pkgs/html/analysis_options.yaml | 2 +- pkgs/html/lib/dom.dart | 15 ++++++++------- pkgs/html/lib/parser.dart | 12 +++++------- pkgs/html/lib/src/constants.dart | 8 +++++--- pkgs/html/lib/src/html_input_stream.dart | 4 ++-- pkgs/html/lib/src/token.dart | 2 +- 6 files changed, 22 insertions(+), 21 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index e608f4c59..87e8300c2 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -17,7 +17,7 @@ linter: - await_only_futures - camel_case_types - cancel_subscriptions - #- comment_references + - comment_references # See https://github.com/dart-lang/logging/issues/43 #- constant_identifier_names - control_flow_in_finally diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index c3d2e5d16..1950ffe01 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -84,7 +84,7 @@ abstract class _ParentNode implements Node { /// [selectors level 4](http://dev.w3.org/csswg/selectors-4/) /// are implemented. For example, nth-child does not implement An+B syntax /// and *-of-type is not implemented. If a selector is not implemented this - /// method will throw [UniplmentedError]. + /// method will throw [UnimplementedError]. Element querySelector(String selector) => query.querySelector(this, selector); /// Returns all descendant nodes matching the given selectors, using a @@ -94,7 +94,7 @@ abstract class _ParentNode implements Node { /// [selectors level 4](http://dev.w3.org/csswg/selectors-4/) /// are implemented. For example, nth-child does not implement An+B syntax /// and *-of-type is not implemented. If a selector is not implemented this - /// method will throw [UniplmentedError]. + /// method will throw [UnimplementedError]. List<Element> querySelectorAll(String selector) => query.querySelectorAll(this, selector); } @@ -183,7 +183,7 @@ abstract class Node { } /// If [sourceSpan] is available, this contains the spans of each attribute's - /// value. Unlike [attributeSpans], this span will inlcude only the value. + /// value. Unlike [attributeSpans], this span will include only the value. /// For example, the value span of "attr" in `<a attr="value">` would be the /// text `value`. LinkedHashMap<Object, FileSpan> get attributeValueSpans { @@ -239,9 +239,10 @@ abstract class Node { } /// Insert [node] as a child of the current node, before [refNode] in the - /// list of child nodes. Raises [UnsupportedOperationException] if [refNode] - /// is not a child of the current node. If refNode is null, this adds to the - /// end of the list. + /// list of child nodes. + /// + /// [refNode] must be a hild of the current node or null. If [refNode] is null + /// [node] will be added to the end of the list. void insertBefore(Node node, Node refNode) { if (refNode == null) { nodes.add(node); @@ -505,7 +506,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { // creating them every call. // 2) Verify that the html does not contain leading or trailing text nodes. // 3) Verify that the html does not contain both <head> and <body> tags. - // 4) Detatch the created element from its dummy parent. + // 4) Detach the created element from its dummy parent. var parentTag = 'div'; String tag; final match = _startTagRegexp.firstMatch(html); diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 00c15629e..5dce969a0 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -136,7 +136,7 @@ class HtmlParser { /// Set [lowercaseElementName] or [lowercaseAttrName] to false to disable the /// automatic conversion of element and attribute names to lower case. Note /// that standard way to parse HTML is to lowercase, which is what the browser - /// DOM will do if you request [Node.outerHTML], for example. + /// DOM will do if you request `Element.outerHTML`, for example. HtmlParser(input, {String encoding, bool parseMeta = true, @@ -3984,12 +3984,10 @@ class ParseError implements SourceSpanException { int get column => span.start.column; - /// Gets the human readable error message for this error. Use - /// [span.getLocationMessage] or [toString] to get a message including span - /// information. If there is a file associated with the span, both - /// [span.getLocationMessage] and [toString] are equivalent. Otherwise, - /// [span.getLocationMessage] will not show any source url information, but - /// [toString] will include 'ParserError:' as a prefix. + /// Returns the human readable error message for this error. + /// + /// Use [SourceSpan.message] or the [toString] from the [span] field to get a + /// message including span information @override String get message => formatStr(errorMessages[errorCode], data); diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index e1fad5a60..0f82805fa 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -15,9 +15,11 @@ class ReparseException implements Exception { // TODO(jmesserly): assuming the programmatic name is not important, it would be // good to make these "static const" fields on an ErrorMessage class. -/// These are error messages emitted by [HtmlParser]. The values use Python -/// style string formatting, as implemented by [formatStr]. That function only -/// supports the subset of format functionality used here. +/// Error messages emitted by `HtmlParser`. +/// +/// The values use Python style string formatting, as implemented by +/// [formatStr]. That function only supports the subset of format functionality +/// used here. const Map<String, String> errorMessages = { 'null-character': 'Null character in input stream, replaced with U+FFFD.', 'invalid-codepoint': 'Invalid codepoint in stream.', diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 51d73bc57..d08163a90 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -43,13 +43,13 @@ class HtmlInputStream { int _offset; - /// Initialises the HtmlInputStream. + /// Initialise an HtmlInputStream. /// /// HtmlInputStream(source, [encoding]) -> Normalized stream from source /// for use by html5lib. /// /// [source] can be either a [String] or a [List<int>] containing the raw - /// bytes, or a file if [consoleSupport] is initialized. + /// bytes. /// /// The optional encoding parameter must be a string that indicates /// the encoding. If specified, that encoding will be used, diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 05fe58dce..1869b4ffb 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -21,7 +21,7 @@ abstract class TagToken extends Token { class StartTagToken extends TagToken { /// The tag's attributes. A map from the name to the value, where the name - /// can be a [String] or [AttributeName]. + /// can be a [String] or `AttributeName`. LinkedHashMap<Object, String> data; /// The attribute spans if requested. Otherwise null. From 2b08713e1fdae06b67ac738977d722fd1affa5cc Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Wed, 13 Jan 2021 17:21:57 -0800 Subject: [PATCH 141/212] Find test data files from package: URI (dart-lang/html#149) In Dart 2.12 the `Platform.packageConfig` changes from `.packages` to `.dart_tool/package_config.json` which causes the data file discovery to fail. Switch to resolving a `package:html` URI and assuming the pub package layout which is more reliable and stable than the package config file location. - Migrate from `Platform.packageConfig` to `Isolate.resolvePackageUri`. - Change the utility methods to be asynchronous and update the `main` for tests to `async`. - Rename from `testDir` to `testDirectory`. - Rename methods away from `get*` --- pkgs/html/test/parser_test.dart | 4 ++-- .../test/selectors/level1_baseline_test.dart | 9 +++++---- pkgs/html/test/support.dart | 20 +++++++++++++------ pkgs/html/test/tokenizer_test.dart | 4 ++-- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 71730452a..7bdbe23c6 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -69,8 +69,8 @@ void runParserTest( } } -void main() { - for (var path in getDataFiles('tree-construction')) { +void main() async { + await for (var path in dataFiles('tree-construction')) { if (!path.endsWith('.dat')) continue; final tests = TestData(path, 'data'); diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 02d513b4a..19d11239e 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -17,15 +17,16 @@ import '../support.dart'; import 'level1_lib.dart'; import 'selectors.dart'; -Document getTestContentDocument() { - final testPath = p.join(testDir, 'selectors', 'level1-content.html'); +Future<Document> testContentDocument() async { + final testPath = + p.join(await testDirectory, 'selectors', 'level1-content.html'); return parse(File(testPath).readAsStringSync()); } var testType = testQsaBaseline; // Only run baseline tests. var docType = 'html'; // Only run tests suitable for HTML -void main() { +void main() async { /* * This test suite tests Selectors API methods in 4 different contexts: * 1. Document node @@ -62,7 +63,7 @@ void main() { // Prepare the nodes for testing //doc = frame.contentDocument; // Document Node tests - doc = getTestContentDocument(); + doc = await testContentDocument(); final element = doc.getElementById('root'); // In-document Element Node tests diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index ee2557a17..60a248ace 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -3,6 +3,7 @@ library support; import 'dart:collection'; import 'dart:io'; +import 'dart:isolate'; import 'package:path/path.dart' as p; import 'package:html/src/treebuilder.dart'; @@ -18,13 +19,20 @@ Map<String, TreeBuilderFactory> get treeTypes { return _treeTypes; } -final testDir = p.join(p.dirname(p.fromUri(Platform.packageConfig)), 'test'); - -final testDataDir = p.join(testDir, 'data'); +Future<String> get testDirectory async { + final packageUriDir = p.dirname(p.fromUri(await Isolate.resolvePackageUri( + Uri(scheme: 'package', path: 'html/html.dart')))); + // Assume pub layout - root is parent directory to package URI (`lib/`). + final rootPackageDir = p.dirname(packageUriDir); + return p.join(rootPackageDir, 'test'); +} -Iterable<String> getDataFiles(String subdirectory) { - final dir = Directory(p.join(testDataDir, subdirectory)); - return dir.listSync().whereType<File>().map((f) => f.path); +Stream<String> dataFiles(String subdirectory) async* { + final dir = Directory(p.join(await testDirectory, 'data', subdirectory)); + await for (final file in dir.list()) { + if (file is! File) continue; + yield file.path; + } } // TODO(jmesserly): make this class simpler. We could probably split on diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index e5a05e9a2..0ae5cab9f 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -258,8 +258,8 @@ String camelCase(String s) { return result.toString(); } -void main() { - for (var path in getDataFiles('tokenizer')) { +void main() async { + await for (var path in dataFiles('tokenizer')) { if (!path.endsWith('.test')) continue; final text = File(path).readAsStringSync(); From f305412832268b846802dac515bbfab3332979fd Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Wed, 20 Jan 2021 13:24:08 -0800 Subject: [PATCH 142/212] Use covariant for non-nullable override of nullable setter --- pkgs/html/lib/dom.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index b9d0f01f9..403de3f7e 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -379,7 +379,7 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { void _addOuterHtml(StringBuffer str) => _addInnerHtml(str); @override - String get text => _getText(this); + String? get text => _getText(this); @override set text(String? value) => _setText(this, value); } @@ -452,8 +452,8 @@ class Text extends Node { @override String get text => data; @override - set text(String? value) { - data = value ?? ''; + set text(covariant String value) { + data = value; } } From 6e014f9f2a3fda11ca1f98a05ceba65365c33328 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 09:59:53 -0800 Subject: [PATCH 143/212] Comment about publish requirements --- pkgs/html/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 5dc06eb0c..10871ece8 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -4,6 +4,7 @@ version: 0.15.0-nullsafety-dev description: APIs for parsing and manipulating HTML content outside the browser. homepage: https://github.com/dart-lang/html +# Ensure package is tested internally and remove -dev from version to publish. publish_to: none environment: From 3f9b47dc8ebc2cb50f2e1909b6b5435d636551ab Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 11:26:02 -0800 Subject: [PATCH 144/212] Remove local cast alias --- pkgs/html/lib/dom.dart | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 2f2496d21..8e0ea0b26 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -58,12 +58,11 @@ class AttributeName implements Comparable<Object> { int compareTo(Object other) { // Not sure about this sort order if (other is! AttributeName) return 1; - final otherAttributeName = other; - var cmp = (prefix ?? '').compareTo((otherAttributeName.prefix ?? '')); + var cmp = (prefix ?? '').compareTo((other.prefix ?? '')); if (cmp != 0) return cmp; - cmp = name.compareTo(otherAttributeName.name); + cmp = name.compareTo(other.name); if (cmp != 0) return cmp; - return namespace.compareTo(otherAttributeName.namespace); + return namespace.compareTo(other.namespace); } @override From 821c66b3cdc16816ab84cb02c73e077549af0b0c Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 11:46:56 -0800 Subject: [PATCH 145/212] Nullable document/head/body --- pkgs/html/lib/dom.dart | 6 +- pkgs/html/test/dom_test.dart | 162 +++++++++--------- pkgs/html/test/parser_feature_test.dart | 28 +-- .../test/selectors/level1_baseline_test.dart | 2 +- 4 files changed, 99 insertions(+), 99 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 8e0ea0b26..cb4d63a32 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -317,9 +317,9 @@ class Document extends Node int get nodeType => Node.DOCUMENT_NODE; // TODO(jmesserly): optmize this if needed - Element get documentElement => querySelector('html')!; - Element get head => documentElement.querySelector('head')!; - Element get body => documentElement.querySelector('body')!; + Element? get documentElement => querySelector('html'); + Element? get head => documentElement?.querySelector('head'); + Element? get body => documentElement?.querySelector('body'); /// Returns a fragment of HTML or XML that represents the element and its /// contents. diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index f9a5cacb7..82db4f4d4 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -24,7 +24,7 @@ void main() { '<div id=Foo>'); test('getElementById', () { - final foo = doc.body.nodes[0]; + final foo = doc.body!.nodes[0]; final fooVar = foo.nodes[2]; expect((foo as Element).id, 'foo'); expect((fooVar as Element).id, 'Foo'); @@ -33,7 +33,7 @@ void main() { }); test('getElementsByClassName', () { - final foo = doc.body.nodes[0]; + final foo = doc.body!.nodes[0]; final barBaz = foo.nodes[0]; final quxBaz = foo.nodes[1]; expect((barBaz as Element).className, ' bar baz'); @@ -45,7 +45,7 @@ void main() { }); test('getElementsByTagName', () { - final foo = doc.body.nodes[0]; + final foo = doc.body!.nodes[0]; final barBaz = foo.nodes[0]; final quxBaz = foo.nodes[1]; final fooVar = foo.nodes[2]; @@ -56,135 +56,135 @@ void main() { group('fragments are flattened', () { test('add', () { final doc = parse('<body>'); - doc.body.nodes.add(parseFragment('<x-foo>')); - expect((doc.body.nodes[0] as Element).localName, 'x-foo'); - doc.body.nodes.add(parseFragment('<x-bar>')); - expect((doc.body.nodes[1] as Element).localName, 'x-bar'); + doc.body!.nodes.add(parseFragment('<x-foo>')); + expect((doc.body!.nodes[0] as Element).localName, 'x-foo'); + doc.body!.nodes.add(parseFragment('<x-bar>')); + expect((doc.body!.nodes[1] as Element).localName, 'x-bar'); }); test('addLast', () { final doc = parse('<body>'); - doc.body.nodes.addLast(parseFragment('<x-foo>')); - expect((doc.body.nodes[0] as Element).localName, 'x-foo'); - doc.body.nodes.addLast(parseFragment('<x-bar>')); - expect((doc.body.nodes[1] as Element).localName, 'x-bar'); + doc.body!.nodes.addLast(parseFragment('<x-foo>')); + expect((doc.body!.nodes[0] as Element).localName, 'x-foo'); + doc.body!.nodes.addLast(parseFragment('<x-bar>')); + expect((doc.body!.nodes[1] as Element).localName, 'x-bar'); }); test('addAll', () { final doc = parse('<body><x-a></x-a>'); - doc.body.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'x-b'); - expect((doc.body.nodes[2] as Element).localName, 'x-c'); + doc.body!.nodes.addAll([parseFragment('<x-b></x-b><x-c></x-c>')]); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'x-b'); + expect((doc.body!.nodes[2] as Element).localName, 'x-c'); }); test('insert', () { var doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>')); - expect((doc.body.nodes[0] as Element).localName, 'x-b'); - expect((doc.body.nodes[1] as Element).localName, 'x-c'); - expect((doc.body.nodes[2] as Element).localName, 'x-a'); + doc.body!.nodes.insert(0, parseFragment('<x-b></x-b><x-c></x-c>')); + expect((doc.body!.nodes[0] as Element).localName, 'x-b'); + expect((doc.body!.nodes[1] as Element).localName, 'x-c'); + expect((doc.body!.nodes[2] as Element).localName, 'x-a'); doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>')); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'x-b'); - expect((doc.body.nodes[2] as Element).localName, 'x-c'); + doc.body!.nodes.insert(1, parseFragment('<x-b></x-b><x-c></x-c>')); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'x-b'); + expect((doc.body!.nodes[2] as Element).localName, 'x-c'); doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insert(0, parseFragment('<x-b></x-b>')); - doc.body.nodes.insert(1, parseFragment('<x-c></x-c>')); - expect((doc.body.nodes[0] as Element).localName, 'x-b'); - expect((doc.body.nodes[1] as Element).localName, 'x-c'); - expect((doc.body.nodes[2] as Element).localName, 'x-a'); + doc.body!.nodes.insert(0, parseFragment('<x-b></x-b>')); + doc.body!.nodes.insert(1, parseFragment('<x-c></x-c>')); + expect((doc.body!.nodes[0] as Element).localName, 'x-b'); + expect((doc.body!.nodes[1] as Element).localName, 'x-c'); + expect((doc.body!.nodes[2] as Element).localName, 'x-a'); }); test('insertAll', () { var doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]); - expect((doc.body.nodes[0] as Element).localName, 'x-b'); - expect((doc.body.nodes[1] as Element).localName, 'x-c'); - expect((doc.body.nodes[2] as Element).localName, 'x-a'); - expect(doc.body.nodes.length, 3); + doc.body!.nodes.insertAll(0, [parseFragment('<x-b></x-b><x-c></x-c>')]); + expect((doc.body!.nodes[0] as Element).localName, 'x-b'); + expect((doc.body!.nodes[1] as Element).localName, 'x-c'); + expect((doc.body!.nodes[2] as Element).localName, 'x-a'); + expect(doc.body!.nodes.length, 3); doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'x-b'); - expect((doc.body.nodes[2] as Element).localName, 'x-c'); + doc.body!.nodes.insertAll(1, [parseFragment('<x-b></x-b><x-c></x-c>')]); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'x-b'); + expect((doc.body!.nodes[2] as Element).localName, 'x-c'); doc = parse('<body><x-a></x-a>'); - doc.body.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]); - doc.body.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]); - expect((doc.body.nodes[0] as Element).localName, 'x-b'); - expect((doc.body.nodes[1] as Element).localName, 'x-c'); - expect((doc.body.nodes[2] as Element).localName, 'x-a'); + doc.body!.nodes.insertAll(0, [parseFragment('<x-b></x-b>')]); + doc.body!.nodes.insertAll(1, [parseFragment('<x-c></x-c>')]); + expect((doc.body!.nodes[0] as Element).localName, 'x-b'); + expect((doc.body!.nodes[1] as Element).localName, 'x-c'); + expect((doc.body!.nodes[2] as Element).localName, 'x-a'); }); test('operator []=', () { var doc = parse('<body><x-a></x-a>'); - doc.body.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>'); - expect((doc.body.nodes[0] as Element).localName, 'x-b'); - expect((doc.body.nodes[1] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 2); + doc.body!.nodes[0] = parseFragment('<x-b></x-b><x-c></x-c>'); + expect((doc.body!.nodes[0] as Element).localName, 'x-b'); + expect((doc.body!.nodes[1] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 2); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>'); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect((doc.body.nodes[3] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 4); + doc.body!.nodes[1] = parseFragment('<y-b></y-b><y-c></y-c>'); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect((doc.body!.nodes[3] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 4); }); test('setRange', () { var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes.setRange(1, 2, fragment.nodes, 0); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect(doc.body.nodes.length, 3); + doc.body!.nodes.setRange(1, 2, fragment.nodes, 0); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect(doc.body!.nodes.length, 3); fragment = parseFragment('<y-b></y-b><y-c></y-c>'); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes.setRange(1, 1, [fragment], 0); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect((doc.body.nodes[3] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 4); + doc.body!.nodes.setRange(1, 1, [fragment], 0); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect((doc.body!.nodes[3] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 4); }); test('replaceRange', () { var fragment = parseFragment('<y-b></y-b><y-c></y-c>'); var doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes.replaceRange(1, 2, fragment.nodes); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect((doc.body.nodes[3] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 4); + doc.body!.nodes.replaceRange(1, 2, fragment.nodes); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect((doc.body!.nodes[3] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 4); fragment = parseFragment('<y-b></y-b><y-c></y-c>'); doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes.replaceRange(1, 2, [fragment]); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect((doc.body.nodes[3] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 4); + doc.body!.nodes.replaceRange(1, 2, [fragment]); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect((doc.body!.nodes[3] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 4); }); test('replaceWith', () { final fragment = parseFragment('<y-b></y-b><y-c></y-c>'); final doc = parse('<body><x-a></x-a><x-b></x-b><x-c></x-c>'); - doc.body.nodes[1].replaceWith(fragment); - expect((doc.body.nodes[0] as Element).localName, 'x-a'); - expect((doc.body.nodes[1] as Element).localName, 'y-b'); - expect((doc.body.nodes[2] as Element).localName, 'y-c'); - expect((doc.body.nodes[3] as Element).localName, 'x-c'); - expect(doc.body.nodes.length, 4); + doc.body!.nodes[1].replaceWith(fragment); + expect((doc.body!.nodes[0] as Element).localName, 'x-a'); + expect((doc.body!.nodes[1] as Element).localName, 'y-b'); + expect((doc.body!.nodes[2] as Element).localName, 'y-c'); + expect((doc.body!.nodes[3] as Element).localName, 'x-c'); + expect(doc.body!.nodes.length, 4); }); }); } diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 7825a23f7..64068d062 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -20,7 +20,7 @@ void main() { test('line counter', () { // http://groups.google.com/group/html5lib-discuss/browse_frm/thread/f4f00e4a2f26d5c0 final doc = parse('<pre>\nx\n&gt;\n</pre>'); - expect(doc.body.innerHtml, '<pre>x\n&gt;\n</pre>'); + expect(doc.body!.innerHtml, '<pre>x\n&gt;\n</pre>'); }); test('namespace html elements on', () { @@ -43,7 +43,7 @@ void main() { </html> ''', generateSpans: true, sourceUrl: 'ParseError'); final doc = parser.parse(); - expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); + expect(doc.body!.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); final error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); @@ -73,7 +73,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. </html> '''); final doc = parser.parse(); - expect(doc.body.outerHtml, '<body>\n \n \n\n</body>'); + expect(doc.body!.outerHtml, '<body>\n \n \n\n</body>'); expect(parser.errors.length, 1); final error = parser.errors[0]; expect(error.errorCode, 'unexpected-doctype'); @@ -86,7 +86,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. final textContent = '\n hello {{name}}'; final html = '<body><div>$textContent</div>'; final doc = parse(html, generateSpans: true); - final text = doc.body.nodes[0].nodes[0] as Text; + final text = doc.body!.nodes[0].nodes[0] as Text; expect(text, const TypeMatcher<Text>()); expect(text.data, textContent); expect(text.sourceSpan!.start.offset, html.indexOf(textContent)); @@ -150,26 +150,26 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('void element innerHTML', () { var doc = parse('<div></div>'); - expect(doc.body.innerHtml, '<div></div>'); + expect(doc.body!.innerHtml, '<div></div>'); doc = parse('<body><script></script></body>'); - expect(doc.body.innerHtml, '<script></script>'); + expect(doc.body!.innerHtml, '<script></script>'); doc = parse('<br>'); - expect(doc.body.innerHtml, '<br>'); + expect(doc.body!.innerHtml, '<br>'); doc = parse('<br><foo><bar>'); - expect(doc.body.innerHtml, '<br><foo><bar></bar></foo>'); + expect(doc.body!.innerHtml, '<br><foo><bar></bar></foo>'); }); test('empty document has html, body, and head', () { final doc = parse(''); final html = '<html><head></head><body></body></html>'; expect(doc.outerHtml, html); - expect(doc.documentElement.outerHtml, html); - expect(doc.head.outerHtml, '<head></head>'); - expect(doc.body.outerHtml, '<body></body>'); + expect(doc.documentElement!.outerHtml, html); + expect(doc.head!.outerHtml, '<head></head>'); + expect(doc.body!.outerHtml, '<body></body>'); }); test('strange table case', () { - final doc = parse('<table><tbody><foo>').body; + final doc = parse('<table><tbody><foo>').body!; expect(doc.innerHtml, '<foo></foo><table><tbody></tbody></table>'); }); @@ -177,7 +177,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('attribute order', () { // Note: the spec only requires a stable order. // However, we preserve the input order via LinkedHashMap - final body = parse('<foo d=1 a=2 c=3 b=4>').body; + final body = parse('<foo d=1 a=2 c=3 b=4>').body!; expect(body.innerHtml, '<foo d="1" a="2" c="3" b="4"></foo>'); expect(body.querySelector('foo')!.attributes.remove('a'), '2'); expect(body.innerHtml, '<foo d="1" c="3" b="4"></foo>'); @@ -249,7 +249,7 @@ On line 4, column 3 of ParseError: Unexpected DOCTYPE. Ignored. test('error printing without spans', () { final parser = HtmlParser('foo'); final doc = parser.parse(); - expect(doc.body.innerHtml, 'foo'); + expect(doc.body!.innerHtml, 'foo'); expect(parser.errors.length, 1); expect(parser.errors[0].errorCode, 'expected-doctype-but-got-chars'); expect(parser.errors[0].message, diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index cba4c2177..5e85c8fcf 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -116,7 +116,7 @@ void main() async { group('out of scope', () { setUp(() { - doc.body.append(outOfScope); // Append before in-document Element tests. + doc.body!.append(outOfScope); // Append before in-document Element tests. // None of these elements should match }); tearDown(outOfScope.remove); From 27531da264e035238532726ebc3549b69c1f9ac5 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 11:47:10 -0800 Subject: [PATCH 146/212] Some comments around scary patterns --- pkgs/html/lib/dom.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index cb4d63a32..87ef15d22 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -427,6 +427,7 @@ class Text extends Node { String get data => _data = _data.toString(); set data(String value) { + // Handle unsound null values. _data = identical(value, null) ? '' : value; } @@ -448,6 +449,7 @@ class Text extends Node { @override String get text => data; @override + // Text has a non-nullable `text` field, while Node has a nullable field. set text(covariant String value) { data = value; } From 9696ffc8486ba4d95a66066b90a974ce6b9f4d70 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 11:55:26 -0800 Subject: [PATCH 147/212] Avoid unused instantiation --- pkgs/html/lib/src/treebuilder.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 04c3a193d..bc4c08938 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -73,7 +73,7 @@ bool _nodesEqual(Element node1, Element node2) { class TreeBuilder { final String? defaultNamespace; - var document = Document(); + late Document document; final List<Element> openElements = <Element>[]; From 831da5b56926be166bfa861ce925a40a0c256fad Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 13:51:14 -0800 Subject: [PATCH 148/212] Migrate to github actions (dart-lang/html#151) - Add workflow for testing with github actions. - Drop Travis config. - Delete unused `.test_config` file. --- pkgs/html/.github/workflows/test-package.yml | 52 ++++++++++++++++++++ pkgs/html/.test_config | 3 -- pkgs/html/.travis.yml | 28 ----------- 3 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 pkgs/html/.github/workflows/test-package.yml delete mode 100644 pkgs/html/.test_config delete mode 100644 pkgs/html/.travis.yml diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml new file mode 100644 index 000000000..0e7e42e2f --- /dev/null +++ b/pkgs/html/.github/workflows/test-package.yml @@ -0,0 +1,52 @@ +name: Dart CI + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + schedule: + - cron: "0 0 * * 0" + +jobs: + analyze: + runs-on: ubuntu-latest + strategy: + fail-fast: false + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: dev + - id: install + name: Install dependencies + run: dart pub get + - name: Check formatting + run: dart format --output=none --set-exit-if-changed . + if: steps.install.outcome == 'success' + - name: Analyze code + run: dart analyze --fatal-infos + if: steps.install.outcome == 'success' + + test: + needs: analyze + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + sdk: [2.8.1, dev] + steps: + - uses: actions/checkout@v2 + - uses: dart-lang/setup-dart@v0.3 + with: + sdk: ${{ matrix.sdk }} + - id: install + name: Install dependencies + run: pub get + - name: Run VM tests + run: pub run test --platform vm + if: steps.install.outcome == 'success' + - name: Run Chrome tests + run: pub run test --platform chrome + if: steps.install.outcome == 'success' diff --git a/pkgs/html/.test_config b/pkgs/html/.test_config deleted file mode 100644 index 412fc5c5c..000000000 --- a/pkgs/html/.test_config +++ /dev/null @@ -1,3 +0,0 @@ -{ - "test_package": true -} \ No newline at end of file diff --git a/pkgs/html/.travis.yml b/pkgs/html/.travis.yml deleted file mode 100644 index 497fe6887..000000000 --- a/pkgs/html/.travis.yml +++ /dev/null @@ -1,28 +0,0 @@ -language: dart - -dart: - - dev - - 2.8.1 - -dart_task: - - test: -p vm - - test: -p chrome - -matrix: - include: - - dart: dev - dart_task: dartfmt - - dart: dev - dart_task: - dartanalyzer: --fatal-warnings --fatal-infos . - - dart: 2.8.1 - dart_task: - dartanalyzer: --fatal-warnings . - -# Only building master means that we don't run two builds for each pull request. -branches: - only: [master] - -cache: - directories: - - $HOME/.pub-cache From 48877de60e195abcaac74a64949bf851f9befbc6 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 14:06:23 -0800 Subject: [PATCH 149/212] Remove unused container field from HtmlParser (dart-lang/html#150) --- pkgs/html/CHANGELOG.md | 4 ++-- pkgs/html/lib/parser.dart | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index e294c419f..8836bf64c 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.15.0-dev -- Drop `HtmlParser.lastPhase` and `HtmlParser.beforeRcDataPhase`. These fields - never had a value other than `null`. +- Drop `lastPhase`, `beforeRcDataPhase`, and `container` fields from + `HtmlParser` class. These fields never had a value other than `null`. ## 0.14.0+4 diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 5dce969a0..6466fa0bb 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -80,8 +80,6 @@ class HtmlParser { final List<ParseError> errors = <ParseError>[]; - String container; - bool firstStartTag = false; // TODO(jmesserly): use enum? From 88d22ae004115f76f4eab50d9eaac756ec1ff3e0 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 14:11:11 -0800 Subject: [PATCH 150/212] Dont' bothery with null_safety branch --- pkgs/html/.github/workflows/test-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index b3bf5783a..cf3d6504a 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -4,7 +4,7 @@ on: push: branches: [master] pull_request: - branches: [master, null_safety] + branches: [master] schedule: - cron: "0 0 * * 0" From 9d2103c0c9d884e05bc1d00a32c7f4ff3c3c766c Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 25 Jan 2021 14:59:53 -0800 Subject: [PATCH 151/212] Use .0 version. Mention migration in changelog --- pkgs/html/CHANGELOG.md | 3 ++- pkgs/html/pubspec.yaml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index c09af11c7..f56089e13 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,5 +1,6 @@ -## 0.15.0-nullsafety-dev +## 0.15.0-nullsafety.0-dev +- Migrate to null safety. - Drop `lastPhase`, `beforeRcDataPhase`, and `container` fields from `HtmlParser` class. These fields never had a value other than `null`. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 10871ece8..df0411b72 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.0-nullsafety-dev +version: 0.15.0-nullsafety.0-dev description: APIs for parsing and manipulating HTML content outside the browser. homepage: https://github.com/dart-lang/html From 93198a066bc46d0602503c06de5f381d9a471221 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Mon, 1 Feb 2021 10:11:42 -0800 Subject: [PATCH 152/212] Prepare to publish (dart-lang/html#152) --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/pubspec.yaml | 11 ++--------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index f56089e13..3ab6de052 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.15.0-nullsafety.0-dev +## 0.15.0-nullsafety.0 - Migrate to null safety. - Drop `lastPhase`, `beforeRcDataPhase`, and `container` fields from diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index df0411b72..7300645d9 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,24 +1,17 @@ name: html -version: 0.15.0-nullsafety.0-dev +version: 0.15.0-nullsafety.0 description: APIs for parsing and manipulating HTML content outside the browser. homepage: https://github.com/dart-lang/html -# Ensure package is tested internally and remove -dev from version to publish. -publish_to: none - environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - csslib: ^0.17.0 + csslib: ^0.17.0-nullsafety source_span: ^1.8.0-nullsafety dev_dependencies: path: ^1.8.0-nullsafety pedantic: ^1.10.0-nullsafety test: ^1.16.0-nullsafety - -dependency_overrides: - csslib: - git: git://github.com/dart-lang/csslib.git From f410ff6dd9ac64f5a723904d9b6f222c6a1a06fc Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Thu, 11 Feb 2021 08:18:45 -0800 Subject: [PATCH 153/212] Stable null safe v0.15.0 (dart-lang/html#154) --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/pubspec.yaml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 3ab6de052..b5c2c9304 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.15.0-nullsafety.0 +## 0.15.0 - Migrate to null safety. - Drop `lastPhase`, `beforeRcDataPhase`, and `container` fields from diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 7300645d9..f5f932a8d 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,17 +1,17 @@ name: html -version: 0.15.0-nullsafety.0 +version: 0.15.0 description: APIs for parsing and manipulating HTML content outside the browser. -homepage: https://github.com/dart-lang/html +repository: https://github.com/dart-lang/html environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - csslib: ^0.17.0-nullsafety - source_span: ^1.8.0-nullsafety + csslib: ^0.17.0 + source_span: ^1.8.0 dev_dependencies: - path: ^1.8.0-nullsafety - pedantic: ^1.10.0-nullsafety - test: ^1.16.0-nullsafety + path: ^1.8.0 + pedantic: ^1.10.0 + test: ^1.16.0 From 7f7be02ede21bf4ee11cd12882534cea55e31ea5 Mon Sep 17 00:00:00 2001 From: Franklin Yow <58489007+franklinyow@users.noreply.github.com> Date: Tue, 30 Mar 2021 16:09:15 -0700 Subject: [PATCH 154/212] Update LICENSE Changed to comply with open source review --- pkgs/html/LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkgs/html/LICENSE b/pkgs/html/LICENSE index d5ee6416d..1d776b2d3 100644 --- a/pkgs/html/LICENSE +++ b/pkgs/html/LICENSE @@ -14,7 +14,7 @@ Adam Barth - abarth@webkit.org Eric Seidel - eric@webkit.org The Mozilla Foundation (contributions from Henri Sivonen since 2008) David Flanagan (Mozilla) - dflanagan@mozilla.com -Google Inc. (contributed the Dart port) - misc@dartlang.org +Google LLC (contributed the Dart port) - misc@dartlang.org Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From c7449e7e1f160ed03e73129c4a7f991d50687821 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Mon, 26 Apr 2021 08:34:48 -0700 Subject: [PATCH 155/212] Fix newly enforced lint (dart-lang/html#161) --- pkgs/html/test/dom_test.dart | 2 +- pkgs/html/test/support.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index 82db4f4d4..df6eb02f7 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -1,9 +1,9 @@ /// Additional feature tests that aren't based on test data. library dom_test; -import 'package:test/test.dart'; import 'package:html/dom.dart'; import 'package:html/parser.dart'; +import 'package:test/test.dart'; void main() { group('Element', () { diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index 83894af77..f4f48f8dd 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -5,10 +5,10 @@ import 'dart:collection'; import 'dart:io'; import 'dart:isolate'; -import 'package:path/path.dart' as p; -import 'package:html/src/treebuilder.dart'; import 'package:html/dom.dart'; import 'package:html/dom_parsing.dart'; +import 'package:html/src/treebuilder.dart'; +import 'package:path/path.dart' as p; typedef TreeBuilderFactory = TreeBuilder Function(bool namespaceHTMLElements); From 61c4df64fd5f60011a41fef44277b6600e73bf84 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@google.com> Date: Sat, 5 Jun 2021 12:57:24 -0700 Subject: [PATCH 156/212] add dependabot --- pkgs/html/.github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 pkgs/html/.github/dependabot.yml diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml new file mode 100644 index 000000000..430a85e7d --- /dev/null +++ b/pkgs/html/.github/dependabot.yml @@ -0,0 +1,11 @@ +# Set update schedule for GitHub Actions +# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot + +version: 2 +updates: + +- package-ecosystem: "github-actions" + directory: "/" + schedule: + # Check for updates to GitHub Actions every weekday + interval: "daily" From 7b20b620ab4306619753782e80b19d067db6527e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 5 Jun 2021 13:06:32 -0700 Subject: [PATCH 157/212] Bump dart-lang/setup-dart from 0.3 to 1 (dart-lang/html#164) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 0.3 to 1. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/v0.3...v1) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index cf3d6504a..fac86a229 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: dev - id: install @@ -35,10 +35,10 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [dev] + sdk: [2.12.0, dev] steps: - uses: actions/checkout@v2 - - uses: dart-lang/setup-dart@v0.3 + - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} - id: install From bb4b6d0dd19ed89988dbf7d6271decd41d4b46dc Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 16 Jul 2021 11:05:44 -0700 Subject: [PATCH 158/212] Update CI (dart-lang/html#166) --- pkgs/html/.github/workflows/test-package.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index fac86a229..9460c263d 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -19,13 +19,10 @@ jobs: with: sdk: dev - id: install - name: Install dependencies run: dart pub get - - name: Check formatting - run: dart format --output=none --set-exit-if-changed . + - run: dart format --output=none --set-exit-if-changed . if: steps.install.outcome == 'success' - - name: Analyze code - run: dart analyze --fatal-infos + - run: dart analyze --fatal-infos if: steps.install.outcome == 'success' test: @@ -42,11 +39,8 @@ jobs: with: sdk: ${{ matrix.sdk }} - id: install - name: Install dependencies - run: pub get - - name: Run VM tests - run: pub run test --platform vm + run: dart pub get + - run: dart test --platform vm if: steps.install.outcome == 'success' - - name: Run Chrome tests - run: pub run test --platform chrome + - run: dart test --platform chrome if: steps.install.outcome == 'success' From c4ac5c3d34c82c3b84749b97aa747995c8beea9a Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Thu, 14 Oct 2021 09:06:13 -0700 Subject: [PATCH 159/212] Move to pkg:lints (dart-lang/html#169) --- pkgs/html/CHANGELOG.md | 2 + pkgs/html/analysis_options.yaml | 2 +- pkgs/html/lib/dom.dart | 104 ++++++++++++++--------- pkgs/html/lib/src/constants.dart | 30 ++++--- pkgs/html/lib/src/html_input_stream.dart | 6 +- pkgs/html/lib/src/list_proxy.dart | 16 ++-- pkgs/html/lib/src/query_selector.dart | 74 ++++++++-------- pkgs/html/lib/src/tokenizer.dart | 4 +- pkgs/html/pubspec.yaml | 6 +- pkgs/html/test/selectors/selectors.dart | 60 ++++++------- 10 files changed, 167 insertions(+), 137 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index b5c2c9304..60c7daf7a 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,5 @@ +## 0.15.1-dev + ## 0.15.0 - Migrate to null safety. diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 87e8300c2..413355027 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,4 +1,4 @@ -include: package:pedantic/analysis_options.yaml +include: package:lints/recommended.yaml analyzer: strong-mode: implicit-casts: false diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 87ef15d22..69ac4367b 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -2,6 +2,8 @@ /// with dart:html, but it is missing many types and APIs. library dom; +// ignore_for_file: constant_identifier_names + // TODO(jmesserly): lots to do here. Originally I wanted to generate this using // our Blink IDL generator, but another idea is to directly use the excellent // http://dom.spec.whatwg.org/ and http://html.spec.whatwg.org/ and just @@ -66,10 +68,11 @@ class AttributeName implements Comparable<Object> { } @override - bool operator ==(x) { - if (x is! AttributeName) return false; - return prefix == x.prefix && name == x.name && namespace == x.namespace; - } + bool operator ==(Object other) => + other is AttributeName && + prefix == other.prefix && + name == other.name && + namespace == other.namespace; } // http://dom.spec.whatwg.org/#parentnode @@ -214,6 +217,7 @@ abstract class Node { // Implemented per: http://dom.spec.whatwg.org/#dom-node-textcontent String? get text => null; + set text(String? value) {} void append(Node node) => nodes.add(node); @@ -311,6 +315,7 @@ abstract class Node { class Document extends Node with _ParentNode, _NonElementParentNode, _ElementAndDocument { Document() : super._(); + factory Document.html(String html) => parse(html); @override @@ -318,7 +323,9 @@ class Document extends Node // TODO(jmesserly): optmize this if needed Element? get documentElement => querySelector('html'); + Element? get head => documentElement?.querySelector('head'); + Element? get body => documentElement?.querySelector('body'); /// Returns a fragment of HTML or XML that represents the element and its @@ -352,6 +359,7 @@ class Document extends Node class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { DocumentFragment() : super._(); + factory DocumentFragment.html(String html) => parseFragment(html); @override @@ -376,6 +384,7 @@ class DocumentFragment extends Node with _ParentNode, _NonElementParentNode { @override String? get text => _getText(this); + @override set text(String? value) => _setText(this, value); } @@ -426,6 +435,7 @@ class Text extends Node { int get nodeType => Node.TEXT_NODE; String get data => _data = _data.toString(); + set data(String value) { // Handle unsound null values. _data = identical(value, null) ? '' : value; @@ -448,6 +458,7 @@ class Text extends Node { @override String get text => data; + @override // Text has a non-nullable `text` field, while Node has a nullable field. set text(covariant String value) { @@ -561,6 +572,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { @override String get text => _getText(this); + @override set text(String? value) => _setText(this, value); @@ -572,6 +584,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { /// Can be set, to replace the contents of the element with nodes parsed from /// the given string. String get innerHtml => _innerHtml; + // TODO(jmesserly): deprecate in favor of: // <https://api.dartlang.org/apidocs/channels/stable/#dart-dom-html.Element@id_setInnerHtml> set innerHtml(String value) { @@ -650,7 +663,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } set id(String value) { - attributes['id'] = '$value'; + attributes['id'] = value; } // http://dom.spec.whatwg.org/#dom-element-classname @@ -660,7 +673,7 @@ class Element extends Node with _ParentNode, _ElementAndDocument { } set className(String value) { - attributes['class'] = '$value'; + attributes['class'] = value; } /// The set of CSS classes applied to this element. @@ -695,6 +708,7 @@ class Comment extends Node { @override String? get text => data; + @override set text(String? value) { data = value; @@ -718,18 +732,18 @@ class NodeList extends ListProxy<Node> { } @override - void add(Node value) { - if (value is DocumentFragment) { - addAll(value.nodes); + void add(Node element) { + if (element is DocumentFragment) { + addAll(element.nodes); } else { - super.add(_setParent(value)); + super.add(_setParent(element)); } } void addLast(Node value) => add(value); @override - void addAll(Iterable<Node> collection) { + void addAll(Iterable<Node> iterable) { // Note: we need to be careful if collection is another NodeList. // In particular: // 1. we need to copy the items before updating their parent pointers, @@ -737,7 +751,7 @@ class NodeList extends ListProxy<Node> { // 2. we should update parent pointers in reverse order. That way they // are removed from the original NodeList (if any) from the end, which // is faster. - final list = _flattenDocFragments(collection); + final list = _flattenDocFragments(iterable); for (var node in list.reversed) { _setParent(node); } @@ -745,11 +759,11 @@ class NodeList extends ListProxy<Node> { } @override - void insert(int index, Node value) { - if (value is DocumentFragment) { - insertAll(index, value.nodes); + void insert(int index, Node element) { + if (element is DocumentFragment) { + insertAll(index, element.nodes); } else { - super.insert(index, _setParent(value)); + super.insert(index, _setParent(element)); } } @@ -757,7 +771,7 @@ class NodeList extends ListProxy<Node> { Node removeLast() => super.removeLast()..parentNode = null; @override - Node removeAt(int i) => super.removeAt(i)..parentNode = null; + Node removeAt(int index) => super.removeAt(index)..parentNode = null; @override void clear() { @@ -781,17 +795,17 @@ class NodeList extends ListProxy<Node> { // TODO(jmesserly): These aren't implemented in DOM _NodeListImpl, see // http://code.google.com/p/dart/issues/detail?id=5371 @override - void setRange(int start, int rangeLength, Iterable<Node> from, - [int startFrom = 0]) { - var fromVar = from as List<Node>; + void setRange(int start, int end, Iterable<Node> iterable, + [int skipCount = 0]) { + var fromVar = iterable as List<Node>; if (fromVar is NodeList) { // Note: this is presumed to make a copy - fromVar = fromVar.sublist(startFrom, startFrom + rangeLength); + fromVar = fromVar.sublist(skipCount, skipCount + end); } // Note: see comment in [addAll]. We need to be careful about the order of // operations if [from] is also a NodeList. - for (var i = rangeLength - 1; i >= 0; i--) { - this[start + i] = fromVar[startFrom + i]; + for (var i = end - 1; i >= 0; i--) { + this[start + i] = fromVar[skipCount + i]; } } @@ -802,11 +816,11 @@ class NodeList extends ListProxy<Node> { } @override - void removeRange(int start, int rangeLength) { - for (var i = start; i < rangeLength; i++) { + void removeRange(int start, int end) { + for (var i = start; i < end; i++) { this[i].parentNode = null; } - super.removeRange(start, rangeLength); + super.removeRange(start, end); } @override @@ -826,9 +840,9 @@ class NodeList extends ListProxy<Node> { } @override - void insertAll(int index, Iterable<Node> collection) { + void insertAll(int index, Iterable<Node> iterable) { // Note: we need to be careful how we copy nodes. See note in addAll. - final list = _flattenDocFragments(collection); + final list = _flattenDocFragments(iterable); for (var node in list.reversed) { _setParent(node); } @@ -876,8 +890,8 @@ class FilteredElementList extends IterableBase<Element> List<Element> get _filtered => _childNodes.whereType<Element>().toList(); @override - void forEach(void Function(Element) f) { - _filtered.forEach(f); + void forEach(void Function(Element) action) { + _filtered.forEach(action); } @override @@ -901,8 +915,8 @@ class FilteredElementList extends IterableBase<Element> String join([String separator = '']) => _filtered.join(separator); @override - void add(Element value) { - _childNodes.add(value); + void add(Element element) { + _childNodes.add(element); } @override @@ -932,12 +946,12 @@ class FilteredElementList extends IterableBase<Element> } @override - void fillRange(int start, int end, [Element? fillValue]) { + void fillRange(int start, int end, [Element? fill]) { throw UnimplementedError(); } @override - void replaceRange(int start, int end, Iterable<Element> iterable) { + void replaceRange(int start, int end, Iterable<Element> newContents) { throw UnimplementedError(); } @@ -960,14 +974,16 @@ class FilteredElementList extends IterableBase<Element> @override Iterable<T> map<T>(T Function(Element) f) => _filtered.map(f); + @override - Iterable<Element> where(bool Function(Element) f) => _filtered.where(f); + Iterable<Element> where(bool Function(Element) test) => _filtered.where(test); + @override Iterable<T> expand<T>(Iterable<T> Function(Element) f) => _filtered.expand(f); @override - void insert(int index, Element value) { - _childNodes.insert(index, value); + void insert(int index, Element element) { + _childNodes.insert(index, element); } @override @@ -1007,14 +1023,18 @@ class FilteredElementList extends IterableBase<Element> } @override - bool every(bool Function(Element) f) => _filtered.every(f); + bool every(bool Function(Element) test) => _filtered.every(test); + @override - bool any(bool Function(Element) f) => _filtered.any(f); + bool any(bool Function(Element) test) => _filtered.any(test); + @override List<Element> toList({bool growable = true}) => List<Element>.from(this, growable: growable); + @override Set<Element> toSet() => Set<Element>.from(this); + @override Element firstWhere(bool Function(Element) test, {Element Function()? orElse}) { @@ -1040,17 +1060,23 @@ class FilteredElementList extends IterableBase<Element> @override bool get isEmpty => _filtered.isEmpty; + @override int get length => _filtered.length; + @override Element operator [](int index) => _filtered[index]; + @override Iterator<Element> get iterator => _filtered.iterator; + @override List<Element> sublist(int start, [int? end]) => _filtered.sublist(start, end); + @override Iterable<Element> getRange(int start, int end) => _filtered.getRange(start, end); + @override int indexOf(Object? element, [int start = 0]) => // Cast forced by ListMixin https://github.com/dart-lang/sdk/issues/31311 diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 2c013d450..e32e03796 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -75,7 +75,7 @@ const Map<String, String> errorMessages = { 'unexpected-character-after-attribute-value': 'Unexpected character after attribute value.', 'eof-in-attribute-value-double-quote': - 'Unexpected end of file in attribute value (\".', + 'Unexpected end of file in attribute value (".', 'eof-in-attribute-value-single-quote': "Unexpected end of file in attribute value (').", 'eof-in-attribute-value-no-quotes': @@ -402,8 +402,8 @@ const mathmlTextIntegrationPointElements = [ const spaceCharacters = ' \n\r\t\u000C'; -const int NEWLINE = 10; -const int RETURN = 13; +const int newLine = 10; +const int returnCode = 13; bool isWhitespace(String? char) { if (char == null) return false; @@ -413,9 +413,9 @@ bool isWhitespace(String? char) { bool isWhitespaceCC(int charCode) { switch (charCode) { case 9: // '\t' - case NEWLINE: // '\n' + case newLine: // '\n' case 12: // '\f' - case RETURN: // '\r' + case returnCode: // '\r' case 32: // ' ' return true; } @@ -433,11 +433,11 @@ const List<String> tableInsertModeElements = [ // TODO(jmesserly): remove these in favor of the test functions const asciiLetters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; -const ZERO = 48; -const LOWER_A = 97; -const LOWER_Z = 122; -const UPPER_A = 65; -const UPPER_Z = 90; +const _zeroCode = 48; +const _lowerACode = 97; +const _lowerZCode = 122; +const _upperACode = 65; +const _upperZCode = 90; bool isLetterOrDigit(String? char) => isLetter(char) || isDigit(char); @@ -445,13 +445,14 @@ bool isLetterOrDigit(String? char) => isLetter(char) || isDigit(char); bool isLetter(String? char) { if (char == null) return false; final cc = char.codeUnitAt(0); - return cc >= LOWER_A && cc <= LOWER_Z || cc >= UPPER_A && cc <= UPPER_Z; + return cc >= _lowerACode && cc <= _lowerZCode || + cc >= _upperACode && cc <= _upperZCode; } bool isDigit(String? char) { if (char == null) return false; final cc = char.codeUnitAt(0); - return cc >= ZERO && cc < ZERO + 10; + return cc >= _zeroCode && cc < _zeroCode + 10; } bool isHexDigit(String? char) { @@ -491,8 +492,9 @@ extension AsciiUpperToLower on String { String toAsciiLowerCase() => String.fromCharCodes(codeUnits.map(_asciiToLower)); - static int _asciiToLower(int c) => - (c >= UPPER_A && c <= UPPER_Z) ? c + LOWER_A - UPPER_A : c; + static int _asciiToLower(int c) => (c >= _upperACode && c <= _upperZCode) + ? c + _lowerACode - _upperACode + : c; } // Heading elements need to be ordered diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 60bf8f8ed..a0e490f77 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -96,7 +96,7 @@ class HtmlInputStream { var c = rawChars[i]; if (skipNewline) { skipNewline = false; - if (c == NEWLINE) continue; + if (c == newLine) continue; } final isSurrogatePair = _isSurrogatePair(rawChars, i); @@ -111,9 +111,9 @@ class HtmlInputStream { } wasSurrogatePair = isSurrogatePair; - if (c == RETURN) { + if (c == returnCode) { skipNewline = true; - c = NEWLINE; + c = newLine; } _chars.add(c); diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 61784c7b9..05086fa08 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -8,7 +8,7 @@ abstract class ListProxy<E> extends ListBase<E> { final List<E> _list = <E>[]; @override - bool remove(Object? item) => _list.remove(item); + bool remove(Object? element) => _list.remove(element); @override int get length => _list.length; @@ -32,16 +32,16 @@ abstract class ListProxy<E> extends ListBase<E> { } @override - void add(E value) { - _list.add(value); + void add(E element) { + _list.add(element); } @override - void insert(int index, E item) => _list.insert(index, item); + void insert(int index, E element) => _list.insert(index, element); @override - void addAll(Iterable<E> collection) { - _list.addAll(collection); + void addAll(Iterable<E> iterable) { + _list.addAll(iterable); } @override @@ -53,7 +53,7 @@ abstract class ListProxy<E> extends ListBase<E> { E removeAt(int index) => _list.removeAt(index); @override - void removeRange(int start, int length) { - _list.removeRange(start, length); + void removeRange(int start, int end) { + _list.removeRange(start, end); } } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 8880cfe7e..b596745df 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -57,17 +57,17 @@ class SelectorEvaluator extends Visitor { } @override - bool visitSelectorGroup(SelectorGroup group) => - group.selectors.any(visitSelector); + bool visitSelectorGroup(SelectorGroup node) => + node.selectors.any(visitSelector); @override - bool visitSelector(Selector selector) { + bool visitSelector(Selector node) { final old = _element; var result = true; // Note: evaluate selectors right-to-left as it's more efficient. int? combinator; - for (var s in selector.simpleSelectorSequences.reversed) { + for (var s in node.simpleSelectorSequences.reversed) { if (combinator == null) { result = s.simpleSelector.visit(this) as bool; } else if (combinator == TokenKind.COMBINATOR_DESCENDANT) { @@ -110,7 +110,7 @@ class SelectorEvaluator extends Visitor { case TokenKind.COMBINATOR_NONE: break; default: - throw _unsupported(selector); + throw _unsupported(node); } if (_element == null) { @@ -131,8 +131,8 @@ class SelectorEvaluator extends Visitor { FormatException("'$selector' is not a valid selector"); @override - bool visitPseudoClassSelector(PseudoClassSelector selector) { - switch (selector.name) { + bool visitPseudoClassSelector(PseudoClassSelector node) { + switch (node.name) { // http://dev.w3.org/csswg/selectors-4/#structural-pseudos // http://dev.w3.org/csswg/selectors-4/#the-root-pseudo @@ -175,17 +175,17 @@ class SelectorEvaluator extends Visitor { } // :before, :after, :first-letter/line can't match DOM elements. - if (_isLegacyPsuedoClass(selector.name)) return false; + if (_isLegacyPsuedoClass(node.name)) return false; - throw _unimplemented(selector); + throw _unimplemented(node); } @override - bool visitPseudoElementSelector(PseudoElementSelector selector) { + bool visitPseudoElementSelector(PseudoElementSelector node) { // :before, :after, :first-letter/line can't match DOM elements. - if (_isLegacyPsuedoClass(selector.name)) return false; + if (_isLegacyPsuedoClass(node.name)) return false; - throw _unimplemented(selector); + throw _unimplemented(node); } static bool _isLegacyPsuedoClass(String name) { @@ -201,18 +201,18 @@ class SelectorEvaluator extends Visitor { } @override - bool visitPseudoElementFunctionSelector(PseudoElementFunctionSelector s) => - throw _unimplemented(s); + bool visitPseudoElementFunctionSelector(PseudoElementFunctionSelector node) => + throw _unimplemented(node); @override - bool visitPseudoClassFunctionSelector(PseudoClassFunctionSelector selector) { - switch (selector.name) { + bool visitPseudoClassFunctionSelector(PseudoClassFunctionSelector node) { + switch (node.name) { // http://dev.w3.org/csswg/selectors-4/#child-index // http://dev.w3.org/csswg/selectors-4/#the-nth-child-pseudo case 'nth-child': // TODO(jmesserly): support An+B syntax too. - final exprs = selector.expression.expressions; + final exprs = node.expression.expressions; if (exprs.length == 1 && exprs[0] is LiteralTerm) { final literal = exprs[0] as LiteralTerm; final parent = _element!.parentNode; @@ -226,12 +226,12 @@ class SelectorEvaluator extends Visitor { case 'lang': // TODO(jmesserly): shouldn't need to get the raw text here, but csslib // gets confused by the "-" in the expression, such as in "es-AR". - final toMatch = selector.expression.span.text; + final toMatch = node.expression.span.text; final lang = _getInheritedLanguage(_element); // TODO(jmesserly): implement wildcards in level 4 return lang != null && lang.startsWith(toMatch); } - throw _unimplemented(selector); + throw _unimplemented(node); } static String? _getInheritedLanguage(Node? node) { @@ -244,45 +244,45 @@ class SelectorEvaluator extends Visitor { } @override - bool visitNamespaceSelector(NamespaceSelector selector) { + bool visitNamespaceSelector(NamespaceSelector node) { // Match element tag name - if (!(selector.nameAsSimpleSelector!.visit(this) as bool)) return false; + if (!(node.nameAsSimpleSelector!.visit(this) as bool)) return false; - if (selector.isNamespaceWildcard) return true; + if (node.isNamespaceWildcard) return true; - if (selector.namespace == '') return _element!.namespaceUri == null; + if (node.namespace == '') return _element!.namespaceUri == null; - throw _unimplemented(selector); + throw _unimplemented(node); } @override - bool visitElementSelector(ElementSelector selector) => - selector.isWildcard || _element!.localName == selector.name.toLowerCase(); + bool visitElementSelector(ElementSelector node) => + node.isWildcard || _element!.localName == node.name.toLowerCase(); @override - bool visitIdSelector(IdSelector selector) => _element!.id == selector.name; + bool visitIdSelector(IdSelector node) => _element!.id == node.name; @override - bool visitClassSelector(ClassSelector selector) => - _element!.classes.contains(selector.name); + bool visitClassSelector(ClassSelector node) => + _element!.classes.contains(node.name); // TODO(jmesserly): negation should support any selectors in level 4, // not just simple selectors. // http://dev.w3.org/csswg/selectors-4/#negation @override - bool visitNegationSelector(NegationSelector selector) => - !(selector.negationArg!.visit(this) as bool); + bool visitNegationSelector(NegationSelector node) => + !(node.negationArg!.visit(this) as bool); @override - bool visitAttributeSelector(AttributeSelector selector) { + bool visitAttributeSelector(AttributeSelector node) { // Match name first - final value = _element!.attributes[selector.name.toLowerCase()]; + final value = _element!.attributes[node.name.toLowerCase()]; if (value == null) return false; - if (selector.operatorKind == TokenKind.NO_MATCH) return true; + if (node.operatorKind == TokenKind.NO_MATCH) return true; - final select = '${selector.value}'; - switch (selector.operatorKind) { + final select = '${node.value}'; + switch (node.operatorKind) { case TokenKind.EQUALS: return value == select; case TokenKind.INCLUDES: @@ -297,7 +297,7 @@ class SelectorEvaluator extends Visitor { case TokenKind.SUBSTRING_MATCH: return value.contains(select); default: - throw _unsupported(selector); + throw _unsupported(node); } } } diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 4ee70fcc9..3defd4e41 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1200,7 +1200,7 @@ class HtmlTokenizer implements Iterator<Token> { state = dataState; } else { _attributeValue.write(data); - _attributeValue.write(stream.charsUntil("\'&")); + _attributeValue.write(stream.charsUntil("'&")); } return true; } @@ -1228,7 +1228,7 @@ class HtmlTokenizer implements Iterator<Token> { _attributeValue.write('\uFFFD'); } else { _attributeValue.write(data); - _attributeValue.write(stream.charsUntil("&>\"\'=<`$spaceCharacters")); + _attributeValue.write(stream.charsUntil("&>\"'=<`$spaceCharacters")); } return true; } diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index f5f932a8d..734c33e7a 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,17 +1,17 @@ name: html -version: 0.15.0 +version: 0.15.1-dev description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html environment: - sdk: ">=2.12.0-0 <3.0.0" + sdk: ">=2.12.0 <3.0.0" dependencies: csslib: ^0.17.0 source_span: ^1.8.0 dev_dependencies: + lints: ^1.0.0 path: ^1.8.0 - pedantic: ^1.10.0 test: ^1.16.0 diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index e18f264f6..289cfda57 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -255,7 +255,7 @@ var validSelectors = [ // - value [att=val] { 'name': 'Attribute value selector, matching align attribute with value', - 'selector': '#attr-value [align=\"center\"]', + 'selector': '#attr-value [align="center"]', 'expect': ['attr-value-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -263,7 +263,7 @@ var validSelectors = [ { 'name': 'Attribute value selector, matching align attribute with empty value', - 'selector': '#attr-value [align=\"\"]', + 'selector': '#attr-value [align=""]', 'expect': ['attr-value-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -271,7 +271,7 @@ var validSelectors = [ { 'name': 'Attribute value selector, not matching align attribute with partial value', - 'selector': '#attr-value [align=\"c\"]', + 'selector': '#attr-value [align="c"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -279,7 +279,7 @@ var validSelectors = [ { 'name': 'Attribute value selector, not matching align attribute with incorrect value', - 'selector': '#attr-value [align=\"centera\"]', + 'selector': '#attr-value [align="centera"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -287,7 +287,7 @@ var validSelectors = [ { 'name': 'Attribute value selector, matching custom data-* attribute with unicode escaped value', - 'selector': '[data-attr-value=\"\\e9\"]', + 'selector': '[data-attr-value="\\e9"]', 'expect': ['attr-value-div3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -295,7 +295,7 @@ var validSelectors = [ { 'name': 'Attribute value selector, matching custom data-* attribute with escaped character', - 'selector': '[data-attr-value\_foo=\"\\e9\"]', + 'selector': '[data-attr-value_foo="\\e9"]', 'expect': ['attr-value-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -357,7 +357,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector, matching class attribute with value', - 'selector': '#attr-whitespace [class~=\"div1\"]', + 'selector': '#attr-whitespace [class~="div1"]', 'expect': ['attr-whitespace-div1'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -365,7 +365,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector, not matching class attribute with empty value', - 'selector': '#attr-whitespace [class~=\"\"]', + 'selector': '#attr-whitespace [class~=""]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -373,7 +373,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector, not matching class attribute with partial value', - 'selector': '[data-attr-whitespace~=\"div\"]', + 'selector': '[data-attr-whitespace~="div"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -381,7 +381,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector, matching custom data-* attribute with unicode escaped value', - 'selector': '[data-attr-whitespace~=\"\\0000e9\"]', + 'selector': '[data-attr-whitespace~="\\0000e9"]', 'expect': ['attr-whitespace-div4'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -389,7 +389,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector, matching custom data-* attribute with escaped character', - 'selector': '[data-attr-whitespace\_foo~=\"\\e9\"]', + 'selector': '[data-attr-whitespace_foo~="\\e9"]', 'expect': ['attr-whitespace-div5'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -442,7 +442,7 @@ var validSelectors = [ { 'name': 'Attribute whitespace-separated list selector with double-quoted value, not matching value with space', - 'selector': '#attr-whitespace a[rel~=\"book mark\"]', + 'selector': '#attr-whitespace a[rel~="book mark"]', 'expect': [] /* no matches */, 'level': 2, 'testType': testQsaBaseline @@ -460,7 +460,7 @@ var validSelectors = [ { 'name': 'Attribute hyphen-separated list selector, not matching unspecified lang attribute', - 'selector': '#attr-hyphen-div1[lang|=\"en\"]', + 'selector': '#attr-hyphen-div1[lang|="en"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -468,7 +468,7 @@ var validSelectors = [ { 'name': 'Attribute hyphen-separated list selector, matching lang attribute with exact value', - 'selector': '#attr-hyphen-div2[lang|=\"fr\"]', + 'selector': '#attr-hyphen-div2[lang|="fr"]', 'expect': ['attr-hyphen-div2'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -476,7 +476,7 @@ var validSelectors = [ { 'name': 'Attribute hyphen-separated list selector, matching lang attribute with partial value', - 'selector': '#attr-hyphen-div3[lang|=\"en\"]', + 'selector': '#attr-hyphen-div3[lang|="en"]', 'expect': ['attr-hyphen-div3'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -484,7 +484,7 @@ var validSelectors = [ { 'name': 'Attribute hyphen-separated list selector, not matching incorrect value', - 'selector': '#attr-hyphen-div4[lang|=\"es-AR\"]', + 'selector': '#attr-hyphen-div4[lang|="es-AR"]', 'expect': [] /*no matches*/, 'level': 2, 'testType': testQsaBaseline @@ -494,7 +494,7 @@ var validSelectors = [ { 'name': 'Attribute begins with selector, matching href attributes beginning with specified substring', - 'selector': '#attr-begins a[href^=\"http://www\"]', + 'selector': '#attr-begins a[href^="http://www"]', 'expect': ['attr-begins-a1', 'attr-begins-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -502,7 +502,7 @@ var validSelectors = [ { 'name': 'Attribute begins with selector, matching lang attributes beginning with specified substring, ', - 'selector': '#attr-begins [lang^=\"en-\"]', + 'selector': '#attr-begins [lang^="en-"]', 'expect': ['attr-begins-div2', 'attr-begins-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -526,7 +526,7 @@ var validSelectors = [ { 'name': 'Attribute begins with selector with double-quoted value, matching class attribute beginning with specified substring', - 'selector': '#attr-begins [class^=\" apple\"]', + 'selector': '#attr-begins [class^=" apple"]', 'expect': ['attr-begins-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -544,7 +544,7 @@ var validSelectors = [ { 'name': 'Attribute ends with selector, matching href attributes ending with specified substring', - 'selector': '#attr-ends a[href\$=\".org\"]', + 'selector': '#attr-ends a[href\$=".org"]', 'expect': ['attr-ends-a1', 'attr-ends-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -552,7 +552,7 @@ var validSelectors = [ { 'name': 'Attribute ends with selector, matching lang attributes ending with specified substring, ', - 'selector': '#attr-ends [lang\$=\"-CH\"]', + 'selector': '#attr-ends [lang\$="-CH"]', 'expect': ['attr-ends-div2', 'attr-ends-div4'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -576,7 +576,7 @@ var validSelectors = [ { 'name': 'Attribute ends with selector with double-quoted value, matching class attribute ending with specified substring', - 'selector': '#attr-ends [class\$=\"apple \"]', + 'selector': '#attr-ends [class\$="apple "]', 'expect': ['attr-ends-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -594,7 +594,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector, matching href attributes beginning with specified substring', - 'selector': '#attr-contains a[href*=\"http://www\"]', + 'selector': '#attr-contains a[href*="http://www"]', 'expect': ['attr-contains-a1', 'attr-contains-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -602,7 +602,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector, matching href attributes ending with specified substring', - 'selector': '#attr-contains a[href*=\".org\"]', + 'selector': '#attr-contains a[href*=".org"]', 'expect': ['attr-contains-a1', 'attr-contains-a2'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -610,7 +610,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector, matching href attributes containing specified substring', - 'selector': '#attr-contains a[href*=\".example.\"]', + 'selector': '#attr-contains a[href*=".example."]', 'expect': ['attr-contains-a1', 'attr-contains-a3'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -618,7 +618,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector, matching lang attributes beginning with specified substring, ', - 'selector': '#attr-contains [lang*=\"en-\"]', + 'selector': '#attr-contains [lang*="en-"]', 'expect': ['attr-contains-div2', 'attr-contains-div6'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -626,7 +626,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector, matching lang attributes ending with specified substring, ', - 'selector': '#attr-contains [lang*=\"-CH\"]', + 'selector': '#attr-contains [lang*="-CH"]', 'expect': ['attr-contains-div3', 'attr-contains-div5'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -658,7 +658,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector with double-quoted value, matching class attribute beginning with specified substring', - 'selector': '#attr-contains [class*=\" apple\"]', + 'selector': '#attr-contains [class*=" apple"]', 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -666,7 +666,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector with double-quoted value, matching class attribute ending with specified substring', - 'selector': '#attr-contains [class*=\"orange \"]', + 'selector': '#attr-contains [class*="orange "]', 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline @@ -674,7 +674,7 @@ var validSelectors = [ { 'name': 'Attribute contains selector with double-quoted value, matching class attribute containing specified substring', - 'selector': '#attr-contains [class*=\"ple banana ora\"]', + 'selector': '#attr-contains [class*="ple banana ora"]', 'expect': ['attr-contains-p1'], 'level': 3, 'testType': testQsaAdditional | testMatchBaseline From a39ec6307a7f94260402b0531e285994f39b946d Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Wed, 15 Dec 2021 15:04:58 -0800 Subject: [PATCH 160/212] Use a late final field over a getter with ??= (dart-lang/html#170) --- pkgs/html/lib/dom.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 69ac4367b..6da922027 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -161,7 +161,7 @@ abstract class Node { /// include all elements but not necessarily other node types. late final nodes = NodeList._(this); - List<Element>? _elements; + late final List<Element> children = FilteredElementList(this); // TODO(jmesserly): consider using an Expando for this, and put it in // dom_parsing. Need to check the performance affect. @@ -192,8 +192,6 @@ abstract class Node { return _attributeValueSpans; } - List<Element> get children => _elements ??= FilteredElementList(this); - /// Returns a copy of this node. /// /// If [deep] is `true`, then all of this node's children and decendents are From d77b8ac6d4fe4c230bbc5e60aa9cbdaf8731342f Mon Sep 17 00:00:00 2001 From: Kabirou Agouda <64534846+kagouda@users.noreply.github.com> Date: Sun, 9 Jan 2022 00:08:02 +0000 Subject: [PATCH 161/212] Update README.md (dart-lang/html#172) Unused import: 'package:html/dom.dart'. --- pkgs/html/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index ca847c2d0..bd6067482 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -8,7 +8,6 @@ Parsing HTML is easy! ```dart import 'package:html/parser.dart' show parse; -import 'package:html/dom.dart'; main() { var document = parse( From 1b361402392dd71c14d65592fcfa289b184f38a0 Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Wed, 9 Feb 2022 02:33:28 -0800 Subject: [PATCH 162/212] Remove dynamic calls --- pkgs/html/analysis_options.yaml | 1 + pkgs/html/lib/parser.dart | 2 +- .../test/selectors/level1_baseline_test.dart | 5 ---- pkgs/html/test/selectors/level1_lib.dart | 26 +++---------------- pkgs/html/test/tokenizer_test.dart | 3 +++ 5 files changed, 8 insertions(+), 29 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 413355027..197d4370a 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -11,6 +11,7 @@ analyzer: dead_code: error linter: rules: + - avoid_dynamic_calls - avoid_function_literals_in_foreach_calls - avoid_returning_null - avoid_unused_constructor_parameters diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index ca193f02a..332370cdc 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -3480,7 +3480,7 @@ class InForeignContentPhase extends Phase { InForeignContentPhase(HtmlParser parser) : super(parser); - void adjustSVGTagNames(token) { + void adjustSVGTagNames(StartTagToken token) { final replacements = const { 'altglyph': 'altGlyph', 'altglyphdef': 'altGlyphDef', diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index 5e85c8fcf..dd0c2c62c 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -88,11 +88,6 @@ void main() async { fragment.append(element.clone(true)); // Setup Tests - interfaceCheck('Document', doc); - interfaceCheck('Detached Element', detached); - interfaceCheck('Fragment', fragment); - interfaceCheck('In-document Element', element); - runSpecialSelectorTests('Document', doc); runSpecialSelectorTests('Detached Element', detached); runSpecialSelectorTests('Fragment', fragment); diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 65f1468f2..6ab3f0262 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -9,6 +9,9 @@ /// from upstream. library html.test.selectors.level1_lib; +// TODO(https://github.com/dart-lang/html/issues/173): Remove. +// ignore_for_file: avoid_dynamic_calls + import 'package:html/dom.dart'; import 'package:test/test.dart' as unittest; @@ -66,29 +69,6 @@ void setupSpecialElements(parent) { parent.append(noNS); } -/* - * Check that the querySelector and querySelectorAll methods exist on the given Node - */ -void interfaceCheck(String type, obj) { - runTest(() { - final q = obj.querySelector is Function; - assertTrue(q, '$type supports querySelector.'); - }, '$type supports querySelector'); - - runTest(() { - final qa = obj.querySelectorAll is Function; - assertTrue(qa, '$type supports querySelectorAll.'); - }, '$type supports querySelectorAll'); - - runTest(() { - final list = obj.querySelectorAll('div'); - // TODO(jmesserly): testing List<Element> for now. It should return an - // ElementList which has extra properties. Needed for dart:html compat. - assertTrue(list is List<Element>, - 'The result should be an instance of a NodeList'); - }, '$type.querySelectorAll returns NodeList instance'); -} - /* * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after * each call. A static list should not be affected by subsequent changes to the DOM. diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 87ba6d0c6..e197b947b 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -1,6 +1,9 @@ @TestOn('vm') library tokenizer_test; +// TODO(https://github.com/dart-lang/html/issues/173): Remove. +// ignore_for_file: avoid_dynamic_calls + // Note: mirrors used to match the getattr usage in the original test import 'dart:convert'; import 'dart:io'; From a60475f2d6cb32dc0f4e175dcf387ef23d97de97 Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Wed, 9 Feb 2022 11:01:53 -0800 Subject: [PATCH 163/212] Move htmlSerializeEscape into its own library --- pkgs/html/lib/dom_parsing.dart | 56 +++------------------------------- pkgs/html/lib/html_escape.dart | 51 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 52 deletions(-) create mode 100644 pkgs/html/lib/html_escape.dart diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 142222ebc..973931b10 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -3,8 +3,12 @@ library dom_parsing; import 'dom.dart'; +import 'html_escape.dart'; import 'src/constants.dart' show rcdataElements; +// Export a function which was previously declared here. +export 'html_escape.dart'; + /// A simple tree visitor for the DOM nodes. class TreeVisitor { void visit(Node node) { @@ -116,58 +120,6 @@ class CodeMarkupVisitor extends TreeVisitor { } } -// TODO(jmesserly): reconcile this with dart:web htmlEscape. -// This one might be more useful, as it is HTML5 spec compliant. -/// Escapes [text] for use in the -/// [HTML fragment serialization algorithm][1]. In particular, as described -/// in the [specification][2]: -/// -/// - Replace any occurrence of the `&` character by the string `&amp;`. -/// - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the -/// string `&nbsp;`. -/// - If the algorithm was invoked in [attributeMode], replace any occurrences -/// of the `"` character by the string `&quot;`. -/// - If the algorithm was not invoked in [attributeMode], replace any -/// occurrences of the `<` character by the string `&lt;`, and any occurrences -/// of the `>` character by the string `&gt;`. -/// -/// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments -/// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString -String htmlSerializeEscape(String text, {bool attributeMode = false}) { - // TODO(jmesserly): is it faster to build up a list of codepoints? - // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. - StringBuffer? result; - for (var i = 0; i < text.length; i++) { - final ch = text[i]; - String? replace; - switch (ch) { - case '&': - replace = '&amp;'; - break; - case '\u00A0' /*NO-BREAK SPACE*/ : - replace = '&nbsp;'; - break; - case '"': - if (attributeMode) replace = '&quot;'; - break; - case '<': - if (!attributeMode) replace = '&lt;'; - break; - case '>': - if (!attributeMode) replace = '&gt;'; - break; - } - if (replace != null) { - result ??= StringBuffer(text.substring(0, i)); - result.write(replace); - } else if (result != null) { - result.write(ch); - } - } - - return result != null ? result.toString() : text; -} - /// Returns true if this tag name is a void element. /// This method is useful to a pretty printer, because void elements must not /// have an end tag. diff --git a/pkgs/html/lib/html_escape.dart b/pkgs/html/lib/html_escape.dart new file mode 100644 index 000000000..b9c20c81f --- /dev/null +++ b/pkgs/html/lib/html_escape.dart @@ -0,0 +1,51 @@ +// TODO(jmesserly): reconcile this with dart:web htmlEscape. +// This one might be more useful, as it is HTML5 spec compliant. +/// Escapes [text] for use in the +/// [HTML fragment serialization algorithm][1]. In particular, as described +/// in the [specification][2]: +/// +/// - Replace any occurrence of the `&` character by the string `&amp;`. +/// - Replace any occurrences of the U+00A0 NO-BREAK SPACE character by the +/// string `&nbsp;`. +/// - If the algorithm was invoked in [attributeMode], replace any occurrences +/// of the `"` character by the string `&quot;`. +/// - If the algorithm was not invoked in [attributeMode], replace any +/// occurrences of the `<` character by the string `&lt;`, and any occurrences +/// of the `>` character by the string `&gt;`. +/// +/// [1]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#serializing-html-fragments +/// [2]: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString +String htmlSerializeEscape(String text, {bool attributeMode = false}) { + // TODO(jmesserly): is it faster to build up a list of codepoints? + // StringBuffer seems cleaner assuming Dart can unbox 1-char strings. + StringBuffer? result; + for (var i = 0; i < text.length; i++) { + final ch = text[i]; + String? replace; + switch (ch) { + case '&': + replace = '&amp;'; + break; + case '\u00A0' /*NO-BREAK SPACE*/ : + replace = '&nbsp;'; + break; + case '"': + if (attributeMode) replace = '&quot;'; + break; + case '<': + if (!attributeMode) replace = '&lt;'; + break; + case '>': + if (!attributeMode) replace = '&gt;'; + break; + } + if (replace != null) { + result ??= StringBuffer(text.substring(0, i)); + result.write(replace); + } else if (result != null) { + result.write(ch); + } + } + + return result != null ? result.toString() : text; +} From 04a2e89d6172e2dddfc54e2a37c636cefe35a9ce Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Wed, 9 Feb 2022 11:21:20 -0800 Subject: [PATCH 164/212] changelog --- pkgs/html/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 60c7daf7a..6adaec5d5 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,5 +1,9 @@ ## 0.15.1-dev +- Move `htmlSerializeEscape` to its own library, + `package:html/html_escape.dart`, which is exported from + `package:html/dom_parsing.dart`. + ## 0.15.0 - Migrate to null safety. From d8189b8e7d6cc4de306fea01785a84299a193b90 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 2 Mar 2022 11:13:40 -0800 Subject: [PATCH 165/212] Bump actions/checkout from 2 to 3 (dart-lang/html#176) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 9460c263d..2e8f5d462 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: dart-lang/setup-dart@v1 with: sdk: ${{ matrix.sdk }} From 2401dce7f4b7fd4605ce6b327125a4483690827d Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Thu, 5 May 2022 10:51:43 -0700 Subject: [PATCH 166/212] Drop unnecessary severity upgrades (dart-lang/html#181) These are a long outdated legacy pattern which brought external CI more inline with internal standards where these errors would fail the build. We are now more strict and the upgrades only impact local development where they are not useful. --- pkgs/html/analysis_options.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 197d4370a..c181e0a96 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -5,10 +5,6 @@ analyzer: errors: # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore - unused_element: error - unused_import: error - unused_local_variable: error - dead_code: error linter: rules: - avoid_dynamic_calls From 40419e8e86d37df1a01852e7ff673db62e800baf Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Thu, 29 Sep 2022 09:25:00 -0700 Subject: [PATCH 167/212] Use growable lists and avoid dynamic --- pkgs/html/analysis_options.yaml | 4 ++-- pkgs/html/lib/dom.dart | 5 +++-- pkgs/html/lib/dom_parsing.dart | 2 +- pkgs/html/lib/parser.dart | 8 ++++---- pkgs/html/lib/src/encoding_parser.dart | 4 ++-- pkgs/html/lib/src/tokenizer.dart | 7 ++++--- pkgs/html/lib/src/treebuilder.dart | 2 +- pkgs/html/test/tokenizer_test.dart | 6 +++--- 8 files changed, 20 insertions(+), 18 deletions(-) diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index c181e0a96..240849036 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,7 +1,7 @@ include: package:lints/recommended.yaml analyzer: - strong-mode: - implicit-casts: false + language: + strict-casts: true errors: # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 6da922027..5ffc15f26 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -885,7 +885,8 @@ class FilteredElementList extends IterableBase<Element> // // TODO(nweiz): we don't always need to create a new list. For example // forEach, every, any, ... could directly work on the _childNodes. - List<Element> get _filtered => _childNodes.whereType<Element>().toList(); + List<Element> get _filtered => + _childNodes.whereType<Element>().toList(growable: false); @override void forEach(void Function(Element) action) { @@ -1028,7 +1029,7 @@ class FilteredElementList extends IterableBase<Element> @override List<Element> toList({bool growable = true}) => - List<Element>.from(this, growable: growable); + List<Element>.of(this, growable: growable); @override Set<Element> toSet() => Set<Element>.from(this); diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 973931b10..35c8dc7b2 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -32,7 +32,7 @@ class TreeVisitor { void visitChildren(Node node) { // Allow for mutations (remove works) while iterating. - for (var child in node.nodes.toList()) { + for (var child in node.nodes.toList(growable: false)) { visit(child); } } diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 332370cdc..30c34b327 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -331,7 +331,7 @@ class HtmlParser { // When the loop finishes it's EOF var reprocess = true; - final reprocessPhases = []; + final reprocessPhases = <Phase>[]; while (reprocess) { reprocessPhases.add(phase); reprocess = phase.processEOF(); @@ -430,7 +430,7 @@ class HtmlParser { 'ychannelselector': 'yChannelSelector', 'zoomandpan': 'zoomAndPan' }; - for (var originalName in token.data.keys.toList()) { + for (var originalName in token.data.keys.toList(growable: false)) { final svgName = replacements[originalName as String]; if (svgName != null) { token.data[svgName] = token.data.remove(originalName)!; @@ -456,7 +456,7 @@ class HtmlParser { 'xmlns:xlink': AttributeName('xmlns', 'xlink', Namespaces.xmlns) }; - for (var originalName in token.data.keys.toList()) { + for (var originalName in token.data.keys.toList(growable: false)) { final foreignName = replacements[originalName as String]; if (foreignName != null) { token.data[foreignName] = token.data.remove(originalName)!; @@ -1468,7 +1468,7 @@ class InBodyPhase extends Phase { tree.insertElement(token); final element = tree.openElements.last; - final matchingElements = []; + final matchingElements = <Node?>[]; for (Node? node in tree.activeFormattingElements.reversed) { if (node == null) { break; diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index e41735170..defe57eea 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -247,8 +247,8 @@ class EncodingParser { return null; } // Step 3 - final attrName = []; - final attrValue = []; + final attrName = <String>[]; + final attrValue = <String>[]; // Step 4 attribute name while (true) { if (c == null) { diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 3defd4e41..603d40572 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -174,7 +174,7 @@ class HtmlTokenizer implements Iterator<Token> { radix = 16; } - final charStack = []; + final charStack = <String?>[]; // Consume all the characters that are in range while making sure we // don't hit an EOF. @@ -297,8 +297,9 @@ class HtmlTokenizer implements Iterator<Token> { while (charStack.last != eof) { final name = charStack.join(); - filteredEntityList = - filteredEntityList.where((e) => e.startsWith(name)).toList(); + filteredEntityList = filteredEntityList + .where((e) => e.startsWith(name)) + .toList(growable: false); if (filteredEntityList.isEmpty) { break; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index bc4c08938..d477eb051 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -111,7 +111,7 @@ class TreeBuilder { final exactNode = target is Node; var listElements1 = scopingElements; - var listElements2 = const []; + var listElements2 = const <Pair>[]; var invert = false; if (variant != null) { switch (variant) { diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index e197b947b..e0af7fb84 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -232,13 +232,13 @@ Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { dynamic decode(inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); testInfo['input'] = decode(testInfo['input']); - for (var token in testInfo['output']) { + for (var token in testInfo['output'] as List) { if (token == 'ParseError') { continue; } else { token[1] = decode(token[1]); if ((token as List).length > 2) { - for (var pair in token[2]) { + for (var pair in token[2] as List) { final key = pair[0]; final value = pair[1]; token[2].remove(key); @@ -276,7 +276,7 @@ void main() async { final testInfo = testList[index] as Map<String, dynamic>; testInfo.putIfAbsent('initialStates', () => ['Data state']); - for (var initialState in testInfo['initialStates']) { + for (var initialState in testInfo['initialStates'] as List) { test(testInfo['description'], () { testInfo['initialState'] = camelCase(initialState as String); runTokenizerTest(testInfo); From 4c4bf4a79ec701407027fc7d07c441695592e735 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Thu, 29 Sep 2022 18:02:10 +0000 Subject: [PATCH 168/212] add markdown badges to the readme --- pkgs/html/README.md | 21 ++++++++++++++------- pkgs/html/pubspec.yaml | 1 - 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/pkgs/html/README.md b/pkgs/html/README.md index bd6067482..fafae1bd9 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -1,8 +1,10 @@ -This is a pure Dart HTML5 parser. -It's a port of [html5lib](https://github.com/html5lib/html5lib-python) from -Python. +[![Dart CI](https://github.com/dart-lang/html/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/html/actions/workflows/test-package.yml) +[![pub package](https://img.shields.io/pub/v/html.svg)](https://pub.dev/packages/html) +[![package publisher](https://img.shields.io/pub/publisher/html.svg)](https://pub.dev/packages/html/publisher) -# Usage +This is a Dart HTML5 parser. + +## Usage Parsing HTML is easy! @@ -16,6 +18,11 @@ main() { } ``` -You can pass a String or list of bytes to `parse`. -There's also `parseFragment` for parsing a document fragment, and `HtmlParser` -if you want more low level control. +You can pass a String or list of bytes to `parse`. There's also `parseFragment` +for parsing a document fragment, and `HtmlParser` if you want more low level +control. + +## Background + +This package was a port of the Python +[html5lib](https://github.com/html5lib/html5lib-python) library. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 734c33e7a..7cd1d854f 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,6 +1,5 @@ name: html version: 0.15.1-dev - description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html From 24b88a5c2eb530a255a7674b17ec285f7e5190df Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Thu, 29 Sep 2022 18:08:28 +0000 Subject: [PATCH 169/212] update to our current CI best practices --- pkgs/html/.github/dependabot.yml | 15 ++++++--------- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml index 430a85e7d..214481934 100644 --- a/pkgs/html/.github/dependabot.yml +++ b/pkgs/html/.github/dependabot.yml @@ -1,11 +1,8 @@ -# Set update schedule for GitHub Actions -# See https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/keeping-your-actions-up-to-date-with-dependabot - +# Dependabot configuration file. version: 2 -updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - # Check for updates to GitHub Actions every weekday - interval: "daily" +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "monthly" diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 2e8f5d462..c197eec27 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,8 +14,8 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: dev - id: install From d9a59be72ab4a4dd5a1c703c15ad53b1325ca9c1 Mon Sep 17 00:00:00 2001 From: Sam Rawlins <srawlins@google.com> Date: Thu, 29 Sep 2022 13:38:53 -0700 Subject: [PATCH 170/212] changelog --- pkgs/html/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 6adaec5d5..340f7d787 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -3,6 +3,8 @@ - Move `htmlSerializeEscape` to its own library, `package:html/html_escape.dart`, which is exported from `package:html/dom_parsing.dart`. +- Use more non-growable lists, and type annotations on List literals. +- Switch analysis option `implicit-casts: false` to `strict-casts: true`. ## 0.15.0 From df886bed595bf5f39a3a2b5e576f71b50cc1d0b4 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Wed, 19 Oct 2022 19:45:35 +0000 Subject: [PATCH 171/212] rev the package version in preparation for publishing (dart-lang/html#190) --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/README.md | 2 +- pkgs/html/analysis_options.yaml | 2 ++ pkgs/html/pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 340f7d787..ae8d726e3 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.15.1-dev +## 0.15.1 - Move `htmlSerializeEscape` to its own library, `package:html/html_escape.dart`, which is exported from diff --git a/pkgs/html/README.md b/pkgs/html/README.md index fafae1bd9..f5388b235 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -2,7 +2,7 @@ [![pub package](https://img.shields.io/pub/v/html.svg)](https://pub.dev/packages/html) [![package publisher](https://img.shields.io/pub/publisher/html.svg)](https://pub.dev/packages/html/publisher) -This is a Dart HTML5 parser. +A Dart implementation of an HTML5 parser. ## Usage diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 240849036..5f87ffeea 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,10 +1,12 @@ include: package:lints/recommended.yaml + analyzer: language: strict-casts: true errors: # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore + linter: rules: - avoid_dynamic_calls diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 7cd1d854f..7b9527c10 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.1-dev +version: 0.15.1 description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html From d0e99d26942954d2112c41712d66a26a6091bdb2 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 9 Nov 2022 15:34:41 -0800 Subject: [PATCH 172/212] blast_repo fixes (dart-lang/html#191) Dependabot GitHub Action --- pkgs/html/.github/dependabot.yml | 1 + pkgs/html/.github/workflows/test-package.yml | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml index 214481934..1603cdd9e 100644 --- a/pkgs/html/.github/dependabot.yml +++ b/pkgs/html/.github/dependabot.yml @@ -1,4 +1,5 @@ # Dependabot configuration file. +# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates version: 2 updates: diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index c197eec27..d0d4ea044 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: dev @@ -34,8 +34,8 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@v3 - - uses: dart-lang/setup-dart@v1 + - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} - id: install From 071a18fb2ee4e0b653b4eccf13f3bc26d7d693ec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 3 Jan 2023 10:12:19 -0800 Subject: [PATCH 173/212] Bump actions/checkout from 3.1.0 to 3.2.0 (dart-lang/html#193) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8...755da8c3cf115ac066823e79a1e1788f8940201b) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index d0d4ea044..990dd45b9 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.12.0, dev] steps: - - uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 + - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d with: sdk: ${{ matrix.sdk }} From 6fbe3e208da57046a52e03a80c7f7bee37e05b75 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Fri, 27 Jan 2023 07:56:40 -0800 Subject: [PATCH 174/212] finish work for avoid_dynamic_calls (dart-lang/html#196) --- pkgs/html/.github/workflows/test-package.yml | 2 +- pkgs/html/CHANGELOG.md | 5 + pkgs/html/analysis_options.yaml | 7 +- pkgs/html/lib/parser.dart | 15 +- pkgs/html/lib/src/constants.dart | 2 +- pkgs/html/lib/src/html_input_stream.dart | 4 +- pkgs/html/lib/src/list_proxy.dart | 2 +- pkgs/html/lib/src/query_selector.dart | 9 +- pkgs/html/lib/src/token.dart | 3 +- pkgs/html/lib/src/tokenizer.dart | 4 +- pkgs/html/lib/src/treebuilder.dart | 14 +- pkgs/html/lib/src/utils.dart | 2 +- pkgs/html/pubspec.yaml | 6 +- pkgs/html/test/parser_test.dart | 2 +- .../test/selectors/level1_baseline_test.dart | 39 +++-- pkgs/html/test/selectors/level1_lib.dart | 155 ++++++++++++------ pkgs/html/test/selectors/selectors.dart | 104 ++++++------ pkgs/html/test/support.dart | 4 +- pkgs/html/test/tokenizer_test.dart | 121 +++++++------- 19 files changed, 285 insertions(+), 215 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 990dd45b9..8421e308e 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.12.0, dev] + sdk: [2.17.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index ae8d726e3..0adcd1a5c 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.15.2-dev + +- Add additional types at the API boundary (in `lib/parser.dart` and others). +- Update to `package:lints` 2.0. + ## 0.15.1 - Move `htmlSerializeEscape` to its own library, diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 5f87ffeea..715ea40f7 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -3,12 +3,14 @@ include: package:lints/recommended.yaml analyzer: language: strict-casts: true + strict-raw-types: true errors: # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore linter: rules: + - always_declare_return_types - avoid_dynamic_calls - avoid_function_literals_in_foreach_calls - avoid_returning_null @@ -17,14 +19,12 @@ linter: - camel_case_types - cancel_subscriptions - comment_references - # See https://github.com/dart-lang/logging/issues/43 - #- constant_identifier_names + - constant_identifier_names - control_flow_in_finally - directives_ordering - empty_statements - hash_and_equals - implementation_imports - #- invariant_booleans - iterable_contains_unrelated_type - list_remove_unrelated_type - no_adjacent_strings_in_list @@ -41,6 +41,7 @@ linter: - prefer_typing_uninitialized_variables - test_types_in_equals - throw_in_finally + - type_annotate_public_apis - unnecessary_brace_in_string_interps - unnecessary_getters_setters - unnecessary_lambdas diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 30c34b327..c4bd1ede7 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -15,6 +15,7 @@ library parser; import 'dart:collection'; import 'dart:math'; + import 'package:source_span/source_span.dart'; import 'dom.dart'; @@ -36,7 +37,7 @@ import 'src/utils.dart'; /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you /// can additionally pass [sourceUrl] to indicate where the [input] was /// extracted from. -Document parse(input, +Document parse(dynamic input, {String? encoding, bool generateSpans = false, String? sourceUrl}) { final p = HtmlParser(input, encoding: encoding, generateSpans: generateSpans, sourceUrl: sourceUrl); @@ -55,7 +56,7 @@ Document parse(input, /// [Node.sourceSpan] property will be `null`. When using [generateSpans] you can /// additionally pass [sourceUrl] to indicate where the [input] was extracted /// from. -DocumentFragment parseFragment(input, +DocumentFragment parseFragment(dynamic input, {String container = 'div', String? encoding, bool generateSpans = false, @@ -93,7 +94,7 @@ class HtmlParser { Phase? originalPhase; - var framesetOK = true; + bool framesetOK = true; // These fields hold the different phase singletons. At any given time one // of them will be active. @@ -140,7 +141,7 @@ class HtmlParser { /// automatic conversion of element and attribute names to lower case. Note /// that standard way to parse HTML is to lowercase, which is what the browser /// DOM will do if you request `Element.outerHTML`, for example. - HtmlParser(input, + HtmlParser(dynamic input, {String? encoding, bool parseMeta = true, bool lowercaseElementName = true, @@ -348,7 +349,7 @@ class HtmlParser { .pointSpan(); void parseError(SourceSpan? span, String errorcode, - [Map? datavars = const {}]) { + [Map<String, Object?>? datavars = const {}]) { if (!generateSpans && span == null) { span = _lastSpan; } @@ -3943,7 +3944,7 @@ class ParseError implements SourceSpanException { final String errorCode; @override final SourceSpan? span; - final Map? data; + final Map<String, Object?>? data; ParseError(this.errorCode, this.span, this.data); @@ -3959,7 +3960,7 @@ class ParseError implements SourceSpanException { String get message => formatStr(errorMessages[errorCode]!, data); @override - String toString({color}) { + String toString({dynamic color}) { final res = span!.message(message, color: color); return span!.sourceUrl == null ? 'ParserError on $res' : 'On $res'; } diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index e32e03796..152f85b06 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -265,7 +265,7 @@ class Namespaces { } } -const List scopingElements = [ +const List<Pair<String, String>> scopingElements = [ Pair(Namespaces.html, 'applet'), Pair(Namespaces.html, 'caption'), Pair(Namespaces.html, 'html'), diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index a0e490f77..54e0231c4 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -35,7 +35,7 @@ class HtmlInputStream { /// Raw UTF-16 codes, used if a Dart String is passed in. List<int>? _rawChars; - var errors = Queue<String>(); + Queue<String> errors = Queue<String>(); SourceFile? fileInfo; @@ -57,7 +57,7 @@ class HtmlInputStream { /// element) /// /// [parseMeta] - Look for a <meta> element containing encoding information - HtmlInputStream(source, + HtmlInputStream(dynamic source, [String? encoding, bool parseMeta = true, this.generateSpans = false, diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 05086fa08..7fe5e828e 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -22,7 +22,7 @@ abstract class ListProxy<E> extends ListBase<E> { E operator [](int index) => _list[index]; @override - operator []=(int index, E value) { + void operator []=(int index, E value) { _list[index] = value; } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index b596745df..32e0a37cc 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -1,9 +1,8 @@ /// Query selector implementation for our DOM. library html.src.query; -import 'package:csslib/parser.dart' as css; -import 'package:csslib/parser.dart' show TokenKind, Message; -import 'package:csslib/visitor.dart'; // the CSSOM +import 'package:csslib/parser.dart'; +import 'package:csslib/visitor.dart'; import 'package:html/dom.dart'; import 'package:html/src/constants.dart' show isWhitespaceCC; @@ -23,7 +22,7 @@ List<Element> querySelectorAll(Node node, String selector) { // http://dev.w3.org/csswg/selectors-4/#grouping SelectorGroup _parseSelectorList(String selector) { final errors = <Message>[]; - final group = css.parseSelectorGroup(selector, errors: errors); + final group = parseSelectorGroup(selector, errors: errors); if (group == null || errors.isNotEmpty) { throw FormatException("'$selector' is not a valid selector: $errors"); } @@ -127,7 +126,7 @@ class SelectorEvaluator extends Visitor { UnimplementedError("'$selector' selector of type " '${selector.runtimeType} is not implemented'); - FormatException _unsupported(selector) => + FormatException _unsupported(TreeNode selector) => FormatException("'$selector' is not a valid selector"); @override diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index b2c3f4082..7a4e7431f 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -2,6 +2,7 @@ library token; import 'dart:collection'; + import 'package:source_span/source_span.dart'; /// An html5 token. @@ -74,7 +75,7 @@ abstract class StringToken extends Token { class ParseErrorToken extends StringToken { /// Extra information that goes along with the error message. - Map? messageParams; + Map<String, Object?>? messageParams; ParseErrorToken(String data, {this.messageParams}) : super(data); diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 603d40572..1ab72a91a 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1,7 +1,9 @@ library tokenizer; import 'dart:collection'; + import 'package:html/parser.dart' show HtmlParser; + import 'constants.dart'; import 'html_input_stream.dart'; import 'token.dart'; @@ -63,7 +65,7 @@ class HtmlTokenizer implements Iterator<Token> { List<TagAttribute>? _attributes; Set<String>? _attributeNames; - HtmlTokenizer(doc, + HtmlTokenizer(dynamic doc, {String? encoding, bool parseMeta = true, this.lowercaseElementName = true, diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index d477eb051..3e39700ce 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -2,9 +2,11 @@ library treebuilder; import 'dart:collection'; + import 'package:html/dom.dart'; import 'package:html/parser.dart' show getElementNameTuple; import 'package:source_span/source_span.dart'; + import 'constants.dart'; import 'list_proxy.dart'; import 'token.dart'; @@ -47,7 +49,7 @@ class ActiveFormattingElements extends ListProxy<Element?> { } // TODO(jmesserly): this should exist in corelib... -bool _mapEquals(Map a, Map b) { +bool _mapEquals(Map<Object, String> a, Map<Object, String> b) { if (a.length != b.length) return false; if (a.isEmpty) return true; @@ -85,7 +87,7 @@ class TreeBuilder { /// Switch the function used to insert an element from the /// normal one to the misnested table one and back again - var insertFromTable = false; + bool insertFromTable = false; TreeBuilder(bool namespaceHTMLElements) : defaultNamespace = namespaceHTMLElements ? Namespaces.html : null { @@ -105,13 +107,13 @@ class TreeBuilder { document = Document(); } - bool elementInScope(target, {String? variant}) { - //If we pass a node in we match that. if we pass a string - //match any node with that name + bool elementInScope(dynamic target, {String? variant}) { + // If we pass a node in we match that. If we pass a string match any node + // with that name. final exactNode = target is Node; var listElements1 = scopingElements; - var listElements2 = const <Pair>[]; + var listElements2 = const <Pair<String, String>>[]; var invert = false; if (variant != null) { switch (variant) { diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 001c706ae..5c4e359fc 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -51,7 +51,7 @@ String padWithZeros(String str, int size) { /// Format a string like Python's % string format operator. Right now this only /// supports a [data] dictionary used with %s or %08x. Those were the only /// things needed for [errorMessages]. -String formatStr(String format, Map? data) { +String formatStr(String format, Map<String, Object?>? data) { if (data == null) return format; data.forEach((key, value) { final result = StringBuffer(); diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 7b9527c10..831bce0ef 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,16 +1,16 @@ name: html -version: 0.15.1 +version: 0.15.2-dev description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html environment: - sdk: ">=2.12.0 <3.0.0" + sdk: '>=2.17.0 <3.0.0' dependencies: csslib: ^0.17.0 source_span: ^1.8.0 dev_dependencies: - lints: ^1.0.0 + lints: ^2.0.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 06fb4c699..7f717fa17 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -35,7 +35,7 @@ void runParserTest( String? innerHTML, String? input, String? expected, - List? errors, + List<String>? errors, TreeBuilderFactory treeCtor, bool namespaceHTMLElements) { // XXX - move this out into the setup function diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index dd0c2c62c..b07d1dc43 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -8,6 +8,7 @@ library html.test.selectors.level1_baseline_test; import 'dart:io'; + import 'package:html/dom.dart'; import 'package:html/parser.dart'; import 'package:path/path.dart' as p; @@ -23,8 +24,8 @@ Future<Document> testContentDocument() async { return parse(File(testPath).readAsStringSync()); } -var testType = testQsaBaseline; // Only run baseline tests. -var docType = 'html'; // Only run tests suitable for HTML +int testType = testQsaBaseline; // Only run baseline tests. +String docType = 'html'; // Only run tests suitable for HTML void main() async { /* @@ -88,15 +89,17 @@ void main() async { fragment.append(element.clone(true)); // Setup Tests - runSpecialSelectorTests('Document', doc); - runSpecialSelectorTests('Detached Element', detached); - runSpecialSelectorTests('Fragment', fragment); - runSpecialSelectorTests('In-document Element', element); - - verifyStaticList('Document', doc); - verifyStaticList('Detached Element', detached); - verifyStaticList('Fragment', fragment); - verifyStaticList('In-document Element', element); + runSpecialSelectorTests('Document', SelectorAdaptor.document(doc)); + runSpecialSelectorTests( + 'Detached Element', SelectorAdaptor.element(detached)); + runSpecialSelectorTests('Fragment', SelectorAdaptor.fragment(fragment)); + runSpecialSelectorTests( + 'In-document Element', SelectorAdaptor.element(element)); + + verifyStaticList('Document', SelectorAdaptor.document(doc)); + verifyStaticList('Detached Element', SelectorAdaptor.element(detached)); + verifyStaticList('Fragment', SelectorAdaptor.fragment(fragment)); + verifyStaticList('In-document Element', SelectorAdaptor.element(element)); // TODO(jmesserly): fix negative tests //runInvalidSelectorTest('Document', doc, invalidSelectors); @@ -104,10 +107,12 @@ void main() async { //runInvalidSelectorTest('Fragment', fragment, invalidSelectors); //runInvalidSelectorTest('In-document Element', element, invalidSelectors); - runValidSelectorTest('Document', doc, validSelectors, testType, docType); - runValidSelectorTest( - 'Detached Element', detached, validSelectors, testType, docType); - runValidSelectorTest('Fragment', fragment, validSelectors, testType, docType); + runValidSelectorTest('Document', SelectorAdaptor.document(doc), + validSelectors, testType, docType); + runValidSelectorTest('Detached Element', SelectorAdaptor.element(detached), + validSelectors, testType, docType); + runValidSelectorTest('Fragment', SelectorAdaptor.fragment(fragment), + validSelectors, testType, docType); group('out of scope', () { setUp(() { @@ -115,7 +120,7 @@ void main() async { // None of these elements should match }); tearDown(outOfScope.remove); - runValidSelectorTest( - 'In-document Element', element, validSelectors, testType, docType); + runValidSelectorTest('In-document Element', + SelectorAdaptor.element(element), validSelectors, testType, docType); }); } diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 6ab3f0262..2f6210301 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -9,18 +9,14 @@ /// from upstream. library html.test.selectors.level1_lib; -// TODO(https://github.com/dart-lang/html/issues/173): Remove. -// ignore_for_file: avoid_dynamic_calls - import 'package:html/dom.dart'; import 'package:test/test.dart' as unittest; late Document doc; -/* - * Create and append special elements that cannot be created correctly with HTML markup alone. - */ -void setupSpecialElements(parent) { +// Create and append special elements that cannot be created correctly with HTML +// markup alone. +void setupSpecialElements(Element parent) { // Setup null and undefined tests parent.append(doc.createElement('null')); parent.append(doc.createElement('undefined')); @@ -69,38 +65,35 @@ void setupSpecialElements(parent) { parent.append(noNS); } -/* - * Verify that the NodeList returned by querySelectorAll is static and and that a new list is created after - * each call. A static list should not be affected by subsequent changes to the DOM. - */ -void verifyStaticList(String type, dynamic root) { - List pre; - List post; +/// Verify that the NodeList returned by querySelectorAll is static and and that +/// a new list is created after each call. A static list should not be affected +/// by subsequent changes to the DOM. +void verifyStaticList(String type, SelectorAdaptor root) { + List<Element> pre; + List<Element> post; late int preLength; runTest(() { - pre = root.querySelectorAll('div') as List; + pre = root.querySelectorAll('div'); preLength = pre.length; final div = doc.createElement('div'); - (root is Document ? root.body : root).append(div); + root.isDocument ? root.body!.append(div) : root.append(div); assertEquals( pre.length, preLength, 'The length of the NodeList should not change.'); }, '$type: static NodeList'); runTest(() { - post = root.querySelectorAll('div') as List; + post = root.querySelectorAll('div'); assertEquals(post.length, preLength + 1, 'The length of the new NodeList should be 1 more than the previous list.'); }, '$type: new NodeList'); } -/* - * Verify handling of special values for the selector parameter, including stringification of - * null and undefined, and the handling of the empty string. - */ -void runSpecialSelectorTests(String type, root) { +/// Verify handling of special values for the selector parameter, including +/// stringification of null and undefined, and the handling of the empty string. +void runSpecialSelectorTests(String type, SelectorAdaptor root) { // Dart note: changed these tests because we don't have auto conversion to // String like JavaScript does. runTest(() { @@ -115,20 +108,20 @@ void runSpecialSelectorTests(String type, root) { "This should find one element with the tag name 'UNDEFINED'."); }, '$type.querySelectorAll undefined'); - runTest(() { - // 3 - assertThrows((e) => e is NoSuchMethodError, () { - root.querySelectorAll(); - }, 'This should throw a TypeError.'); - }, '$type.querySelectorAll no parameter'); + // runTest(() { + // // 3 + // assertThrows((e) => e is NoSuchMethodError, () { + // root.querySelectorAll(); + // }, 'This should throw a TypeError.'); + // }, '$type.querySelectorAll no parameter'); runTest(() { // 4 final elm = root.querySelector('null'); assertNotEquals(elm, null, 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assertEquals( - elm.localName.toUpperCase(), 'NULL', "The tag name should be 'NULL'."); + assertEquals(elm!.localName?.toUpperCase(), 'NULL', + "The tag name should be 'NULL'."); }, '$type.querySelector null'); runTest(() { @@ -136,23 +129,23 @@ void runSpecialSelectorTests(String type, root) { final elm = root.querySelector('undefined'); assertNotEquals(elm, 'undefined', 'This should find an element.'); // TODO(jmesserly): change "localName" back to "tagName" once implemented. - assertEquals(elm.localName.toUpperCase(), 'UNDEFINED', + assertEquals(elm!.localName?.toUpperCase(), 'UNDEFINED', "The tag name should be 'UNDEFINED'."); }, '$type.querySelector undefined'); - runTest(() { - // 6 - assertThrows((e) => e is NoSuchMethodError, () { - root.querySelector(); - }, 'This should throw a TypeError.'); - }, '$type.querySelector no parameter'); + // runTest(() { + // // 6 + // assertThrows((e) => e is NoSuchMethodError, () { + // root.querySelector(); + // }, 'This should throw a TypeError.'); + // }, '$type.querySelector no parameter'); runTest(() { // 7 final result = root.querySelectorAll('*'); var i = 0; - traverse(root as Node, (elem) { - if (!identical(elem, root)) { + traverse(root.asNode!, (elem) { + if (!identical(elem, root.asNode)) { assertEquals( elem, result[i], 'The result in index $i should be in tree order.'); i++; @@ -175,8 +168,8 @@ String? _getSkip(String name) { * Execute queries with the specified valid selectors for both querySelector() and querySelectorAll() * Only run these tests when results are expected. Don't run for syntax error tests. */ -void runValidSelectorTest(String type, Node root, - List<Map<String, dynamic>> selectors, testType, docType) { +void runValidSelectorTest(String type, SelectorAdaptor root, + List<Map<String, dynamic>> selectors, int testType, String docType) { var nodeType = ''; switch (root.nodeType) { case Node.DOCUMENT_NODE: @@ -199,16 +192,17 @@ void runValidSelectorTest(String type, Node root, final q = s['selector'] as String; final e = s['expect'] as List?; - if ((s['exclude'] is! List || - (s['exclude'].indexOf(nodeType) == -1 && - s['exclude'].indexOf(docType) == -1)) && - (s['testType'] & testType != 0)) { + final exclude = s['exclude']; + + if ((exclude is! List || + (!(exclude).contains(nodeType) && !exclude.contains(docType))) && + ((s['testType'] as int) & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) late List<Element> foundall; Element? found; runTest(() { - foundall = (root as dynamic).querySelectorAll(q) as List<Element>; + foundall = root.querySelectorAll(q); assertNotEquals(foundall, null, 'The method should not return null.'); assertEquals(foundall.length, e!.length, 'The method should return the expected number of matches.'); @@ -224,7 +218,7 @@ void runValidSelectorTest(String type, Node root, }, '$type.querySelectorAll: $n:$q', skip: skip); runTest(() { - found = (root as dynamic).querySelector(q) as Element?; + found = root.querySelector(q); if (e!.isNotEmpty) { assertNotEquals(found, null, 'The method should return a match.'); @@ -248,7 +242,8 @@ void runValidSelectorTest(String type, Node root, * Execute queries with the specified invalid selectors for both querySelector() and querySelectorAll() * Only run these tests when errors are expected. Don't run for valid selector tests. */ -void runInvalidSelectorTest(String type, root, List selectors) { +void runInvalidSelectorTest( + String type, SelectorAdaptor root, List<Map<String, dynamic>> selectors) { for (var i = 0; i < selectors.length; i++) { final s = selectors[i]; final n = s['name'] as String; @@ -256,13 +251,13 @@ void runInvalidSelectorTest(String type, root, List selectors) { // Dart note: FormatException seems a reasonable mapping of SyntaxError runTest(() { - assertThrows((e) => e is FormatException, () { + assertThrows((Object e) => e is FormatException, () { root.querySelector(q); }); }, '$type.querySelector: $n:$q'); runTest(() { - assertThrows((e) => e is FormatException, () { + assertThrows((Object e) => e is FormatException, () { root.querySelectorAll(q); }); }, '$type.querySelectorAll: $n:$q'); @@ -289,10 +284,64 @@ void assertTrue(bool value, String reason) => void assertFalse(bool value, String reason) => unittest.expect(value, unittest.isFalse, reason: reason); -void assertEquals(x, y, String reason) => unittest.expect(x, y, reason: reason); +void assertEquals(dynamic x, dynamic y, String reason) => + unittest.expect(x, y, reason: reason); -void assertNotEquals(x, y, String reason) => +void assertNotEquals(dynamic x, dynamic y, String reason) => unittest.expect(x, unittest.isNot(y), reason: reason); -void assertThrows(exception, void Function() body, [String? reason]) => +void assertThrows(Object exception, void Function() body, [String? reason]) => unittest.expect(body, unittest.throwsA(exception), reason: reason); + +/// Used for testing. +/// +/// This class delegates to one of three different kinds of objects. They share +/// methods with similar signatures but do not share a type hierarchy. +/// Previously these methods were invoked through `dynamic`. +class SelectorAdaptor { + final Document? document; + final Element? element; + final DocumentFragment? fragment; + + SelectorAdaptor.document(this.document) + : element = null, + fragment = null; + + SelectorAdaptor.element(this.element) + : document = null, + fragment = null; + + SelectorAdaptor.fragment(this.fragment) + : document = null, + element = null; + + bool get isDocument => document != null; + + Element? get body => document?.body; + + Node? get asNode => document ?? element ?? fragment; + + int get nodeType => asNode!.nodeType; + + Node? get parentNode => asNode!.parentNode; + + void append(Node node) { + asNode!.append(node); + } + + Element? querySelector(String selector) { + if (document != null) return document!.querySelector(selector); + if (element != null) return element!.querySelector(selector); + if (fragment != null) return fragment!.querySelector(selector); + + throw StateError('unsupported'); + } + + List<Element> querySelectorAll(String selector) { + if (document != null) return document!.querySelectorAll(selector); + if (element != null) return element!.querySelectorAll(selector); + if (fragment != null) return fragment!.querySelectorAll(selector); + + throw StateError('unsupported'); + } +} diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index 289cfda57..93d91cdd0 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -3,16 +3,16 @@ library html.test.selectors.selectors; // Bit-mapped flags to indicate which tests the selector is suitable for -final testQsaBaseline = +final int testQsaBaseline = 0x01; // querySelector() and querySelectorAll() baseline tests -final testQsaAdditional = +final int testQsaAdditional = 0x02; // querySelector() and querySelectorAll() additional tests -final testFindBaseline = +final int testFindBaseline = 0x04; // find() and findAll() baseline tests, may be unsuitable for querySelector[All] -final testFindAdditional = +final int testFindAdditional = 0x08; // find() and findAll() additional tests, may be unsuitable for querySelector[All] -final testMatchBaseline = 0x10; // matches() baseline tests -var testMatchAdditional = 0x20; // matches() additional tests +final int testMatchBaseline = 0x10; // matches() baseline tests +int testMatchAdditional = 0x20; // matches() additional tests /* * All of these invalid selectors should result in a SyntaxError being thrown by the APIs. @@ -74,7 +74,7 @@ final invalidSelectors = [ * * Note: Interactive pseudo-classes (:active :hover and :focus) have not been tested in this test suite. */ -var validSelectors = [ +final List<Map<String, dynamic>> validSelectors = [ // Type Selector { 'name': 'Type selector, matching html element', @@ -87,7 +87,7 @@ var validSelectors = [ { 'name': 'Type selector, matching html element', 'selector': 'html', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline @@ -103,7 +103,7 @@ var validSelectors = [ { 'name': 'Type selector, matching body element', 'selector': 'body', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline @@ -142,7 +142,7 @@ var validSelectors = [ 'name': 'Universal selector, matching all children of empty element with specified ID', 'selector': '#empty>*', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -196,7 +196,7 @@ var validSelectors = [ 'name': 'Attribute presence selector, not matching title attribute, case sensitivity', 'selector': '#attr-presence [TiTlE]', - 'expect': [], + 'expect': <String>[], 'exclude': ['html'], 'level': 2, 'testType': testQsaBaseline | testMatchBaseline @@ -212,7 +212,7 @@ var validSelectors = [ 'name': 'Attribute presence selector, not matching attribute with similar name', 'selector': '.attr-presence-div3[align], .attr-presence-div4[align]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -228,7 +228,7 @@ var validSelectors = [ 'name': 'Attribute presence selector, not matching default option without selected attribute', 'selector': '#attr-presence-select1 option[selected]', - 'expect': [] /* no matches */, + 'expect': <String>[] /* no matches */, 'level': 2, 'testType': testQsaBaseline }, @@ -272,7 +272,7 @@ var validSelectors = [ 'name': 'Attribute value selector, not matching align attribute with partial value', 'selector': '#attr-value [align="c"]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -280,7 +280,7 @@ var validSelectors = [ 'name': 'Attribute value selector, not matching align attribute with incorrect value', 'selector': '#attr-value [align="centera"]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -366,7 +366,7 @@ var validSelectors = [ 'name': 'Attribute whitespace-separated list selector, not matching class attribute with empty value', 'selector': '#attr-whitespace [class~=""]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -374,7 +374,7 @@ var validSelectors = [ 'name': 'Attribute whitespace-separated list selector, not matching class attribute with partial value', 'selector': '[data-attr-whitespace~="div"]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -443,7 +443,7 @@ var validSelectors = [ 'name': 'Attribute whitespace-separated list selector with double-quoted value, not matching value with space', 'selector': '#attr-whitespace a[rel~="book mark"]', - 'expect': [] /* no matches */, + 'expect': <String>[] /* no matches */, 'level': 2, 'testType': testQsaBaseline }, @@ -461,7 +461,7 @@ var validSelectors = [ 'name': 'Attribute hyphen-separated list selector, not matching unspecified lang attribute', 'selector': '#attr-hyphen-div1[lang|="en"]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -485,7 +485,7 @@ var validSelectors = [ 'name': 'Attribute hyphen-separated list selector, not matching incorrect value', 'selector': '#attr-hyphen-div4[lang|="es-AR"]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -511,7 +511,7 @@ var validSelectors = [ 'name': 'Attribute begins with selector, not matching class attribute not beginning with specified substring', 'selector': '#attr-begins [class^=apple]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -535,7 +535,7 @@ var validSelectors = [ 'name': 'Attribute begins with selector with unquoted value, not matching class attribute not beginning with specified substring', 'selector': '#attr-begins [class^= apple]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -561,7 +561,7 @@ var validSelectors = [ 'name': 'Attribute ends with selector, not matching class attribute not ending with specified substring', 'selector': '#attr-ends [class\$=apple]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -585,7 +585,7 @@ var validSelectors = [ 'name': 'Attribute ends with selector with unquoted value, not matching class attribute not ending with specified substring', 'selector': '#attr-ends [class\$=apple ]', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -717,7 +717,7 @@ var validSelectors = [ { 'name': ':root pseudo-class selector, not matching document root element', 'selector': ':root', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document'], 'level': 3, 'testType': testQsaAdditional @@ -946,7 +946,7 @@ var validSelectors = [ ":first-child pseudo-class selector, doesn't match non-first-child elements", 'selector': '.pseudo-first-child-div2:first-child, .pseudo-first-child-div3:first-child', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -977,7 +977,7 @@ var validSelectors = [ ":last-child pseudo-class selector, doesn't match non-last-child elements", 'selector': '.pseudo-last-child-div1:last-child, .pseudo-last-child-div2:first-child', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1007,7 +1007,7 @@ var validSelectors = [ 'name': ':pseudo-only-child pseudo-class selector, matching only-child em elements', 'selector': '#pseudo-only em:only-child', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1070,7 +1070,7 @@ var validSelectors = [ 'name': ':link and :visited pseudo-class selectors, not matching link elements with href attributes', 'selector': '#head :link, #head :visited', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline @@ -1079,7 +1079,7 @@ var validSelectors = [ 'name': ':link and :visited pseudo-class selectors, chained, mutually exclusive pseudo-classes match nothing', 'selector': ':link:visited', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document'], 'level': 1, 'testType': testQsaBaseline @@ -1090,7 +1090,7 @@ var validSelectors = [ 'name': ':target pseudo-class selector, matching the element referenced by the URL fragment identifier', 'selector': ':target', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document', 'element'], 'level': 3, 'testType': testQsaAdditional @@ -1118,7 +1118,7 @@ var validSelectors = [ 'name': ':lang pseudo-class selector, not matching element with no inherited language', 'selector': '#pseudo-lang-div1:lang(en)', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'exclude': ['document', 'element'], 'level': 2, 'testType': testQsaBaseline @@ -1142,7 +1142,7 @@ var validSelectors = [ { 'name': ':lang pseudo-class selector, not matching incorrect language', 'selector': '#pseudo-lang-div4:lang(es-AR)', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1224,14 +1224,14 @@ var validSelectors = [ { 'name': ':not pseudo-class selector, matching nothing', 'selector': ':not(*)', - 'expect': [] /* no matches */, + 'expect': <String>[] /* no matches */, 'level': 3, 'testType': testQsaAdditional }, { 'name': ':not pseudo-class selector, matching nothing', 'selector': ':not(*|*)', - 'expect': [] /* no matches */, + 'expect': <String>[] /* no matches */, 'level': 3, 'testType': testQsaAdditional }, @@ -1242,7 +1242,7 @@ var validSelectors = [ 'name': ':first-line pseudo-element (one-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element:first-line', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1250,7 +1250,7 @@ var validSelectors = [ 'name': '::first-line pseudo-element (two-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element::first-line', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1260,7 +1260,7 @@ var validSelectors = [ 'name': ':first-letter pseudo-element (one-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element:first-letter', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1268,7 +1268,7 @@ var validSelectors = [ 'name': '::first-letter pseudo-element (two-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element::first-letter', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1278,7 +1278,7 @@ var validSelectors = [ 'name': ':before pseudo-element (one-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element:before', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1286,7 +1286,7 @@ var validSelectors = [ 'name': '::before pseudo-element (two-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element::before', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1296,7 +1296,7 @@ var validSelectors = [ 'name': ':after pseudo-element (one-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element:after', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1304,7 +1304,7 @@ var validSelectors = [ 'name': '::after pseudo-element (two-colon syntax) selector, not matching any elements', 'selector': '#pseudo-element::after', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1413,14 +1413,14 @@ var validSelectors = [ { 'name': 'ID selector, not matching non-existent descendant', 'selector': '#id #none', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, { 'name': 'ID selector, not matching non-existent ancestor', 'selector': '#none #id-div1', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, @@ -1565,7 +1565,7 @@ var validSelectors = [ 'name': 'Descendant combinator, not matching element with id that is not a descendant of an element with id', 'selector': '#descendant-div1 #descendant-div4', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 1, 'testType': testQsaBaseline }, @@ -1622,7 +1622,7 @@ var validSelectors = [ 'name': 'Child combinator, not matching element with id that is not a child of an element with id', 'selector': '#child>#child-div3', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1630,7 +1630,7 @@ var validSelectors = [ 'name': 'Child combinator, not matching element with id that is not a child of an element with class', 'selector': '#child-div1>.child-div3', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1638,7 +1638,7 @@ var validSelectors = [ 'name': 'Child combinator, not matching element with class that is not a child of an element with class', 'selector': '.child-div1>.child-div3', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1724,7 +1724,7 @@ var validSelectors = [ 'name': 'Adjacent sibling combinator, not matching element with id that is not an adjacent sibling of an element with id', 'selector': '#adjacent-div2+#adjacent-p2, #adjacent-div2+#adjacent-div1', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 2, 'testType': testQsaBaseline }, @@ -1802,7 +1802,7 @@ var validSelectors = [ 'name': 'General sibling combinator, not matching element with id that is not a sibling after a p element', 'selector': '#sibling>p~div', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, @@ -1810,7 +1810,7 @@ var validSelectors = [ 'name': 'General sibling combinator, not matching element with id that is not a sibling after an element with id', 'selector': '#sibling-div2~#sibling-div3, #sibling-div2~#sibling-div1', - 'expect': [] /*no matches*/, + 'expect': <String>[] /*no matches*/, 'level': 3, 'testType': testQsaAdditional }, diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index f4f48f8dd..a74242cce 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -15,7 +15,7 @@ typedef TreeBuilderFactory = TreeBuilder Function(bool namespaceHTMLElements); Map<String, TreeBuilderFactory>? _treeTypes; Map<String, TreeBuilderFactory>? get treeTypes { // TODO(jmesserly): add DOM here once it's implemented - _treeTypes ??= {'simpletree': (useNs) => TreeBuilder(useNs)}; + _treeTypes ??= {'simpletree': TreeBuilder.new}; return _treeTypes; } @@ -144,7 +144,7 @@ class TestSerializer extends TreeVisitor { } @override - void visitDocument(node) => _visitDocumentOrFragment(node); + void visitDocument(Document node) => _visitDocumentOrFragment(node); void _visitDocumentOrFragment(Node node) { indent += 1; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index e0af7fb84..d8041848e 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -1,13 +1,10 @@ @TestOn('vm') library tokenizer_test; -// TODO(https://github.com/dart-lang/html/issues/173): Remove. -// ignore_for_file: avoid_dynamic_calls - -// Note: mirrors used to match the getattr usage in the original test import 'dart:convert'; import 'dart:io'; -import 'dart:mirrors'; +// Note: mirrors used to match the getattr usage in the original test +import 'dart:mirrors' show reflect; import 'package:html/src/token.dart'; import 'package:html/src/tokenizer.dart'; @@ -16,11 +13,37 @@ import 'package:test/test.dart'; import 'support.dart'; +void main() async { + await for (var path in dataFiles('tokenizer')) { + if (!path.endsWith('.test')) continue; + + final text = File(path).readAsStringSync(); + final tests = jsonDecode(text) as Map<String, dynamic>; + final testName = pathos.basenameWithoutExtension(path); + final testList = tests['tests'] as List?; + if (testList == null) continue; + + group(testName, () { + for (var index = 0; index < testList.length; index++) { + final testInfo = testList[index] as Map<String, dynamic>; + + testInfo.putIfAbsent('initialStates', () => ['Data state']); + for (var initialState in testInfo['initialStates'] as List) { + test(testInfo['description'], () { + testInfo['initialState'] = camelCase(initialState as String); + runTokenizerTest(testInfo); + }); + } + } + }); + } +} + class TokenizerTestParser { final String? _state; final String? _lastStartTag; final bool _generateSpans; - List? outputTokens; + List<List<Object?>>? outputTokens; TokenizerTestParser(String? initialState, [String? lastStartTag, bool generateSpans = false]) @@ -28,7 +51,7 @@ class TokenizerTestParser { _lastStartTag = lastStartTag, _generateSpans = generateSpans; - List? parse(String str) { + List<dynamic>? parse(String str) { // Note: we need to pass bytes to the tokenizer if we want it to handle BOM. final bytes = utf8.encode(str); final tokenizer = @@ -101,7 +124,7 @@ class TokenizerTestParser { addOutputToken(token, ['Character', token.data]); } - void processEOF(token) {} + void processEOF(StringToken token) {} void processParseError(StringToken token) { // TODO(jmesserly): when debugging test failures it can be useful to add @@ -110,7 +133,7 @@ class TokenizerTestParser { addOutputToken(token, ['ParseError', token.data]); } - void addOutputToken(Token token, List array) { + void addOutputToken(Token token, List<Object?> array) { outputTokens!.add([ ...array, if (token.span != null && _generateSpans) token.span!.start.offset, @@ -119,14 +142,16 @@ class TokenizerTestParser { } } -List concatenateCharacterTokens(List tokens) { - final outputTokens = []; +/// [tokens] can contain strings, lists, and maps. +List<dynamic> concatenateCharacterTokens(List<dynamic> tokens) { + final outputTokens = <dynamic>[]; for (var token in tokens) { - if (token.indexOf('ParseError') == -1 && token[0] == 'Character') { + if (token != 'ParseError' && (token as List)[0] == 'Character') { if (outputTokens.isNotEmpty && - outputTokens.last.indexOf('ParseError') == -1 && - outputTokens.last[0] == 'Character') { - outputTokens.last[1] = '${outputTokens.last[1]}${token[1]}'; + outputTokens.last != 'ParseError' && + (outputTokens.last as List)[0] == 'Character') { + (outputTokens.last as List)[1] = + '${(outputTokens.last as List)[1]}${token[1]}'; } else { outputTokens.add(token); } @@ -137,10 +162,10 @@ List concatenateCharacterTokens(List tokens) { return outputTokens; } -List normalizeTokens(List tokens) { +List<dynamic> normalizeTokens(List<dynamic> tokens) { // TODO: convert tests to reflect arrays for (var i = 0; i < tokens.length; i++) { - final token = tokens[i]; + final token = tokens[i] as List; if (token[0] == 'ParseError') { tokens[i] = token[0]; } @@ -152,13 +177,13 @@ List normalizeTokens(List tokens) { /// /// If the ignoreErrorOrder flag is set to true we don't test the relative /// positions of parse errors and non parse errors. -void expectTokensMatch( - List expectedTokens, List receivedTokens, bool ignoreErrorOrder, +void expectTokensMatch(List<dynamic> expectedTokens, + List<dynamic> receivedTokens, bool ignoreErrorOrder, [bool ignoreErrors = false, String? message]) { // If the 'selfClosing' attribute is not included in the expected test tokens, // remove it from the received token. var removeSelfClosing = false; - for (var token in expectedTokens) { + for (var token in expectedTokens.whereType<List<dynamic>>()) { if (token[0] == 'StartTag' && token.length == 3 || token[0] == 'EndTag' && token.length == 2) { removeSelfClosing = true; @@ -167,7 +192,7 @@ void expectTokensMatch( } if (removeSelfClosing) { - for (var token in receivedTokens) { + for (var token in receivedTokens.whereType<List<dynamic>>()) { if (token[0] == 'StartTag' || token[0] == 'EndTag') { token.removeLast(); } @@ -229,24 +254,30 @@ Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { // TODO(sigmundch,jmesserly): we currently use jsonDecode to unescape the // unicode characters in the string, we should use a decoding that works with // any control characters. - dynamic decode(inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); + dynamic decode(String inp) => inp == '\u0000' ? inp : jsonDecode('"$inp"'); + + testInfo['input'] = decode(testInfo['input'] as String); - testInfo['input'] = decode(testInfo['input']); for (var token in testInfo['output'] as List) { if (token == 'ParseError') { continue; - } else { - token[1] = decode(token[1]); - if ((token as List).length > 2) { - for (var pair in token[2] as List) { - final key = pair[0]; - final value = pair[1]; - token[2].remove(key); - token[2][decode(key)] = decode(value); - } + } + + token as List; + token[1] = decode(token[1] as String); + + if ((token).length > 2) { + for (var pair in (token[2] as List)) { + pair as List; + final key = pair[0] as String; + final value = pair[1] as String; + + (token[2] as Map).remove(key); + (token[2] as Map)[decode(key)] = decode(value); } } } + return testInfo; } @@ -260,29 +291,3 @@ String camelCase(String s) { } return result.toString(); } - -void main() async { - await for (var path in dataFiles('tokenizer')) { - if (!path.endsWith('.test')) continue; - - final text = File(path).readAsStringSync(); - final tests = jsonDecode(text); - final testName = pathos.basenameWithoutExtension(path); - final testList = tests['tests'] as List?; - if (testList == null) continue; - - group(testName, () { - for (var index = 0; index < testList.length; index++) { - final testInfo = testList[index] as Map<String, dynamic>; - - testInfo.putIfAbsent('initialStates', () => ['Data state']); - for (var initialState in testInfo['initialStates'] as List) { - test(testInfo['description'], () { - testInfo['initialState'] = camelCase(initialState as String); - runTokenizerTest(testInfo); - }); - } - } - }); - } -} From da9a4a5f1528f87ef21a3b53cff4b0e237dcc625 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Mon, 30 Jan 2023 07:40:00 -0800 Subject: [PATCH 175/212] Update test-package.yml (dart-lang/html#198) --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 8421e308e..413bb3095 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -2,9 +2,9 @@ name: Dart CI on: push: - branches: [master] + branches: [main] pull_request: - branches: [master] + branches: [main] schedule: - cron: "0 0 * * 0" From 5e8374612fbfd3efb1a8020d973053de3917344f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 08:40:22 -0800 Subject: [PATCH 176/212] Bump dart-lang/setup-dart from 1.3 to 1.4 (dart-lang/html#199) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.3 to 1.4. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/6a218f2413a3e78e9087f638a238f6b40893203d...a57a6c04cf7d4840e88432aad6281d1e125f0d46) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 413bb3095..0ec49aae0 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [2.17.0, dev] steps: - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b - - uses: dart-lang/setup-dart@6a218f2413a3e78e9087f638a238f6b40893203d + - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} - id: install From dfe81f1f9754cba2711dc57e8e548848e054548f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Jan 2023 08:43:19 -0800 Subject: [PATCH 177/212] Bump actions/checkout from 3.2.0 to 3.3.0 (dart-lang/html#200) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.2.0 to 3.3.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/755da8c3cf115ac066823e79a1e1788f8940201b...ac593985615ec2ede58e132d2e21d2b1cbd6127c) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 0ec49aae0..0610b92a8 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@755da8c3cf115ac066823e79a1e1788f8940201b + - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 26707fab39cbe8bf05f045d5a4753c0d122dc024 Mon Sep 17 00:00:00 2001 From: Ron Booth <ronbooth@gmail.com> Date: Mon, 30 Jan 2023 15:15:24 -0700 Subject: [PATCH 178/212] fixed issue dart-lang/html#157 (querySelector fails), and added test for it (dart-lang/html#158) --- pkgs/html/lib/src/query_selector.dart | 35 ++++++++++++++----------- pkgs/html/test/query_selector_test.dart | 26 ++++++++++++++++++ 2 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 pkgs/html/test/query_selector_test.dart diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 32e0a37cc..c45d11c3e 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -69,22 +69,25 @@ class SelectorEvaluator extends Visitor { for (var s in node.simpleSelectorSequences.reversed) { if (combinator == null) { result = s.simpleSelector.visit(this) as bool; - } else if (combinator == TokenKind.COMBINATOR_DESCENDANT) { - // descendant combinator - // http://dev.w3.org/csswg/selectors-4/#descendant-combinators - do { - _element = _element!.parent; - } while (_element != null && !(s.simpleSelector.visit(this) as bool)); - - if (_element == null) result = false; - } else if (combinator == TokenKind.COMBINATOR_TILDE) { - // Following-sibling combinator - // http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators - do { - _element = _element!.previousElementSibling; - } while (_element != null && !(s.simpleSelector.visit(this) as bool)); - - if (_element == null) result = false; + } else { + if (combinator == TokenKind.COMBINATOR_DESCENDANT) { + // descendant combinator + // http://dev.w3.org/csswg/selectors-4/#descendant-combinators + do { + _element = _element!.parent; + } while (_element != null && !(s.simpleSelector.visit(this) as bool)); + + if (_element == null) result = false; + } else if (combinator == TokenKind.COMBINATOR_TILDE) { + // Following-sibling combinator + // http://dev.w3.org/csswg/selectors-4/#general-sibling-combinators + do { + _element = _element!.previousElementSibling; + } while (_element != null && !(s.simpleSelector.visit(this) as bool)); + + if (_element == null) result = false; + } + combinator = null; } if (!result) break; diff --git a/pkgs/html/test/query_selector_test.dart b/pkgs/html/test/query_selector_test.dart new file mode 100644 index 000000000..9b81e936b --- /dev/null +++ b/pkgs/html/test/query_selector_test.dart @@ -0,0 +1,26 @@ +library query_selector_test; + +import 'package:test/test.dart'; +import 'package:html/dom.dart'; + +void main() { + group('querySelector descendant', () { + late Element el; + + setUp(() { + el = Element.html('<div id="a" class="a"><div id="b"></div></div>'); + }); + + test('descendant of type', () { + expect(el.querySelector('div div')?.id, 'b'); + }); + + test('descendant of class', () { + expect(el.querySelector('.a div')?.id, 'b'); + }); + + test('descendant of type and class', () { + expect(el.querySelector('div.a div')?.id, 'b'); + }); + }); +} From 9411b013e84eef60ec2f6a832e34f6c1be684869 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Mon, 30 Jan 2023 15:31:21 -0800 Subject: [PATCH 179/212] updates from dart-lang/html#158 (dart-lang/html#202) * updates from dart-lang/html#158 * typo --- pkgs/html/CHANGELOG.md | 2 ++ pkgs/html/test/query_selector_test.dart | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 0adcd1a5c..6124708da 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -2,6 +2,8 @@ - Add additional types at the API boundary (in `lib/parser.dart` and others). - Update to `package:lints` 2.0. +- Fixed an issue with `querySelector` where it would fail in some cases with + descendant or sibling combinators (#157). ## 0.15.1 diff --git a/pkgs/html/test/query_selector_test.dart b/pkgs/html/test/query_selector_test.dart index 9b81e936b..149250f76 100644 --- a/pkgs/html/test/query_selector_test.dart +++ b/pkgs/html/test/query_selector_test.dart @@ -1,7 +1,7 @@ library query_selector_test; -import 'package:test/test.dart'; import 'package:html/dom.dart'; +import 'package:test/test.dart'; void main() { group('querySelector descendant', () { From 946c7e96017bdb2298974cb2f5b131cb717564f4 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Mon, 30 Jan 2023 15:49:51 -0800 Subject: [PATCH 180/212] lint with dart_flutter_team_lints (dart-lang/html#201) --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/analysis_options.yaml | 43 ++---------------------- pkgs/html/lib/dom.dart | 2 +- pkgs/html/lib/parser.dart | 14 ++++---- pkgs/html/lib/src/constants.dart | 2 +- pkgs/html/lib/src/encoding_parser.dart | 27 +++++++++------ pkgs/html/lib/src/html_input_stream.dart | 2 +- pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/selectors/level1_lib.dart | 2 +- pkgs/html/test/tokenizer_test.dart | 4 +-- 10 files changed, 33 insertions(+), 67 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 6124708da..2588feac3 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,7 +1,7 @@ ## 0.15.2-dev - Add additional types at the API boundary (in `lib/parser.dart` and others). -- Update to `package:lints` 2.0. +- Adopted the `package:dart_flutter_team_lints` linting rules. - Fixed an issue with `querySelector` where it would fail in some cases with descendant or sibling combinators (#157). diff --git a/pkgs/html/analysis_options.yaml b/pkgs/html/analysis_options.yaml index 715ea40f7..90d920ee7 100644 --- a/pkgs/html/analysis_options.yaml +++ b/pkgs/html/analysis_options.yaml @@ -1,49 +1,10 @@ -include: package:lints/recommended.yaml +include: package:dart_flutter_team_lints/analysis_options.yaml analyzer: language: strict-casts: true strict-raw-types: true errors: + lines_longer_than_80_chars: ignore # https://github.com/dart-lang/linter/issues/1649 prefer_collection_literals: ignore - -linter: - rules: - - always_declare_return_types - - avoid_dynamic_calls - - avoid_function_literals_in_foreach_calls - - avoid_returning_null - - avoid_unused_constructor_parameters - - await_only_futures - - camel_case_types - - cancel_subscriptions - - comment_references - - constant_identifier_names - - control_flow_in_finally - - directives_ordering - - empty_statements - - hash_and_equals - - implementation_imports - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - no_adjacent_strings_in_list - - non_constant_identifier_names - - only_throw_errors - - overridden_fields - - package_api_docs - - package_names - - package_prefixed_library_names - - prefer_const_constructors - - prefer_final_locals - - prefer_initializing_formals - - prefer_interpolation_to_compose_strings - - prefer_typing_uninitialized_variables - - test_types_in_equals - - throw_in_finally - - type_annotate_public_apis - - unnecessary_brace_in_string_interps - - unnecessary_getters_setters - - unnecessary_lambdas - - unnecessary_null_aware_assignments - - unnecessary_statements diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 5ffc15f26..28d75944c 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -60,7 +60,7 @@ class AttributeName implements Comparable<Object> { int compareTo(Object other) { // Not sure about this sort order if (other is! AttributeName) return 1; - var cmp = (prefix ?? '').compareTo((other.prefix ?? '')); + var cmp = (prefix ?? '').compareTo(other.prefix ?? ''); if (cmp != 0) return cmp; cmp = name.compareTo(other.name); if (cmp != 0) return cmp; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index c4bd1ede7..3eb7a9722 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -151,7 +151,7 @@ class HtmlParser { String? sourceUrl, TreeBuilder? tree}) : tree = tree ?? TreeBuilder(true), - tokenizer = (input is HtmlTokenizer + tokenizer = input is HtmlTokenizer ? input : HtmlTokenizer(input, encoding: encoding, @@ -159,7 +159,7 @@ class HtmlParser { lowercaseElementName: lowercaseElementName, lowercaseAttrName: lowercaseAttrName, generateSpans: generateSpans, - sourceUrl: sourceUrl)) { + sourceUrl: sourceUrl) { tokenizer.parser = this; } @@ -653,9 +653,9 @@ class InitialPhase extends Phase { final systemId = token.systemId; final correct = token.correct; - if ((name != 'html' || + if (name != 'html' || publicId != null || - systemId != null && systemId != 'about:legacy-compat')) { + systemId != null && systemId != 'about:legacy-compat') { parser.parseError(token.span, 'unknown-doctype'); } @@ -1573,8 +1573,8 @@ class InBodyPhase extends Phase { void startTagFrameset(StartTagToken token) { parser.parseError(token.span, 'unexpected-start-tag', {'name': 'frameset'}); - if ((tree.openElements.length == 1 || - tree.openElements[1].localName != 'body')) { + if (tree.openElements.length == 1 || + tree.openElements[1].localName != 'body') { assert(parser.innerHTMLMode); } else if (parser.framesetOK) { if (tree.openElements[1].parentNode != null) { @@ -2121,7 +2121,7 @@ class InBodyPhase extends Phase { } // Step 6.4 if (lastNode == furthestBlock) { - bookmark = (tree.activeFormattingElements.indexOf(node) + 1); + bookmark = tree.activeFormattingElements.indexOf(node) + 1; } // Step 6.5 //cite = node.parent diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 152f85b06..5c41f81ea 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -200,7 +200,7 @@ const Map<String, String> errorMessages = { 'unexpected-end-tag-after-body': 'Unexpected end tag token (%(name)s)' ' in the after body phase.', 'unexpected-char-in-frameset': - 'Unepxected characters in the frameset phase. Characters ignored.', + 'Unexpected characters in the frameset phase. Characters ignored.', 'unexpected-start-tag-in-frameset': 'Unexpected start tag token (%(name)s)' ' in the frameset phase. Ignored.', 'unexpected-frameset-in-frameset-innerhtml': diff --git a/pkgs/html/lib/src/encoding_parser.dart b/pkgs/html/lib/src/encoding_parser.dart index defe57eea..2ecd5c416 100644 --- a/pkgs/html/lib/src/encoding_parser.dart +++ b/pkgs/html/lib/src/encoding_parser.dart @@ -1,9 +1,8 @@ import 'constants.dart'; import 'html_input_stream.dart'; -// TODO(jmesserly): I converted StopIteration to StateError("No more elements"). -// Seems strange to throw this from outside of an iterator though. -/// String-like object with an associated position and various extra methods +/// String-like object with an associated position and various extra methods. +/// /// If the position is ever greater than the string length then an exception is /// raised. class EncodingBytes { @@ -17,7 +16,7 @@ class EncodingBytes { String _next() { final p = __position = __position + 1; if (p >= _length) { - throw StateError('No more elements'); + throw _EncodingRangeException('No more elements'); } else if (p < 0) { throw RangeError(p); } @@ -27,7 +26,7 @@ class EncodingBytes { String _previous() { var p = __position; if (p >= _length) { - throw StateError('No more elements'); + throw _EncodingRangeException('No more elements'); } else if (p < 0) { throw RangeError(p); } @@ -37,14 +36,14 @@ class EncodingBytes { set _position(int value) { if (__position >= _length) { - throw StateError('No more elements'); + throw _EncodingRangeException('No more elements'); } __position = value; } int get _position { if (__position >= _length) { - throw StateError('No more elements'); + throw _EncodingRangeException('No more elements'); } if (__position >= 0) { return __position; @@ -108,7 +107,7 @@ class EncodingBytes { __position = newPosition + bytes.length - 1; return true; } else { - throw StateError('No more elements'); + throw _EncodingRangeException('No more elements'); } } @@ -161,7 +160,7 @@ class EncodingParser { } _data._position += 1; } - } on StateError catch (_) { + } on _EncodingRangeException catch (_) { // Catch this here to match behavior of Python's StopIteration // TODO(jmesserly): refactor to not use exceptions } @@ -355,12 +354,12 @@ class ContentAttrParser { try { data._skipUntil(isWhitespace); return data._slice(oldPosition, data._position); - } on StateError catch (_) { + } on _EncodingRangeException catch (_) { //Return the whole remaining value return data._slice(oldPosition); } } - } on StateError catch (_) { + } on _EncodingRangeException catch (_) { return null; } } @@ -371,3 +370,9 @@ bool _isSpaceOrAngleBracket(String char) { } typedef _CharPredicate = bool Function(String char); + +class _EncodingRangeException implements Exception { + final String message; + + _EncodingRangeException(this.message); +} diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 54e0231c4..1c1bcc8b4 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -22,7 +22,7 @@ class HtmlInputStream { /// The name of the character encoding. String? charEncodingName; - /// True if we are certain about [charEncodingName], false for tenative. + /// True if we are certain about [charEncodingName], false for tentative. bool charEncodingCertain = true; final bool generateSpans; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 831bce0ef..2a61ef43b 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -11,6 +11,6 @@ dependencies: source_span: ^1.8.0 dev_dependencies: - lints: ^2.0.0 + dart_flutter_team_lints: ^0.1.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 2f6210301..833e70229 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -195,7 +195,7 @@ void runValidSelectorTest(String type, SelectorAdaptor root, final exclude = s['exclude']; if ((exclude is! List || - (!(exclude).contains(nodeType) && !exclude.contains(docType))) && + (!exclude.contains(nodeType) && !exclude.contains(docType))) && ((s['testType'] as int) & testType != 0)) { //console.log("Running tests " + nodeType + ": " + s["testType"] + "&" + testType + "=" + (s["testType"] & testType) + ": " + JSON.stringify(s)) late List<Element> foundall; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index d8041848e..128190635 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -266,8 +266,8 @@ Map<String, dynamic> unescape(Map<String, dynamic> testInfo) { token as List; token[1] = decode(token[1] as String); - if ((token).length > 2) { - for (var pair in (token[2] as List)) { + if (token.length > 2) { + for (var pair in token[2] as List) { pair as List; final key = pair[0] as String; final value = pair[1] as String; From 02f79fa854e0c3728f9f65d6f9230ea3b380f090 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Sat, 4 Feb 2023 19:41:37 -0800 Subject: [PATCH 181/212] add an api example (dart-lang/html#204) --- pkgs/html/CHANGELOG.md | 1 + pkgs/html/README.md | 4 +-- pkgs/html/example/main.dart | 57 +++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 pkgs/html/example/main.dart diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 2588feac3..0e9440ff3 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -4,6 +4,7 @@ - Adopted the `package:dart_flutter_team_lints` linting rules. - Fixed an issue with `querySelector` where it would fail in some cases with descendant or sibling combinators (#157). +- Add an API example in `example/`. ## 0.15.1 diff --git a/pkgs/html/README.md b/pkgs/html/README.md index f5388b235..05a19a82c 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -9,9 +9,9 @@ A Dart implementation of an HTML5 parser. Parsing HTML is easy! ```dart -import 'package:html/parser.dart' show parse; +import 'package:html/parser.dart'; -main() { +void main() { var document = parse( '<body>Hello world! <a href="www.html5rocks.com">HTML5 rocks!'); print(document.outerHtml); diff --git a/pkgs/html/example/main.dart b/pkgs/html/example/main.dart new file mode 100644 index 000000000..309ed7c61 --- /dev/null +++ b/pkgs/html/example/main.dart @@ -0,0 +1,57 @@ +import 'package:html/dom.dart'; +import 'package:html/dom_parsing.dart'; +import 'package:html/parser.dart'; + +void main(List<String> args) { + var document = parse(''' +<body> + <h2>Header 1</h2> + <p>Text.</p> + <h2>Header 2</h2> + More text. + <br/> +</body>'''); + + // outerHtml output + print('outer html:'); + print(document.outerHtml); + + print(''); + + // visitor output + print('html visitor:'); + _Visitor().visit(document); +} + +// Note: this example visitor doesn't handle things like printing attributes and +// such. +class _Visitor extends TreeVisitor { + String indent = ''; + + @override + void visitText(Text node) { + if (node.data.trim().isNotEmpty) { + print('$indent${node.data.trim()}'); + } + } + + @override + void visitElement(Element node) { + if (isVoidElement(node.localName)) { + print('$indent<${node.localName}/>'); + } else { + print('$indent<${node.localName}>'); + indent += ' '; + visitChildren(node); + indent = indent.substring(0, indent.length - 2); + print('$indent</${node.localName}>'); + } + } + + @override + void visitChildren(Node node) { + for (var child in node.nodes) { + visit(child); + } + } +} From f7a00b20151e4d7a108f8a57a553b708008ade2b Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Thu, 2 Mar 2023 11:36:59 -0800 Subject: [PATCH 182/212] prep for publishing 0.15.2 (dart-lang/html#205) --- pkgs/html/CHANGELOG.md | 2 +- pkgs/html/pubspec.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 0e9440ff3..725d15772 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,4 +1,4 @@ -## 0.15.2-dev +## 0.15.2 - Add additional types at the API boundary (in `lib/parser.dart` and others). - Adopted the `package:dart_flutter_team_lints` linting rules. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 2a61ef43b..eb222a6c7 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.2-dev +version: 0.15.2 description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html From 51cb6d109da99dbf6ad35cf91b8239ace760190b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:33:06 -0700 Subject: [PATCH 183/212] Bump actions/checkout from 3.3.0 to 3.5.0 (dart-lang/html#210) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.3.0 to 3.5.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/ac593985615ec2ede58e132d2e21d2b1cbd6127c...8f4b7f84864484a7bf31766abe9204da3cbe65b3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 0610b92a8..ea3601c52 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c + - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 with: sdk: ${{ matrix.sdk }} From 20771ff4907bd4b9977ec92b3c90ff2715f65fd3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Apr 2023 15:55:31 -0700 Subject: [PATCH 184/212] Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (dart-lang/html#209) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.4.0 to 1.5.0. - [Release notes](https://github.com/dart-lang/setup-dart/releases) - [Changelog](https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md) - [Commits](https://github.com/dart-lang/setup-dart/compare/a57a6c04cf7d4840e88432aad6281d1e125f0d46...d6a63dab3335f427404425de0fbfed4686d93c4f) --- updated-dependencies: - dependency-name: dart-lang/setup-dart dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index ea3601c52..568b20976 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [2.17.0, dev] steps: - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 - - uses: dart-lang/setup-dart@a57a6c04cf7d4840e88432aad6281d1e125f0d46 + - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} - id: install From 8479abd7229bf8be4183847a11c73d3a3138c7d3 Mon Sep 17 00:00:00 2001 From: Oleh Prypin <oprypin@google.com> Date: Wed, 5 Apr 2023 02:12:31 +0200 Subject: [PATCH 185/212] Dart 3 compatibility: turn classes into mixins (dart-lang/html#208) These are private definitions and are only ever used in a `with` clause. They should just be changed to `mixin` to become compatible with Dart language 3.0. --- pkgs/html/lib/dom.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 28d75944c..5b8f8c97c 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -76,7 +76,7 @@ class AttributeName implements Comparable<Object> { } // http://dom.spec.whatwg.org/#parentnode -abstract class _ParentNode implements Node { +mixin _ParentNode implements Node { // TODO(jmesserly): this is only a partial implementation /// Seaches for the first descendant node matching the given selectors, using @@ -103,7 +103,7 @@ abstract class _ParentNode implements Node { } // http://dom.spec.whatwg.org/#interface-nonelementparentnode -abstract class _NonElementParentNode implements _ParentNode { +mixin _NonElementParentNode implements _ParentNode { // TODO(jmesserly): could be faster, should throw on invalid id. Element? getElementById(String id) => querySelector('#$id'); } From 63e613f9543dfe8ef813c8d0477364f648a764df Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Wed, 3 May 2023 12:13:26 -0700 Subject: [PATCH 186/212] added package topics to the pubspec file (dart-lang/html#215) * added package topics to the pubspec file * Update pubspec.yaml --- pkgs/html/CHANGELOG.md | 4 ++++ pkgs/html/pubspec.yaml | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 725d15772..7b2ab389d 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.15.3 + +- Added package topics to the pubspec file. + ## 0.15.2 - Add additional types at the API boundary (in `lib/parser.dart` and others). diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index eb222a6c7..f6f56f128 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,8 +1,12 @@ name: html -version: 0.15.2 +version: 0.15.3 description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html +topics: + - html + - web + environment: sdk: '>=2.17.0 <3.0.0' From 249811f39a184f211dcae329b85a23bc1c9c519e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 8 May 2023 12:24:21 -0700 Subject: [PATCH 187/212] Bump actions/checkout from 3.5.0 to 3.5.2 (dart-lang/html#214) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.0 to 3.5.2. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/8f4b7f84864484a7bf31766abe9204da3cbe65b3...8e5e7e5ab8b370d6c329ec480221332ada57f0ab) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 568b20976..4dda1cdd0 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.17.0, dev] steps: - - uses: actions/checkout@8f4b7f84864484a7bf31766abe9204da3cbe65b3 + - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 16e0d047abed33055a79167354754e456987d4aa Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Wed, 17 May 2023 11:10:15 -0700 Subject: [PATCH 188/212] blast_repo fixes (dart-lang/html#216) dependabot --- pkgs/html/.github/dependabot.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml index 1603cdd9e..725f03af2 100644 --- a/pkgs/html/.github/dependabot.yml +++ b/pkgs/html/.github/dependabot.yml @@ -3,7 +3,9 @@ version: 2 updates: - - package-ecosystem: "github-actions" - directory: "/" + - package-ecosystem: github-actions + directory: / schedule: - interval: "monthly" + interval: monthly + labels: + - autosubmit From ffeaa23f01ee55fb2d1647353597a6d69eb7fcd6 Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Wed, 7 Jun 2023 13:56:38 -0700 Subject: [PATCH 189/212] widen the dependency on 'package:csslib' (dart-lang/html#217) * widen the dependency on 'package:csslib' * update CI * Update CHANGELOG.md --- pkgs/html/.github/workflows/test-package.yml | 2 +- pkgs/html/CHANGELOG.md | 5 +++++ pkgs/html/lib/src/css_class_set.dart | 1 - pkgs/html/lib/src/tokenizer.dart | 2 -- pkgs/html/pubspec.yaml | 8 ++++---- pkgs/html/test/query_selector_test.dart | 2 -- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 4dda1cdd0..96656cbc9 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.17.0, dev] + sdk: [2.19.0, stable, dev] steps: - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 7b2ab389d..27ce0c04d 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.15.4 + +- Widen the dependency on `package:csslib`. +- Require Dart `2.19`. + ## 0.15.3 - Added package topics to the pubspec file. diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index cebb5656c..508fd2b8f 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -3,7 +3,6 @@ // BSD-style license that can be found in the LICENSE file. // TODO(jmesserly): everything in this file is copied straight from "dart:html". -library html.dom.src; import 'dart:collection'; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index 1ab72a91a..b1bfa36c3 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1,5 +1,3 @@ -library tokenizer; - import 'dart:collection'; import 'package:html/parser.dart' show HtmlParser; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index f6f56f128..e16c0ee51 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.3 +version: 0.15.4 description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html @@ -8,13 +8,13 @@ topics: - web environment: - sdk: '>=2.17.0 <3.0.0' + sdk: '>=2.19.0 <4.0.0' dependencies: - csslib: ^0.17.0 + csslib: '>=0.17.0 <2.0.0' source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^0.1.0 + dart_flutter_team_lints: ^1.0.0 path: ^1.8.0 test: ^1.16.0 diff --git a/pkgs/html/test/query_selector_test.dart b/pkgs/html/test/query_selector_test.dart index 149250f76..495b0f10b 100644 --- a/pkgs/html/test/query_selector_test.dart +++ b/pkgs/html/test/query_selector_test.dart @@ -1,5 +1,3 @@ -library query_selector_test; - import 'package:html/dom.dart'; import 'package:test/test.dart'; From 98f016a939ca4f91e1b881d1bbbffc7c22bd677a Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Sat, 1 Jul 2023 16:04:00 -0700 Subject: [PATCH 190/212] address new analysis issues (dart-lang/html#219) --- pkgs/html/CHANGELOG.md | 3 +++ pkgs/html/pubspec.yaml | 2 +- pkgs/html/test/tokenizer_test.dart | 2 -- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index 27ce0c04d..fa79fbcf1 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.15.5-wip + + ## 0.15.4 - Widen the dependency on `package:csslib`. diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index e16c0ee51..e73d47995 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.4 +version: 0.15.5-wip description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/html diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 128190635..74a4a48fa 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -124,8 +124,6 @@ class TokenizerTestParser { addOutputToken(token, ['Character', token.data]); } - void processEOF(StringToken token) {} - void processParseError(StringToken token) { // TODO(jmesserly): when debugging test failures it can be useful to add // logging here like `print('ParseError $token');`. It would be nice to From 0d16414ce80716885ab8f56a31471f2003c03696 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jul 2023 23:24:12 +0000 Subject: [PATCH 191/212] Bump actions/checkout from 3.5.2 to 3.5.3 (dart-lang/html#218) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.2 to 3.5.3. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v3.5.3</h2> <h2>What's Changed</h2> <ul> <li>Fix: Checkout Issue in self hosted runner due to faulty submodule check-ins by <a href="https://github.com/megamanics"><code>@​megamanics</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1196">actions/checkoutdart-lang/html#1196</a></li> <li>Fix typos found by codespell by <a href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1287">actions/checkoutdart-lang/html#1287</a></li> <li>Add support for sparse checkouts by <a href="https://github.com/dscho"><code>@​dscho</code></a> and <a href="https://github.com/dfdez"><code>@​dfdez</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1369">actions/checkoutdart-lang/html#1369</a></li> <li>Release v3.5.3 by <a href="https://github.com/TingluoHuang"><code>@​TingluoHuang</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1376">actions/checkoutdart-lang/html#1376</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/megamanics"><code>@​megamanics</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1196">actions/checkoutdart-lang/html#1196</a></li> <li><a href="https://github.com/DimitriPapadopoulos"><code>@​DimitriPapadopoulos</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1287">actions/checkoutdart-lang/html#1287</a></li> <li><a href="https://github.com/dfdez"><code>@​dfdez</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1369">actions/checkoutdart-lang/html#1369</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v3...v3.5.3">https://github.com/actions/checkout/compare/v3...v3.5.3</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1246">Fix slow checkout on Windows</a></li> </ul> <h2>v3.5.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1237">Add new public key for known_hosts</a></li> </ul> <h2>v3.4.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1209">Upgrade codeql actions to v2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1210">Upgrade dependencies</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1225">Upgrade <code>@​actions/io</code></a></li> </ul> <h2>v3.3.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1045">Implement branch list using callbacks from exec function</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1050">Add in explicit reference to private checkout options</a></li> <li>[Fix comment typos (that got added in <a href="https://redirect.github.com/actions/checkout/issues/770">dart-lang/html#770</a>)](<a href="https://redirect.github.com/actions/checkout/pull/1057">actions/checkoutdart-lang/html#1057</a>)</li> </ul> <h2>v3.2.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/942">Add GitHub Action to perform release</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/967">Fix status badge</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1002">Replace datadog/squid with ubuntu/squid Docker image</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/964">Wrap pipeline commands for submoduleForeach in quotes</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1029">Update <code>@​actions/io</code> to 1.1.2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1039">Upgrading version to 3.2.0</a></li> </ul> <h2>v3.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/939">Use <code>@​actions/core</code> <code>saveState</code> and <code>getState</code></a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/922">Add <code>github-server-url</code> input</a></li> </ul> <h2>v3.0.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/770">Add input <code>set-safe-directory</code></a></li> </ul> <h2>v3.0.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/762">Fixed an issue where checkout failed to run in container jobs due to the new git setting <code>safe.directory</code></a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/744">Bumped various npm package versions</a></li> </ul> <h2>v3.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/689">Update to node 16</a></li> </ul> <h2>v2.3.1</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/c85c95e3d7251135ab7dc9ce3241c5835cc595a9"><code>c85c95e</code></a> Release v3.5.3 (<a href="https://redirect.github.com/actions/checkout/issues/1376">dart-lang/html#1376</a>)</li> <li><a href="https://github.com/actions/checkout/commit/d106d4669b3bfcb17f11f83f98e1cab478e9f635"><code>d106d46</code></a> Add support for sparse checkouts (<a href="https://redirect.github.com/actions/checkout/issues/1369">dart-lang/html#1369</a>)</li> <li><a href="https://github.com/actions/checkout/commit/f095bcc56b7c2baf48f3ac70d6d6782f4f553222"><code>f095bcc</code></a> Fix typos found by codespell (<a href="https://redirect.github.com/actions/checkout/issues/1287">dart-lang/html#1287</a>)</li> <li><a href="https://github.com/actions/checkout/commit/47fbe2df0ad0e27efb67a70beac3555f192b062f"><code>47fbe2d</code></a> Fix: Checkout fail in self-hosted runners when faulty submodule are checked-i...</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/8e5e7e5ab8b370d6c329ec480221332ada57f0ab...c85c95e3d7251135ab7dc9ce3241c5835cc595a9">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.2&new-version=3.5.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 96656cbc9..a123b0ef0 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, stable, dev] steps: - - uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab + - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 335cec303b8c0697015d704085572cb9a1445c4e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 1 Sep 2023 16:54:59 +0000 Subject: [PATCH 192/212] Bump actions/checkout from 3.5.3 to 3.6.0 (dart-lang/html#225) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.5.3 to 3.6.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v3.6.0</h2> <h2>What's Changed</h2> <ul> <li>Mark test scripts with Bash'isms to be run via Bash by <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1377">actions/checkoutdart-lang/html#1377</a></li> <li>Add option to fetch tags even if fetch-depth &gt; 0 by <a href="https://github.com/RobertWieczoreck"><code>@​RobertWieczoreck</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/579">actions/checkoutdart-lang/html#579</a></li> <li>Release 3.6.0 by <a href="https://github.com/luketomlinson"><code>@​luketomlinson</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1437">actions/checkoutdart-lang/html#1437</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/RobertWieczoreck"><code>@​RobertWieczoreck</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/579">actions/checkoutdart-lang/html#579</a></li> <li><a href="https://github.com/luketomlinson"><code>@​luketomlinson</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1437">actions/checkoutdart-lang/html#1437</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v3.5.3...v3.6.0">https://github.com/actions/checkout/compare/v3.5.3...v3.6.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1246">Fix slow checkout on Windows</a></li> </ul> <h2>v3.5.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1237">Add new public key for known_hosts</a></li> </ul> <h2>v3.4.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1209">Upgrade codeql actions to v2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1210">Upgrade dependencies</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1225">Upgrade <code>@​actions/io</code></a></li> </ul> <h2>v3.3.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1045">Implement branch list using callbacks from exec function</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1050">Add in explicit reference to private checkout options</a></li> <li>[Fix comment typos (that got added in <a href="https://redirect.github.com/actions/checkout/issues/770">dart-lang/html#770</a>)](<a href="https://redirect.github.com/actions/checkout/pull/1057">actions/checkoutdart-lang/html#1057</a>)</li> </ul> <h2>v3.2.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/942">Add GitHub Action to perform release</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/967">Fix status badge</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1002">Replace datadog/squid with ubuntu/squid Docker image</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/964">Wrap pipeline commands for submoduleForeach in quotes</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1029">Update <code>@​actions/io</code> to 1.1.2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1039">Upgrading version to 3.2.0</a></li> </ul> <h2>v3.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/939">Use <code>@​actions/core</code> <code>saveState</code> and <code>getState</code></a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/922">Add <code>github-server-url</code> input</a></li> </ul> <h2>v3.0.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/770">Add input <code>set-safe-directory</code></a></li> </ul> <h2>v3.0.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/762">Fixed an issue where checkout failed to run in container jobs due to the new git setting <code>safe.directory</code></a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/744">Bumped various npm package versions</a></li> </ul> <h2>v3.0.0</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/f43a0e5ff2bd294095638e18286ca9a3d1956744"><code>f43a0e5</code></a> Release 3.6.0 (<a href="https://redirect.github.com/actions/checkout/issues/1437">dart-lang/html#1437</a>)</li> <li><a href="https://github.com/actions/checkout/commit/7739b9ba2efcda9dde65ad1e3c2dbe65b41dfba7"><code>7739b9b</code></a> Add option to fetch tags even if fetch-depth &gt; 0 (<a href="https://redirect.github.com/actions/checkout/issues/579">dart-lang/html#579</a>)</li> <li><a href="https://github.com/actions/checkout/commit/96f53100ba2a5449eb71d2e6604bbcd94b9449b5"><code>96f5310</code></a> Mark test scripts with Bash'isms to be run via Bash (<a href="https://redirect.github.com/actions/checkout/issues/1377">dart-lang/html#1377</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/c85c95e3d7251135ab7dc9ce3241c5835cc595a9...f43a0e5ff2bd294095638e18286ca9a3d1956744">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.5.3&new-version=3.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index a123b0ef0..0294965be 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, stable, dev] steps: - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 + - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From f8be255778c3b353d8c14a4d9d5fb5a1ee1a7ba7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:49:13 +0000 Subject: [PATCH 193/212] Bump actions/checkout from 3.6.0 to 4.1.0 (dart-lang/html#227) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 3.6.0 to 4.1.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.0</h2> <h2>What's Changed</h2> <ul> <li>Update README.md for V4 by <a href="https://github.com/sivapalan"><code>@​sivapalan</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1452">actions/checkoutdart-lang/html#1452</a></li> <li>Add support for partial checkout filters by <a href="https://github.com/finleygn"><code>@​finleygn</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1396">actions/checkoutdart-lang/html#1396</a></li> <li>Prepare 4.1.0 release by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1496">actions/checkoutdart-lang/html#1496</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/sivapalan"><code>@​sivapalan</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1452">actions/checkoutdart-lang/html#1452</a></li> <li><a href="https://github.com/finleygn"><code>@​finleygn</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1396">actions/checkoutdart-lang/html#1396</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.0.0...v4.1.0">https://github.com/actions/checkout/compare/v4.0.0...v4.1.0</a></p> <h2>v4.0.0</h2> <h2>What's Changed</h2> <ul> <li>Update default runtime to node20 by <a href="https://github.com/takost"><code>@​takost</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1436">actions/checkoutdart-lang/html#1436</a></li> <li>Support fetching without the --progress option by <a href="https://github.com/simonbaird"><code>@​simonbaird</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1067">actions/checkoutdart-lang/html#1067</a></li> <li>Release 4.0.0 by <a href="https://github.com/takost"><code>@​takost</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1447">actions/checkoutdart-lang/html#1447</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/takost"><code>@​takost</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1436">actions/checkoutdart-lang/html#1436</a></li> <li><a href="https://github.com/simonbaird"><code>@​simonbaird</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1067">actions/checkoutdart-lang/html#1067</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v3...v4.0.0">https://github.com/actions/checkout/compare/v3...v4.0.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1246">Fix slow checkout on Windows</a></li> </ul> <h2>v3.5.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1237">Add new public key for known_hosts</a></li> </ul> <h2>v3.4.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1209">Upgrade codeql actions to v2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1210">Upgrade dependencies</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1225">Upgrade <code>@​actions/io</code></a></li> </ul> <h2>v3.3.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1045">Implement branch list using callbacks from exec function</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1050">Add in explicit reference to private checkout options</a></li> <li>[Fix comment typos (that got added in <a href="https://redirect.github.com/actions/checkout/issues/770">dart-lang/html#770</a>)](<a href="https://redirect.github.com/actions/checkout/pull/1057">actions/checkoutdart-lang/html#1057</a>)</li> </ul> <h2>v3.2.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/942">Add GitHub Action to perform release</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/967">Fix status badge</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1002">Replace datadog/squid with ubuntu/squid Docker image</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/964">Wrap pipeline commands for submoduleForeach in quotes</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1029">Update <code>@​actions/io</code> to 1.1.2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1039">Upgrading version to 3.2.0</a></li> </ul> <h2>v3.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/939">Use <code>@​actions/core</code> <code>saveState</code> and <code>getState</code></a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/922">Add <code>github-server-url</code> input</a></li> </ul> <h2>v3.0.2</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/8ade135a41bc03ea155e62e844d188df1ea18608"><code>8ade135</code></a> Prepare 4.1.0 release (<a href="https://redirect.github.com/actions/checkout/issues/1496">dart-lang/html#1496</a>)</li> <li><a href="https://github.com/actions/checkout/commit/c533a0a4cfc4962971818edcfac47a2899e69799"><code>c533a0a</code></a> Add support for partial checkout filters (<a href="https://redirect.github.com/actions/checkout/issues/1396">dart-lang/html#1396</a>)</li> <li><a href="https://github.com/actions/checkout/commit/72f2cec99f417b1a1c5e2e88945068983b7965f9"><code>72f2cec</code></a> Update README.md for V4 (<a href="https://redirect.github.com/actions/checkout/issues/1452">dart-lang/html#1452</a>)</li> <li><a href="https://github.com/actions/checkout/commit/3df4ab11eba7bda6032a0b82a6bb43b11571feac"><code>3df4ab1</code></a> Release 4.0.0 (<a href="https://redirect.github.com/actions/checkout/issues/1447">dart-lang/html#1447</a>)</li> <li><a href="https://github.com/actions/checkout/commit/8b5e8b768746b50394015010d25e690bfab9dfbc"><code>8b5e8b7</code></a> Support fetching without the --progress option (<a href="https://redirect.github.com/actions/checkout/issues/1067">dart-lang/html#1067</a>)</li> <li><a href="https://github.com/actions/checkout/commit/97a652b80035363df47baee5031ec8670b8878ac"><code>97a652b</code></a> Update default runtime to node20 (<a href="https://redirect.github.com/actions/checkout/issues/1436">dart-lang/html#1436</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/f43a0e5ff2bd294095638e18286ca9a3d1956744...8ade135a41bc03ea155e62e844d188df1ea18608">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=3.6.0&new-version=4.1.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 0294965be..20a39b5e9 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, stable, dev] steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 + - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f with: sdk: ${{ matrix.sdk }} From 91034b03e827e81b550cb1c84bf1514eb737e897 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:38:43 +0000 Subject: [PATCH 194/212] Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (dart-lang/html#228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.0 to 1.5.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/releases">dart-lang/setup-dart's releases</a>.</em></p> <blockquote> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md">dart-lang/setup-dart's changelog</a>.</em></p> <blockquote> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> <h2>v1.5.0</h2> <ul> <li>Re-wrote the implementation of the action into Dart.</li> <li>Auto-detect the platform architecture (<code>x64</code>, <code>ia32</code>, <code>arm</code>, <code>arm64</code>).</li> <li>Improved the caching and download resilience of the sdk.</li> <li>Added a new action output: <code>dart-version</code> - the installed version of the sdk.</li> </ul> <h2>v1.4.0</h2> <ul> <li>Automatically create OIDC token for pub.dev.</li> <li>Add a reusable workflow for publishing.</li> </ul> <h2>v1.3.0</h2> <ul> <li>The install location of the Dart SDK is now available in an environment variable, <code>DART_HOME</code> (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/43">dart-lang/html#43</a>).</li> <li>Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/35">dart-lang/html#35</a>).</li> </ul> <h2>v1.2.0</h2> <ul> <li>Fixed a path issue impacting git dependencies on Windows.</li> </ul> <h2>v1.1.0</h2> <ul> <li>Added a <code>flavor</code> option setup.sh to allow downloading unpublished builds.</li> </ul> <h2>v1.0.0</h2> <ul> <li>Promoted to 1.0 stable.</li> </ul> <h2>v0.5</h2> <ul> <li>Fixed a Windows <code>pub global activate</code> path issue.</li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dart-lang/setup-dart/commit/8a4b97ea2017cc079571daec46542f76189836b1"><code>8a4b97e</code></a> Support renaming the be channel to main. (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/102">dart-lang/html#102</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/0970dcf46e056fb521e7027775fdff076fe1e732"><code>0970dcf</code></a> Bump <code>@​actions/http-client</code> from 2.1.0 to 2.1.1 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/101">dart-lang/html#101</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/e58aeb62aef51dcc4d0ba8eada7c08092aad5314"><code>e58aeb6</code></a> updates for the latest version of extension types (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/100">dart-lang/html#100</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/deafe40ee7284c48e67c783c88eed8c8b52b19ca"><code>deafe40</code></a> Convert to extension types (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/99">dart-lang/html#99</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/cdb51fff2b088939ef86fe041b18e82cb4733522"><code>cdb51ff</code></a> Bump semver from 6.3.0 to 6.3.1 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/98">dart-lang/html#98</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/e2fce1213c49504e0029ade4bac39403dfc11fb3"><code>e2fce12</code></a> update JS interop - remove JS typedef references (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/97">dart-lang/html#97</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/42c988f214b6652e0b56ca2ad2f1d477bf6098b7"><code>42c988f</code></a> set up a cron to build the action's javascript (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/96">dart-lang/html#96</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/007c7cbb377cdbdf8922e2f8c4172dc60fbaaf9a"><code>007c7cb</code></a> blast_repo fixes (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/92">dart-lang/html#92</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/08de7e0c9a57cb3229b052af11c7f8eae4a845bd"><code>08de7e0</code></a> Remove annotations no longer needed (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/91">dart-lang/html#91</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/bd8bef0960777f45de11f484bcb7beacadb321cf"><code>bd8bef0</code></a> Bump dart-lang/setup-dart from 1.4.0 to 1.5.0 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/89">dart-lang/html#89</a>)</li> <li>Additional commits viewable in <a href="https://github.com/dart-lang/setup-dart/compare/d6a63dab3335f427404425de0fbfed4686d93c4f...8a4b97ea2017cc079571daec46542f76189836b1">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.0&new-version=1.5.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 20a39b5e9..68ac72251 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [2.19.0, stable, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@d6a63dab3335f427404425de0fbfed4686d93c4f + - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 with: sdk: ${{ matrix.sdk }} - id: install From 2f601aaa7991632d03a71b54251a87d553b22424 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:26:21 +0000 Subject: [PATCH 195/212] Bump dart-lang/setup-dart from 1.5.1 to 1.6.0 (dart-lang/html#233) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.5.1 to 1.6.0. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/releases">dart-lang/setup-dart's releases</a>.</em></p> <blockquote> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md">dart-lang/setup-dart's changelog</a>.</em></p> <blockquote> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> <h2>v1.5.0</h2> <ul> <li>Re-wrote the implementation of the action into Dart.</li> <li>Auto-detect the platform architecture (<code>x64</code>, <code>ia32</code>, <code>arm</code>, <code>arm64</code>).</li> <li>Improved the caching and download resilience of the sdk.</li> <li>Added a new action output: <code>dart-version</code> - the installed version of the sdk.</li> </ul> <h2>v1.4.0</h2> <ul> <li>Automatically create OIDC token for pub.dev.</li> <li>Add a reusable workflow for publishing.</li> </ul> <h2>v1.3.0</h2> <ul> <li>The install location of the Dart SDK is now available in an environment variable, <code>DART_HOME</code> (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/43">dart-lang/html#43</a>).</li> <li>Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/35">dart-lang/html#35</a>).</li> </ul> <h2>v1.2.0</h2> <ul> <li>Fixed a path issue impacting git dependencies on Windows.</li> </ul> <h2>v1.1.0</h2> <ul> <li>Added a <code>flavor</code> option setup.sh to allow downloading unpublished builds.</li> </ul> <h2>v1.0.0</h2> <ul> <li>Promoted to 1.0 stable.</li> </ul> <h2>v0.5</h2> <ul> <li>Fixed a Windows <code>pub global activate</code> path issue.</li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dart-lang/setup-dart/commit/b64355ae6ca0b5d484f0106a033dd1388965d06d"><code>b64355a</code></a> debugging issues around specifying the latest patch release (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/108">dart-lang/html#108</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/cd21d0e7475915575e022d2cacd7c54e5026e159"><code>cd21d0e</code></a> Bump dart-lang/setup-dart from 1.5.0 to 1.5.1 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/110">dart-lang/html#110</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/2118353f672662accb7785f6afd28ab61c7cfec9"><code>2118353</code></a> Bump actions/checkout from 3 to 4 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/109">dart-lang/html#109</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/8ef13bcca6c9bb2219391088bc9d968125f68406"><code>8ef13bc</code></a> support sdk version wildcard format (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/106">dart-lang/html#106</a>)</li> <li>See full diff in <a href="https://github.com/dart-lang/setup-dart/compare/8a4b97ea2017cc079571daec46542f76189836b1...b64355ae6ca0b5d484f0106a033dd1388965d06d">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.5.1&new-version=1.6.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 68ac72251..eb563aaec 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [2.19.0, stable, dev] steps: - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 - - uses: dart-lang/setup-dart@8a4b97ea2017cc079571daec46542f76189836b1 + - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} - id: install From 86af1fdbb426a56c7be9b4b2ad98d599f187d1fa Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 Nov 2023 16:31:00 +0000 Subject: [PATCH 196/212] Bump actions/checkout from 4.1.0 to 4.1.1 (dart-lang/html#232) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.0 to 4.1.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.1</h2> <h2>What's Changed</h2> <ul> <li>Update CODEOWNERS to Launch team by <a href="https://github.com/joshmgross"><code>@​joshmgross</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1510">actions/checkoutdart-lang/html#1510</a></li> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/joshmgross"><code>@​joshmgross</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1510">actions/checkoutdart-lang/html#1510</a></li> <li><a href="https://github.com/peterbe"><code>@​peterbe</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.0...v4.1.1">https://github.com/actions/checkout/compare/v4.1.0...v4.1.1</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/b4ffde65f46336ab88eb53be808477a3936bae11"><code>b4ffde6</code></a> Link to release page from what's new section (<a href="https://redirect.github.com/actions/checkout/issues/1514">dart-lang/html#1514</a>)</li> <li><a href="https://github.com/actions/checkout/commit/8530928916aaef40f59e6f221989ccb31f5759e7"><code>8530928</code></a> Correct link to GitHub Docs (<a href="https://redirect.github.com/actions/checkout/issues/1511">dart-lang/html#1511</a>)</li> <li><a href="https://github.com/actions/checkout/commit/7cdaf2fbc075e6f3b9ca94cfd6cec5adc8a75622"><code>7cdaf2f</code></a> Update CODEOWNERS to Launch team (<a href="https://redirect.github.com/actions/checkout/issues/1510">dart-lang/html#1510</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/8ade135a41bc03ea155e62e844d188df1ea18608...b4ffde65f46336ab88eb53be808477a3936bae11">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.0&new-version=4.1.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index eb563aaec..dd52d5d29 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [2.19.0, stable, dev] steps: - - uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 + - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d with: sdk: ${{ matrix.sdk }} From 8985ef5cee9747c60661ca1c1241c92363ebd0f7 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Thu, 25 Jan 2024 13:52:33 -0800 Subject: [PATCH 197/212] blast_repo fixes (dart-lang/html#235) auto-publish, github-actions, no-response --- pkgs/html/.github/workflows/no-response.yml | 37 ++++++++++++++++++++ pkgs/html/.github/workflows/publish.yaml | 17 +++++++++ pkgs/html/.github/workflows/test-package.yml | 4 +-- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 pkgs/html/.github/workflows/no-response.yml create mode 100644 pkgs/html/.github/workflows/publish.yaml diff --git a/pkgs/html/.github/workflows/no-response.yml b/pkgs/html/.github/workflows/no-response.yml new file mode 100644 index 000000000..ab1ac4984 --- /dev/null +++ b/pkgs/html/.github/workflows/no-response.yml @@ -0,0 +1,37 @@ +# A workflow to close issues where the author hasn't responded to a request for +# more information; see https://github.com/actions/stale. + +name: No Response + +# Run as a daily cron. +on: + schedule: + # Every day at 8am + - cron: '0 8 * * *' + +# All permissions not specified are set to 'none'. +permissions: + issues: write + pull-requests: write + +jobs: + no-response: + runs-on: ubuntu-latest + if: ${{ github.repository_owner == 'dart-lang' }} + steps: + - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e + with: + # Don't automatically mark inactive issues+PRs as stale. + days-before-stale: -1 + # Close needs-info issues and PRs after 14 days of inactivity. + days-before-close: 14 + stale-issue-label: "needs-info" + close-issue-message: > + Without additional information we're not able to resolve this issue. + Feel free to add more info or respond to any questions above and we + can reopen the case. Thanks for your contribution! + stale-pr-label: "needs-info" + close-pr-message: > + Without additional information we're not able to resolve this PR. + Feel free to add more info or respond to any questions above. + Thanks for your contribution! diff --git a/pkgs/html/.github/workflows/publish.yaml b/pkgs/html/.github/workflows/publish.yaml new file mode 100644 index 000000000..1cb7e9cfb --- /dev/null +++ b/pkgs/html/.github/workflows/publish.yaml @@ -0,0 +1,17 @@ +# A CI configuration to auto-publish pub packages. + +name: Publish + +on: + pull_request: + branches: [ main ] + push: + tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] + +jobs: + publish: + if: ${{ github.repository_owner == 'dart-lang' }} + uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main + permissions: + id-token: write # Required for authentication using OIDC + pull-requests: write # Required for writing the pull request note diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index dd52d5d29..aa34b6bb2 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [2.19.0, stable, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d + - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b with: sdk: ${{ matrix.sdk }} - id: install From 5a099778e8c751a1a104d2ce0de3a358310729bc Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Fri, 26 Jan 2024 09:15:50 -0800 Subject: [PATCH 198/212] Update lints, require Dart 3.2 (dart-lang/html#236) --- pkgs/html/.github/workflows/test-package.yml | 2 +- pkgs/html/CHANGELOG.md | 1 + pkgs/html/lib/dom.dart | 2 +- pkgs/html/lib/dom_parsing.dart | 26 +++++------ pkgs/html/lib/parser.dart | 46 ++++++++++---------- pkgs/html/lib/src/constants.dart | 25 ++++------- pkgs/html/lib/src/css_class_set.dart | 2 +- pkgs/html/lib/src/html_input_stream.dart | 16 +++---- pkgs/html/lib/src/query_selector.dart | 33 ++++++-------- pkgs/html/lib/src/token.dart | 8 ++-- pkgs/html/lib/src/tokenizer.dart | 2 +- pkgs/html/lib/src/treebuilder.dart | 4 +- pkgs/html/pubspec.yaml | 6 +-- 13 files changed, 75 insertions(+), 98 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index aa34b6bb2..8e69bc421 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -32,7 +32,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest] - sdk: [2.19.0, stable, dev] + sdk: [3.2, stable, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index fa79fbcf1..c0d6cb501 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,5 +1,6 @@ ## 0.15.5-wip +- Require Dart `3.2`. ## 0.15.4 diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 5b8f8c97c..733362a0e 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -112,7 +112,7 @@ mixin _NonElementParentNode implements _ParentNode { // common methods from these: // http://dom.spec.whatwg.org/#interface-document // http://dom.spec.whatwg.org/#element -abstract class _ElementAndDocument implements _ParentNode { +abstract mixin class _ElementAndDocument implements _ParentNode { // TODO(jmesserly): could be faster, should throw on invalid tag/class names. List<Element> getElementsByTagName(String localName) => diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 35c8dc7b2..5cf3cab7f 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -12,22 +12,16 @@ export 'html_escape.dart'; /// A simple tree visitor for the DOM nodes. class TreeVisitor { void visit(Node node) { - switch (node.nodeType) { - case Node.ELEMENT_NODE: - return visitElement(node as Element); - case Node.TEXT_NODE: - return visitText(node as Text); - case Node.COMMENT_NODE: - return visitComment(node as Comment); - case Node.DOCUMENT_FRAGMENT_NODE: - return visitDocumentFragment(node as DocumentFragment); - case Node.DOCUMENT_NODE: - return visitDocument(node as Document); - case Node.DOCUMENT_TYPE_NODE: - return visitDocumentType(node as DocumentType); - default: - throw UnsupportedError('DOM node type ${node.nodeType}'); - } + return switch (node.nodeType) { + Node.ELEMENT_NODE => visitElement(node as Element), + Node.TEXT_NODE => visitText(node as Text), + Node.COMMENT_NODE => visitComment(node as Comment), + Node.DOCUMENT_FRAGMENT_NODE => + visitDocumentFragment(node as DocumentFragment), + Node.DOCUMENT_NODE => visitDocument(node as Document), + Node.DOCUMENT_TYPE_NODE => visitDocumentType(node as DocumentType), + _ => throw UnsupportedError('DOM node type ${node.nodeType}') + }; } void visitChildren(Node node) { diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 3eb7a9722..3c6340a26 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -633,7 +633,7 @@ class Phase { } class InitialPhase extends Phase { - InitialPhase(HtmlParser parser) : super(parser); + InitialPhase(super.parser); @override Token? processSpaceCharacters(SpaceCharactersToken token) { @@ -788,7 +788,7 @@ class InitialPhase extends Phase { } class BeforeHtmlPhase extends Phase { - BeforeHtmlPhase(HtmlParser parser) : super(parser); + BeforeHtmlPhase(super.parser); // helper methods void insertHtmlElement() { @@ -849,7 +849,7 @@ class BeforeHtmlPhase extends Phase { } class BeforeHeadPhase extends Phase { - BeforeHeadPhase(HtmlParser parser) : super(parser); + BeforeHeadPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -923,7 +923,7 @@ class BeforeHeadPhase extends Phase { } class InHeadPhase extends Phase { - InHeadPhase(HtmlParser parser) : super(parser); + InHeadPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -1070,7 +1070,7 @@ class InHeadPhase extends Phase { // class InHeadNoScriptPhase extends Phase { class AfterHeadPhase extends Phase { - AfterHeadPhase(HtmlParser parser) : super(parser); + AfterHeadPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -1189,7 +1189,7 @@ class InBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///parsing-main-inbody // the really-really-really-very crazy mode - InBodyPhase(HtmlParser parser) : super(parser); + InBodyPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -2227,7 +2227,7 @@ class InBodyPhase extends Phase { } class TextPhase extends Phase { - TextPhase(HtmlParser parser) : super(parser); + TextPhase(super.parser); // "Tried to process start tag %s in RCDATA/RAWTEXT mode"%token.name @override @@ -2277,7 +2277,7 @@ class TextPhase extends Phase { class InTablePhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table - InTablePhase(HtmlParser parser) : super(parser); + InTablePhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -2507,9 +2507,7 @@ class InTableTextPhase extends Phase { Phase? originalPhase; List<StringToken> characterTokens; - InTableTextPhase(HtmlParser parser) - : characterTokens = <StringToken>[], - super(parser); + InTableTextPhase(super.parser) : characterTokens = <StringToken>[]; void flushCharacters() { if (characterTokens.isEmpty) return; @@ -2578,7 +2576,7 @@ class InTableTextPhase extends Phase { class InCaptionPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-caption - InCaptionPhase(HtmlParser parser) : super(parser); + InCaptionPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -2700,7 +2698,7 @@ class InCaptionPhase extends Phase { class InColumnGroupPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-column - InColumnGroupPhase(HtmlParser parser) : super(parser); + InColumnGroupPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -2788,7 +2786,7 @@ class InColumnGroupPhase extends Phase { class InTableBodyPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-table0 - InTableBodyPhase(HtmlParser parser) : super(parser); + InTableBodyPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -2927,7 +2925,7 @@ class InTableBodyPhase extends Phase { class InRowPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-row - InRowPhase(HtmlParser parser) : super(parser); + InRowPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3073,7 +3071,7 @@ class InRowPhase extends Phase { class InCellPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-cell - InCellPhase(HtmlParser parser) : super(parser); + InCellPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3197,7 +3195,7 @@ class InCellPhase extends Phase { } class InSelectPhase extends Phase { - InSelectPhase(HtmlParser parser) : super(parser); + InSelectPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3353,7 +3351,7 @@ class InSelectPhase extends Phase { } class InSelectInTablePhase extends Phase { - InSelectInTablePhase(HtmlParser parser) : super(parser); + InSelectInTablePhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3479,7 +3477,7 @@ class InForeignContentPhase extends Phase { 'var' ]; - InForeignContentPhase(HtmlParser parser) : super(parser); + InForeignContentPhase(super.parser); void adjustSVGTagNames(StartTagToken token) { final replacements = const { @@ -3609,7 +3607,7 @@ class InForeignContentPhase extends Phase { } class AfterBodyPhase extends Phase { - AfterBodyPhase(HtmlParser parser) : super(parser); + AfterBodyPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3681,7 +3679,7 @@ class AfterBodyPhase extends Phase { class InFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///in-frameset - InFramesetPhase(HtmlParser parser) : super(parser); + InFramesetPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3774,7 +3772,7 @@ class InFramesetPhase extends Phase { class AfterFramesetPhase extends Phase { // http://www.whatwg.org/specs/web-apps/current-work///after3 - AfterFramesetPhase(HtmlParser parser) : super(parser); + AfterFramesetPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3831,7 +3829,7 @@ class AfterFramesetPhase extends Phase { } class AfterAfterBodyPhase extends Phase { - AfterAfterBodyPhase(HtmlParser parser) : super(parser); + AfterAfterBodyPhase(super.parser); @override Token? processStartTag(StartTagToken token) { @@ -3882,7 +3880,7 @@ class AfterAfterBodyPhase extends Phase { } class AfterAfterFramesetPhase extends Phase { - AfterAfterFramesetPhase(HtmlParser parser) : super(parser); + AfterAfterFramesetPhase(super.parser); @override Token? processStartTag(StartTagToken token) { diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index 5c41f81ea..abd483bbe 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -246,22 +246,15 @@ class Namespaces { Namespaces._(); static String? getPrefix(String? url) { - switch (url) { - case html: - return 'html'; - case mathml: - return 'math'; - case svg: - return 'svg'; - case xlink: - return 'xlink'; - case xml: - return 'xml'; - case xmlns: - return 'xmlns'; - default: - return null; - } + return switch (url) { + html => 'html', + mathml => 'math', + svg => 'svg', + xlink => 'xlink', + xml => 'xml', + xmlns => 'xmlns', + _ => null + }; } } diff --git a/pkgs/html/lib/src/css_class_set.dart b/pkgs/html/lib/src/css_class_set.dart index 508fd2b8f..deca7a541 100644 --- a/pkgs/html/lib/src/css_class_set.dart +++ b/pkgs/html/lib/src/css_class_set.dart @@ -6,7 +6,7 @@ import 'dart:collection'; -import 'package:html/dom.dart'; +import '../dom.dart'; class ElementCssClassSet extends _CssClassSetImpl { final Element _element; diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index 1c1bcc8b4..abae4cfb8 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -329,16 +329,12 @@ bool _hasUtf8Bom(List<int> bytes, [int offset = 0, int? length]) { /// the codepoints. Supports the major unicode encodings as well as ascii and /// and windows-1252 encodings. List<int> _decodeBytes(String encoding, List<int> bytes) { - switch (encoding) { - case 'ascii': - return ascii.decode(bytes).codeUnits; - - case 'utf-8': + return switch (encoding) { + 'ascii' => ascii.decode(bytes).codeUnits, + 'utf-8' => // NOTE: To match the behavior of the other decode functions, we eat the // UTF-8 BOM here. This is the default behavior of `utf8.decode`. - return utf8.decode(bytes).codeUnits; - - default: - throw ArgumentError('Encoding $encoding not supported'); - } + utf8.decode(bytes).codeUnits, + _ => throw ArgumentError('Encoding $encoding not supported') + }; } diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index c45d11c3e..96fe4d2ad 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -3,8 +3,9 @@ library html.src.query; import 'package:csslib/parser.dart'; import 'package:csslib/visitor.dart'; -import 'package:html/dom.dart'; -import 'package:html/src/constants.dart' show isWhitespaceCC; + +import '../dom.dart'; +import 'constants.dart' show isWhitespaceCC; bool matches(Element node, String selector) => SelectorEvaluator().matches(node, _parseSelectorList(selector)); @@ -284,22 +285,16 @@ class SelectorEvaluator extends Visitor { if (node.operatorKind == TokenKind.NO_MATCH) return true; final select = '${node.value}'; - switch (node.operatorKind) { - case TokenKind.EQUALS: - return value == select; - case TokenKind.INCLUDES: - return value.split(' ').any((v) => v.isNotEmpty && v == select); - case TokenKind.DASH_MATCH: - return value.startsWith(select) && - (value.length == select.length || value[select.length] == '-'); - case TokenKind.PREFIX_MATCH: - return value.startsWith(select); - case TokenKind.SUFFIX_MATCH: - return value.endsWith(select); - case TokenKind.SUBSTRING_MATCH: - return value.contains(select); - default: - throw _unsupported(node); - } + return switch (node.operatorKind) { + TokenKind.EQUALS => value == select, + TokenKind.INCLUDES => + value.split(' ').any((v) => v.isNotEmpty && v == select), + TokenKind.DASH_MATCH => value.startsWith(select) && + (value.length == select.length || value[select.length] == '-'), + TokenKind.PREFIX_MATCH => value.startsWith(select), + TokenKind.SUFFIX_MATCH => value.endsWith(select), + TokenKind.SUBSTRING_MATCH => value.contains(select), + _ => throw _unsupported(node) + }; } } diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index 7a4e7431f..bbcec2601 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -77,14 +77,14 @@ class ParseErrorToken extends StringToken { /// Extra information that goes along with the error message. Map<String, Object?>? messageParams; - ParseErrorToken(String data, {this.messageParams}) : super(data); + ParseErrorToken(String super.data, {this.messageParams}); @override int get kind => TokenKind.parseError; } class CharactersToken extends StringToken { - CharactersToken([String? data]) : super(data); + CharactersToken([super.data]); @override int get kind => TokenKind.characters; @@ -98,14 +98,14 @@ class CharactersToken extends StringToken { } class SpaceCharactersToken extends StringToken { - SpaceCharactersToken([String? data]) : super(data); + SpaceCharactersToken([super.data]); @override int get kind => TokenKind.spaceCharacters; } class CommentToken extends StringToken { - CommentToken([String? data]) : super(data); + CommentToken([super.data]); @override int get kind => TokenKind.comment; diff --git a/pkgs/html/lib/src/tokenizer.dart b/pkgs/html/lib/src/tokenizer.dart index b1bfa36c3..3bed0b0b6 100644 --- a/pkgs/html/lib/src/tokenizer.dart +++ b/pkgs/html/lib/src/tokenizer.dart @@ -1,6 +1,6 @@ import 'dart:collection'; -import 'package:html/parser.dart' show HtmlParser; +import '../parser.dart' show HtmlParser; import 'constants.dart'; import 'html_input_stream.dart'; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index 3e39700ce..a7a8e8290 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -3,10 +3,10 @@ library treebuilder; import 'dart:collection'; -import 'package:html/dom.dart'; -import 'package:html/parser.dart' show getElementNameTuple; import 'package:source_span/source_span.dart'; +import '../dom.dart'; +import '../parser.dart' show getElementNameTuple; import 'constants.dart'; import 'list_proxy.dart'; import 'token.dart'; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index e73d47995..5824b768d 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -8,13 +8,13 @@ topics: - web environment: - sdk: '>=2.19.0 <4.0.0' + sdk: ^3.2.0 dependencies: - csslib: '>=0.17.0 <2.0.0' + csslib: ^1.0.0 source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^1.0.0 + dart_flutter_team_lints: ^2.0.0 path: ^1.8.0 test: ^1.16.0 From 6c321c7e9faedaf4652ed1a98562e930655727f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:23:20 +0000 Subject: [PATCH 199/212] Bump dart-lang/setup-dart from 1.6.1 to 1.6.2 (dart-lang/html#237) Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.1 to 1.6.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/releases">dart-lang/setup-dart's releases</a>.</em></p> <blockquote> <h2>v1.6.2</h2> <ul> <li>Switch to running the workflow on <code>node20</code> from <code>node16</code>. See also <a href="https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/">Transitioning from Node 16 to Node 20</a>.</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md">dart-lang/setup-dart's changelog</a>.</em></p> <blockquote> <h2>v1.6.2</h2> <ul> <li>Switch to running the workflow on <code>node20`` from </code>node16`. See also <a href="https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/">Transitioning from Node 16 to Node 20</a>.</li> </ul> <h2>v1.6.1</h2> <ul> <li>Updated the google storage url for <code>main</code> channel releases.</li> </ul> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> <h2>v1.5.0</h2> <ul> <li>Re-wrote the implementation of the action into Dart.</li> <li>Auto-detect the platform architecture (<code>x64</code>, <code>ia32</code>, <code>arm</code>, <code>arm64</code>).</li> <li>Improved the caching and download resilience of the sdk.</li> <li>Added a new action output: <code>dart-version</code> - the installed version of the sdk.</li> </ul> <h2>v1.4.0</h2> <ul> <li>Automatically create OIDC token for pub.dev.</li> <li>Add a reusable workflow for publishing.</li> </ul> <h2>v1.3.0</h2> <ul> <li>The install location of the Dart SDK is now available in an environment variable, <code>DART_HOME</code> (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/43">dart-lang/html#43</a>).</li> <li>Fixed an issue where cached downloads could lead to unzip issues on self-hosted runners (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/35">dart-lang/html#35</a>).</li> </ul> <h2>v1.2.0</h2> <ul> <li>Fixed a path issue impacting git dependencies on Windows.</li> </ul> <h2>v1.1.0</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dart-lang/setup-dart/commit/fedb1266e91cf51be2fdb382869461a434b920a3"><code>fedb126</code></a> switch to using node20 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/122">dart-lang/html#122</a>)</li> <li>See full diff in <a href="https://github.com/dart-lang/setup-dart/compare/ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b...fedb1266e91cf51be2fdb382869461a434b920a3">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.1&new-version=1.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 8e69bc421..0a520fb20 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [3.2, stable, dev] steps: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - - uses: dart-lang/setup-dart@ca7e6fee45ffbd82b555a7ebfc236d2c86439f5b + - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} - id: install From 15f4177010e2ab0ae30a4d861ae5e19e47dcfd51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Apr 2024 16:35:19 +0000 Subject: [PATCH 200/212] Bump actions/checkout from 4.1.1 to 4.1.2 (dart-lang/html#239) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.1 to 4.1.2. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.2</h2> <p>We are investigating the following issue with this release and have rolled-back the <code>v4</code> tag to point to <code>v4.1.1</code></p> <ul> <li><code>sparse-checkout</code> is not available on git versions prior to 2.27.0 (see <a href="https://redirect.github.com/actions/checkout/issues/1651">actions/checkoutdart-lang/html#1651</a>)</li> </ul> <h2>What's Changed</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> <li>Bump tough-cookie from 4.0.0 to 4.1.3 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1406">actions/checkoutdart-lang/html#1406</a></li> <li>Bump <code>@​babel/traverse</code> from 7.20.5 to 7.24.0 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1642">actions/checkoutdart-lang/html#1642</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/jww3"><code>@​jww3</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1616">actions/checkoutdart-lang/html#1616</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.1...v4.1.2">https://github.com/actions/checkout/compare/v4.1.1...v4.1.2</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.1.2</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> </ul> <h2>v4.1.1</h2> <ul> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1246">Fix slow checkout on Windows</a></li> </ul> <h2>v3.5.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1237">Add new public key for known_hosts</a></li> </ul> <h2>v3.4.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1209">Upgrade codeql actions to v2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1210">Upgrade dependencies</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1225">Upgrade <code>@​actions/io</code></a></li> </ul> <h2>v3.3.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1045">Implement branch list using callbacks from exec function</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1050">Add in explicit reference to private checkout options</a></li> <li>[Fix comment typos (that got added in <a href="https://redirect.github.com/actions/checkout/issues/770">dart-lang/html#770</a>)](<a href="https://redirect.github.com/actions/checkout/pull/1057">actions/checkoutdart-lang/html#1057</a>)</li> </ul> <h2>v3.2.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/942">Add GitHub Action to perform release</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/967">Fix status badge</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1002">Replace datadog/squid with ubuntu/squid Docker image</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/964">Wrap pipeline commands for submoduleForeach in quotes</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1029">Update <code>@​actions/io</code> to 1.1.2</a></li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/9bb56186c3b09b4f86b1c65136769dd318469633"><code>9bb5618</code></a> Prep for release of v4.1.2 (<a href="https://redirect.github.com/actions/checkout/issues/1649">dart-lang/html#1649</a>)</li> <li><a href="https://github.com/actions/checkout/commit/8eb1f6a495037164bea451156472f35fdd6bafc0"><code>8eb1f6a</code></a> Bump <code>@​babel/traverse</code> from 7.20.5 to 7.24.0 (<a href="https://redirect.github.com/actions/checkout/issues/1642">dart-lang/html#1642</a>)</li> <li><a href="https://github.com/actions/checkout/commit/556e4c3cb0b8b54b734286d5439adadcb0a8cb92"><code>556e4c3</code></a> Bump tough-cookie from 4.0.0 to 4.1.3 (<a href="https://redirect.github.com/actions/checkout/issues/1406">dart-lang/html#1406</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b32f140b0c872d58512e0a66172253c302617b90"><code>b32f140</code></a> Warn on attempts to publish <code>test-ubuntu-git</code> from non-main branch. (<a href="https://redirect.github.com/actions/checkout/issues/1623">dart-lang/html#1623</a>)</li> <li><a href="https://github.com/actions/checkout/commit/2650dbd060003e3b5ae211e4358852f336b682a7"><code>2650dbd</code></a> Give <code>test-ubuntu-git</code> its own <code>README</code> (<a href="https://redirect.github.com/actions/checkout/issues/1620">dart-lang/html#1620</a>)</li> <li><a href="https://github.com/actions/checkout/commit/aadec899646c8e0f34c52d9219c2faac36626b55"><code>aadec89</code></a> Explicitly disable sparse checkout unless asked for (<a href="https://redirect.github.com/actions/checkout/issues/1598">dart-lang/html#1598</a>)</li> <li><a href="https://github.com/actions/checkout/commit/df0bcddf6d6823307c716b56a7ef9c3b25078874"><code>df0bcdd</code></a> Refine workflow for generating <code>test-ubuntu-git</code> (<a href="https://redirect.github.com/actions/checkout/issues/1617">dart-lang/html#1617</a>)</li> <li><a href="https://github.com/actions/checkout/commit/473055ba18d6d2da209cd46110aadb9275e3194e"><code>473055b</code></a> Create <code>test-ubuntu-git</code> Docker Container for Proxy Tests (<a href="https://redirect.github.com/actions/checkout/issues/1616">dart-lang/html#1616</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/b4ffde65f46336ab88eb53be808477a3936bae11...9bb56186c3b09b4f86b1c65136769dd318469633">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.1&new-version=4.1.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 0a520fb20..51e6b3324 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 + - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 with: sdk: ${{ matrix.sdk }} From 83030027c9e989b4619fdd39b120b5bd5d027243 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:29:17 +0000 Subject: [PATCH 201/212] Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (dart-lang/html#242) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart) from 1.6.2 to 1.6.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/releases">dart-lang/setup-dart's releases</a>.</em></p> <blockquote> <h2>v1.6.4</h2> <ul> <li>Rebuild JS code to include changes from v1.6.3</li> </ul> <h2>v1.6.3</h2> <ul> <li>Roll <code>undici</code> dependency to address <a href="https://github.com/nodejs/undici/security/advisories/GHSA-m4v8-wqvr-p9f7">CVE-2024-30260</a> and <a href="https://github.com/nodejs/undici/security/advisories/GHSA-9qxr-qj54-h672">CVE-2024-30261</a>.</li> </ul> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md">dart-lang/setup-dart's changelog</a>.</em></p> <blockquote> <h2>v1.6.4</h2> <ul> <li>Rebuild JS code.</li> </ul> <h2>v1.6.3</h2> <ul> <li>Roll <code>undici</code> dependency to address <a href="https://github.com/nodejs/undici/security/advisories/GHSA-m4v8-wqvr-p9f7">CVE-2024-30260</a> and <a href="https://github.com/nodejs/undici/security/advisories/GHSA-9qxr-qj54-h672">CVE-2024-30261</a>.</li> </ul> <h2>v1.6.2</h2> <ul> <li>Switch to running the workflow on <code>node20`` from </code>node16`. See also <a href="https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/">Transitioning from Node 16 to Node 20</a>.</li> </ul> <h2>v1.6.1</h2> <ul> <li>Updated the google storage url for <code>main</code> channel releases.</li> </ul> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> <h2>v1.5.0</h2> <ul> <li>Re-wrote the implementation of the action into Dart.</li> <li>Auto-detect the platform architecture (<code>x64</code>, <code>ia32</code>, <code>arm</code>, <code>arm64</code>).</li> <li>Improved the caching and download resilience of the sdk.</li> <li>Added a new action output: <code>dart-version</code> - the installed version of the sdk.</li> </ul> <h2>v1.4.0</h2> <ul> <li>Automatically create OIDC token for pub.dev.</li> <li>Add a reusable workflow for publishing.</li> </ul> <h2>v1.3.0</h2> <ul> <li>The install location of the Dart SDK is now available</li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dart-lang/setup-dart/commit/f0ead981b4d9a35b37f30d36160575d60931ec30"><code>f0ead98</code></a> Rebuild JS code (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/129">dart-lang/html#129</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/65c82982aa686933bf10d50aced7a27b2b63f2a6"><code>65c8298</code></a> Update CHANGELOG.md (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/128">dart-lang/html#128</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/57338d64c065775c2cf86eaf665316ea44e0249d"><code>57338d6</code></a> Bump undici from 5.28.3 to 5.28.4 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/127">dart-lang/html#127</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/05d3f5ec28dca4e3ae8991f2be7828a62942f8a8"><code>05d3f5e</code></a> Bump <code>@​actions/http-client</code> from 2.2.0 to 2.2.1 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/126">dart-lang/html#126</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/b8c0b77d1f6fb52c5ddff2fc3da6cfa3f9585860"><code>b8c0b77</code></a> no longer specify the inline-class experiment flag (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/125">dart-lang/html#125</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/b9952d818df9b43bab696de0e1b7bbf09464a829"><code>b9952d8</code></a> Bump undici from 5.27.0 to 5.28.3 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/124">dart-lang/html#124</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/9a6ee8904aa6a1fa76b02bb3e7b0ec30cddcaaac"><code>9a6ee89</code></a> Bump dart-lang/setup-dart from 1.6.0 to 1.6.2 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/123">dart-lang/html#123</a>)</li> <li>See full diff in <a href="https://github.com/dart-lang/setup-dart/compare/fedb1266e91cf51be2fdb382869461a434b920a3...f0ead981b4d9a35b37f30d36160575d60931ec30">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=dart-lang/setup-dart&package-manager=github_actions&previous-version=1.6.2&new-version=1.6.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 51e6b3324..9cf5e87cd 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -15,7 +15,7 @@ jobs: fail-fast: false steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: dev - id: install @@ -35,7 +35,7 @@ jobs: sdk: [3.2, stable, dev] steps: - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 - - uses: dart-lang/setup-dart@fedb1266e91cf51be2fdb382869461a434b920a3 + - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} - id: install From 4a63f3360d7544c37166fc1b68898df5f38e38dc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 1 May 2024 16:33:19 +0000 Subject: [PATCH 202/212] Bump actions/checkout from 4.1.2 to 4.1.4 (dart-lang/html#241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚠️ **Dependabot is rebasing this PR** ⚠️ Rebasing might not happen immediately, so don't worry if this takes some time. Note: if you make any changes to this PR yourself, they will take precedence over the rebase. --- Bumps [actions/checkout](https://github.com/actions/checkout) from 4.1.2 to 4.1.4. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.4</h2> <h2>What's Changed</h2> <ul> <li>Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkoutdart-lang/html#1692</a></li> <li>Add dependabot config by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkoutdart-lang/html#1688</a></li> <li>Bump word-wrap from 1.2.3 to 1.2.5 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkoutdart-lang/html#1643</a></li> <li>Bump the minor-actions-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkoutdart-lang/html#1693</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.3...v4.1.4">https://github.com/actions/checkout/compare/v4.1.3...v4.1.4</a></p> <h2>v4.1.3</h2> <h2>What's Changed</h2> <ul> <li>Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1650">actions/checkoutdart-lang/html#1650</a></li> <li>Check git version before attempting to disable <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1656">actions/checkoutdart-lang/html#1656</a></li> <li>Add SSH user parameter by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1685">actions/checkoutdart-lang/html#1685</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.2...v4.1.3">https://github.com/actions/checkout/compare/v4.1.2...v4.1.3</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.1.4</h2> <ul> <li>Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkoutdart-lang/html#1692</a></li> <li>Add dependabot config by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkoutdart-lang/html#1688</a></li> <li>Bump the minor-actions-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkoutdart-lang/html#1693</a></li> <li>Bump word-wrap from 1.2.3 to 1.2.5 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkoutdart-lang/html#1643</a></li> </ul> <h2>v4.1.3</h2> <ul> <li>Check git version before attempting to disable <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1656">actions/checkoutdart-lang/html#1656</a></li> <li>Add SSH user parameter by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1685">actions/checkoutdart-lang/html#1685</a></li> <li>Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1650">actions/checkoutdart-lang/html#1650</a></li> </ul> <h2>v4.1.2</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> </ul> <h2>v4.1.1</h2> <ul> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1246">Fix slow checkout on Windows</a></li> </ul> <h2>v3.5.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1237">Add new public key for known_hosts</a></li> </ul> <h2>v3.4.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1209">Upgrade codeql actions to v2</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1210">Upgrade dependencies</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1225">Upgrade <code>@​actions/io</code></a></li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/0ad4b8fadaa221de15dcec353f45205ec38ea70b"><code>0ad4b8f</code></a> Prep Release v4.1.4 (<a href="https://redirect.github.com/actions/checkout/issues/1704">dart-lang/html#1704</a>)</li> <li><a href="https://github.com/actions/checkout/commit/43045ae669be728bd34ed56fcd1a230c0dc4d8e2"><code>43045ae</code></a> Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> (<a href="https://redirect.github.com/actions/checkout/issues/1692">dart-lang/html#1692</a>)</li> <li><a href="https://github.com/actions/checkout/commit/37b082107ba410260a3aaddf93122e04801ce631"><code>37b0821</code></a> Bump the minor-actions-dependencies group with 2 updates (<a href="https://redirect.github.com/actions/checkout/issues/1693">dart-lang/html#1693</a>)</li> <li><a href="https://github.com/actions/checkout/commit/9839dc14a02ddc6b6995e69eb3ecb98132fc8b6b"><code>9839dc1</code></a> Add dependabot config (<a href="https://redirect.github.com/actions/checkout/issues/1688">dart-lang/html#1688</a>)</li> <li><a href="https://github.com/actions/checkout/commit/9b4c13b0bfa31b4514c14f74b5a166c2708f43c6"><code>9b4c13b</code></a> Bump word-wrap from 1.2.3 to 1.2.5 (<a href="https://redirect.github.com/actions/checkout/issues/1643">dart-lang/html#1643</a>)</li> <li><a href="https://github.com/actions/checkout/commit/1d96c772d19495a3b5c517cd2bc0cb401ea0529f"><code>1d96c77</code></a> Add SSH user parameter (<a href="https://redirect.github.com/actions/checkout/issues/1685">dart-lang/html#1685</a>)</li> <li><a href="https://github.com/actions/checkout/commit/cd7d8d697e10461458bc61a30d094dc601a8b017"><code>cd7d8d6</code></a> Check git version before attempting to disable <code>sparse-checkout</code> (<a href="https://redirect.github.com/actions/checkout/issues/1656">dart-lang/html#1656</a>)</li> <li><a href="https://github.com/actions/checkout/commit/8410ad0602e1e429cee44a835ae9f77f654a6694"><code>8410ad0</code></a> Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> (<a href="https://redirect.github.com/actions/checkout/issues/1650">dart-lang/html#1650</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/9bb56186c3b09b4f86b1c65136769dd318469633...0ad4b8fadaa221de15dcec353f45205ec38ea70b">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.2&new-version=4.1.4)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 9cf5e87cd..3ea3bc763 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 + - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 8091fdf65c5e1869a4386990f84bbbd8ca6f7bba Mon Sep 17 00:00:00 2001 From: Devon Carew <devoncarew@google.com> Date: Mon, 6 May 2024 15:05:30 -0700 Subject: [PATCH 203/212] blast_repo fixes (dart-lang/html#244) dependabot --- pkgs/html/.github/dependabot.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml index 725f03af2..cde02ad6a 100644 --- a/pkgs/html/.github/dependabot.yml +++ b/pkgs/html/.github/dependabot.yml @@ -9,3 +9,7 @@ updates: interval: monthly labels: - autosubmit + groups: + github-actions: + patterns: + - "*" From 60f83a27e93724b63e7939cdf521680fa2231b5b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 May 2024 22:07:38 +0000 Subject: [PATCH 204/212] Bump actions/checkout from 4.1.4 to 4.1.5 in the github-actions group (dart-lang/html#245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.4 to 4.1.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.5</h2> <h2>What's Changed</h2> <ul> <li>Update NPM dependencies by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkoutdart-lang/html#1703</a></li> <li>Bump github/codeql-action from 2 to 3 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkoutdart-lang/html#1694</a></li> <li>Bump actions/setup-node from 1 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkoutdart-lang/html#1696</a></li> <li>Bump actions/upload-artifact from 2 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkoutdart-lang/html#1695</a></li> <li>README: Suggest <code>user.email</code> to be <code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkoutdart-lang/html#1707</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.4...v4.1.5">https://github.com/actions/checkout/compare/v4.1.4...v4.1.5</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b"><code>44c2b7a</code></a> README: Suggest <code>user.email</code> to be `41898282+github-actions[bot]<a href="https://github.com/users"><code>@​users</code></a>.norepl...</li> <li><a href="https://github.com/actions/checkout/commit/8459bc0c7e3759cdf591f513d9f141a95fef0a8f"><code>8459bc0</code></a> Bump actions/upload-artifact from 2 to 4 (<a href="https://redirect.github.com/actions/checkout/issues/1695">dart-lang/html#1695</a>)</li> <li><a href="https://github.com/actions/checkout/commit/3f603f6d5e9f40714f97b2f017aa0df2a443192a"><code>3f603f6</code></a> Bump actions/setup-node from 1 to 4 (<a href="https://redirect.github.com/actions/checkout/issues/1696">dart-lang/html#1696</a>)</li> <li><a href="https://github.com/actions/checkout/commit/fd084cde189b7b76ec305d52e27be545a0172823"><code>fd084cd</code></a> Bump github/codeql-action from 2 to 3 (<a href="https://redirect.github.com/actions/checkout/issues/1694">dart-lang/html#1694</a>)</li> <li><a href="https://github.com/actions/checkout/commit/9c1e94e0ad997d618b6113a2171b055037589028"><code>9c1e94e</code></a> Update NPM dependencies (<a href="https://redirect.github.com/actions/checkout/issues/1703">dart-lang/html#1703</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/0ad4b8fadaa221de15dcec353f45205ec38ea70b...44c2b7a8a4ea60a981eaca3cf939b5f4305c123b">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.4&new-version=4.1.5)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 3ea3bc763..4da2a3f34 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@0ad4b8fadaa221de15dcec353f45205ec38ea70b + - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From a24637a9163e1eb7416bfa2e233cf10d89065a8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Jun 2024 16:12:35 +0000 Subject: [PATCH 205/212] Bump actions/checkout from 4.1.5 to 4.1.6 in the github-actions group (dart-lang/html#247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.5 to 4.1.6 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.6</h2> <h2>What's Changed</h2> <ul> <li>Check platform to set archive extension appropriately by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkoutdart-lang/html#1732</a></li> <li>Update for 4.1.6 release by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1733">actions/checkoutdart-lang/html#1733</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.5...v4.1.6">https://github.com/actions/checkout/compare/v4.1.5...v4.1.6</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.1.6</h2> <ul> <li>Check platform to set archive extension appropriately by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkoutdart-lang/html#1732</a></li> </ul> <h2>v4.1.5</h2> <ul> <li>Update NPM dependencies by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkoutdart-lang/html#1703</a></li> <li>Bump github/codeql-action from 2 to 3 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkoutdart-lang/html#1694</a></li> <li>Bump actions/setup-node from 1 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkoutdart-lang/html#1696</a></li> <li>Bump actions/upload-artifact from 2 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkoutdart-lang/html#1695</a></li> <li>README: Suggest <code>user.email</code> to be <code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkoutdart-lang/html#1707</a></li> </ul> <h2>v4.1.4</h2> <ul> <li>Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkoutdart-lang/html#1692</a></li> <li>Add dependabot config by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkoutdart-lang/html#1688</a></li> <li>Bump the minor-actions-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkoutdart-lang/html#1693</a></li> <li>Bump word-wrap from 1.2.3 to 1.2.5 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkoutdart-lang/html#1643</a></li> </ul> <h2>v4.1.3</h2> <ul> <li>Check git version before attempting to disable <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1656">actions/checkoutdart-lang/html#1656</a></li> <li>Add SSH user parameter by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1685">actions/checkoutdart-lang/html#1685</a></li> <li>Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1650">actions/checkoutdart-lang/html#1650</a></li> </ul> <h2>v4.1.2</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> </ul> <h2>v4.1.1</h2> <ul> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1369">Add support for sparse checkouts</a></li> </ul> <h2>v3.5.2</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1289">Fix api endpoint for GHES</a></li> </ul> <h2>v3.5.1</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/a5ac7e51b41094c92402da3b24376905380afc29"><code>a5ac7e5</code></a> Update for 4.1.6 release (<a href="https://redirect.github.com/actions/checkout/issues/1733">dart-lang/html#1733</a>)</li> <li><a href="https://github.com/actions/checkout/commit/24ed1a352802348c9e4e8d13de9177fb95b537ba"><code>24ed1a3</code></a> Check platform for extension (<a href="https://redirect.github.com/actions/checkout/issues/1732">dart-lang/html#1732</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/44c2b7a8a4ea60a981eaca3cf939b5f4305c123b...a5ac7e51b41094c92402da3b24376905380afc29">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.5&new-version=4.1.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index 4da2a3f34..cd09be68e 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b + - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 with: sdk: ${{ matrix.sdk }} From 37ebcdc6c1f395afd024a1a2513cee71c001a793 Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:38:24 -0700 Subject: [PATCH 206/212] update lints (dart-lang/html#249) --- pkgs/html/lib/dom.dart | 2 +- pkgs/html/lib/dom_parsing.dart | 2 +- pkgs/html/lib/parser.dart | 2 +- pkgs/html/lib/src/list_proxy.dart | 2 +- pkgs/html/lib/src/query_selector.dart | 2 +- pkgs/html/lib/src/token.dart | 2 +- pkgs/html/lib/src/treebuilder.dart | 2 +- pkgs/html/pubspec.yaml | 4 ++-- pkgs/html/test/dom_test.dart | 2 +- pkgs/html/test/parser_feature_test.dart | 2 +- pkgs/html/test/parser_test.dart | 2 +- pkgs/html/test/selectors/level1_baseline_test.dart | 2 +- pkgs/html/test/selectors/level1_lib.dart | 2 +- pkgs/html/test/selectors/selectors.dart | 2 +- pkgs/html/test/support.dart | 2 +- pkgs/html/test/tokenizer_test.dart | 2 +- 16 files changed, 17 insertions(+), 17 deletions(-) diff --git a/pkgs/html/lib/dom.dart b/pkgs/html/lib/dom.dart index 733362a0e..0c6b38e58 100644 --- a/pkgs/html/lib/dom.dart +++ b/pkgs/html/lib/dom.dart @@ -1,6 +1,6 @@ /// A simple tree API that results from parsing html. Intended to be compatible /// with dart:html, but it is missing many types and APIs. -library dom; +library; // ignore_for_file: constant_identifier_names diff --git a/pkgs/html/lib/dom_parsing.dart b/pkgs/html/lib/dom_parsing.dart index 5cf3cab7f..69b0bbd4d 100644 --- a/pkgs/html/lib/dom_parsing.dart +++ b/pkgs/html/lib/dom_parsing.dart @@ -1,6 +1,6 @@ /// This library contains extra APIs that aren't in the DOM, but are useful /// when interacting with the parse tree. -library dom_parsing; +library; import 'dom.dart'; import 'html_escape.dart'; diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 3c6340a26..749859890 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -11,7 +11,7 @@ /// /// The resulting document you get back has a DOM-like API for easy tree /// traversal and manipulation. -library parser; +library; import 'dart:collection'; import 'dart:math'; diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 7fe5e828e..9ed878309 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -1,5 +1,5 @@ /// A [List] proxy that you can subclass. -library list_proxy; +library; import 'dart:collection'; diff --git a/pkgs/html/lib/src/query_selector.dart b/pkgs/html/lib/src/query_selector.dart index 96fe4d2ad..b57b81145 100644 --- a/pkgs/html/lib/src/query_selector.dart +++ b/pkgs/html/lib/src/query_selector.dart @@ -1,5 +1,5 @@ /// Query selector implementation for our DOM. -library html.src.query; +library; import 'package:csslib/parser.dart'; import 'package:csslib/visitor.dart'; diff --git a/pkgs/html/lib/src/token.dart b/pkgs/html/lib/src/token.dart index bbcec2601..1ade790f5 100644 --- a/pkgs/html/lib/src/token.dart +++ b/pkgs/html/lib/src/token.dart @@ -1,5 +1,5 @@ /// This library contains token types used by the html5 tokenizer. -library token; +library; import 'dart:collection'; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index a7a8e8290..b63395cd6 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -1,5 +1,5 @@ /// Internals to the tree builders. -library treebuilder; +library; import 'dart:collection'; diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 5824b768d..64eaed969 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -15,6 +15,6 @@ dependencies: source_span: ^1.8.0 dev_dependencies: - dart_flutter_team_lints: ^2.0.0 + dart_flutter_team_lints: ^3.0.0 path: ^1.8.0 - test: ^1.16.0 + test: ^1.16.6 diff --git a/pkgs/html/test/dom_test.dart b/pkgs/html/test/dom_test.dart index df6eb02f7..293443f12 100644 --- a/pkgs/html/test/dom_test.dart +++ b/pkgs/html/test/dom_test.dart @@ -1,5 +1,5 @@ /// Additional feature tests that aren't based on test data. -library dom_test; +library; import 'package:html/dom.dart'; import 'package:html/parser.dart'; diff --git a/pkgs/html/test/parser_feature_test.dart b/pkgs/html/test/parser_feature_test.dart index 64068d062..7156146e0 100644 --- a/pkgs/html/test/parser_feature_test.dart +++ b/pkgs/html/test/parser_feature_test.dart @@ -1,5 +1,5 @@ /// Additional feature tests that aren't based on test data. -library parser_feature_test; +library; import 'package:html/dom.dart'; import 'package:html/parser.dart'; diff --git a/pkgs/html/test/parser_test.dart b/pkgs/html/test/parser_test.dart index 7f717fa17..952c1b2e8 100644 --- a/pkgs/html/test/parser_test.dart +++ b/pkgs/html/test/parser_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library parser_test; +library; import 'dart:convert'; diff --git a/pkgs/html/test/selectors/level1_baseline_test.dart b/pkgs/html/test/selectors/level1_baseline_test.dart index b07d1dc43..d5614e960 100644 --- a/pkgs/html/test/selectors/level1_baseline_test.dart +++ b/pkgs/html/test/selectors/level1_baseline_test.dart @@ -5,7 +5,7 @@ /// an iframe, but instead operate over a parsed DOM. @TestOn('vm') -library html.test.selectors.level1_baseline_test; +library; import 'dart:io'; diff --git a/pkgs/html/test/selectors/level1_lib.dart b/pkgs/html/test/selectors/level1_lib.dart index 833e70229..d77aac796 100644 --- a/pkgs/html/test/selectors/level1_lib.dart +++ b/pkgs/html/test/selectors/level1_lib.dart @@ -7,7 +7,7 @@ /// As usual with ports: being faithful to the original style is more important /// than other style goals, as it reduces friction to integrating changes /// from upstream. -library html.test.selectors.level1_lib; +library; import 'package:html/dom.dart'; import 'package:test/test.dart' as unittest; diff --git a/pkgs/html/test/selectors/selectors.dart b/pkgs/html/test/selectors/selectors.dart index 93d91cdd0..81e69c693 100644 --- a/pkgs/html/test/selectors/selectors.dart +++ b/pkgs/html/test/selectors/selectors.dart @@ -1,6 +1,6 @@ /// Test for the Selectors API ported from /// <https://github.com/w3c/web-platform-tests/tree/master/selectors-api> -library html.test.selectors.selectors; +library; // Bit-mapped flags to indicate which tests the selector is suitable for final int testQsaBaseline = diff --git a/pkgs/html/test/support.dart b/pkgs/html/test/support.dart index a74242cce..82f8e62d8 100644 --- a/pkgs/html/test/support.dart +++ b/pkgs/html/test/support.dart @@ -1,5 +1,5 @@ /// Support code for the tests in this directory. -library support; +library; import 'dart:collection'; import 'dart:io'; diff --git a/pkgs/html/test/tokenizer_test.dart b/pkgs/html/test/tokenizer_test.dart index 74a4a48fa..92103ef23 100644 --- a/pkgs/html/test/tokenizer_test.dart +++ b/pkgs/html/test/tokenizer_test.dart @@ -1,5 +1,5 @@ @TestOn('vm') -library tokenizer_test; +library; import 'dart:convert'; import 'dart:io'; From 1264793351cc86374ab9852a8370ff0458c3dcb1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Jul 2024 16:18:50 +0000 Subject: [PATCH 207/212] Bump the github-actions group with 2 updates (dart-lang/html#250) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [dart-lang/setup-dart](https://github.com/dart-lang/setup-dart). Updates `actions/checkout` from 4.1.6 to 4.1.7 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.1.7</h2> <h2>What's Changed</h2> <ul> <li>Bump the minor-npm-dependencies group across 1 directory with 4 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkoutdart-lang/html#1739</a></li> <li>Bump actions/checkout from 3 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkoutdart-lang/html#1697</a></li> <li>Check out other refs/* by commit by <a href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkoutdart-lang/html#1774</a></li> <li>Pin actions/checkout's own workflows to a known, good, stable version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkoutdart-lang/html#1776</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/orhantoy"><code>@​orhantoy</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkoutdart-lang/html#1774</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.6...v4.1.7">https://github.com/actions/checkout/compare/v4.1.6...v4.1.7</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.1.7</h2> <ul> <li>Bump the minor-npm-dependencies group across 1 directory with 4 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkoutdart-lang/html#1739</a></li> <li>Bump actions/checkout from 3 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkoutdart-lang/html#1697</a></li> <li>Check out other refs/* by commit by <a href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkoutdart-lang/html#1774</a></li> <li>Pin actions/checkout's own workflows to a known, good, stable version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkoutdart-lang/html#1776</a></li> </ul> <h2>v4.1.6</h2> <ul> <li>Check platform to set archive extension appropriately by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkoutdart-lang/html#1732</a></li> </ul> <h2>v4.1.5</h2> <ul> <li>Update NPM dependencies by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkoutdart-lang/html#1703</a></li> <li>Bump github/codeql-action from 2 to 3 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkoutdart-lang/html#1694</a></li> <li>Bump actions/setup-node from 1 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkoutdart-lang/html#1696</a></li> <li>Bump actions/upload-artifact from 2 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkoutdart-lang/html#1695</a></li> <li>README: Suggest <code>user.email</code> to be <code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkoutdart-lang/html#1707</a></li> </ul> <h2>v4.1.4</h2> <ul> <li>Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkoutdart-lang/html#1692</a></li> <li>Add dependabot config by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkoutdart-lang/html#1688</a></li> <li>Bump the minor-actions-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkoutdart-lang/html#1693</a></li> <li>Bump word-wrap from 1.2.3 to 1.2.5 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkoutdart-lang/html#1643</a></li> </ul> <h2>v4.1.3</h2> <ul> <li>Check git version before attempting to disable <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1656">actions/checkoutdart-lang/html#1656</a></li> <li>Add SSH user parameter by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1685">actions/checkoutdart-lang/html#1685</a></li> <li>Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1650">actions/checkoutdart-lang/html#1650</a></li> </ul> <h2>v4.1.2</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> </ul> <h2>v4.1.1</h2> <ul> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/579">Add option to fetch tags even if fetch-depth &gt; 0</a></li> </ul> <h2>v3.5.3</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1196">Fix: Checkout fail in self-hosted runners when faulty submodule are checked-in</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1287">Fix typos found by codespell</a></li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/692973e3d937129bcbf40652eb9f2f61becf3332"><code>692973e</code></a> Prepare 4.1.7 release (<a href="https://redirect.github.com/actions/checkout/issues/1775">dart-lang/html#1775</a>)</li> <li><a href="https://github.com/actions/checkout/commit/6ccd57f4c5d15bdc2fef309bd9fb6cc9db2ef1c6"><code>6ccd57f</code></a> Pin actions/checkout's own workflows to a known, good, stable version. (<a href="https://redirect.github.com/actions/checkout/issues/1776">dart-lang/html#1776</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b17fe1e4d59a9d1d95a7aead5e6fcd13e50939a5"><code>b17fe1e</code></a> Handle hidden refs (<a href="https://redirect.github.com/actions/checkout/issues/1774">dart-lang/html#1774</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b80ff79f1755d06ba70441c368a6fe801f5f3a62"><code>b80ff79</code></a> Bump actions/checkout from 3 to 4 (<a href="https://redirect.github.com/actions/checkout/issues/1697">dart-lang/html#1697</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b1ec3021b8fa02164da82ca1557d017d83b0e179"><code>b1ec302</code></a> Bump the minor-npm-dependencies group across 1 directory with 4 updates (<a href="https://redirect.github.com/actions/checkout/issues/1739">dart-lang/html#1739</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/a5ac7e51b41094c92402da3b24376905380afc29...692973e3d937129bcbf40652eb9f2f61becf3332">compare view</a></li> </ul> </details> <br /> Updates `dart-lang/setup-dart` from 1.6.4 to 1.6.5 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/releases">dart-lang/setup-dart's releases</a>.</em></p> <blockquote> <h2>v1.6.5</h2> <ul> <li>Fix zip path handling on Windows 11 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/html#118</a>[])</li> </ul> <p><a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/html#118</a>: <a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/setup-dartdart-lang/html#118</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/dart-lang/setup-dart/blob/main/CHANGELOG.md">dart-lang/setup-dart's changelog</a>.</em></p> <blockquote> <h2>v1.6.5</h2> <ul> <li>Fix zip path handling on Windows 11 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/html#118</a>[])</li> </ul> <p><a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/html#118</a>: <a href="https://redirect.github.com/dart-lang/setup-dart/issues/118">dart-lang/setup-dartdart-lang/html#118</a></p> <h2>v1.6.4</h2> <ul> <li>Rebuild JS code.</li> </ul> <h2>v1.6.3</h2> <ul> <li>Roll <code>undici</code> dependency to address <a href="https://github.com/nodejs/undici/security/advisories/GHSA-m4v8-wqvr-p9f7">CVE-2024-30260</a> and <a href="https://github.com/nodejs/undici/security/advisories/GHSA-9qxr-qj54-h672">CVE-2024-30261</a>.</li> </ul> <h2>v1.6.2</h2> <ul> <li>Switch to running the workflow on <code>node20`` from </code>node16`. See also <a href="https://github.blog/changelog/2023-09-22-github-actions-transitioning-from-node-16-to-node-20/">Transitioning from Node 16 to Node 20</a>.</li> </ul> <h2>v1.6.1</h2> <ul> <li>Updated the google storage url for <code>main</code> channel releases.</li> </ul> <h2>v1.6.0</h2> <ul> <li>Enable provisioning of the latest Dart SDK patch release by specifying just the major and minor version (e.g. <code>3.2</code>).</li> </ul> <h2>v1.5.1</h2> <ul> <li>No longer test the <code>setup-dart</code> action on pre-2.12 SDKs.</li> <li>Upgrade JS interop code to use extension types (the new name for inline classes).</li> <li>The upcoming rename of the <code>be</code> channel to <code>main</code> is now supported with forward compatibility that switches when the rename happens.</li> </ul> <h2>v1.5.0</h2> <ul> <li>Re-wrote the implementation of the action into Dart.</li> <li>Auto-detect the platform architecture (<code>x64</code>, <code>ia32</code>, <code>arm</code>, <code>arm64</code>).</li> <li>Improved the caching and download resilience of the sdk.</li> <li>Added a new action output: <code>dart-version</code> - the installed version of the sdk.</li> </ul> <h2>v1.4.0</h2> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/dart-lang/setup-dart/commit/0a8a0fc875eb934c15d08629302413c671d3f672"><code>0a8a0fc</code></a> rev to v1.6.5 in prep for publishing (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/135">dart-lang/html#135</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/4e61f04f255b227a0511bf9ef0f5ddc7c8542531"><code>4e61f04</code></a> fix: Use <code>.zip</code> in archive path (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/119">dart-lang/html#119</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/2986c8e337a31eb7b455ce93dc984e9bf5797756"><code>2986c8e</code></a> blast_repo fixes (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/132">dart-lang/html#132</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/40a7d12289757ab3aaa39d47d6f99a9cb1dd701e"><code>40a7d12</code></a> Bump dart-lang/setup-dart from 1.6.2 to 1.6.4 (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/131">dart-lang/html#131</a>)</li> <li><a href="https://github.com/dart-lang/setup-dart/commit/40f1ce0b1c8f24a4e9cb7eb026e4dbbdb431eb76"><code>40f1ce0</code></a> Update dart.yml (<a href="https://redirect.github.com/dart-lang/setup-dart/issues/130">dart-lang/html#130</a>)</li> <li>See full diff in <a href="https://github.com/dart-lang/setup-dart/compare/f0ead981b4d9a35b37f30d36160575d60931ec30...0a8a0fc875eb934c15d08629302413c671d3f672">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --- pkgs/html/.github/workflows/test-package.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index cd09be68e..c85e4538c 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,8 +14,8 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: dev - id: install @@ -34,8 +34,8 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 - - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30 + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} - id: install From d226b1aa39fbc6ceb4eba3ded23786be8ee080e8 Mon Sep 17 00:00:00 2001 From: Nate Bosch <nbosch@google.com> Date: Wed, 28 Aug 2024 17:49:18 -0700 Subject: [PATCH 208/212] Fix doc comments (dart-lang/html#256) Update comments that set off a false positive in the `unintended_html_in_doc_comment` lint. For references to core Dart types with generics, replace the square braces with backticks since it isn't useful to constantly link them. For the comments that are edited, and a few nearby, update for style: - Separate out a header as it's own paragraph. - Reduce repetitive phrasing and redundant links to the same arguments. Use a trailing comma for a long argument list, and re-order the arguments so that the always-useful arguments are at the top, and the arguments only pertaining to certain uses follow. --- pkgs/html/lib/parser.dart | 47 +++++++++++++++--------- pkgs/html/lib/src/html_input_stream.dart | 2 +- pkgs/html/lib/src/list_proxy.dart | 2 +- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 749859890..95aaa9a63 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -26,8 +26,10 @@ import 'src/tokenizer.dart'; import 'src/treebuilder.dart'; import 'src/utils.dart'; -/// Parse the [input] html5 document into a tree. The [input] can be -/// a [String], [List<int>] of bytes or an [HtmlTokenizer]. +/// Parse an html5 document into a tree. +/// +/// The [input] can be a `String`, a `List<int>` of bytes, or an +/// [HtmlTokenizer]. /// /// If [input] is not a [HtmlTokenizer], you can optionally specify the file's /// [encoding], which must be a string. If specified that encoding will be @@ -44,9 +46,12 @@ Document parse(dynamic input, return p.parse(); } -/// Parse the [input] html5 document fragment into a tree. The [input] can be -/// a [String], [List<int>] of bytes or an [HtmlTokenizer]. The [container] -/// element can optionally be specified, otherwise it defaults to "div". +/// Parse an html5 document fragment into a tree. +/// +/// The [input] can be a `String`, a `List<int>` of bytes, or an +/// [HtmlTokenizer]. +/// The [container] element can optionally be specified, otherwise it defaults +/// to "div". /// /// If [input] is not a [HtmlTokenizer], you can optionally specify the file's /// [encoding], which must be a string. If specified, that encoding will be used, @@ -126,8 +131,13 @@ class HtmlParser { late final _afterAfterBodyPhase = AfterAfterBodyPhase(this); late final _afterAfterFramesetPhase = AfterAfterFramesetPhase(this); - /// Create an HtmlParser and configure the [tree] builder and [strict] mode. - /// The [input] can be a [String], [List<int>] of bytes or an [HtmlTokenizer]. + /// Create and configure an HtmlParser. + /// + /// The [input] can be a `String`, a `List<int>` of bytes, or an + /// [HtmlTokenizer]. + /// + /// The [strict], [tree] builder, and [generateSpans] arguments configure + /// behavior for any type of input. /// /// If [input] is not a [HtmlTokenizer], you can specify a few more arguments. /// @@ -141,16 +151,17 @@ class HtmlParser { /// automatic conversion of element and attribute names to lower case. Note /// that standard way to parse HTML is to lowercase, which is what the browser /// DOM will do if you request `Element.outerHTML`, for example. - HtmlParser(dynamic input, - {String? encoding, - bool parseMeta = true, - bool lowercaseElementName = true, - bool lowercaseAttrName = true, - this.strict = false, - this.generateSpans = false, - String? sourceUrl, - TreeBuilder? tree}) - : tree = tree ?? TreeBuilder(true), + HtmlParser( + dynamic input, { + TreeBuilder? tree, + this.strict = false, + this.generateSpans = false, + String? encoding, + bool parseMeta = true, + bool lowercaseElementName = true, + bool lowercaseAttrName = true, + String? sourceUrl, + }) : tree = tree ?? TreeBuilder(true), tokenizer = input is HtmlTokenizer ? input : HtmlTokenizer(input, @@ -166,6 +177,7 @@ class HtmlParser { bool get innerHTMLMode => innerHTML != null; /// Parse an html5 document into a tree. + /// /// After parsing, [errors] will be populated with parse errors, if any. Document parse() { innerHTML = null; @@ -174,6 +186,7 @@ class HtmlParser { } /// Parse an html5 document fragment into a tree. + /// /// Pass a [container] to change the type of the containing element. /// After parsing, [errors] will be populated with parse errors, if any. DocumentFragment parseFragment([String container = 'div']) { diff --git a/pkgs/html/lib/src/html_input_stream.dart b/pkgs/html/lib/src/html_input_stream.dart index abae4cfb8..b093d3ce3 100644 --- a/pkgs/html/lib/src/html_input_stream.dart +++ b/pkgs/html/lib/src/html_input_stream.dart @@ -48,7 +48,7 @@ class HtmlInputStream { /// HtmlInputStream(source, [encoding]) -> Normalized stream from source /// for use by html5lib. /// - /// [source] can be either a [String] or a [List<int>] containing the raw + /// [source] can be either a `String` or a `List<int>` containing the raw /// bytes. /// /// The optional encoding parameter must be a string that indicates diff --git a/pkgs/html/lib/src/list_proxy.dart b/pkgs/html/lib/src/list_proxy.dart index 9ed878309..f226d7f7b 100644 --- a/pkgs/html/lib/src/list_proxy.dart +++ b/pkgs/html/lib/src/list_proxy.dart @@ -4,7 +4,7 @@ library; import 'dart:collection'; abstract class ListProxy<E> extends ListBase<E> { - /// The inner [List<T>] with the actual storage. + /// The proxied list with actual storage. final List<E> _list = <E>[]; @override From cb0c12fdbe77da54fd20f3d5f341dd254ecb11bb Mon Sep 17 00:00:00 2001 From: Kevin Moore <kevmoo@users.noreply.github.com> Date: Wed, 28 Aug 2024 18:24:46 -0700 Subject: [PATCH 209/212] Drop Pair util class (dart-lang/html#255) --- pkgs/html/lib/parser.dart | 8 +- pkgs/html/lib/src/constants.dart | 238 ++++++++++++++--------------- pkgs/html/lib/src/treebuilder.dart | 17 +-- pkgs/html/lib/src/utils.dart | 14 -- 4 files changed, 131 insertions(+), 146 deletions(-) diff --git a/pkgs/html/lib/parser.dart b/pkgs/html/lib/parser.dart index 95aaa9a63..0e89e663a 100644 --- a/pkgs/html/lib/parser.dart +++ b/pkgs/html/lib/parser.dart @@ -248,13 +248,13 @@ class HtmlParser { return enc == 'text/html' || enc == 'application/xhtml+xml'; } else { return htmlIntegrationPointElements - .contains(Pair(element.namespaceUri, element.localName)); + .contains((element.namespaceUri, element.localName)); } } bool isMathMLTextIntegrationPoint(Element element) { return mathmlTextIntegrationPointElements - .contains(Pair(element.namespaceUri, element.localName)); + .contains((element.namespaceUri, element.localName)); } bool inForeignContent(Token token, int type) { @@ -3978,7 +3978,7 @@ class ParseError implements SourceSpanException { } /// Convenience function to get the pair of namespace and localName. -Pair<String, String?> getElementNameTuple(Element e) { +(String, String?) getElementNameTuple(Element e) { final ns = e.namespaceUri ?? Namespaces.html; - return Pair(ns, e.localName); + return (ns, e.localName); } diff --git a/pkgs/html/lib/src/constants.dart b/pkgs/html/lib/src/constants.dart index abd483bbe..e70b1e263 100644 --- a/pkgs/html/lib/src/constants.dart +++ b/pkgs/html/lib/src/constants.dart @@ -258,139 +258,139 @@ class Namespaces { } } -const List<Pair<String, String>> scopingElements = [ - Pair(Namespaces.html, 'applet'), - Pair(Namespaces.html, 'caption'), - Pair(Namespaces.html, 'html'), - Pair(Namespaces.html, 'marquee'), - Pair(Namespaces.html, 'object'), - Pair(Namespaces.html, 'table'), - Pair(Namespaces.html, 'td'), - Pair(Namespaces.html, 'th'), - Pair(Namespaces.mathml, 'mi'), - Pair(Namespaces.mathml, 'mo'), - Pair(Namespaces.mathml, 'mn'), - Pair(Namespaces.mathml, 'ms'), - Pair(Namespaces.mathml, 'mtext'), - Pair(Namespaces.mathml, 'annotation-xml'), - Pair(Namespaces.svg, 'foreignObject'), - Pair(Namespaces.svg, 'desc'), - Pair(Namespaces.svg, 'title') +const List<(String, String)> scopingElements = [ + (Namespaces.html, 'applet'), + (Namespaces.html, 'caption'), + (Namespaces.html, 'html'), + (Namespaces.html, 'marquee'), + (Namespaces.html, 'object'), + (Namespaces.html, 'table'), + (Namespaces.html, 'td'), + (Namespaces.html, 'th'), + (Namespaces.mathml, 'mi'), + (Namespaces.mathml, 'mo'), + (Namespaces.mathml, 'mn'), + (Namespaces.mathml, 'ms'), + (Namespaces.mathml, 'mtext'), + (Namespaces.mathml, 'annotation-xml'), + (Namespaces.svg, 'foreignObject'), + (Namespaces.svg, 'desc'), + (Namespaces.svg, 'title') ]; const formattingElements = [ - Pair(Namespaces.html, 'a'), - Pair(Namespaces.html, 'b'), - Pair(Namespaces.html, 'big'), - Pair(Namespaces.html, 'code'), - Pair(Namespaces.html, 'em'), - Pair(Namespaces.html, 'font'), - Pair(Namespaces.html, 'i'), - Pair(Namespaces.html, 'nobr'), - Pair(Namespaces.html, 's'), - Pair(Namespaces.html, 'small'), - Pair(Namespaces.html, 'strike'), - Pair(Namespaces.html, 'strong'), - Pair(Namespaces.html, 'tt'), - Pair(Namespaces.html, '') + (Namespaces.html, 'a'), + (Namespaces.html, 'b'), + (Namespaces.html, 'big'), + (Namespaces.html, 'code'), + (Namespaces.html, 'em'), + (Namespaces.html, 'font'), + (Namespaces.html, 'i'), + (Namespaces.html, 'nobr'), + (Namespaces.html, 's'), + (Namespaces.html, 'small'), + (Namespaces.html, 'strike'), + (Namespaces.html, 'strong'), + (Namespaces.html, 'tt'), + (Namespaces.html, '') ]; const specialElements = [ - Pair(Namespaces.html, 'address'), - Pair(Namespaces.html, 'applet'), - Pair(Namespaces.html, 'area'), - Pair(Namespaces.html, 'article'), - Pair(Namespaces.html, 'aside'), - Pair(Namespaces.html, 'base'), - Pair(Namespaces.html, 'basefont'), - Pair(Namespaces.html, 'bgsound'), - Pair(Namespaces.html, 'blockquote'), - Pair(Namespaces.html, 'body'), - Pair(Namespaces.html, 'br'), - Pair(Namespaces.html, 'button'), - Pair(Namespaces.html, 'caption'), - Pair(Namespaces.html, 'center'), - Pair(Namespaces.html, 'col'), - Pair(Namespaces.html, 'colgroup'), - Pair(Namespaces.html, 'command'), - Pair(Namespaces.html, 'dd'), - Pair(Namespaces.html, 'details'), - Pair(Namespaces.html, 'dir'), - Pair(Namespaces.html, 'div'), - Pair(Namespaces.html, 'dl'), - Pair(Namespaces.html, 'dt'), - Pair(Namespaces.html, 'embed'), - Pair(Namespaces.html, 'fieldset'), - Pair(Namespaces.html, 'figure'), - Pair(Namespaces.html, 'footer'), - Pair(Namespaces.html, 'form'), - Pair(Namespaces.html, 'frame'), - Pair(Namespaces.html, 'frameset'), - Pair(Namespaces.html, 'h1'), - Pair(Namespaces.html, 'h2'), - Pair(Namespaces.html, 'h3'), - Pair(Namespaces.html, 'h4'), - Pair(Namespaces.html, 'h5'), - Pair(Namespaces.html, 'h6'), - Pair(Namespaces.html, 'head'), - Pair(Namespaces.html, 'header'), - Pair(Namespaces.html, 'hr'), - Pair(Namespaces.html, 'html'), - Pair(Namespaces.html, 'iframe'), + (Namespaces.html, 'address'), + (Namespaces.html, 'applet'), + (Namespaces.html, 'area'), + (Namespaces.html, 'article'), + (Namespaces.html, 'aside'), + (Namespaces.html, 'base'), + (Namespaces.html, 'basefont'), + (Namespaces.html, 'bgsound'), + (Namespaces.html, 'blockquote'), + (Namespaces.html, 'body'), + (Namespaces.html, 'br'), + (Namespaces.html, 'button'), + (Namespaces.html, 'caption'), + (Namespaces.html, 'center'), + (Namespaces.html, 'col'), + (Namespaces.html, 'colgroup'), + (Namespaces.html, 'command'), + (Namespaces.html, 'dd'), + (Namespaces.html, 'details'), + (Namespaces.html, 'dir'), + (Namespaces.html, 'div'), + (Namespaces.html, 'dl'), + (Namespaces.html, 'dt'), + (Namespaces.html, 'embed'), + (Namespaces.html, 'fieldset'), + (Namespaces.html, 'figure'), + (Namespaces.html, 'footer'), + (Namespaces.html, 'form'), + (Namespaces.html, 'frame'), + (Namespaces.html, 'frameset'), + (Namespaces.html, 'h1'), + (Namespaces.html, 'h2'), + (Namespaces.html, 'h3'), + (Namespaces.html, 'h4'), + (Namespaces.html, 'h5'), + (Namespaces.html, 'h6'), + (Namespaces.html, 'head'), + (Namespaces.html, 'header'), + (Namespaces.html, 'hr'), + (Namespaces.html, 'html'), + (Namespaces.html, 'iframe'), // Note that image is commented out in the spec as "this isn't an // element that can end up on the stack, so it doesn't matter," - Pair(Namespaces.html, 'image'), - Pair(Namespaces.html, 'img'), - Pair(Namespaces.html, 'input'), - Pair(Namespaces.html, 'isindex'), - Pair(Namespaces.html, 'li'), - Pair(Namespaces.html, 'link'), - Pair(Namespaces.html, 'listing'), - Pair(Namespaces.html, 'marquee'), - Pair(Namespaces.html, 'men'), - Pair(Namespaces.html, 'meta'), - Pair(Namespaces.html, 'nav'), - Pair(Namespaces.html, 'noembed'), - Pair(Namespaces.html, 'noframes'), - Pair(Namespaces.html, 'noscript'), - Pair(Namespaces.html, 'object'), - Pair(Namespaces.html, 'ol'), - Pair(Namespaces.html, 'p'), - Pair(Namespaces.html, 'param'), - Pair(Namespaces.html, 'plaintext'), - Pair(Namespaces.html, 'pre'), - Pair(Namespaces.html, 'script'), - Pair(Namespaces.html, 'section'), - Pair(Namespaces.html, 'select'), - Pair(Namespaces.html, 'style'), - Pair(Namespaces.html, 'table'), - Pair(Namespaces.html, 'tbody'), - Pair(Namespaces.html, 'td'), - Pair(Namespaces.html, 'textarea'), - Pair(Namespaces.html, 'tfoot'), - Pair(Namespaces.html, 'th'), - Pair(Namespaces.html, 'thead'), - Pair(Namespaces.html, 'title'), - Pair(Namespaces.html, 'tr'), - Pair(Namespaces.html, 'ul'), - Pair(Namespaces.html, 'wbr'), - Pair(Namespaces.html, 'xmp'), - Pair(Namespaces.svg, 'foreignObject') + (Namespaces.html, 'image'), + (Namespaces.html, 'img'), + (Namespaces.html, 'input'), + (Namespaces.html, 'isindex'), + (Namespaces.html, 'li'), + (Namespaces.html, 'link'), + (Namespaces.html, 'listing'), + (Namespaces.html, 'marquee'), + (Namespaces.html, 'men'), + (Namespaces.html, 'meta'), + (Namespaces.html, 'nav'), + (Namespaces.html, 'noembed'), + (Namespaces.html, 'noframes'), + (Namespaces.html, 'noscript'), + (Namespaces.html, 'object'), + (Namespaces.html, 'ol'), + (Namespaces.html, 'p'), + (Namespaces.html, 'param'), + (Namespaces.html, 'plaintext'), + (Namespaces.html, 'pre'), + (Namespaces.html, 'script'), + (Namespaces.html, 'section'), + (Namespaces.html, 'select'), + (Namespaces.html, 'style'), + (Namespaces.html, 'table'), + (Namespaces.html, 'tbody'), + (Namespaces.html, 'td'), + (Namespaces.html, 'textarea'), + (Namespaces.html, 'tfoot'), + (Namespaces.html, 'th'), + (Namespaces.html, 'thead'), + (Namespaces.html, 'title'), + (Namespaces.html, 'tr'), + (Namespaces.html, 'ul'), + (Namespaces.html, 'wbr'), + (Namespaces.html, 'xmp'), + (Namespaces.svg, 'foreignObject') ]; const htmlIntegrationPointElements = [ - Pair(Namespaces.mathml, 'annotaion-xml'), - Pair(Namespaces.svg, 'foreignObject'), - Pair(Namespaces.svg, 'desc'), - Pair(Namespaces.svg, 'title') + (Namespaces.mathml, 'annotaion-xml'), + (Namespaces.svg, 'foreignObject'), + (Namespaces.svg, 'desc'), + (Namespaces.svg, 'title') ]; const mathmlTextIntegrationPointElements = [ - Pair(Namespaces.mathml, 'mi'), - Pair(Namespaces.mathml, 'mo'), - Pair(Namespaces.mathml, 'mn'), - Pair(Namespaces.mathml, 'ms'), - Pair(Namespaces.mathml, 'mtext') + (Namespaces.mathml, 'mi'), + (Namespaces.mathml, 'mo'), + (Namespaces.mathml, 'mn'), + (Namespaces.mathml, 'ms'), + (Namespaces.mathml, 'mtext') ]; const spaceCharacters = ' \n\r\t\u000C'; diff --git a/pkgs/html/lib/src/treebuilder.dart b/pkgs/html/lib/src/treebuilder.dart index b63395cd6..781f3f680 100644 --- a/pkgs/html/lib/src/treebuilder.dart +++ b/pkgs/html/lib/src/treebuilder.dart @@ -10,7 +10,6 @@ import '../parser.dart' show getElementNameTuple; import 'constants.dart'; import 'list_proxy.dart'; import 'token.dart'; -import 'utils.dart'; /// Open elements in the formatting category, most recent element last. /// @@ -113,29 +112,29 @@ class TreeBuilder { final exactNode = target is Node; var listElements1 = scopingElements; - var listElements2 = const <Pair<String, String>>[]; + var listElements2 = const <(String, String)>[]; var invert = false; if (variant != null) { switch (variant) { case 'button': - listElements2 = const [Pair(Namespaces.html, 'button')]; + listElements2 = const [(Namespaces.html, 'button')]; break; case 'list': listElements2 = const [ - Pair(Namespaces.html, 'ol'), - Pair(Namespaces.html, 'ul') + (Namespaces.html, 'ol'), + (Namespaces.html, 'ul') ]; break; case 'table': listElements1 = const [ - Pair(Namespaces.html, 'html'), - Pair(Namespaces.html, 'table') + (Namespaces.html, 'html'), + (Namespaces.html, 'table') ]; break; case 'select': listElements1 = const [ - Pair(Namespaces.html, 'optgroup'), - Pair(Namespaces.html, 'option') + (Namespaces.html, 'optgroup'), + (Namespaces.html, 'option') ]; invert = true; break; diff --git a/pkgs/html/lib/src/utils.dart b/pkgs/html/lib/src/utils.dart index 5c4e359fc..4f4bd1a00 100644 --- a/pkgs/html/lib/src/utils.dart +++ b/pkgs/html/lib/src/utils.dart @@ -1,19 +1,5 @@ import 'constants.dart'; -class Pair<F, S> { - final F first; - final S second; - - const Pair(this.first, this.second); - - @override - int get hashCode => 37 * first.hashCode + second.hashCode; - - @override - bool operator ==(Object other) => - other is Pair && other.first == first && other.second == second; -} - bool startsWithAny(String str, List<String> prefixes) => prefixes.any(str.startsWith); From 1f9e1d255a62caf01bf1c886fc3640dd7e5a6415 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 16:41:18 +0000 Subject: [PATCH 210/212] Bump actions/checkout from 4.1.7 to 4.2.0 in the github-actions group (dart-lang/html#257) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the github-actions group with 1 update: [actions/checkout](https://github.com/actions/checkout). Updates `actions/checkout` from 4.1.7 to 4.2.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/releases">actions/checkout's releases</a>.</em></p> <blockquote> <h2>v4.2.0</h2> <h2>What's Changed</h2> <ul> <li>Add Ref and Commit outputs by <a href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkoutdart-lang/html#1180</a></li> <li>Dependabot updates in <a href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkoutdart-lang/html#1777</a> &amp; <a href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkoutdart-lang/html#1872</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/yasonk"><code>@​yasonk</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1869">actions/checkoutdart-lang/html#1869</a></li> <li><a href="https://github.com/lucacome"><code>@​lucacome</code></a> made their first contribution in <a href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkoutdart-lang/html#1180</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/checkout/compare/v4.1.7...v4.2.0">https://github.com/actions/checkout/compare/v4.1.7...v4.2.0</a></p> </blockquote> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/checkout/blob/main/CHANGELOG.md">actions/checkout's changelog</a>.</em></p> <blockquote> <h1>Changelog</h1> <h2>v4.2.0</h2> <ul> <li>Add Ref and Commit outputs by <a href="https://github.com/lucacome"><code>@​lucacome</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1180">actions/checkoutdart-lang/html#1180</a></li> <li>Dependency updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a>- <a href="https://redirect.github.com/actions/checkout/pull/1777">actions/checkoutdart-lang/html#1777</a>, <a href="https://redirect.github.com/actions/checkout/pull/1872">actions/checkoutdart-lang/html#1872</a></li> </ul> <h2>v4.1.7</h2> <ul> <li>Bump the minor-npm-dependencies group across 1 directory with 4 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1739">actions/checkoutdart-lang/html#1739</a></li> <li>Bump actions/checkout from 3 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1697">actions/checkoutdart-lang/html#1697</a></li> <li>Check out other refs/* by commit by <a href="https://github.com/orhantoy"><code>@​orhantoy</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1774">actions/checkoutdart-lang/html#1774</a></li> <li>Pin actions/checkout's own workflows to a known, good, stable version. by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1776">actions/checkoutdart-lang/html#1776</a></li> </ul> <h2>v4.1.6</h2> <ul> <li>Check platform to set archive extension appropriately by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1732">actions/checkoutdart-lang/html#1732</a></li> </ul> <h2>v4.1.5</h2> <ul> <li>Update NPM dependencies by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1703">actions/checkoutdart-lang/html#1703</a></li> <li>Bump github/codeql-action from 2 to 3 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1694">actions/checkoutdart-lang/html#1694</a></li> <li>Bump actions/setup-node from 1 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1696">actions/checkoutdart-lang/html#1696</a></li> <li>Bump actions/upload-artifact from 2 to 4 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1695">actions/checkoutdart-lang/html#1695</a></li> <li>README: Suggest <code>user.email</code> to be <code>41898282+github-actions[bot]@users.noreply.github.com</code> by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1707">actions/checkoutdart-lang/html#1707</a></li> </ul> <h2>v4.1.4</h2> <ul> <li>Disable <code>extensions.worktreeConfig</code> when disabling <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1692">actions/checkoutdart-lang/html#1692</a></li> <li>Add dependabot config by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1688">actions/checkoutdart-lang/html#1688</a></li> <li>Bump the minor-actions-dependencies group with 2 updates by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1693">actions/checkoutdart-lang/html#1693</a></li> <li>Bump word-wrap from 1.2.3 to 1.2.5 by <a href="https://github.com/dependabot"><code>@​dependabot</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1643">actions/checkoutdart-lang/html#1643</a></li> </ul> <h2>v4.1.3</h2> <ul> <li>Check git version before attempting to disable <code>sparse-checkout</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1656">actions/checkoutdart-lang/html#1656</a></li> <li>Add SSH user parameter by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1685">actions/checkoutdart-lang/html#1685</a></li> <li>Update <code>actions/checkout</code> version in <code>update-main-version.yml</code> by <a href="https://github.com/jww3"><code>@​jww3</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1650">actions/checkoutdart-lang/html#1650</a></li> </ul> <h2>v4.1.2</h2> <ul> <li>Fix: Disable sparse checkout whenever <code>sparse-checkout</code> option is not present <a href="https://github.com/dscho"><code>@​dscho</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1598">actions/checkoutdart-lang/html#1598</a></li> </ul> <h2>v4.1.1</h2> <ul> <li>Correct link to GitHub Docs by <a href="https://github.com/peterbe"><code>@​peterbe</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1511">actions/checkoutdart-lang/html#1511</a></li> <li>Link to release page from what's new section by <a href="https://github.com/cory-miller"><code>@​cory-miller</code></a> in <a href="https://redirect.github.com/actions/checkout/pull/1514">actions/checkoutdart-lang/html#1514</a></li> </ul> <h2>v4.1.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1396">Add support for partial checkout filters</a></li> </ul> <h2>v4.0.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1067">Support fetching without the --progress option</a></li> <li><a href="https://redirect.github.com/actions/checkout/pull/1436">Update to node20</a></li> </ul> <h2>v3.6.0</h2> <ul> <li><a href="https://redirect.github.com/actions/checkout/pull/1377">Fix: Mark test scripts with Bash'isms to be run via Bash</a></li> </ul> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/actions/checkout/commit/d632683dd7b4114ad314bca15554477dd762a938"><code>d632683</code></a> Prepare 4.2.0 release (<a href="https://redirect.github.com/actions/checkout/issues/1878">dart-lang/html#1878</a>)</li> <li><a href="https://github.com/actions/checkout/commit/6d193bf28034eafb982f37bd894289fe649468fc"><code>6d193bf</code></a> Bump braces from 3.0.2 to 3.0.3 (<a href="https://redirect.github.com/actions/checkout/issues/1777">dart-lang/html#1777</a>)</li> <li><a href="https://github.com/actions/checkout/commit/db0cee9a514becbbd4a101a5fbbbf47865ee316c"><code>db0cee9</code></a> Bump the minor-npm-dependencies group across 1 directory with 4 updates (<a href="https://redirect.github.com/actions/checkout/issues/1872">dart-lang/html#1872</a>)</li> <li><a href="https://github.com/actions/checkout/commit/b6849436894e144dbce29d7d7fda2ae3bf9d8365"><code>b684943</code></a> Add Ref and Commit outputs (<a href="https://redirect.github.com/actions/checkout/issues/1180">dart-lang/html#1180</a>)</li> <li><a href="https://github.com/actions/checkout/commit/2d7d9f7ff5b310f983d059b68785b3c74d8b8edd"><code>2d7d9f7</code></a> Provide explanation for where user email came from (<a href="https://redirect.github.com/actions/checkout/issues/1869">dart-lang/html#1869</a>)</li> <li><a href="https://github.com/actions/checkout/commit/9a9194f87191a7e9055e3e9b95b8cfb13023bb08"><code>9a9194f</code></a> Bump docker/build-push-action from 5.3.0 to 6.5.0 (<a href="https://redirect.github.com/actions/checkout/issues/1832">dart-lang/html#1832</a>)</li> <li><a href="https://github.com/actions/checkout/commit/dd960bd3c3f080561a1810e32349ac211ecec7d4"><code>dd960bd</code></a> Bump docker/login-action in the minor-actions-dependencies group (<a href="https://redirect.github.com/actions/checkout/issues/1831">dart-lang/html#1831</a>)</li> <li>See full diff in <a href="https://github.com/actions/checkout/compare/692973e3d937129bcbf40652eb9f2f61becf3332...d632683dd7b4114ad314bca15554477dd762a938">compare view</a></li> </ul> </details> <br /> [![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=actions/checkout&package-manager=github_actions&previous-version=4.1.7&new-version=4.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> --- pkgs/html/.github/workflows/test-package.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkgs/html/.github/workflows/test-package.yml b/pkgs/html/.github/workflows/test-package.yml index c85e4538c..ed13464ce 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/pkgs/html/.github/workflows/test-package.yml @@ -14,7 +14,7 @@ jobs: strategy: fail-fast: false steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: dev @@ -34,7 +34,7 @@ jobs: os: [ubuntu-latest] sdk: [3.2, stable, dev] steps: - - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 + - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672 with: sdk: ${{ matrix.sdk }} From b609e879e327ba8896095627ef58d772ff890ec2 Mon Sep 17 00:00:00 2001 From: Moritz <mosum@google.com> Date: Fri, 25 Oct 2024 14:58:23 +0200 Subject: [PATCH 211/212] Add issue template and other fixes --- .github/ISSUE_TEMPLATE/html.md | 5 +++++ pkgs/html/pubspec.yaml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 .github/ISSUE_TEMPLATE/html.md diff --git a/.github/ISSUE_TEMPLATE/html.md b/.github/ISSUE_TEMPLATE/html.md new file mode 100644 index 000000000..ec1e01d85 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/html.md @@ -0,0 +1,5 @@ +--- +name: "package:html" +about: "Create a bug or file a feature request against package:html." +labels: "package:html" +--- \ No newline at end of file diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 64eaed969..14dcf47f4 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,7 +1,7 @@ name: html version: 0.15.5-wip description: APIs for parsing and manipulating HTML content outside the browser. -repository: https://github.com/dart-lang/html +repository: https://github.com/dart-lang/tools/tree/main/pkgs/html topics: - html From e12f92ebe4d1aae0d19b364e93929bf9b2f110e6 Mon Sep 17 00:00:00 2001 From: Moritz <mosum@google.com> Date: Fri, 25 Oct 2024 15:02:04 +0200 Subject: [PATCH 212/212] Moving fixes --- .github/labeler.yml | 4 ++ .../workflows/html.yaml | 21 +++++++++-- README.md | 1 + pkgs/html/.github/dependabot.yml | 15 -------- pkgs/html/.github/workflows/no-response.yml | 37 ------------------- pkgs/html/.github/workflows/publish.yaml | 17 --------- pkgs/html/CHANGELOG.md | 3 +- pkgs/html/README.md | 2 +- pkgs/html/pubspec.yaml | 2 +- 9 files changed, 27 insertions(+), 75 deletions(-) rename pkgs/html/.github/workflows/test-package.yml => .github/workflows/html.yaml (77%) delete mode 100644 pkgs/html/.github/dependabot.yml delete mode 100644 pkgs/html/.github/workflows/no-response.yml delete mode 100644 pkgs/html/.github/workflows/publish.yaml diff --git a/.github/labeler.yml b/.github/labeler.yml index c3d5de0b9..e7a8976af 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -32,6 +32,10 @@ - changed-files: - any-glob-to-any-file: 'pkgs/graphs/**' +'package:html': + - changed-files: + - any-glob-to-any-file: 'pkgs/html/**' + 'package:mime': - changed-files: - any-glob-to-any-file: 'pkgs/mime/**' diff --git a/pkgs/html/.github/workflows/test-package.yml b/.github/workflows/html.yaml similarity index 77% rename from pkgs/html/.github/workflows/test-package.yml rename to .github/workflows/html.yaml index ed13464ce..fe75a0dfb 100644 --- a/pkgs/html/.github/workflows/test-package.yml +++ b/.github/workflows/html.yaml @@ -1,13 +1,28 @@ -name: Dart CI +name: package:html on: + # Run on PRs and pushes to the default branch. push: - branches: [main] + branches: [ main ] + paths: + - '.github/workflows/html.yml' + - 'pkgs/html/**' pull_request: - branches: [main] + branches: [ main ] + paths: + - '.github/workflows/html.yml' + - 'pkgs/html/**' schedule: - cron: "0 0 * * 0" +env: + PUB_ENVIRONMENT: bot.github + + +defaults: + run: + working-directory: pkgs/html/ + jobs: analyze: runs-on: ubuntu-latest diff --git a/README.md b/README.md index ac4edf204..961b99000 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ don't naturally belong to other topic monorepos (like | [file](pkgs/file/) | A pluggable, mockable file system abstraction for Dart. | [![pub package](https://img.shields.io/pub/v/file.svg)](https://pub.dev/packages/file) | | [file_testing](pkgs/file_testing/) | Testing utilities for package:file (published but unlisted). | [![pub package](https://img.shields.io/pub/v/file_testing.svg)](https://pub.dev/packages/file_testing) | | [graphs](pkgs/graphs/) | Graph algorithms that operate on graphs in any representation | [![pub package](https://img.shields.io/pub/v/graphs.svg)](https://pub.dev/packages/graphs) | +| [html](pkgs/html/) | APIs for parsing and manipulating HTML content outside the browser. | [![pub package](https://img.shields.io/pub/v/html.svg)](https://pub.dev/packages/html) | | [mime](pkgs/mime/) | Utilities for handling media (MIME) types. | [![pub package](https://img.shields.io/pub/v/mime.svg)](https://pub.dev/packages/mime) | | [oauth2](pkgs/oauth2/) | A client library for authenticatingand making requests via OAuth2. | [![pub package](https://img.shields.io/pub/v/oauth2.svg)](https://pub.dev/packages/oauth2) | | [source_map_stack_trace](pkgs/source_map_stack_trace/) | A package for applying source maps to stack traces. | [![pub package](https://img.shields.io/pub/v/source_map_stack_trace.svg)](https://pub.dev/packages/source_map_stack_trace) | diff --git a/pkgs/html/.github/dependabot.yml b/pkgs/html/.github/dependabot.yml deleted file mode 100644 index cde02ad6a..000000000 --- a/pkgs/html/.github/dependabot.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Dependabot configuration file. -# See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates -version: 2 - -updates: - - package-ecosystem: github-actions - directory: / - schedule: - interval: monthly - labels: - - autosubmit - groups: - github-actions: - patterns: - - "*" diff --git a/pkgs/html/.github/workflows/no-response.yml b/pkgs/html/.github/workflows/no-response.yml deleted file mode 100644 index ab1ac4984..000000000 --- a/pkgs/html/.github/workflows/no-response.yml +++ /dev/null @@ -1,37 +0,0 @@ -# A workflow to close issues where the author hasn't responded to a request for -# more information; see https://github.com/actions/stale. - -name: No Response - -# Run as a daily cron. -on: - schedule: - # Every day at 8am - - cron: '0 8 * * *' - -# All permissions not specified are set to 'none'. -permissions: - issues: write - pull-requests: write - -jobs: - no-response: - runs-on: ubuntu-latest - if: ${{ github.repository_owner == 'dart-lang' }} - steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e - with: - # Don't automatically mark inactive issues+PRs as stale. - days-before-stale: -1 - # Close needs-info issues and PRs after 14 days of inactivity. - days-before-close: 14 - stale-issue-label: "needs-info" - close-issue-message: > - Without additional information we're not able to resolve this issue. - Feel free to add more info or respond to any questions above and we - can reopen the case. Thanks for your contribution! - stale-pr-label: "needs-info" - close-pr-message: > - Without additional information we're not able to resolve this PR. - Feel free to add more info or respond to any questions above. - Thanks for your contribution! diff --git a/pkgs/html/.github/workflows/publish.yaml b/pkgs/html/.github/workflows/publish.yaml deleted file mode 100644 index 1cb7e9cfb..000000000 --- a/pkgs/html/.github/workflows/publish.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# A CI configuration to auto-publish pub packages. - -name: Publish - -on: - pull_request: - branches: [ main ] - push: - tags: [ 'v[0-9]+.[0-9]+.[0-9]+' ] - -jobs: - publish: - if: ${{ github.repository_owner == 'dart-lang' }} - uses: dart-lang/ecosystem/.github/workflows/publish.yaml@main - permissions: - id-token: write # Required for authentication using OIDC - pull-requests: write # Required for writing the pull request note diff --git a/pkgs/html/CHANGELOG.md b/pkgs/html/CHANGELOG.md index c0d6cb501..9a881e9d7 100644 --- a/pkgs/html/CHANGELOG.md +++ b/pkgs/html/CHANGELOG.md @@ -1,6 +1,7 @@ -## 0.15.5-wip +## 0.15.5 - Require Dart `3.2`. +- Move to `dart-lang/tools` monorepo. ## 0.15.4 diff --git a/pkgs/html/README.md b/pkgs/html/README.md index 05a19a82c..ed1d000e0 100644 --- a/pkgs/html/README.md +++ b/pkgs/html/README.md @@ -1,4 +1,4 @@ -[![Dart CI](https://github.com/dart-lang/html/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/html/actions/workflows/test-package.yml) +[![Build Status](https://github.com/dart-lang/tools/actions/workflows/html.yaml/badge.svg)](https://github.com/dart-lang/tools/actions/workflows/html.yaml) [![pub package](https://img.shields.io/pub/v/html.svg)](https://pub.dev/packages/html) [![package publisher](https://img.shields.io/pub/publisher/html.svg)](https://pub.dev/packages/html/publisher) diff --git a/pkgs/html/pubspec.yaml b/pkgs/html/pubspec.yaml index 14dcf47f4..930fa4db1 100644 --- a/pkgs/html/pubspec.yaml +++ b/pkgs/html/pubspec.yaml @@ -1,5 +1,5 @@ name: html -version: 0.15.5-wip +version: 0.15.5 description: APIs for parsing and manipulating HTML content outside the browser. repository: https://github.com/dart-lang/tools/tree/main/pkgs/html