Fix newly enforced package:pedantic lints (#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
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 2d3a54d..b8dcf93 100644
--- a/analysis_options.yaml
+++ b/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/lib/dom.dart b/lib/dom.dart
index 08d1c12..835d8da 100644
--- a/lib/dom.dart
+++ b/lib/dom.dart
@@ -36,6 +36,7 @@
 
   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 @@
     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 @@
     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 @@
   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 @@
     }
   }
 
-  _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 @@
   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 @@
   // 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 @@
   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 @@
   // 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 @@
 
   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 @@
   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 @@
     sb.write(data);
   }
 
+  @override
   String get text => data;
+  @override
   set text(String value) {
     data = value;
   }
@@ -484,7 +502,7 @@
     // 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 @@
     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 @@
   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 @@
     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 @@
     return prefix == null ? '' : '$prefix:';
   }
 
+  @override
   Element clone(bool deep) {
     var result = Element._(localName, namespaceUri)
       ..attributes = LinkedHashMap.from(attributes);
@@ -620,7 +644,7 @@
   // 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 @@
   // 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 @@
 
   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 @@
     return node;
   }
 
+  @override
   void add(Node value) {
     if (value is DocumentFragment) {
       addAll(value.nodes);
@@ -697,6 +728,7 @@
 
   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 @@
     super.addAll(list);
   }
 
+  @override
   void insert(int index, Node value) {
     if (value is DocumentFragment) {
       insertAll(index, value.nodes);
@@ -720,10 +753,13 @@
     }
   }
 
+  @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 @@
     super.clear();
   }
 
+  @override
   void operator []=(int index, Node value) {
     if (value is DocumentFragment) {
       removeAt(index);
@@ -743,46 +780,52 @@
 
   // 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 @@
   // 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 @@
     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 @@
     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 @@
 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/lib/dom_parsing.dart b/lib/dom_parsing.dart
index 27eedb3..f16018c 100644
--- a/lib/dom_parsing.dart
+++ b/lib/dom_parsing.dart
@@ -7,7 +7,7 @@
 
 /// 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 @@
     }
   }
 
-  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 @@
   /// 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 @@
 
   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 @@
       });
     }
     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 @@
   // 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 @@
         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 @@
 /// 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/lib/parser.dart b/lib/parser.dart
index 58ae1c8..c4eafb6 100644
--- a/lib/parser.dart
+++ b/lib/parser.dart
@@ -56,7 +56,7 @@
 /// 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 @@
 
   // 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 @@
       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 @@
   /// 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 @@
     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 @@
   }
 
   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 @@
 
     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 @@
       }
     }
 
-    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 @@
           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 @@
 
       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 @@
   }
 
   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 @@
     // 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 @@
     // 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 @@
       // 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 @@
         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 @@
   /// 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 @@
   }
 
   Token processDoctype(DoctypeToken token) {
-    parser.parseError(token.span, "unexpected-doctype");
+    parser.parseError(token.span, 'unexpected-doctype');
     return null;
   }
 
@@ -634,8 +634,8 @@
   }
 
   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 @@
 
   /// 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 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 @@
   // 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 BeforeHeadPhase extends Phase {
   BeforeHeadPhase(parser) : super(parser);
 
+  @override
   Token processStartTag(StartTagToken token) {
     switch (token.name) {
       case 'html':
@@ -887,12 +900,13 @@
     }
   }
 
+  @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 @@
     }
   }
 
+  @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 @@
   }
 
   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 @@
     }
   }
 
+  @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 @@
   }
 
   // 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 @@
 
     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 @@
   }
 
   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 @@
 
   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 @@
   }
 
   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 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 @@
     }
   }
 
+  @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 @@
     }
   }
 
+  @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 @@
   }
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
   // 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 @@
     }
   }
 
+  @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 @@
   }
 
   // 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 @@
     // 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 @@
     }
   }
 
+  @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 @@
     return null;
   }
 
+  @override
   Token processSpaceCharacters(SpaceCharactersToken token) {
     if (dropNewline) {
       processSpaceCharactersDropNewline(token);
@@ -1561,9 +1594,9 @@
   }
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
 
   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 @@
     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 @@
         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 @@
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
   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 @@
   }
 
   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 @@
 
   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 @@
 
   /// 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 @@
   }
 
   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 @@
   /// "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 @@
   }
 
   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 @@
 
   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 @@
 
   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 @@
       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 @@
     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 @@
 
   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 @@
       }
     }
     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 @@
     // 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 @@
           (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 @@
       // 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 @@
       }
       // 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 @@
       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 @@
         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 @@
       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 @@
   }
 
   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 @@
         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 @@
       } 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 @@
   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 @@
     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 @@
 
   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 @@
   // 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 @@
     }
   }
 
+  @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 @@
 
   // 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 @@
   }
 
   // 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 @@
     return false;
   }
 
+  @override
   Token processSpaceCharacters(SpaceCharactersToken token) {
     var originalPhase = parser.phase;
     parser.phase = parser._inTableTextPhase;
@@ -2381,6 +2420,7 @@
     return null;
   }
 
+  @override
   Token processCharacters(CharactersToken token) {
     var originalPhase = parser.phase;
     parser.phase = parser._inTableTextPhase;
@@ -2412,7 +2452,7 @@
 
   Token startTagCol(StartTagToken token) {
     startTagColgroup(
-        StartTagToken("colgroup", data: LinkedHashMap<dynamic, String>()));
+        StartTagToken('colgroup', data: LinkedHashMap<dynamic, String>()));
     return token;
   }
 
@@ -2424,14 +2464,14 @@
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
   }
 
   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 @@
     } 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 @@
     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 @@
     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 @@
   // 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 @@
   }
 
   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 @@
     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 @@
     } 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 @@
   }
 
   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 @@
   // 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 @@
     }
   }
 
+  @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 @@
   }
 
   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 @@
 
   Token startTagOther(StartTagToken token) {
     var ignoreEndTag = ignoreEndTagColgroup();
-    endTagColgroup(EndTagToken("colgroup"));
+    endTagColgroup(EndTagToken('colgroup'));
     return ignoreEndTag ? null : token;
   }
 
@@ -2756,7 +2810,7 @@
     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 @@
   }
 
   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 @@
   // 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 @@
 
   // 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 @@
 
   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 @@
   }
 
   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 @@
   // 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 @@
   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 @@
   }
 
   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 @@
     } 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 @@
   // 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 @@
 
   // 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 @@
   }
 
   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 @@
       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 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 @@
   }
 
   // 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 @@
 
   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 @@
 
   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 @@
   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 @@
   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 @@
 
   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 @@
     }
   }
 
+  @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 @@
     }
   }
 
+  @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 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 @@
   }
 
   //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 @@
     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 @@
       }
     }
     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 @@
 
   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 @@
   // 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 @@
     }
   }
 
+  @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 @@
 
   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 @@
 
   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 @@
   // 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 @@
     }
   }
 
+  @override
   Token processEndTag(EndTagToken token) {
     switch (token.name) {
-      case "html":
+      case 'html':
         endTagHtml(token);
         return null;
       default:
@@ -3754,10 +3845,12 @@
   }
 
   // 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 @@
   }
 
   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 @@
 
   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 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 @@
     }
   }
 
+  @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 @@
 
   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 @@
 /// Error in parsed document.
 class ParseError implements SourceSpanException {
   final String errorCode;
+  @override
   final SourceSpan span;
   final Map data;
 
@@ -3893,8 +4001,10 @@
   /// [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 @@
 
 /// 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/lib/src/constants.dart b/lib/src/constants.dart
index 34addfc..e8d0f62 100644
--- a/lib/src/constants.dart
+++ b/lib/src/constants.dart
@@ -11,7 +11,8 @@
 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 @@
 /// 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 @@
 }
 
 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 @@
 }
 
 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 @@
 // 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 @@
 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 @@
 }
 
 // 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 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 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/lib/src/css_class_set.dart b/lib/src/css_class_set.dart
index 939bf41..3fa49e0 100644
--- a/lib/src/css_class_set.dart
+++ b/lib/src/css_class_set.dart
@@ -14,12 +14,13 @@
 
   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 @@
     return s;
   }
 
+  @override
   void writeClasses(Set<String> s) {
     _element.className = s.join(' ');
   }
@@ -49,6 +51,7 @@
   ///
   /// 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 @@
   /// 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 @@
   ///
   /// 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 _CssClassSetImpl extends SetBase<String> implements CssClassSet {
+  @override
   String toString() {
     return readClasses().join(' ');
   }
@@ -102,10 +110,11 @@
   ///
   /// 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 @@
 
   /// 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 @@
   ///
   /// 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 @@
   ///
   /// 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 @@
   /// 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 @@
   ///
   ///   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/lib/src/encoding_parser.dart b/lib/src/encoding_parser.dart
index d0f40d6..51766a9 100644
--- a/lib/src/encoding_parser.dart
+++ b/lib/src/encoding_parser.dart
@@ -17,7 +17,7 @@
   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 @@
   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 @@
 
   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 @@
 
   /// 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 @@
       __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 @@
 
   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 @@
   }
 
   /// Skip over comments.
-  bool _handleComment() => _data._jumpTo("-->");
+  bool _handleComment() => _data._jumpTo('-->');
 
   bool _handleMeta() {
     if (!isWhitespace(_data._currentByte)) {
@@ -182,14 +182,14 @@
       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 @@
     }
 
     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 @@
     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 @@
     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 @@
       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 @@
           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 @@
     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 @@
 }
 
 bool _isSpaceOrAngleBracket(String char) {
-  return char == ">" || char == "<" || isWhitespace(char);
+  return char == '>' || char == '<' || isWhitespace(char);
 }
 
 typedef _CharPredicate = bool Function(String char);
diff --git a/lib/src/html_input_stream.dart b/lib/src/html_input_stream.dart
index 4590c5d..0b72da7 100644
--- a/lib/src/html_input_stream.dart
+++ b/lib/src/html_input_stream.dart
@@ -91,14 +91,12 @@
     _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 @@
   /// 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 @@
 /// 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 @@
 /// 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/lib/src/list_proxy.dart b/lib/src/list_proxy.dart
index 63aeea6..ef271ab 100644
--- a/lib/src/list_proxy.dart
+++ b/lib/src/list_proxy.dart
@@ -7,40 +7,52 @@
   /// 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/lib/src/query_selector.dart b/lib/src/query_selector.dart
index 0503707..0c660b7 100644
--- a/lib/src/query_selector.dart
+++ b/lib/src/query_selector.dart
@@ -58,9 +58,11 @@
     }
   }
 
+  @override
   bool visitSelectorGroup(SelectorGroup group) =>
       group.selectors.any(visitSelector);
 
+  @override
   bool visitSelector(Selector selector) {
     var old = _element;
     var result = true;
@@ -123,13 +125,14 @@
     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 @@
     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 @@
     }
   }
 
+  @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 @@
     return null;
   }
 
+  @override
   bool visitNamespaceSelector(NamespaceSelector selector) {
     // Match element tag name
     if (!selector.nameAsSimpleSelector.visit(this)) return false;
@@ -250,20 +257,25 @@
     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/lib/src/token.dart b/lib/src/token.dart
index ea0a855..e92ec8e 100644
--- a/lib/src/token.dart
+++ b/lib/src/token.dart
@@ -39,6 +39,7 @@
       this.namespace})
       : super(name, selfClosing);
 
+  @override
   int get kind => TokenKind.startTag;
 }
 
@@ -46,6 +47,7 @@
   EndTagToken(String name, {bool selfClosing = false})
       : super(name, selfClosing);
 
+  @override
   int get kind => TokenKind.endTag;
 }
 
@@ -77,12 +79,14 @@
 
   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 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/lib/src/tokenizer.dart b/lib/src/tokenizer.dart
index 638663e..cf67744 100644
--- a/lib/src/tokenizer.dart
+++ b/lib/src/tokenizer.dart
@@ -84,6 +84,7 @@
   StringToken get currentStringToken => currentToken;
 
   Token _current;
+  @override
   Token get current => _current;
 
   final StringBuffer _attributeName = StringBuffer();
@@ -107,7 +108,7 @@
   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 @@
   /// 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 @@
   /// 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 @@
     // 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 @@
             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 @@
 
   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 @@
         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 @@
         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 @@
       //
       // 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 @@
 
       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 @@
       }
       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 @@
 
   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 @@
       // 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 @@
 
   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 @@
       _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 @@
 
   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 @@
     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 @@
 
   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 @@
     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 @@
     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 @@
 
   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 @@
       _buffer.write(data);
       state = rcdataEndTagNameState;
     } else {
-      _addToken(CharactersToken("</"));
+      _addToken(CharactersToken('</'));
       stream.unget(data);
       state = rcdataState;
     }
@@ -626,17 +627,17 @@
     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 @@
 
   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 @@
       _buffer.write(data);
       state = rawtextEndTagNameState;
     } else {
-      _addToken(CharactersToken("</"));
+      _addToken(CharactersToken('</'));
       stream.unget(data);
       state = rawtextState;
     }
@@ -675,17 +676,17 @@
     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 @@
 
   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 @@
       _buffer.write(data);
       state = scriptDataEndTagNameState;
     } else {
-      _addToken(CharactersToken("</"));
+      _addToken(CharactersToken('</'));
       stream.unget(data);
       state = scriptDataState;
     }
@@ -727,17 +728,17 @@
     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 @@
 
   bool scriptDataEscapeStartState() {
     var data = stream.char();
-    if (data == "-") {
-      _addToken(CharactersToken("-"));
+    if (data == '-') {
+      _addToken(CharactersToken('-'));
       state = scriptDataEscapeStartDashState;
     } else {
       stream.unget(data);
@@ -758,8 +759,8 @@
 
   bool scriptDataEscapeStartDashState() {
     var data = stream.char();
-    if (data == "-") {
-      _addToken(CharactersToken("-"));
+    if (data == '-') {
+      _addToken(CharactersToken('-'));
       state = scriptDataEscapedDashDashState;
     } else {
       stream.unget(data);
@@ -770,33 +771,33 @@
 
   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 @@
 
   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 @@
 
   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 @@
       _buffer.write(data);
       state = scriptDataEscapedEndTagNameState;
     } else {
-      _addToken(CharactersToken("</"));
+      _addToken(CharactersToken('</'));
       stream.unget(data);
       state = scriptDataEscapedState;
     }
@@ -867,17 +868,17 @@
     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 @@
 
   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 @@
 
   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 @@
 
   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 @@
   // (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 @@
 
   bool scriptDataDoubleEscapedLessThanSignState() {
     var data = stream.char();
-    if (data == "/") {
-      _addToken(CharactersToken("/"));
+    if (data == '/') {
+      _addToken(CharactersToken('/'));
       _buffer.clear();
       state = scriptDataDoubleEscapeEndState;
     } else {
@@ -986,9 +987,9 @@
 
   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 @@
     } 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 @@
 
   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 @@
         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 @@
     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 @@
     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 @@
 
   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 @@
       _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 @@
     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 @@
     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 @@
 
   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 @@
     // 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 @@
 
   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 @@
         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 @@
       }
     }
 
-    _addToken(ParseErrorToken("expected-dashes-or-doctype"));
+    _addToken(ParseErrorToken('expected-dashes-or-doctype'));
 
     while (charStack.isNotEmpty) {
       stream.unget(charStack.removeLast());
@@ -1340,17 +1341,17 @@
 
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
 
   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 @@
     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 @@
     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 @@
     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 @@
     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 @@
           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 @@
       // 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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 @@
 
   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 @@
     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 @@
     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 @@
 
   bool bogusDoctypeState() {
     var data = stream.char();
-    if (data == ">") {
+    if (data == '>') {
       _addToken(currentToken);
       state = dataState;
     } else if (data == eof) {
@@ -1870,24 +1871,24 @@
   }
 
   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/lib/src/treebuilder.dart b/lib/src/treebuilder.dart
index f6db7ad..e096214 100644
--- a/lib/src/treebuilder.dart
+++ b/lib/src/treebuilder.dart
@@ -21,8 +21,9 @@
   // 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 @@
   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 @@
     }
 
     // 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 @@
   }
 
   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 @@
 
   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 @@
         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 @@
     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 @@
     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/lib/src/utils.dart b/lib/src/utils.dart
index 54b578b..fec6870 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -11,14 +11,16 @@
 
   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 @@
 
 // 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 @@
 }
 
 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 @@
   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 @@
       result.write(format.substring(last, match));
       match += search.length;
 
-      int digits = match;
+      var digits = match;
       while (isDigit(format[digits])) {
         digits++;
       }
@@ -112,8 +114,8 @@
           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/test/dom_test.dart b/test/dom_test.dart
index 1cf912e..078c3c7 100644
--- a/test/dom_test.dart
+++ b/test/dom_test.dart
@@ -5,7 +5,7 @@
 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/test/parser_feature_test.dart b/test/parser_feature_test.dart
index 0889f44..536f98f 100644
--- a/test/parser_feature_test.dart
+++ b/test/parser_feature_test.dart
@@ -9,7 +9,7 @@
 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 @@
 
   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 @@
     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 @@
     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 @@
   });
 
   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 @@
   });
 }
 
-_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/test/parser_test.dart b/test/parser_test.dart
index 1db1586..21c54d2 100644
--- a/test/parser_test.dart
+++ b/test/parser_test.dart
@@ -19,15 +19,15 @@
   // 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 @@
 
   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 @@
   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 @@
         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 @@
 }
 
 /// 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/test/selectors/level1_baseline_test.dart b/test/selectors/level1_baseline_test.dart
index 7ed1cc4..d5defb1 100644
--- a/test/selectors/level1_baseline_test.dart
+++ b/test/selectors/level1_baseline_test.dart
@@ -23,9 +23,9 @@
 }
 
 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 @@
   //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 @@
 
   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 @@
   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 @@
       outOfScope.remove();
     });
     runValidSelectorTest(
-        "In-document Element", element, validSelectors, testType, docType);
+        'In-document Element', element, validSelectors, testType, docType);
   });
 }
diff --git a/test/selectors/level1_lib.dart b/test/selectors/level1_lib.dart
index d87c795..f97dafc 100644
--- a/test/selectors/level1_lib.dart
+++ b/test/selectors/level1_lib.dart
@@ -17,47 +17,47 @@
 /*
  * 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 @@
 /*
  * 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 @@
  * 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 @@
  * 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 @@
   }
 }
 
-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/test/selectors/selectors.dart b/test/selectors/selectors.dart
index 9810f5f..e18f264 100644
--- a/test/selectors/selectors.dart
+++ b/test/selectors/selectors.dart
@@ -21,41 +21,41 @@
  *   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': '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': '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': '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 @@
 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 @@
   // 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 @@
   // 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 @@
 
   // - 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 @@
   // - 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 @@
   // - 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 @@
   // - 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 @@
   // - 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 @@
   // - 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 @@
   // 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 @@
   // - :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 @@
     '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 @@
   // - :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 @@
     '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 @@
   // - :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 @@
   // - :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 @@
   // 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 @@
   // - :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 @@
   // - :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 @@
   // - :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 @@
   // - :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 @@
 
   // - :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 @@
   // - ::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 @@
   // - ::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 @@
   // - ::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 @@
   // - ::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 @@
 
   // 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 @@
 
   // 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 @@
   // 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 @@
   // - 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 @@
   // - 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 @@
   // - 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 @@
   // - 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/test/support.dart b/test/support.dart
index 83e137a..afcf952 100644
--- a/test/support.dart
+++ b/test/support.dart
@@ -13,10 +13,8 @@
 
 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 @@
   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 @@
           data = <String, String>{};
         }
         key = heading;
-        data[key] = "";
+        data[key] = '';
       } else if (key != null) {
         data[key] = '${data[key]}$line\n';
       }
@@ -77,13 +76,13 @@
   /// 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 @@
 }
 
 /// Serialize the [document] into the html5 test data format.
-testSerializer(document) {
+String testSerializer(document) {
   return (TestSerializer()..visit(document)).toString();
 }
 
@@ -104,6 +103,7 @@
 
   TestSerializer() : _str = StringBuffer();
 
+  @override
   String toString() => _str.toString();
 
   int get indent => _indent;
@@ -112,7 +112,7 @@
     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 @@
     _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 @@
     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 @@
     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 @@
         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/test/tokenizer_test.dart b/test/tokenizer_test.dart
index 3d2aeb3..62d5f8a 100644
--- a/test/tokenizer_test.dart
+++ b/test/tokenizer_test.dart
@@ -73,20 +73,20 @@
 
   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 @@
   }
 
   void processCharacters(StringToken token) {
-    addOutputToken(token, ["Character", token.data]);
+    addOutputToken(token, ['Character', token.data]);
   }
 
   void processEOF(token) {}
@@ -103,7 +103,7 @@
     // 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 @@
 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 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 @@
   // 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 @@
 
   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 @@
     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 @@
   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 @@
   // 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 @@
 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 @@
     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);
           });
         }