]> git.earlybird.gay Git - today/commitdiff
Add 'engine/' from commit 'af763240f03d2f9f91c3bb3cce15d320acfd6223'
authorearly <me@earlybird.gay>
Sat, 2 Nov 2024 18:22:45 +0000 (12:22 -0600)
committerearly <me@earlybird.gay>
Sat, 2 Nov 2024 18:22:45 +0000 (12:22 -0600)
git-subtree-dir: engine
git-subtree-mainline: a4b4db1b57a547474699d6c3213aa9e6663709cc
git-subtree-split: af763240f03d2f9f91c3bb3cce15d320acfd6223

132 files changed:
1  2 
engine/.gitignore
engine/LICENSE.txt
engine/README.md
engine/cmd/standard-test/main.go
engine/cmd/standard-test/pages/index.html
engine/cmd/standard-test/pages/static.html
engine/cmd/standard-test/public/style.css
engine/cmd/standard-test/test_thing.html
engine/component/component.go
engine/go.mod
engine/go.sum
engine/htmltree/attrs.go
engine/htmltree/prettify.go
engine/include/callstack.go
engine/include/include.go
engine/internal/compile/compile.go
engine/internal/compile/component.go
engine/internal/compile/compute.go
engine/internal/compile/conversions.go
engine/internal/compile/template.go
engine/internal/html/LICENSE
engine/internal/html/PATENTS
engine/internal/html/README.md
engine/internal/html/atom/atom.go
engine/internal/html/atom/atom_test.go
engine/internal/html/atom/gen.go
engine/internal/html/atom/table.go
engine/internal/html/atom/table_test.go
engine/internal/html/charset/charset.go
engine/internal/html/charset/charset_test.go
engine/internal/html/charset/testdata/HTTP-charset.html
engine/internal/html/charset/testdata/HTTP-vs-UTF-8-BOM.html
engine/internal/html/charset/testdata/HTTP-vs-meta-charset.html
engine/internal/html/charset/testdata/HTTP-vs-meta-content.html
engine/internal/html/charset/testdata/No-encoding-declaration.html
engine/internal/html/charset/testdata/README
engine/internal/html/charset/testdata/UTF-16BE-BOM.html
engine/internal/html/charset/testdata/UTF-16LE-BOM.html
engine/internal/html/charset/testdata/UTF-8-BOM-vs-meta-charset.html
engine/internal/html/charset/testdata/UTF-8-BOM-vs-meta-content.html
engine/internal/html/charset/testdata/meta-charset-attribute.html
engine/internal/html/charset/testdata/meta-content-attribute.html
engine/internal/html/comment_test.go
engine/internal/html/const.go
engine/internal/html/doc.go
engine/internal/html/doctype.go
engine/internal/html/entity.go
engine/internal/html/entity_test.go
engine/internal/html/escape.go
engine/internal/html/escape_test.go
engine/internal/html/example_test.go
engine/internal/html/foreign.go
engine/internal/html/node.go
engine/internal/html/node_test.go
engine/internal/html/parse.go
engine/internal/html/parse_test.go
engine/internal/html/render.go
engine/internal/html/render_test.go
engine/internal/html/testdata/go/issue_30600_parse_panics_in_cell_mode.dat
engine/internal/html/testdata/go/issue_30961_error_nested_unknown_tag_types.dat
engine/internal/html/testdata/go/raw_tags_to_be_ignored.dat
engine/internal/html/testdata/go/select.dat
engine/internal/html/testdata/go/template.dat
engine/internal/html/testdata/go1.html
engine/internal/html/testdata/webkit/README
engine/internal/html/testdata/webkit/adoption01.dat
engine/internal/html/testdata/webkit/adoption02.dat
engine/internal/html/testdata/webkit/blocks.dat
engine/internal/html/testdata/webkit/comments01.dat
engine/internal/html/testdata/webkit/doctype01.dat
engine/internal/html/testdata/webkit/domjs-unsafe.dat
engine/internal/html/testdata/webkit/entities01.dat
engine/internal/html/testdata/webkit/entities02.dat
engine/internal/html/testdata/webkit/foreign-fragment.dat
engine/internal/html/testdata/webkit/html5test-com.dat
engine/internal/html/testdata/webkit/inbody01.dat
engine/internal/html/testdata/webkit/isindex.dat
engine/internal/html/testdata/webkit/main-element.dat
engine/internal/html/testdata/webkit/math.dat
engine/internal/html/testdata/webkit/menuitem-element.dat
engine/internal/html/testdata/webkit/namespace-sensitivity.dat
engine/internal/html/testdata/webkit/noscript01.dat
engine/internal/html/testdata/webkit/pending-spec-changes-plain-text-unsafe.dat
engine/internal/html/testdata/webkit/pending-spec-changes.dat
engine/internal/html/testdata/webkit/plain-text-unsafe.dat
engine/internal/html/testdata/webkit/ruby.dat
engine/internal/html/testdata/webkit/scriptdata01.dat
engine/internal/html/testdata/webkit/scripted/adoption01.dat
engine/internal/html/testdata/webkit/scripted/ark.dat
engine/internal/html/testdata/webkit/scripted/webkit01.dat
engine/internal/html/testdata/webkit/svg.dat
engine/internal/html/testdata/webkit/tables01.dat
engine/internal/html/testdata/webkit/template.dat
engine/internal/html/testdata/webkit/tests1.dat
engine/internal/html/testdata/webkit/tests10.dat
engine/internal/html/testdata/webkit/tests11.dat
engine/internal/html/testdata/webkit/tests12.dat
engine/internal/html/testdata/webkit/tests14.dat
engine/internal/html/testdata/webkit/tests15.dat
engine/internal/html/testdata/webkit/tests16.dat
engine/internal/html/testdata/webkit/tests17.dat
engine/internal/html/testdata/webkit/tests18.dat
engine/internal/html/testdata/webkit/tests19.dat
engine/internal/html/testdata/webkit/tests2.dat
engine/internal/html/testdata/webkit/tests20.dat
engine/internal/html/testdata/webkit/tests21.dat
engine/internal/html/testdata/webkit/tests22.dat
engine/internal/html/testdata/webkit/tests23.dat
engine/internal/html/testdata/webkit/tests24.dat
engine/internal/html/testdata/webkit/tests25.dat
engine/internal/html/testdata/webkit/tests26.dat
engine/internal/html/testdata/webkit/tests3.dat
engine/internal/html/testdata/webkit/tests4.dat
engine/internal/html/testdata/webkit/tests5.dat
engine/internal/html/testdata/webkit/tests6.dat
engine/internal/html/testdata/webkit/tests7.dat
engine/internal/html/testdata/webkit/tests8.dat
engine/internal/html/testdata/webkit/tests9.dat
engine/internal/html/testdata/webkit/tests_innerHTML_1.dat
engine/internal/html/testdata/webkit/tricky01.dat
engine/internal/html/testdata/webkit/webkit01.dat
engine/internal/html/testdata/webkit/webkit02.dat
engine/internal/html/token.go
engine/internal/html/token_test.go
engine/page/page.go
engine/page/serve.go
engine/part/part.go
engine/render/data.go
engine/render/id.go
engine/run.go
engine/standard/part/contact_form.go
engine/standard/part/contact_form.html

index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..38454277d0142c3e15aabf4264fd9fd10f18cafd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++# Ignore anything ending in local
++*local
++
++# Disregard ignore rules for example files
++!*.example
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a8876ed210f4173fd04a8b41a7f6522ea2dd1a64
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++Copyright © 2024 Early
++
++Permission is hereby granted, free of charge, to any person obtaining a copy of
++this software and associated documentation files (the “Software”), to deal in
++the Software without restriction, including without limitation the rights to
++use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
++the Software, and to permit persons to whom the Software is furnished to do so,
++subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
++FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
++COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
++IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..df9e1df941c409777fdb2e9d573f6817d2ac697f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,31 @@@
++# Today Engine
++
++The Today engine builds on Go's templating with reusable parts in the style of
++the Web Components standard. It aims to be usable for anything from static HTML
++websites to complex applications with a mix of server and client-side behavior.
++
++Author: Early N.
++License: MIT, BSD
++
++## Installation
++
++go get git.earlybird.gay/today-engine@latest
++
++## Why?
++
++In short, to help guide new developers in making a website (today). The
++technologies that dominate the modern web are complex in unique ways that do
++not promote foundational knowledge of the web platform. Today focuses on:
++
++- Building websites from a basis of standard HTML/CSS
++- Promoting use of the Web Components standard of JS
++- Expanding on Go's robust template system with reusable chunks of HTML
++
++## How?
++
++## License
++
++The portions of `today-engine` owned by Early N. are under the MIT license. Some
++code sections have a different license:
++
++- `package html` is under a BSD-3-Clause style license from Google.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..88fad7c8c4ac66a690bd4f339bee5708933cbbb6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,54 @@@
++package main
++
++import (
++      "context"
++      "net/http"
++      "syscall"
++      "text/template"
++
++      tapp "git.earlybird.gay/today-app/app"
++      "git.earlybird.gay/today-engine/page"
++      "git.earlybird.gay/today-engine/part"
++      "git.earlybird.gay/today-engine/render"
++      stdpart "git.earlybird.gay/today-engine/standard/part"
++)
++
++var Thing = part.New("test-thing", "test_thing.html",
++      part.OnLoad(func(ctx context.Context, data render.Data) error {
++              // fmt.Println(data.Get("value"))
++              return nil
++      }),
++)
++
++var Page = page.New("index", "pages/index.html",
++      page.Includes(
++              stdpart.ContactForm([]string{"Feedback"}), Thing,
++      ),
++      page.Funcs(template.FuncMap{
++              "SliceOfLen": func(i int) []int {
++                      out := make([]int, i)
++                      for i := range i {
++                              out[i] = i
++                      }
++                      return out
++              },
++      }),
++)
++
++var Static = page.Static("pages/static.html")
++
++func main() {
++      app := tapp.New()
++      tapp.GetEnv().Apply(app)
++      app.ShutdownOnSignal(syscall.SIGINT, syscall.SIGTERM)
++
++      app.Handle("GET /{$}", Page)
++      app.Handle("GET /static", Static)
++      app.Handle("GET /", http.FileServer(http.Dir("public")))
++      app.Handle("GET /contact", stdpart.HandleContactForm(nil, stdpart.PrintContact))
++      app.Handle("POST /contact", stdpart.HandleContactForm(nil, stdpart.PrintContact))
++
++      // fmt.Println(Page.Raw())
++
++      app.ListenAndServe()
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b7a2f80041b77a0d7645bb0c0375fdc1c5c5641f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,22 @@@
++<!DOCTYPE html>
++<html>
++
++<head>
++    <title>Today Engine Examples</title>
++    <link rel="stylesheet" href="/style.css">
++</head>
++
++<body>
++    <main>
++        <stdp-contact-form :action="/contact" id="cf-get"></stdp-contact-form>
++        <stdp-contact-form :action="/contact" :method="POST" id="cf-post"></stdp-contact-form>
++
++        {{- range $i, $v := SliceOfLen 5 }}
++        <test-thing :value="."></test-thing>
++        {{ end -}}
++
++        <a href="/static">Link to static page</a>
++    </main>
++</body>
++
++</html>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e03b202ddb5678159b708e91363acf312dff7748
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++<!DOCTYPE html>
++<html>
++
++<head>
++    <title>Today Engine Examples</title>
++    <link rel="stylesheet" href="/style.css">
++</head>
++
++<body>
++    <main>
++      <h1>This is a normal static page.</h1>
++      <p>It doesn't do anything except exist. Neat.</p>
++    </main>
++</body>
++
++</html>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c0a3157c552e55b730ba14d20cd08ff4d675527e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++/* The Great Reset */
++* {
++    padding: 0;
++    margin: 0;
++}
++
++/* Containers */
++
++html {
++    font-family: sans-serif;
++}
++
++main, section, nav {
++    display: flex;
++    flex-direction: column;
++    gap: 1rem;
++}
++
++main {
++    margin: 2rem 25%;
++}
++
++span {
++    display: inline;
++}
++
++span + span {
++    margin-left: .5rem;
++}
++
++/* Forms */
++
++form {
++    display: grid;
++    grid-template-columns: 1fr 3fr;
++    gap: .5rem;
++}
++
++form > input[type="submit"] {
++    grid-column: span 2;
++}
++
++/* Typography */
++
++:not(pre) > code {
++    font-size: 1rem;
++}
++
++li {
++    margin-left: 20px;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5988d75a339d1ecc2fd486d538a01468e2fee849
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++<template>
++  <p>{{ .value }}</p>
++</template>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..22370e2bee4f9f5c6851bff308e4b71c5c11b890
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,52 @@@
++// Copyright (C) 2024 early (LGPL)
++package component
++
++import (
++      "git.earlybird.gay/today-engine/include"
++      "git.earlybird.gay/today-engine/internal/compile"
++)
++
++type Component struct {
++      name     string
++      fileName string
++      source   include.Opener
++
++      includes []compile.Source
++}
++
++type Config func(*Component)
++
++func Includes(includes ...compile.Source) Config {
++      return func(p *Component) {
++              p.includes = includes
++      }
++}
++
++func New(name string, source string, optional ...func(*Component)) *Component {
++      p := new(Component)
++      // Assign basic parameters
++      p.name = name
++      p.fileName = source
++      p.source = include.File(source, "git.earlybird.gay/today-engine/component")
++      // Run optional arguments
++      for _, of := range optional {
++              of(p)
++      }
++      return p
++}
++
++func (p *Component) Name() string {
++      return p.name
++}
++
++func (p *Component) FileName() string {
++      return p.fileName
++}
++
++func (p *Component) File() include.Opener {
++      return p.source
++}
++
++func (p *Component) Includes() []compile.Source {
++      return p.includes
++}
diff --cc engine/go.mod
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fb5c1b4f80be11835abf49b8ab97a1993feeffb8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++module git.earlybird.gay/today-engine
++
++go 1.22.4
++
++require (
++      git.earlybird.gay/today-app v0.0.0-20240813010007-675f08ae35b1
++      golang.org/x/text v0.17.0
++)
diff --cc engine/go.sum
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ca1ee0b6aba21ffde806d76ae89136519dbb3248
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++git.earlybird.gay/today-app v0.0.0-20240813010007-675f08ae35b1 h1:Fbz2uRIWK6CR+jcNN0KQrna4u/kYZccn2obcla7dPfQ=
++git.earlybird.gay/today-app v0.0.0-20240813010007-675f08ae35b1/go.mod h1:AxsoC2ERffYriW60C1vdV34ew6JPKxllG9mHOTs128I=
++golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc=
++golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4d9ab2e9edcafe4dc0a1d3ab7b92e8babc6bc24b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,22 @@@
++// Copyright (C) 2024 early (LGPL)
++package htmltree
++
++import "git.earlybird.gay/today-engine/internal/html"
++
++func GetAttr(n *html.Node, name string) string {
++      for _, attr := range n.Attr {
++              if attr.Key == name {
++                      return attr.Val
++              }
++      }
++      return ""
++}
++
++func SetAttr(n *html.Node, name string, value string) {
++      for i, attr := range n.Attr {
++              if attr.Key == name {
++                      n.Attr = append(n.Attr[:i], n.Attr[i+1:]...)
++              }
++      }
++      n.Attr = append(n.Attr, html.Attribute{Key: name, Val: value})
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..33fbdd0e5675e00c8aa0cb4e62501c0e220e8ccb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,142 @@@
++// Copyright (C) 2024 early (LGPL)
++package htmltree
++
++import (
++      "fmt"
++      "regexp"
++      "strings"
++
++      "git.earlybird.gay/today-engine/internal/html"
++)
++
++func Walk(root *html.Node, f func(*html.Node) (bool, error)) error {
++      var node, child *html.Node
++      var siblings []*html.Node
++      var stop bool
++      var err error
++
++      node = root
++
++      for node != nil && err == nil {
++              child = node.FirstChild
++              if node.NextSibling != nil {
++                      siblings = append(siblings, node.NextSibling)
++              }
++              stop, err = f(node)
++
++              if !stop && child != nil {
++                      node = child
++                      child = nil
++              } else if nextSibling := len(siblings) - 1; nextSibling != -1 {
++                      node = siblings[nextSibling]
++                      siblings = siblings[:nextSibling]
++              } else {
++                      node = nil
++              }
++      }
++      return err
++}
++
++func Print(root *html.Node) {
++      Walk(root, func(n *html.Node) (bool, error) {
++              fmt.Printf("%p: %+v\n", n, n)
++              return false, nil
++      })
++}
++
++func doctype(n *html.Node) bool {
++      return n.Type == html.DoctypeNode
++}
++
++func comment(n *html.Node) bool {
++      return n.Type == html.CommentNode
++}
++
++func template(n *html.Node) bool {
++      return n.Type == html.TextNode && strings.HasPrefix(n.Data, "{{")
++}
++
++func elem(n *html.Node) bool {
++      return n.Type == html.ElementNode || comment(n) || template(n)
++}
++
++var unindentRegexp = regexp.MustCompile(`^\n\s*`)
++var despaceRegexp = regexp.MustCompile(`\n\s*`)
++
++func Minify() func(root *html.Node) {
++      return func(root *html.Node) {
++              Walk(root, func(n *html.Node) (bool, error) {
++                      if n.Type == html.ElementNode && n.Data == "pre" {
++                              return true, nil
++                      }
++                      if n.Type == html.ElementNode && n.Data == "script" {
++                              return true, nil
++                      }
++                      if n.Type == html.TextNode {
++                              n.Data = unindentRegexp.ReplaceAllString(n.Data, "")
++                              n.Data = despaceRegexp.ReplaceAllString(n.Data, " ")
++                              if n.PrevSibling == nil {
++                                      n.Data = strings.TrimLeft(n.Data, " \t")
++                              }
++                              if n.NextSibling == nil {
++                                      n.Data = strings.TrimRight(n.Data, " \t")
++                              }
++                              // Remove empty nodes
++                              if n.Data == "" {
++                                      n.Parent.RemoveChild(n)
++                              }
++                      }
++                      return false, nil
++              })
++      }
++}
++
++func spacer(indent string, depth int) *html.Node {
++      return &html.Node{
++              Type: html.TextNode,
++              Data: "\n" + strings.Repeat(indent, depth),
++      }
++}
++
++func pad(n *html.Node, indent string, depth int) {
++      if depth == 0 {
++              return
++      }
++      n.InsertBefore(spacer(indent, depth), n.FirstChild)
++      n.InsertBefore(spacer(indent, depth-1), nil)
++}
++
++func newline(n *html.Node, indent string, depth int) {
++      if n.Parent == nil {
++              return
++      }
++      n.Parent.InsertBefore(spacer(indent, depth), n.NextSibling)
++}
++
++func Prettify(indent string) func(root *html.Node) {
++      return func(root *html.Node) {
++              Minify()(root)
++
++              var prettify func(n *html.Node, depth int)
++
++              prettify = func(n *html.Node, depth int) {
++                      if n == nil {
++                              return
++                      }
++                      if elem(n) && n.Data == "pre" {
++                              return
++                      }
++                      if n.NextSibling != nil && (elem(n) || doctype(n)) && elem(n.NextSibling) {
++                              newline(n, indent, depth-1)
++                      }
++                      if n.FirstChild != nil && elem(n.FirstChild) {
++                              pad(n, indent, depth)
++                      }
++
++                      prettify(n.FirstChild, depth+1)
++                      prettify(n.NextSibling, depth)
++              }
++
++              prettify(root, 0)
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..15e49101cb93982cfdd4842ea1060a1fff97e4c3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,64 @@@
++// Copyright (C) 2024 early (LGPL)
++package include
++
++import (
++      "errors"
++      "runtime"
++      "slices"
++      "strings"
++)
++
++var ErrNoEligibleCaller = errors.New("no eligible caller on the stack")
++var ErrNoRuntimeAccess = errors.New("couldn't access the runtime")
++
++var callStackNotEligible = []string{
++      "runtime",
++      "git.earlybird.gay/today-engine/include",
++}
++
++// SetNotEligible marks a package as ineligible for including files.
++// You should use the arguments of include to to this if you can, but if you are
++// using a package that passes through to include, you can call this in an init
++// function.
++func SetNotEligible(pkg string) {
++      callStackNotEligible = append(callStackNotEligible, pkg)
++}
++
++func isNotEligible(caller string, ignorePackages []string) bool {
++      return slices.ContainsFunc(callStackNotEligible, func(notEligible string) bool {
++              return strings.HasPrefix(caller, notEligible+".")
++      }) || slices.ContainsFunc(ignorePackages, func(notEligible string) bool {
++              return strings.HasPrefix(caller, notEligible+".")
++      })
++}
++
++// getCallStackButt gets the calling file, ignoring any file in an ignored
++// package.
++func getCallStackButt(ignorePackages []string) (string, error) {
++      const incr int = 2
++      const max int = incr * 10
++      for skip := 0; skip < max; skip += incr {
++              callers := make([]uintptr, incr)
++              count := runtime.Callers(skip, callers)
++              frames := runtime.CallersFrames(callers)
++
++              frame, more := frames.Next()
++              for {
++                      // If getCallStackButt gets called from main, use the runtime to
++                      // determine what module main is in.
++                      if isNotEligible(frame.Function, ignorePackages) {
++                              if !more {
++                                      break
++                              }
++                              frame, more = frames.Next()
++                      } else {
++                              return frame.File, nil
++                      }
++              }
++              if count < incr {
++                      break
++              }
++      }
++
++      return "", ErrNoEligibleCaller
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c2ee4fd946716a51c3572bed67a66ebf400d0348
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,58 @@@
++// Copyright (C) 2024 early (LGPL)
++package include
++
++import (
++      "io"
++      "os"
++      "path"
++)
++
++type Opener interface {
++      Open() (io.ReadCloser, error)
++}
++
++type FileOpener interface {
++      Opener
++      FileName() string
++}
++
++type OpenerFunc func() (io.ReadCloser, error)
++
++func (opener OpenerFunc) Open() (io.ReadCloser, error) {
++      return opener()
++}
++
++type fileOpener struct {
++      absPath   string
++      alwaysErr error
++}
++
++func (opener *fileOpener) Open() (io.ReadCloser, error) {
++      if opener.alwaysErr != nil {
++              return nil, opener.alwaysErr
++      }
++      return os.Open(opener.absPath)
++}
++
++func (fopener *fileOpener) FileName() string {
++      return fopener.absPath
++}
++
++// File returns an Opener that Opens() a file.
++// If filename is a relative path, it is considered relative to the *calling
++// file*, not the working directory.
++// If ignorePackages is nonempty, callers in any package specified are ignored.
++func File(filename string, ignorePackages ...string) FileOpener {
++      opener := new(fileOpener)
++      if path.IsAbs(filename) {
++              opener.absPath = filename
++      } else {
++              caller, err := getCallStackButt(ignorePackages)
++              if err != nil {
++                      opener.alwaysErr = err
++              } else {
++                      opener.absPath = path.Join(path.Dir(caller), filename)
++              }
++      }
++      return opener
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9b8880730781957dd502958d7cbfc9155d16f9ad
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,188 @@@
++// Copyright (C) 2024 early (LGPL)
++package compile
++
++import (
++      "errors"
++      "html/template"
++      "regexp"
++      "strings"
++
++      "git.earlybird.gay/today-engine/htmltree"
++      "git.earlybird.gay/today-engine/include"
++      "git.earlybird.gay/today-engine/internal/html"
++      "git.earlybird.gay/today-engine/render"
++)
++
++type Source interface {
++      Name() string
++      Source() include.Opener
++      Includes() []Source
++}
++
++type TemplateSource interface {
++      Source
++      IncludeTagName() bool
++      TemplateFuncs() template.FuncMap
++      OnLoad() render.OnLoadFunc
++}
++
++type Sources map[string]Source
++
++func mapSources(dst Sources, slice []Source) {
++      for _, source := range slice {
++              dst[source.Name()] = source
++              mapSources(dst, source.Includes())
++      }
++}
++
++type Result struct {
++      TemplateRaw        string
++      TemplateFuncs      template.FuncMap
++      TemplateDataLoader render.Loader
++}
++
++func Compile(root TemplateSource, transform ...func(root *html.Node)) (Result, error) {
++      var result Result
++      reader, err := root.Source().Open()
++      if err != nil {
++              return result, err
++      }
++      document, err := html.Parse(reader)
++      if err != nil {
++              return result, err
++      }
++
++      fullDependencies := Sources{root.Name(): root}
++      mapSources(fullDependencies, root.Includes())
++      computeRoot := &computeNode{
++              name:    root.Name(),
++              compute: root.OnLoad(),
++      }
++      // Insert an assignment to $compute so we can always raise scope, even
++      // in pipelines
++      document.InsertBefore(&html.Node{
++              Type: html.TextNode,
++              Data: "{{ $compute := .compute }}",
++      }, document.FirstChild)
++
++      // Replace template functions in the root before we add any subsources
++      // fmt.Println(root.TemplateFuncs())
++      htmltree.Walk(document, func(n *html.Node) (bool, error) {
++              replaceTemplateFuncs(root, n)
++              return false, nil
++      })
++
++      // Insert component sources into document
++      for name, subSource := range fullDependencies {
++              // Easiest way to tell right now is what isn't a template source,
++              // but this bears re-evaluating later
++              if _, ok := subSource.(TemplateSource); ok {
++                      continue
++              }
++              err := insertComponentSource(subSource, document)
++              if err != nil {
++                      return result, err
++              }
++              delete(fullDependencies, name)
++      }
++
++      // gather global template funcs
++      // Start with the root's template, then add template funcs for all subsource
++      // with a namespace
++      templateFuncs := make(template.FuncMap)
++      for fname, f := range root.TemplateFuncs() {
++              templateFuncs[snakeCase(root.Name())+"_"+fname] = f
++      }
++
++      var process func(n *html.Node, c *computeNode) error
++      process = func(n *html.Node, c *computeNode) error {
++              childComputeNode := c
++              siblingComputeNode := c
++              if n.Type == html.ElementNode {
++                      if subSource, ok := fullDependencies[n.Data]; ok {
++                              if templateSource, ok := subSource.(TemplateSource); ok {
++                                      // Template sources (parts) are inserted inline
++                                      // Add template funcs
++                                      for fname, f := range templateSource.TemplateFuncs() {
++                                              templateFuncs[snakeCase(n.Data)+"_"+fname] = f
++                                      }
++                                      // Parse HTML fragment and replace the content of the node with it
++                                      computeSubSource, err := insertTemplateSource(templateSource, n)
++                                      if err != nil {
++                                              return err
++                                      }
++                                      // Add compute node for subsource
++                                      c.children = append(c.children, computeSubSource)
++                                      childComputeNode = computeSubSource
++                              }
++                      }
++              }
++              var procErr error
++              if n.FirstChild != nil {
++                      procErr = errors.Join(procErr, process(n.FirstChild, childComputeNode))
++              }
++              if n.NextSibling != nil {
++                      procErr = errors.Join(procErr, process(n.NextSibling, siblingComputeNode))
++              }
++              return procErr
++      }
++      err = process(document, computeRoot)
++      if err != nil {
++              return result, err
++      }
++
++      // POSTPROCESSING
++
++      // Assign .SetDot to $setDot
++      document.InsertBefore(&html.Node{
++              Type: html.TextNode,
++              Data: `{{ $setDot := .SetDot }}{{ with .Data }}`,
++      }, document.FirstChild)
++      // Add end to end
++      document.InsertBefore(&html.Node{
++              Type: html.TextNode,
++              Data: "{{ end -}}",
++      }, nil)
++
++      // Split up templates in text nodes
++      splitTemplateNodes(document)
++
++      // Traverse the document and add $setDot on entry and exit from pipelines
++      addSetDots(document)
++
++      for _, tf := range transform {
++              tf(document)
++      }
++
++      raw, err := renderDocument(document)
++      if err != nil {
++              return result, err
++      }
++      result = Result{
++              TemplateRaw:        raw,
++              TemplateFuncs:      templateFuncs,
++              TemplateDataLoader: computeRoot,
++      }
++      return result, err
++}
++
++func renderDocument(document *html.Node) (string, error) {
++      // Basic render
++      buf := new(strings.Builder)
++      err := html.Render(buf, document)
++      if err != nil {
++              return "", err
++      }
++      raw := html.UnescapeString(buf.String())
++
++      // Clean boolean attributes
++      raw = removeEmptyAttrValues(raw)
++
++      return raw, nil
++}
++
++var emptyAttrRegex = regexp.MustCompile(`%%(?P<templateattr>[^<>]+?)%%=""`)
++
++func removeEmptyAttrValues(raw string) string {
++      return emptyAttrRegex.ReplaceAllString(raw, "$templateattr")
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7f779493f88ff4fb289d134ddaf851afec2f8d77
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,67 @@@
++package compile
++
++import (
++      "errors"
++
++      "git.earlybird.gay/today-engine/htmltree"
++      "git.earlybird.gay/today-engine/internal/html"
++      "git.earlybird.gay/today-engine/internal/html/atom"
++)
++
++var ErrBadComponentFormat = errors.New("web components must either be a script or a template and script")
++
++// insertComponentSource inserts a web component subSource into a document.
++// Unlike insertTemplateSource, this expects the root document and not the
++// context where the web component is being included.
++func insertComponentSource(subSource Source, document *html.Node) error {
++      // ===== SUBSOURCE PROCESSING =====
++      // Parse the subSource in the context of a node named subSource.Name().
++      // subSource should be:
++      // <template> and <script>
++      // <script>
++      reader, err := subSource.Source().Open()
++      if err != nil {
++              return err
++      }
++      innerHTML, err := html.ParseFragment(reader, &html.Node{
++              Type:     html.ElementNode,
++              Data:     "div",
++              DataAtom: atom.Div,
++      })
++      if err != nil {
++              return err
++      }
++      htmltree.Minify()(innerHTML[0])
++
++      var template, script, body *html.Node
++
++      for _, node := range innerHTML {
++              if node.Type == html.ElementNode && node.DataAtom == atom.Template {
++                      template = node
++              }
++              if node.Type == html.ElementNode && node.DataAtom == atom.Script {
++                      script = node
++              }
++      }
++
++      if script == nil {
++              return ErrBadComponentFormat
++      }
++
++      // Get body of document
++      htmltree.Walk(document, func(n *html.Node) (bool, error) {
++              if n.Type == html.ElementNode && n.Data == "body" {
++                      body = n
++                      return true, nil
++              }
++              return false, nil
++      })
++
++      // Insert template and script at start of body
++      body.InsertBefore(script, body.FirstChild)
++      if template != nil {
++              body.InsertBefore(template, body.FirstChild)
++      }
++
++      return nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5c5f69a9eb886bb61dc7e2134a2ccbe9df8c80fa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,126 @@@
++// Copyright (C) 2024 early (LGPL)
++package compile
++
++import (
++      "fmt"
++      "net/http"
++      "reflect"
++      "strings"
++
++      "git.earlybird.gay/today-engine/render"
++)
++
++type computeNode struct {
++      name             string
++      htmlId           string
++      compute          render.OnLoadFunc
++      asDataFromParent map[string]string
++      raiseFromParent  []string
++      children         []*computeNode
++}
++
++func (root *computeNode) Compute(r *http.Request) (render.Data, func(any) error, error) {
++      impose := func(cData, pData render.Data, raise []string) {
++              for _, key := range raise {
++                      cData.Set(key, pData.Get(key))
++              }
++      }
++      var dot any
++      setDot := func(val any) error {
++              dot = val
++              return nil
++      }
++      ctx := r.Context()
++
++      var f func(n *computeNode, data render.Data) error
++      f = func(n *computeNode, data render.Data) error {
++              // Set the htmlId of the component if it exists as "id"
++              if n.htmlId != "" {
++                      data.Set("id", n.htmlId)
++              }
++              n.compute(ctx, data)
++              computeFuncs := make(render.Data)
++              for _, child := range n.children {
++                      computeFuncName := child.name
++                      if child.htmlId != "" {
++                              computeFuncName += "_" + snakeCase(child.htmlId)
++                      }
++                      if computeFuncs.IsSet(computeFuncName) {
++                              continue
++                      }
++                      // Defer rendering of the child to when it's needed
++                      computeFuncs.Set(computeFuncName, func() (render.Data, error) {
++                              childData := render.NewData(r)
++                              // Stuff here is available to the OnLoad AND renderer:
++                              // Assign all data from parent
++                              for dataKey, rawOrIdentifier := range child.asDataFromParent {
++                                      // Assume raw...
++                                      var val any = rawOrIdentifier
++                                      // ...but treat as an identifier if starts with .
++                                      if rawOrIdentifier[0] == '.' {
++                                              val = getVarFromData(dot, rawOrIdentifier)
++                                              if val == nil {
++                                                      return nil, fmt.Errorf("key %s not found in passed data", rawOrIdentifier)
++                                              }
++                                      }
++                                      childData.Set(dataKey, val)
++                              }
++                              // Raise parent variables to the "parent" var
++                              childParentData := make(render.Data)
++                              impose(childParentData, data, child.raiseFromParent)
++                              childData.Set("parent", childParentData)
++                              f(child, childData)
++                              return childData, child.compute(ctx, childData)
++                      })
++                      // Stuff here is ONLY available to the renderer:
++              }
++              data.Set("compute", computeFuncs)
++              return nil
++      }
++
++      data := render.NewData(r)
++      return data, setDot, f(root, data)
++}
++
++// Get a variable from data.
++// key must be of the form .x.y.z, and will try to get that value from data.
++func getVarFromData(data any, key string) any {
++      // special case; if the key is ".", just return data.
++      if key == "." {
++              return data
++      }
++      var val any = data
++      keyStack := strings.Split(key, ".")[1:]
++findKey:
++      for val != nil && len(keyStack) > 0 {
++              key = keyStack[0]
++              if key == "" {
++                      return data
++              }
++              keyStack = keyStack[1:]
++              refV := reflect.ValueOf(val)
++              refT := refV.Type()
++              refK := refT.Kind()
++
++              switch refK {
++              case reflect.Struct:
++                      field := refV.FieldByName(key)
++                      if !field.IsValid() {
++                              val = nil
++                      } else {
++                              val = field.Interface()
++                      }
++              case reflect.Map:
++                      field := refV.MapIndex(reflect.ValueOf(key))
++                      if !field.IsValid() {
++                              val = nil
++                      } else {
++                              val = field.Interface()
++                      }
++              default:
++                      break findKey
++              }
++      }
++
++      return val
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..303aff125673960cac4a75357cee438b7f3c5723
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,9 @@@
++// Copyright (C) 2024 early (LGPL)
++package compile
++
++import "strings"
++
++// EXTREMELY lazy snake caser
++func snakeCase(s string) string {
++      return strings.ToLower(strings.Replace(s, "-", "_", -1))
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1fd6f5b7191178d97e3d868ff5624de313906a10
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,587 @@@
++// Copyright (C) 2024 early (LGPL)
++package compile
++
++import (
++      "errors"
++      "fmt"
++      "regexp"
++      "slices"
++      "strings"
++
++      "git.earlybird.gay/today-engine/htmltree"
++      "git.earlybird.gay/today-engine/internal/html"
++)
++
++const (
++      tokenOpenTemplate  = "{{"
++      tokenCloseTemplate = "}}"
++)
++
++var funcRegexp = regexp.MustCompile(`^\(?([a-zA-Z]\w*)\)?$`)
++var fieldRegexp = regexp.MustCompile(`^(?:\.[a-zA-Z]\w*)+$`)
++var scopesDownRegexp = regexp.MustCompile(`[\{\s]end[\}\s]`)
++var setsDotRegexp = regexp.MustCompile(`^\{\{-?\s*(?:with|range).*?\}\}$`)
++var templateRegexp = regexp.MustCompile(`\{\{.*\}\}`)
++
++func funcFrom(token string) string {
++      submatches := funcRegexp.FindStringSubmatch(token)
++      if len(submatches) > 1 {
++              return submatches[1]
++      }
++      return ""
++}
++
++func isField(token string) bool {
++      return fieldRegexp.MatchString(token)
++}
++
++func containsTemplate(token string) bool {
++      return templateRegexp.MatchString(token)
++}
++
++func scopesUp(token string) bool {
++      return strings.Contains(token, "with") ||
++              strings.Contains(token, "if") ||
++              strings.Contains(token, "range")
++}
++
++func scopesDown(token string) bool {
++      return scopesDownRegexp.MatchString(token)
++}
++
++func setsDot(token string) bool {
++      return setsDotRegexp.MatchString(token)
++}
++
++func getAttr(n *html.Node, key string) string {
++      idx := slices.IndexFunc(n.Attr, func(attr html.Attribute) bool {
++              return attr.Key == key
++      })
++      if idx == -1 {
++              return ""
++      }
++      return n.Attr[idx].Val
++}
++
++func splitTemplateNodes(n *html.Node) {
++      htmltree.Walk(n, func(n *html.Node) (bool, error) {
++              if n.Parent == nil {
++                      return false, nil
++              } else if n.Type != html.TextNode {
++                      return false, nil
++              } else if !containsTemplate(n.Data) {
++                      return false, nil
++              }
++
++              // n is a text node with at least one template
++              // split it into text nodes where every {{ template }} is its own node
++              splitNodes := make([]string, 0)
++
++              var t, i, open, close, depth int
++              limit := 0
++              for limit < 10 {
++                      limit++
++                      // Find next open and close token
++                      // Increment to the closest one, if at least one exists
++                      open = strings.Index(n.Data[i:], tokenOpenTemplate)
++                      close = strings.Index(n.Data[i:], tokenCloseTemplate)
++
++                      if open != -1 && open < close {
++                              if depth == 0 {
++                                      // If we're just starting a pipeline, set the "template"
++                                      // cursor to the template open position
++                                      splitNodes = append(splitNodes, n.Data[t:i+open])
++                                      t += open
++                              }
++                              depth++
++                              i += open + 2
++                      } else if close != -1 {
++                              depth--
++                              if depth == 0 {
++                                      // If we're closing a pipeline, append from the "template"
++                                      // cursor to the closing position, + 2 for the length
++                                      // of the closeToken
++                                      splitNodes = append(splitNodes, n.Data[t:i+close+2])
++                                      t = i + close + 2
++                              }
++                              i += close + 2
++                      } else {
++                              splitNodes = append(splitNodes, n.Data[i:])
++                              break
++                      }
++              }
++
++              // Append all splitNodes as nodes where n was
++              head := n.NextSibling
++              for _, data := range splitNodes {
++                      n.Parent.InsertBefore(&html.Node{
++                              Type: html.TextNode,
++                              Data: data,
++                      }, head)
++              }
++              n.Parent.RemoveChild(n)
++              return false, nil
++      })
++}
++
++// replaceTemplateFuncs replaces template functions in a node with their
++// namespaced versions.
++func replaceTemplateFuncs(source TemplateSource, n *html.Node) {
++      var datas []string
++      var sets []func(string)
++
++      switch n.Type {
++      case html.TextNode:
++              datas = append(datas, n.Data)
++              sets = append(sets, func(s string) {
++                      n.Data = s
++              })
++      case html.ElementNode:
++              depth := 0
++              inTemplate := false
++              var key, space string
++              for _, attr := range n.Attr {
++                      key += space + attr.Key
++                      // Track if in a template in the attributes list
++                      if !inTemplate && strings.HasPrefix(attr.Key, tokenOpenTemplate) {
++                              inTemplate = true
++                              if depth == 0 {
++                                      key = "%%" + key
++                              }
++                      }
++                      // If in a template, and the current key indicates entering a
++                      // template pipeline, increase depth
++                      if inTemplate && scopesUp(attr.Key) {
++                              depth++
++                      }
++                      if inTemplate && scopesDown(attr.Key) {
++                              depth--
++                      }
++                      // Track exiting a template
++                      if inTemplate && strings.HasSuffix(attr.Key, tokenCloseTemplate) {
++                              inTemplate = false
++                              if depth == 0 {
++                                      key = key + "%%"
++                              }
++                      }
++                      // Accumulate keys if they are in a template, or outside of a template
++                      // but inside a pipeline
++                      if inTemplate || depth > 0 {
++                              space = " "
++                              // Accumulate attribute values outside of templates into the key
++                              // IF the attribute is rendered as a result of a pipeline
++                              if depth > 0 && attr.Val != "" {
++                                      key += `="` + attr.Val + `"`
++                                      space = ""
++                                      continue
++                              }
++                              continue
++                      }
++                      setKey := key
++                      // set 1; process key and transform setKey
++                      datas = append(datas, setKey)
++                      sets = append(sets, func(s string) {
++                              setKey = s
++                      })
++
++                      // set 2; set attr setKey="s"
++                      datas = append(datas, attr.Val)
++                      sets = append(sets, func(s string) {
++                              htmltree.SetAttr(n, setKey, s)
++                      })
++
++                      // Reset key and spacing
++                      key = ""
++                      space = ""
++              }
++
++              // Reset attributes
++              n.Attr = make([]html.Attribute, 0, len(n.Attr))
++      }
++      for i, data := range datas {
++              var done, inTemplate bool
++              var output []string
++              for {
++                      endToken := strings.IndexAny(data, " ")
++                      if endToken == -1 {
++                              endToken = len(data)
++                              done = true
++                      }
++
++                      token := data[:endToken]
++                      // Track when we're in a template using open/close brackets
++                      if token == tokenOpenTemplate {
++                              inTemplate = true
++                      }
++                      if token == tokenCloseTemplate {
++                              inTemplate = false
++                      }
++                      // If we're in a template and found a function identifier, replace it
++                      // with a namespaced version
++                      if inTemplate {
++                              funcName := funcFrom(token)
++                              if funcName == "" {
++                                      goto done
++                              }
++                              // fmt.Println("func", token)
++                              // fmt.Println(source.TemplateFuncs())
++                              // Skip anything that the target source doesn't have as a templatefunc
++                              if _, ok := source.TemplateFuncs()[funcName]; ok {
++                                      // fmt.Println("found", token)
++                                      namespaced := snakeCase(source.Name()) + "_" + funcName
++                                      token = strings.Replace(token, funcName, namespaced, -1)
++                              }
++                      }
++
++              done:
++                      output = append(output, token)
++                      if done {
++                              break
++                      }
++                      data = data[endToken+1:]
++              }
++              sets[i](strings.Join(output, " "))
++      }
++}
++
++// Sets template fields (.field) in any template strings in this node to
++// .parent.field.
++// Returns a list of raised fields.
++func replaceTemplateFields(n *html.Node) []string {
++      var done, inTemplate, inAttrs bool
++      var datas []string
++      var isDataAttr []bool
++      var sets []func(string)
++      var raised []string
++
++      switch n.Type {
++      case html.TextNode:
++              datas = append(datas, n.Data)
++              sets = append(sets, func(s string) {
++                      n.Data = s
++              })
++      case html.ElementNode:
++              inAttrs = true
++              for _, attr := range n.Attr {
++                      datas = append(datas, attr.Val)
++                      isDataAttr = append(isDataAttr, attr.Key[0] == ':')
++                      sets = append(sets, func(s string) {
++                              htmltree.SetAttr(n, attr.Key, s)
++                      })
++              }
++      }
++      for i, data := range datas {
++              var output []string
++              for {
++                      endToken := strings.Index(data, " ")
++                      if endToken == -1 {
++                              endToken = len(data)
++                              done = true
++                      }
++                      token := data[:endToken]
++
++                      // Track when we're in a template using open/close brackets
++                      if token == tokenOpenTemplate {
++                              inTemplate = true
++                      }
++                      if token == tokenCloseTemplate {
++                              inTemplate = false
++                      }
++                      // If we're in a template and found a template value identifier, replace it
++                      // with a namespaced version
++                      if inTemplate && isField(token) ||
++                              inAttrs && isDataAttr[i] {
++                              raised = append(raised, token[1:])
++                              token = ".parent" + token
++                      }
++
++                      output = append(output, token)
++                      if done {
++                              break
++                      }
++                      data = data[endToken+1:]
++              }
++              sets[i](strings.Join(output, " "))
++      }
++
++      return raised
++}
++
++// Removes data attributes :name.
++// Returns a map attr->val of the removed data attributes (: removed).
++func removeDataAttrs(n *html.Node) map[string]string {
++      if n.Type != html.ElementNode {
++              return nil
++      }
++      dataAttrs := make(map[string]string)
++      for i := 0; i < len(n.Attr); {
++              attr := n.Attr[i]
++              if attr.Key[0] == ':' {
++                      dataAttrs[attr.Key[1:]] = attr.Val
++                      n.Attr = append(n.Attr[:i], n.Attr[i+1:]...)
++              } else {
++                      i++
++              }
++      }
++      return dataAttrs
++}
++
++func insertTemplateSource(subSource TemplateSource, context *html.Node) (*computeNode, error) {
++      computedName := snakeCase(subSource.Name())
++      // ===== CONTEXT PREPROCESSING =====
++      // Raise any fields pre-existing in the context to .parent.field.
++      raiseFields := make([]string, 0)
++      raiseDepth := 0
++      htmltree.Walk(context.FirstChild, func(n *html.Node) (bool, error) {
++              if raiseDepth == 0 {
++                      raiseFields = append(raiseFields, replaceTemplateFields(n)...)
++              }
++              if n.Type == html.TextNode {
++                      if scopesUp(n.Data) {
++                              raiseDepth++
++                      } else if scopesDown(n.Data) {
++                              raiseDepth--
++                      }
++              }
++              return false, nil
++      })
++      // Remove :data attributes from the root of context, and prepare them
++      // to be used as data for the computeNode.
++      asData := removeDataAttrs(context)
++      // ===== SUBSOURCE PROCESSING =====
++      // Parse the subSource in the context of context.
++      // Require that subSource be contained in a template.
++      reader, err := subSource.Source().Open()
++      if err != nil {
++              return nil, err
++      }
++      innerHTML, err := html.ParseFragment(reader, context)
++      if err != nil {
++              return nil, err
++      }
++      root := innerHTML[0]
++      if root.Type != html.ElementNode || root.Data != "template" {
++              return nil, errors.New("fragments must be contained in a template")
++      }
++
++      isShadow := false
++      if getAttr(root, "shadowrootmode") != "" {
++              isShadow = true
++      }
++
++      // Walk the tree to do a couple of things:
++      //   - Replace template functions with namespaced functions.
++      //   - Find slots in the subSource.
++      slots := make(map[string]*html.Node)
++      usedSlot := make(map[string]bool)
++      htmltree.Walk(root, func(n *html.Node) (bool, error) {
++              // Replace template functions with namespaced functions.
++              replaceTemplateFuncs(subSource, n)
++              // Find slots in the subSource.
++              if n.Type == html.ElementNode && n.Data == "slot" {
++                      slotName := htmltree.GetAttr(n, "name")
++                      if _, ok := slots[slotName]; ok {
++                              return true, fmt.Errorf("found multiple slots named '%s'", slotName)
++                      } else {
++                              slots[slotName] = n
++                              usedSlot[slotName] = false
++                      }
++              }
++              return false, nil
++      })
++
++      // Mix stuff from the context into the template using slots...
++      n := context.FirstChild
++      // slot context is the nodes currently considered candidates for slotting.
++      // Being in the slotCtx doesn't mean a node *will* be slotted, just that it
++      // might be, and if it is it needs to have its order preserved with every
++      // other node in the ctx.
++      slotCtx := make([]*html.Node, 0)
++      // nonslotCtx is a copy of slotCtx, but elements with no slot go here instead.
++      nonslotCtx := make([]*html.Node, 0)
++      var slotUsed, nonslotUsed bool
++      var targetSlot *html.Node
++      // slotCtxDepth is the depth of any template scope biz that surrounds a
++      // slotted node.
++      slotCtxDepth := 0
++      for n != nil {
++              next := n.NextSibling
++              context.RemoveChild(n)
++              switch n.Type {
++              case html.TextNode:
++                      // Raise/lower the slot context depth if scope goes up or down.
++                      if scopesUp(n.Data) {
++                              slotCtxDepth++
++                      } else if scopesDown(n.Data) {
++                              slotCtxDepth--
++                      }
++                      // Add the node to slotCtx, and a copy to nonslotCtx
++                      slotCtx = append(slotCtx, n)
++                      nonslotCtx = append(nonslotCtx, &html.Node{
++                              Type: n.Type,
++                              Data: n.Data,
++                      })
++              case html.ElementNode:
++                      slotName := htmltree.GetAttr(n, "slot")
++                      slot, ok := slots[slotName]
++                      if slotName != "" && ok {
++                              // Add this element to the current slottable context.
++                              slotCtx = append(slotCtx, n)
++                              slotUsed = true
++                              targetSlot = slot
++                              // Mark the slot as used in usedSlot so its default content
++                              // is removed.
++                              usedSlot[slotName] = true
++                      } else {
++                              // Add it to the nonslottable context.
++                              nonslotCtx = append(nonslotCtx, n)
++                              nonslotUsed = true
++                      }
++              }
++              if slotCtxDepth == 0 {
++                      if slotUsed {
++                              for _, slotCtxNode := range slotCtx {
++                                      targetSlot.Parent.InsertBefore(slotCtxNode, targetSlot)
++                              }
++                              slotCtx = make([]*html.Node, 0)
++                              slotUsed = false
++                      }
++                      if nonslotUsed {
++                              for _, nonslotCtxNode := range nonslotCtx {
++                                      root.AppendChild(nonslotCtxNode)
++                              }
++                              nonslotCtx = make([]*html.Node, 0)
++                              nonslotUsed = false
++                      }
++              }
++              n = next
++      }
++
++      // ...then move content from the template to the context...
++      if !isShadow {
++              // If not in shadow, move stuff out of the root into the context.
++              n = root.FirstChild
++              for n != nil {
++                      next := n.NextSibling
++                      root.RemoveChild(n)
++                      context.AppendChild(n)
++                      n = next
++              }
++      } else {
++              // If in shadow, move the whole root.
++              context.InsertBefore(root, context.FirstChild)
++      }
++
++      // ...then remove any slots that were used.
++      // For slots that aren't used, move up their data first.
++      if !isShadow {
++              htmltree.Walk(context, func(n *html.Node) (bool, error) {
++                      if n.Type == html.ElementNode && n.Data == "slot" {
++                              slotName := htmltree.GetAttr(n, "name")
++                              slot := slots[slotName]
++                              used := usedSlot[slotName]
++                              if !used {
++                                      n = slot.FirstChild
++                                      for n != nil {
++                                              next := n.NextSibling
++                                              slot.RemoveChild(n)
++                                              slot.Parent.InsertBefore(n, slot)
++                                              n = next
++                                      }
++                              }
++                              slot.Parent.RemoveChild(slot)
++                      }
++                      return false, nil
++              })
++      }
++
++      // Generate a computeNode for this part.
++      htmlId := getAttr(context, "id")
++      scopeName := computedName + "_" + snakeCase(htmlId)
++      if htmlId == "" || containsTemplate(htmlId) {
++              htmlId = ""
++              scopeName = computedName
++      }
++      compute := &computeNode{
++              name:             computedName,
++              htmlId:           htmlId,
++              compute:          subSource.OnLoad(),
++              asDataFromParent: asData,
++              raiseFromParent:  raiseFields,
++      }
++
++      // Insert scope up/down template pipeline
++      head := context.FirstChild
++      up, down := scopeNodes(scopeName)
++      context.InsertBefore(up, head)
++      // Insert an assignment to $compute so we can always raise
++      // scope, even in pipelines
++      context.InsertBefore(&html.Node{
++              Type: html.TextNode,
++              Data: "{{ $compute := .compute }}",
++      }, head)
++      context.InsertBefore(down, nil)
++
++      // If not using custom tags for this subSource, remove them.
++      if !subSource.IncludeTagName() {
++              n := context.FirstChild
++              for n != nil {
++                      context.RemoveChild(n)
++                      context.Parent.InsertBefore(n, context)
++                      n = context.FirstChild
++              }
++              context.Parent.RemoveChild(context)
++      }
++      return compute, nil
++}
++
++func scopeNodes(scopeName string) (up, down *html.Node) {
++      upVal := fmt.Sprintf(`{{ with call $compute.%s }}`, scopeName)
++      up = &html.Node{
++              Type: html.TextNode,
++              Data: upVal,
++      }
++      downVal := `{{ end -}}`
++      down = &html.Node{
++              Type: html.TextNode,
++              Data: downVal,
++      }
++      return up, down
++}
++
++func addSetDots(document *html.Node) {
++      endAcc := make([]bool, 0)
++      htmltree.Walk(document, func(n *html.Node) (bool, error) {
++              if n.Type != html.TextNode {
++                      return false, nil
++              } else if !containsTemplate(n.Data) {
++                      return false, nil
++              }
++
++              if scopesUp(n.Data) {
++                      if setsDot(n.Data) {
++                              n.Parent.InsertBefore(&html.Node{
++                                      Type: html.TextNode,
++                                      Data: `{{ call $setDot . }}`,
++                              }, n.NextSibling)
++                              endAcc = append(endAcc, true)
++                      } else {
++                              endAcc = append(endAcc, false)
++                      }
++              } else if scopesDown(n.Data) || strings.Contains(n.Data, "else") {
++                      shouldSet := endAcc[len(endAcc)-1]
++                      endAcc = endAcc[:len(endAcc)-1]
++                      if shouldSet {
++                              n.Parent.InsertBefore(&html.Node{
++                                      Type: html.TextNode,
++                                      Data: "{{ call $setDot . }}",
++                              }, n.NextSibling)
++                      }
++                      if strings.Contains(n.Data, "else") {
++                              endAcc = append(endAcc, false)
++                      }
++              }
++
++              return false, nil
++      })
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2a7cf70da6e498df9c11ab6a5eaa2ddd7af34da4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,27 @@@
++Copyright 2009 The Go Authors.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are
++met:
++
++   * Redistributions of source code must retain the above copyright
++notice, this list of conditions and the following disclaimer.
++   * Redistributions in binary form must reproduce the above
++copyright notice, this list of conditions and the following disclaimer
++in the documentation and/or other materials provided with the
++distribution.
++   * Neither the name of Google LLC nor the names of its
++contributors may be used to endorse or promote products derived from
++this software without specific prior written permission.
++
++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..733099041f84fa1e58611ab2e11af51c1f26d1d2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,22 @@@
++Additional IP Rights Grant (Patents)
++
++"This implementation" means the copyrightable works distributed by
++Google as part of the Go project.
++
++Google hereby grants to You a perpetual, worldwide, non-exclusive,
++no-charge, royalty-free, irrevocable (except as stated in this section)
++patent license to make, have made, use, offer to sell, sell, import,
++transfer and otherwise run, modify and propagate the contents of this
++implementation of Go, where such license applies only to those patent
++claims, both currently owned or controlled by Google and acquired in
++the future, licensable by Google that are necessarily infringed by this
++implementation of Go.  This grant does not include claims that would be
++infringed only as a consequence of further modification of this
++implementation.  If you or your agent or exclusive licensee institute or
++order or agree to the institution of patent litigation against any
++entity (including a cross-claim or counterclaim in a lawsuit) alleging
++that this implementation of Go or any code incorporated within this
++implementation of Go constitutes direct or contributory patent
++infringement, or inducement of patent infringement, then any patent
++rights granted to you under this License for this implementation of Go
++shall terminate as of the date such litigation is filed.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ad72cd715bdde3dc46e07e1b924281c70bc9ed41
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++# HTML
++
++## This is a fork.
++
++This repo forks `golang.org/x/net/html` and makes limited changes:
++
++- Foster parenting is disabled.
++- Attribute keys are not automatically set to lowercase.
++
++These changes are made to support Today's use of `x/net/html` to parse and
++re-render Go templates. They have the intended side effect of allowing invalid
++HTML to be rendered, which is almost definitely not what you want.
++
++Please see the LICENSE and PATENTS file for this directory.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cb79263be33c5da4ffd49e23fc297377eecf551e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++// Copyright 2012 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Package atom provides integer codes (also known as atoms) for a fixed set of
++// frequently occurring HTML strings: tag names and attribute keys such as "p"
++// and "id".
++//
++// Sharing an atom's name between all elements with the same tag can result in
++// fewer string allocations when tokenizing and parsing HTML. Integer
++// comparisons are also generally faster than string comparisons.
++//
++// The value of an atom's particular code is not guaranteed to stay the same
++// between versions of this package. Neither is any ordering guaranteed:
++// whether atom.H1 < atom.H2 may also change. The codes are not guaranteed to
++// be dense. The only guarantees are that e.g. looking up "div" will yield
++// atom.Div, calling atom.Div.String will return "div", and atom.Div != 0.
++package atom // import "git.earlybird.gay/today-engine/internal/html/atom"
++
++// Atom is an integer code for a string. The zero value maps to "".
++type Atom uint32
++
++// String returns the atom's name.
++func (a Atom) String() string {
++      start := uint32(a >> 8)
++      n := uint32(a & 0xff)
++      if start+n > uint32(len(atomText)) {
++              return ""
++      }
++      return atomText[start : start+n]
++}
++
++func (a Atom) string() string {
++      return atomText[a>>8 : a>>8+a&0xff]
++}
++
++// fnv computes the FNV hash with an arbitrary starting value h.
++func fnv(h uint32, s []byte) uint32 {
++      for i := range s {
++              h ^= uint32(s[i])
++              h *= 16777619
++      }
++      return h
++}
++
++func match(s string, t []byte) bool {
++      for i, c := range t {
++              if s[i] != c {
++                      return false
++              }
++      }
++      return true
++}
++
++// Lookup returns the atom whose name is s. It returns zero if there is no
++// such atom. The lookup is case sensitive.
++func Lookup(s []byte) Atom {
++      if len(s) == 0 || len(s) > maxAtomLen {
++              return 0
++      }
++      h := fnv(hash0, s)
++      if a := table[h&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
++              return a
++      }
++      if a := table[(h>>16)&uint32(len(table)-1)]; int(a&0xff) == len(s) && match(a.string(), s) {
++              return a
++      }
++      return 0
++}
++
++// String returns a string whose contents are equal to s. In that sense, it is
++// equivalent to string(s) but may be more efficient.
++func String(s []byte) string {
++      if a := Lookup(s); a != 0 {
++              return a.String()
++      }
++      return string(s)
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6e33704dd5e114c1610e8239f6162a828db39132
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,109 @@@
++// Copyright 2012 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package atom
++
++import (
++      "sort"
++      "testing"
++)
++
++func TestKnown(t *testing.T) {
++      for _, s := range testAtomList {
++              if atom := Lookup([]byte(s)); atom.String() != s {
++                      t.Errorf("Lookup(%q) = %#x (%q)", s, uint32(atom), atom.String())
++              }
++      }
++}
++
++func TestHits(t *testing.T) {
++      for _, a := range table {
++              if a == 0 {
++                      continue
++              }
++              got := Lookup([]byte(a.String()))
++              if got != a {
++                      t.Errorf("Lookup(%q) = %#x, want %#x", a.String(), uint32(got), uint32(a))
++              }
++      }
++}
++
++func TestMisses(t *testing.T) {
++      testCases := []string{
++              "",
++              "\x00",
++              "\xff",
++              "A",
++              "DIV",
++              "Div",
++              "dIV",
++              "aa",
++              "a\x00",
++              "ab",
++              "abb",
++              "abbr0",
++              "abbr ",
++              " abbr",
++              " a",
++              "acceptcharset",
++              "acceptCharset",
++              "accept_charset",
++              "h0",
++              "h1h2",
++              "h7",
++              "onClick",
++              "λ",
++              // The following string has the same hash (0xa1d7fab7) as "onmouseover".
++              "\x00\x00\x00\x00\x00\x50\x18\xae\x38\xd0\xb7",
++      }
++      for _, tc := range testCases {
++              got := Lookup([]byte(tc))
++              if got != 0 {
++                      t.Errorf("Lookup(%q): got %d, want 0", tc, got)
++              }
++      }
++}
++
++func TestForeignObject(t *testing.T) {
++      const (
++              afo = Foreignobject
++              afO = ForeignObject
++              sfo = "foreignobject"
++              sfO = "foreignObject"
++      )
++      if got := Lookup([]byte(sfo)); got != afo {
++              t.Errorf("Lookup(%q): got %#v, want %#v", sfo, got, afo)
++      }
++      if got := Lookup([]byte(sfO)); got != afO {
++              t.Errorf("Lookup(%q): got %#v, want %#v", sfO, got, afO)
++      }
++      if got := afo.String(); got != sfo {
++              t.Errorf("Atom(%#v).String(): got %q, want %q", afo, got, sfo)
++      }
++      if got := afO.String(); got != sfO {
++              t.Errorf("Atom(%#v).String(): got %q, want %q", afO, got, sfO)
++      }
++}
++
++func BenchmarkLookup(b *testing.B) {
++      sortedTable := make([]string, 0, len(table))
++      for _, a := range table {
++              if a != 0 {
++                      sortedTable = append(sortedTable, a.String())
++              }
++      }
++      sort.Strings(sortedTable)
++
++      x := make([][]byte, 1000)
++      for i := range x {
++              x[i] = []byte(sortedTable[i%len(sortedTable)])
++      }
++
++      b.ResetTimer()
++      for i := 0; i < b.N; i++ {
++              for _, s := range x {
++                      Lookup(s)
++              }
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1e249d163cc1d37e988056bb6164d1772181c7ea
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,711 @@@
++// Copyright 2012 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++//go:build ignore
++
++//go:generate go run gen.go
++//go:generate go run gen.go -test
++
++package main
++
++import (
++      "bytes"
++      "flag"
++      "fmt"
++      "go/format"
++      "math/rand"
++      "os"
++      "sort"
++      "strings"
++)
++
++// identifier converts s to a Go exported identifier.
++// It converts "div" to "Div" and "accept-charset" to "AcceptCharset".
++func identifier(s string) string {
++      b := make([]byte, 0, len(s))
++      cap := true
++      for _, c := range s {
++              if c == '-' {
++                      cap = true
++                      continue
++              }
++              if cap && 'a' <= c && c <= 'z' {
++                      c -= 'a' - 'A'
++              }
++              cap = false
++              b = append(b, byte(c))
++      }
++      return string(b)
++}
++
++var test = flag.Bool("test", false, "generate table_test.go")
++
++func genFile(name string, buf *bytes.Buffer) {
++      b, err := format.Source(buf.Bytes())
++      if err != nil {
++              fmt.Fprintln(os.Stderr, err)
++              os.Exit(1)
++      }
++      if err := os.WriteFile(name, b, 0644); err != nil {
++              fmt.Fprintln(os.Stderr, err)
++              os.Exit(1)
++      }
++}
++
++func main() {
++      flag.Parse()
++
++      var all []string
++      all = append(all, elements...)
++      all = append(all, attributes...)
++      all = append(all, eventHandlers...)
++      all = append(all, extra...)
++      sort.Strings(all)
++
++      // uniq - lists have dups
++      w := 0
++      for _, s := range all {
++              if w == 0 || all[w-1] != s {
++                      all[w] = s
++                      w++
++              }
++      }
++      all = all[:w]
++
++      if *test {
++              var buf bytes.Buffer
++              fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
++              fmt.Fprintln(&buf, "//go:generate go run gen.go -test\n")
++              fmt.Fprintln(&buf, "package atom\n")
++              fmt.Fprintln(&buf, "var testAtomList = []string{")
++              for _, s := range all {
++                      fmt.Fprintf(&buf, "\t%q,\n", s)
++              }
++              fmt.Fprintln(&buf, "}")
++
++              genFile("table_test.go", &buf)
++              return
++      }
++
++      // Find hash that minimizes table size.
++      var best *table
++      for i := 0; i < 1000000; i++ {
++              if best != nil && 1<<(best.k-1) < len(all) {
++                      break
++              }
++              h := rand.Uint32()
++              for k := uint(0); k <= 16; k++ {
++                      if best != nil && k >= best.k {
++                              break
++                      }
++                      var t table
++                      if t.init(h, k, all) {
++                              best = &t
++                              break
++                      }
++              }
++      }
++      if best == nil {
++              fmt.Fprintf(os.Stderr, "failed to construct string table\n")
++              os.Exit(1)
++      }
++
++      // Lay out strings, using overlaps when possible.
++      layout := append([]string{}, all...)
++
++      // Remove strings that are substrings of other strings
++      for changed := true; changed; {
++              changed = false
++              for i, s := range layout {
++                      if s == "" {
++                              continue
++                      }
++                      for j, t := range layout {
++                              if i != j && t != "" && strings.Contains(s, t) {
++                                      changed = true
++                                      layout[j] = ""
++                              }
++                      }
++              }
++      }
++
++      // Join strings where one suffix matches another prefix.
++      for {
++              // Find best i, j, k such that layout[i][len-k:] == layout[j][:k],
++              // maximizing overlap length k.
++              besti := -1
++              bestj := -1
++              bestk := 0
++              for i, s := range layout {
++                      if s == "" {
++                              continue
++                      }
++                      for j, t := range layout {
++                              if i == j {
++                                      continue
++                              }
++                              for k := bestk + 1; k <= len(s) && k <= len(t); k++ {
++                                      if s[len(s)-k:] == t[:k] {
++                                              besti = i
++                                              bestj = j
++                                              bestk = k
++                                      }
++                              }
++                      }
++              }
++              if bestk > 0 {
++                      layout[besti] += layout[bestj][bestk:]
++                      layout[bestj] = ""
++                      continue
++              }
++              break
++      }
++
++      text := strings.Join(layout, "")
++
++      atom := map[string]uint32{}
++      for _, s := range all {
++              off := strings.Index(text, s)
++              if off < 0 {
++                      panic("lost string " + s)
++              }
++              atom[s] = uint32(off<<8 | len(s))
++      }
++
++      var buf bytes.Buffer
++      // Generate the Go code.
++      fmt.Fprintln(&buf, "// Code generated by go generate gen.go; DO NOT EDIT.\n")
++      fmt.Fprintln(&buf, "//go:generate go run gen.go\n")
++      fmt.Fprintln(&buf, "package atom\n\nconst (")
++
++      // compute max len
++      maxLen := 0
++      for _, s := range all {
++              if maxLen < len(s) {
++                      maxLen = len(s)
++              }
++              fmt.Fprintf(&buf, "\t%s Atom = %#x\n", identifier(s), atom[s])
++      }
++      fmt.Fprintln(&buf, ")\n")
++
++      fmt.Fprintf(&buf, "const hash0 = %#x\n\n", best.h0)
++      fmt.Fprintf(&buf, "const maxAtomLen = %d\n\n", maxLen)
++
++      fmt.Fprintf(&buf, "var table = [1<<%d]Atom{\n", best.k)
++      for i, s := range best.tab {
++              if s == "" {
++                      continue
++              }
++              fmt.Fprintf(&buf, "\t%#x: %#x, // %s\n", i, atom[s], s)
++      }
++      fmt.Fprintf(&buf, "}\n")
++      datasize := (1 << best.k) * 4
++
++      fmt.Fprintln(&buf, "const atomText =")
++      textsize := len(text)
++      for len(text) > 60 {
++              fmt.Fprintf(&buf, "\t%q +\n", text[:60])
++              text = text[60:]
++      }
++      fmt.Fprintf(&buf, "\t%q\n\n", text)
++
++      genFile("table.go", &buf)
++
++      fmt.Fprintf(os.Stdout, "%d atoms; %d string bytes + %d tables = %d total data\n", len(all), textsize, datasize, textsize+datasize)
++}
++
++type byLen []string
++
++func (x byLen) Less(i, j int) bool { return len(x[i]) > len(x[j]) }
++func (x byLen) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }
++func (x byLen) Len() int           { return len(x) }
++
++// fnv computes the FNV hash with an arbitrary starting value h.
++func fnv(h uint32, s string) uint32 {
++      for i := 0; i < len(s); i++ {
++              h ^= uint32(s[i])
++              h *= 16777619
++      }
++      return h
++}
++
++// A table represents an attempt at constructing the lookup table.
++// The lookup table uses cuckoo hashing, meaning that each string
++// can be found in one of two positions.
++type table struct {
++      h0   uint32
++      k    uint
++      mask uint32
++      tab  []string
++}
++
++// hash returns the two hashes for s.
++func (t *table) hash(s string) (h1, h2 uint32) {
++      h := fnv(t.h0, s)
++      h1 = h & t.mask
++      h2 = (h >> 16) & t.mask
++      return
++}
++
++// init initializes the table with the given parameters.
++// h0 is the initial hash value,
++// k is the number of bits of hash value to use, and
++// x is the list of strings to store in the table.
++// init returns false if the table cannot be constructed.
++func (t *table) init(h0 uint32, k uint, x []string) bool {
++      t.h0 = h0
++      t.k = k
++      t.tab = make([]string, 1<<k)
++      t.mask = 1<<k - 1
++      for _, s := range x {
++              if !t.insert(s) {
++                      return false
++              }
++      }
++      return true
++}
++
++// insert inserts s in the table.
++func (t *table) insert(s string) bool {
++      h1, h2 := t.hash(s)
++      if t.tab[h1] == "" {
++              t.tab[h1] = s
++              return true
++      }
++      if t.tab[h2] == "" {
++              t.tab[h2] = s
++              return true
++      }
++      if t.push(h1, 0) {
++              t.tab[h1] = s
++              return true
++      }
++      if t.push(h2, 0) {
++              t.tab[h2] = s
++              return true
++      }
++      return false
++}
++
++// push attempts to push aside the entry in slot i.
++func (t *table) push(i uint32, depth int) bool {
++      if depth > len(t.tab) {
++              return false
++      }
++      s := t.tab[i]
++      h1, h2 := t.hash(s)
++      j := h1 + h2 - i
++      if t.tab[j] != "" && !t.push(j, depth+1) {
++              return false
++      }
++      t.tab[j] = s
++      return true
++}
++
++// The lists of element names and attribute keys were taken from
++// https://html.spec.whatwg.org/multipage/indices.html#index
++// as of the "HTML Living Standard - Last Updated 16 April 2018" version.
++
++// "command", "keygen" and "menuitem" have been removed from the spec,
++// but are kept here for backwards compatibility.
++var elements = []string{
++      "a",
++      "abbr",
++      "address",
++      "area",
++      "article",
++      "aside",
++      "audio",
++      "b",
++      "base",
++      "bdi",
++      "bdo",
++      "blockquote",
++      "body",
++      "br",
++      "button",
++      "canvas",
++      "caption",
++      "cite",
++      "code",
++      "col",
++      "colgroup",
++      "command",
++      "data",
++      "datalist",
++      "dd",
++      "del",
++      "details",
++      "dfn",
++      "dialog",
++      "div",
++      "dl",
++      "dt",
++      "em",
++      "embed",
++      "fieldset",
++      "figcaption",
++      "figure",
++      "footer",
++      "form",
++      "h1",
++      "h2",
++      "h3",
++      "h4",
++      "h5",
++      "h6",
++      "head",
++      "header",
++      "hgroup",
++      "hr",
++      "html",
++      "i",
++      "iframe",
++      "img",
++      "input",
++      "ins",
++      "kbd",
++      "keygen",
++      "label",
++      "legend",
++      "li",
++      "link",
++      "main",
++      "map",
++      "mark",
++      "menu",
++      "menuitem",
++      "meta",
++      "meter",
++      "nav",
++      "noscript",
++      "object",
++      "ol",
++      "optgroup",
++      "option",
++      "output",
++      "p",
++      "param",
++      "picture",
++      "pre",
++      "progress",
++      "q",
++      "rp",
++      "rt",
++      "ruby",
++      "s",
++      "samp",
++      "script",
++      "section",
++      "select",
++      "slot",
++      "small",
++      "source",
++      "span",
++      "strong",
++      "style",
++      "sub",
++      "summary",
++      "sup",
++      "table",
++      "tbody",
++      "td",
++      "template",
++      "textarea",
++      "tfoot",
++      "th",
++      "thead",
++      "time",
++      "title",
++      "tr",
++      "track",
++      "u",
++      "ul",
++      "var",
++      "video",
++      "wbr",
++}
++
++// https://html.spec.whatwg.org/multipage/indices.html#attributes-3
++//
++// "challenge", "command", "contextmenu", "dropzone", "icon", "keytype", "mediagroup",
++// "radiogroup", "spellcheck", "scoped", "seamless", "sortable" and "sorted" have been removed from the spec,
++// but are kept here for backwards compatibility.
++var attributes = []string{
++      "abbr",
++      "accept",
++      "accept-charset",
++      "accesskey",
++      "action",
++      "allowfullscreen",
++      "allowpaymentrequest",
++      "allowusermedia",
++      "alt",
++      "as",
++      "async",
++      "autocomplete",
++      "autofocus",
++      "autoplay",
++      "challenge",
++      "charset",
++      "checked",
++      "cite",
++      "class",
++      "color",
++      "cols",
++      "colspan",
++      "command",
++      "content",
++      "contenteditable",
++      "contextmenu",
++      "controls",
++      "coords",
++      "crossorigin",
++      "data",
++      "datetime",
++      "default",
++      "defer",
++      "dir",
++      "dirname",
++      "disabled",
++      "download",
++      "draggable",
++      "dropzone",
++      "enctype",
++      "for",
++      "form",
++      "formaction",
++      "formenctype",
++      "formmethod",
++      "formnovalidate",
++      "formtarget",
++      "headers",
++      "height",
++      "hidden",
++      "high",
++      "href",
++      "hreflang",
++      "http-equiv",
++      "icon",
++      "id",
++      "inputmode",
++      "integrity",
++      "is",
++      "ismap",
++      "itemid",
++      "itemprop",
++      "itemref",
++      "itemscope",
++      "itemtype",
++      "keytype",
++      "kind",
++      "label",
++      "lang",
++      "list",
++      "loop",
++      "low",
++      "manifest",
++      "max",
++      "maxlength",
++      "media",
++      "mediagroup",
++      "method",
++      "min",
++      "minlength",
++      "multiple",
++      "muted",
++      "name",
++      "nomodule",
++      "nonce",
++      "novalidate",
++      "open",
++      "optimum",
++      "pattern",
++      "ping",
++      "placeholder",
++      "playsinline",
++      "poster",
++      "preload",
++      "radiogroup",
++      "readonly",
++      "referrerpolicy",
++      "rel",
++      "required",
++      "reversed",
++      "rows",
++      "rowspan",
++      "sandbox",
++      "spellcheck",
++      "scope",
++      "scoped",
++      "seamless",
++      "selected",
++      "shape",
++      "size",
++      "sizes",
++      "sortable",
++      "sorted",
++      "slot",
++      "span",
++      "spellcheck",
++      "src",
++      "srcdoc",
++      "srclang",
++      "srcset",
++      "start",
++      "step",
++      "style",
++      "tabindex",
++      "target",
++      "title",
++      "translate",
++      "type",
++      "typemustmatch",
++      "updateviacache",
++      "usemap",
++      "value",
++      "width",
++      "workertype",
++      "wrap",
++}
++
++// "onautocomplete", "onautocompleteerror", "onmousewheel",
++// "onshow" and "onsort" have been removed from the spec,
++// but are kept here for backwards compatibility.
++var eventHandlers = []string{
++      "onabort",
++      "onautocomplete",
++      "onautocompleteerror",
++      "onauxclick",
++      "onafterprint",
++      "onbeforeprint",
++      "onbeforeunload",
++      "onblur",
++      "oncancel",
++      "oncanplay",
++      "oncanplaythrough",
++      "onchange",
++      "onclick",
++      "onclose",
++      "oncontextmenu",
++      "oncopy",
++      "oncuechange",
++      "oncut",
++      "ondblclick",
++      "ondrag",
++      "ondragend",
++      "ondragenter",
++      "ondragexit",
++      "ondragleave",
++      "ondragover",
++      "ondragstart",
++      "ondrop",
++      "ondurationchange",
++      "onemptied",
++      "onended",
++      "onerror",
++      "onfocus",
++      "onhashchange",
++      "oninput",
++      "oninvalid",
++      "onkeydown",
++      "onkeypress",
++      "onkeyup",
++      "onlanguagechange",
++      "onload",
++      "onloadeddata",
++      "onloadedmetadata",
++      "onloadend",
++      "onloadstart",
++      "onmessage",
++      "onmessageerror",
++      "onmousedown",
++      "onmouseenter",
++      "onmouseleave",
++      "onmousemove",
++      "onmouseout",
++      "onmouseover",
++      "onmouseup",
++      "onmousewheel",
++      "onwheel",
++      "onoffline",
++      "ononline",
++      "onpagehide",
++      "onpageshow",
++      "onpaste",
++      "onpause",
++      "onplay",
++      "onplaying",
++      "onpopstate",
++      "onprogress",
++      "onratechange",
++      "onreset",
++      "onresize",
++      "onrejectionhandled",
++      "onscroll",
++      "onsecuritypolicyviolation",
++      "onseeked",
++      "onseeking",
++      "onselect",
++      "onshow",
++      "onsort",
++      "onstalled",
++      "onstorage",
++      "onsubmit",
++      "onsuspend",
++      "ontimeupdate",
++      "ontoggle",
++      "onunhandledrejection",
++      "onunload",
++      "onvolumechange",
++      "onwaiting",
++}
++
++// extra are ad-hoc values not covered by any of the lists above.
++var extra = []string{
++      "acronym",
++      "align",
++      "annotation",
++      "annotation-xml",
++      "applet",
++      "basefont",
++      "bgsound",
++      "big",
++      "blink",
++      "center",
++      "color",
++      "desc",
++      "face",
++      "font",
++      "foreignObject", // HTML is case-insensitive, but SVG-embedded-in-HTML is case-sensitive.
++      "foreignobject",
++      "frame",
++      "frameset",
++      "image",
++      "isindex", // "isindex" has been removed from the spec, but are kept here for backwards compatibility.
++      "listing",
++      "malignmark",
++      "marquee",
++      "math",
++      "mglyph",
++      "mi",
++      "mn",
++      "mo",
++      "ms",
++      "mtext",
++      "nobr",
++      "noembed",
++      "noframes",
++      "plaintext",
++      "prompt",
++      "public",
++      "rb",
++      "rtc",
++      "spacer",
++      "strike",
++      "svg",
++      "system",
++      "tt",
++      "xmp",
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2a938864cb9d3e88b3259c4856412517a39dce5f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,783 @@@
++// Code generated by go generate gen.go; DO NOT EDIT.
++
++//go:generate go run gen.go
++
++package atom
++
++const (
++      A                         Atom = 0x1
++      Abbr                      Atom = 0x4
++      Accept                    Atom = 0x1a06
++      AcceptCharset             Atom = 0x1a0e
++      Accesskey                 Atom = 0x2c09
++      Acronym                   Atom = 0xaa07
++      Action                    Atom = 0x27206
++      Address                   Atom = 0x6f307
++      Align                     Atom = 0xb105
++      Allowfullscreen           Atom = 0x2080f
++      Allowpaymentrequest       Atom = 0xc113
++      Allowusermedia            Atom = 0xdd0e
++      Alt                       Atom = 0xf303
++      Annotation                Atom = 0x1c90a
++      AnnotationXml             Atom = 0x1c90e
++      Applet                    Atom = 0x31906
++      Area                      Atom = 0x35604
++      Article                   Atom = 0x3fc07
++      As                        Atom = 0x3c02
++      Aside                     Atom = 0x10705
++      Async                     Atom = 0xff05
++      Audio                     Atom = 0x11505
++      Autocomplete              Atom = 0x2780c
++      Autofocus                 Atom = 0x12109
++      Autoplay                  Atom = 0x13c08
++      B                         Atom = 0x101
++      Base                      Atom = 0x3b04
++      Basefont                  Atom = 0x3b08
++      Bdi                       Atom = 0xba03
++      Bdo                       Atom = 0x14b03
++      Bgsound                   Atom = 0x15e07
++      Big                       Atom = 0x17003
++      Blink                     Atom = 0x17305
++      Blockquote                Atom = 0x1870a
++      Body                      Atom = 0x2804
++      Br                        Atom = 0x202
++      Button                    Atom = 0x19106
++      Canvas                    Atom = 0x10306
++      Caption                   Atom = 0x23107
++      Center                    Atom = 0x22006
++      Challenge                 Atom = 0x29b09
++      Charset                   Atom = 0x2107
++      Checked                   Atom = 0x47907
++      Cite                      Atom = 0x19c04
++      Class                     Atom = 0x56405
++      Code                      Atom = 0x5c504
++      Col                       Atom = 0x1ab03
++      Colgroup                  Atom = 0x1ab08
++      Color                     Atom = 0x1bf05
++      Cols                      Atom = 0x1c404
++      Colspan                   Atom = 0x1c407
++      Command                   Atom = 0x1d707
++      Content                   Atom = 0x58b07
++      Contenteditable           Atom = 0x58b0f
++      Contextmenu               Atom = 0x3800b
++      Controls                  Atom = 0x1de08
++      Coords                    Atom = 0x1ea06
++      Crossorigin               Atom = 0x1fb0b
++      Data                      Atom = 0x4a504
++      Datalist                  Atom = 0x4a508
++      Datetime                  Atom = 0x2b808
++      Dd                        Atom = 0x2d702
++      Default                   Atom = 0x10a07
++      Defer                     Atom = 0x5c705
++      Del                       Atom = 0x45203
++      Desc                      Atom = 0x56104
++      Details                   Atom = 0x7207
++      Dfn                       Atom = 0x8703
++      Dialog                    Atom = 0xbb06
++      Dir                       Atom = 0x9303
++      Dirname                   Atom = 0x9307
++      Disabled                  Atom = 0x16408
++      Div                       Atom = 0x16b03
++      Dl                        Atom = 0x5e602
++      Download                  Atom = 0x46308
++      Draggable                 Atom = 0x17a09
++      Dropzone                  Atom = 0x40508
++      Dt                        Atom = 0x64b02
++      Em                        Atom = 0x6e02
++      Embed                     Atom = 0x6e05
++      Enctype                   Atom = 0x28d07
++      Face                      Atom = 0x21e04
++      Fieldset                  Atom = 0x22608
++      Figcaption                Atom = 0x22e0a
++      Figure                    Atom = 0x24806
++      Font                      Atom = 0x3f04
++      Footer                    Atom = 0xf606
++      For                       Atom = 0x25403
++      ForeignObject             Atom = 0x2540d
++      Foreignobject             Atom = 0x2610d
++      Form                      Atom = 0x26e04
++      Formaction                Atom = 0x26e0a
++      Formenctype               Atom = 0x2890b
++      Formmethod                Atom = 0x2a40a
++      Formnovalidate            Atom = 0x2ae0e
++      Formtarget                Atom = 0x2c00a
++      Frame                     Atom = 0x8b05
++      Frameset                  Atom = 0x8b08
++      H1                        Atom = 0x15c02
++      H2                        Atom = 0x2de02
++      H3                        Atom = 0x30d02
++      H4                        Atom = 0x34502
++      H5                        Atom = 0x34f02
++      H6                        Atom = 0x64d02
++      Head                      Atom = 0x33104
++      Header                    Atom = 0x33106
++      Headers                   Atom = 0x33107
++      Height                    Atom = 0x5206
++      Hgroup                    Atom = 0x2ca06
++      Hidden                    Atom = 0x2d506
++      High                      Atom = 0x2db04
++      Hr                        Atom = 0x15702
++      Href                      Atom = 0x2e004
++      Hreflang                  Atom = 0x2e008
++      Html                      Atom = 0x5604
++      HttpEquiv                 Atom = 0x2e80a
++      I                         Atom = 0x601
++      Icon                      Atom = 0x58a04
++      Id                        Atom = 0x10902
++      Iframe                    Atom = 0x2fc06
++      Image                     Atom = 0x30205
++      Img                       Atom = 0x30703
++      Input                     Atom = 0x44b05
++      Inputmode                 Atom = 0x44b09
++      Ins                       Atom = 0x20403
++      Integrity                 Atom = 0x23f09
++      Is                        Atom = 0x16502
++      Isindex                   Atom = 0x30f07
++      Ismap                     Atom = 0x31605
++      Itemid                    Atom = 0x38b06
++      Itemprop                  Atom = 0x19d08
++      Itemref                   Atom = 0x3cd07
++      Itemscope                 Atom = 0x67109
++      Itemtype                  Atom = 0x31f08
++      Kbd                       Atom = 0xb903
++      Keygen                    Atom = 0x3206
++      Keytype                   Atom = 0xd607
++      Kind                      Atom = 0x17704
++      Label                     Atom = 0x5905
++      Lang                      Atom = 0x2e404
++      Legend                    Atom = 0x18106
++      Li                        Atom = 0xb202
++      Link                      Atom = 0x17404
++      List                      Atom = 0x4a904
++      Listing                   Atom = 0x4a907
++      Loop                      Atom = 0x5d04
++      Low                       Atom = 0xc303
++      Main                      Atom = 0x1004
++      Malignmark                Atom = 0xb00a
++      Manifest                  Atom = 0x6d708
++      Map                       Atom = 0x31803
++      Mark                      Atom = 0xb604
++      Marquee                   Atom = 0x32707
++      Math                      Atom = 0x32e04
++      Max                       Atom = 0x33d03
++      Maxlength                 Atom = 0x33d09
++      Media                     Atom = 0xe605
++      Mediagroup                Atom = 0xe60a
++      Menu                      Atom = 0x38704
++      Menuitem                  Atom = 0x38708
++      Meta                      Atom = 0x4b804
++      Meter                     Atom = 0x9805
++      Method                    Atom = 0x2a806
++      Mglyph                    Atom = 0x30806
++      Mi                        Atom = 0x34702
++      Min                       Atom = 0x34703
++      Minlength                 Atom = 0x34709
++      Mn                        Atom = 0x2b102
++      Mo                        Atom = 0xa402
++      Ms                        Atom = 0x67402
++      Mtext                     Atom = 0x35105
++      Multiple                  Atom = 0x35f08
++      Muted                     Atom = 0x36705
++      Name                      Atom = 0x9604
++      Nav                       Atom = 0x1303
++      Nobr                      Atom = 0x3704
++      Noembed                   Atom = 0x6c07
++      Noframes                  Atom = 0x8908
++      Nomodule                  Atom = 0xa208
++      Nonce                     Atom = 0x1a605
++      Noscript                  Atom = 0x21608
++      Novalidate                Atom = 0x2b20a
++      Object                    Atom = 0x26806
++      Ol                        Atom = 0x13702
++      Onabort                   Atom = 0x19507
++      Onafterprint              Atom = 0x2360c
++      Onautocomplete            Atom = 0x2760e
++      Onautocompleteerror       Atom = 0x27613
++      Onauxclick                Atom = 0x61f0a
++      Onbeforeprint             Atom = 0x69e0d
++      Onbeforeunload            Atom = 0x6e70e
++      Onblur                    Atom = 0x56d06
++      Oncancel                  Atom = 0x11908
++      Oncanplay                 Atom = 0x14d09
++      Oncanplaythrough          Atom = 0x14d10
++      Onchange                  Atom = 0x41b08
++      Onclick                   Atom = 0x2f507
++      Onclose                   Atom = 0x36c07
++      Oncontextmenu             Atom = 0x37e0d
++      Oncopy                    Atom = 0x39106
++      Oncuechange               Atom = 0x3970b
++      Oncut                     Atom = 0x3a205
++      Ondblclick                Atom = 0x3a70a
++      Ondrag                    Atom = 0x3b106
++      Ondragend                 Atom = 0x3b109
++      Ondragenter               Atom = 0x3ba0b
++      Ondragexit                Atom = 0x3c50a
++      Ondragleave               Atom = 0x3df0b
++      Ondragover                Atom = 0x3ea0a
++      Ondragstart               Atom = 0x3f40b
++      Ondrop                    Atom = 0x40306
++      Ondurationchange          Atom = 0x41310
++      Onemptied                 Atom = 0x40a09
++      Onended                   Atom = 0x42307
++      Onerror                   Atom = 0x42a07
++      Onfocus                   Atom = 0x43107
++      Onhashchange              Atom = 0x43d0c
++      Oninput                   Atom = 0x44907
++      Oninvalid                 Atom = 0x45509
++      Onkeydown                 Atom = 0x45e09
++      Onkeypress                Atom = 0x46b0a
++      Onkeyup                   Atom = 0x48007
++      Onlanguagechange          Atom = 0x48d10
++      Onload                    Atom = 0x49d06
++      Onloadeddata              Atom = 0x49d0c
++      Onloadedmetadata          Atom = 0x4b010
++      Onloadend                 Atom = 0x4c609
++      Onloadstart               Atom = 0x4cf0b
++      Onmessage                 Atom = 0x4da09
++      Onmessageerror            Atom = 0x4da0e
++      Onmousedown               Atom = 0x4e80b
++      Onmouseenter              Atom = 0x4f30c
++      Onmouseleave              Atom = 0x4ff0c
++      Onmousemove               Atom = 0x50b0b
++      Onmouseout                Atom = 0x5160a
++      Onmouseover               Atom = 0x5230b
++      Onmouseup                 Atom = 0x52e09
++      Onmousewheel              Atom = 0x53c0c
++      Onoffline                 Atom = 0x54809
++      Ononline                  Atom = 0x55108
++      Onpagehide                Atom = 0x5590a
++      Onpageshow                Atom = 0x5730a
++      Onpaste                   Atom = 0x57f07
++      Onpause                   Atom = 0x59a07
++      Onplay                    Atom = 0x5a406
++      Onplaying                 Atom = 0x5a409
++      Onpopstate                Atom = 0x5ad0a
++      Onprogress                Atom = 0x5b70a
++      Onratechange              Atom = 0x5cc0c
++      Onrejectionhandled        Atom = 0x5d812
++      Onreset                   Atom = 0x5ea07
++      Onresize                  Atom = 0x5f108
++      Onscroll                  Atom = 0x60008
++      Onsecuritypolicyviolation Atom = 0x60819
++      Onseeked                  Atom = 0x62908
++      Onseeking                 Atom = 0x63109
++      Onselect                  Atom = 0x63a08
++      Onshow                    Atom = 0x64406
++      Onsort                    Atom = 0x64f06
++      Onstalled                 Atom = 0x65909
++      Onstorage                 Atom = 0x66209
++      Onsubmit                  Atom = 0x66b08
++      Onsuspend                 Atom = 0x67b09
++      Ontimeupdate              Atom = 0x400c
++      Ontoggle                  Atom = 0x68408
++      Onunhandledrejection      Atom = 0x68c14
++      Onunload                  Atom = 0x6ab08
++      Onvolumechange            Atom = 0x6b30e
++      Onwaiting                 Atom = 0x6c109
++      Onwheel                   Atom = 0x6ca07
++      Open                      Atom = 0x1a304
++      Optgroup                  Atom = 0x5f08
++      Optimum                   Atom = 0x6d107
++      Option                    Atom = 0x6e306
++      Output                    Atom = 0x51d06
++      P                         Atom = 0xc01
++      Param                     Atom = 0xc05
++      Pattern                   Atom = 0x6607
++      Picture                   Atom = 0x7b07
++      Ping                      Atom = 0xef04
++      Placeholder               Atom = 0x1310b
++      Plaintext                 Atom = 0x1b209
++      Playsinline               Atom = 0x1400b
++      Poster                    Atom = 0x2cf06
++      Pre                       Atom = 0x47003
++      Preload                   Atom = 0x48607
++      Progress                  Atom = 0x5b908
++      Prompt                    Atom = 0x53606
++      Public                    Atom = 0x58606
++      Q                         Atom = 0xcf01
++      Radiogroup                Atom = 0x30a
++      Rb                        Atom = 0x3a02
++      Readonly                  Atom = 0x35708
++      Referrerpolicy            Atom = 0x3d10e
++      Rel                       Atom = 0x48703
++      Required                  Atom = 0x24c08
++      Reversed                  Atom = 0x8008
++      Rows                      Atom = 0x9c04
++      Rowspan                   Atom = 0x9c07
++      Rp                        Atom = 0x23c02
++      Rt                        Atom = 0x19a02
++      Rtc                       Atom = 0x19a03
++      Ruby                      Atom = 0xfb04
++      S                         Atom = 0x2501
++      Samp                      Atom = 0x7804
++      Sandbox                   Atom = 0x12907
++      Scope                     Atom = 0x67505
++      Scoped                    Atom = 0x67506
++      Script                    Atom = 0x21806
++      Seamless                  Atom = 0x37108
++      Section                   Atom = 0x56807
++      Select                    Atom = 0x63c06
++      Selected                  Atom = 0x63c08
++      Shape                     Atom = 0x1e505
++      Size                      Atom = 0x5f504
++      Sizes                     Atom = 0x5f505
++      Slot                      Atom = 0x1ef04
++      Small                     Atom = 0x20605
++      Sortable                  Atom = 0x65108
++      Sorted                    Atom = 0x33706
++      Source                    Atom = 0x37806
++      Spacer                    Atom = 0x43706
++      Span                      Atom = 0x9f04
++      Spellcheck                Atom = 0x4740a
++      Src                       Atom = 0x5c003
++      Srcdoc                    Atom = 0x5c006
++      Srclang                   Atom = 0x5f907
++      Srcset                    Atom = 0x6f906
++      Start                     Atom = 0x3fa05
++      Step                      Atom = 0x58304
++      Strike                    Atom = 0xd206
++      Strong                    Atom = 0x6dd06
++      Style                     Atom = 0x6ff05
++      Sub                       Atom = 0x66d03
++      Summary                   Atom = 0x70407
++      Sup                       Atom = 0x70b03
++      Svg                       Atom = 0x70e03
++      System                    Atom = 0x71106
++      Tabindex                  Atom = 0x4be08
++      Table                     Atom = 0x59505
++      Target                    Atom = 0x2c406
++      Tbody                     Atom = 0x2705
++      Td                        Atom = 0x9202
++      Template                  Atom = 0x71408
++      Textarea                  Atom = 0x35208
++      Tfoot                     Atom = 0xf505
++      Th                        Atom = 0x15602
++      Thead                     Atom = 0x33005
++      Time                      Atom = 0x4204
++      Title                     Atom = 0x11005
++      Tr                        Atom = 0xcc02
++      Track                     Atom = 0x1ba05
++      Translate                 Atom = 0x1f209
++      Tt                        Atom = 0x6802
++      Type                      Atom = 0xd904
++      Typemustmatch             Atom = 0x2900d
++      U                         Atom = 0xb01
++      Ul                        Atom = 0xa702
++      Updateviacache            Atom = 0x460e
++      Usemap                    Atom = 0x59e06
++      Value                     Atom = 0x1505
++      Var                       Atom = 0x16d03
++      Video                     Atom = 0x2f105
++      Wbr                       Atom = 0x57c03
++      Width                     Atom = 0x64905
++      Workertype                Atom = 0x71c0a
++      Wrap                      Atom = 0x72604
++      Xmp                       Atom = 0x12f03
++)
++
++const hash0 = 0x81cdf10e
++
++const maxAtomLen = 25
++
++var table = [1 << 9]Atom{
++      0x1:   0xe60a,  // mediagroup
++      0x2:   0x2e404, // lang
++      0x4:   0x2c09,  // accesskey
++      0x5:   0x8b08,  // frameset
++      0x7:   0x63a08, // onselect
++      0x8:   0x71106, // system
++      0xa:   0x64905, // width
++      0xc:   0x2890b, // formenctype
++      0xd:   0x13702, // ol
++      0xe:   0x3970b, // oncuechange
++      0x10:  0x14b03, // bdo
++      0x11:  0x11505, // audio
++      0x12:  0x17a09, // draggable
++      0x14:  0x2f105, // video
++      0x15:  0x2b102, // mn
++      0x16:  0x38704, // menu
++      0x17:  0x2cf06, // poster
++      0x19:  0xf606,  // footer
++      0x1a:  0x2a806, // method
++      0x1b:  0x2b808, // datetime
++      0x1c:  0x19507, // onabort
++      0x1d:  0x460e,  // updateviacache
++      0x1e:  0xff05,  // async
++      0x1f:  0x49d06, // onload
++      0x21:  0x11908, // oncancel
++      0x22:  0x62908, // onseeked
++      0x23:  0x30205, // image
++      0x24:  0x5d812, // onrejectionhandled
++      0x26:  0x17404, // link
++      0x27:  0x51d06, // output
++      0x28:  0x33104, // head
++      0x29:  0x4ff0c, // onmouseleave
++      0x2a:  0x57f07, // onpaste
++      0x2b:  0x5a409, // onplaying
++      0x2c:  0x1c407, // colspan
++      0x2f:  0x1bf05, // color
++      0x30:  0x5f504, // size
++      0x31:  0x2e80a, // http-equiv
++      0x33:  0x601,   // i
++      0x34:  0x5590a, // onpagehide
++      0x35:  0x68c14, // onunhandledrejection
++      0x37:  0x42a07, // onerror
++      0x3a:  0x3b08,  // basefont
++      0x3f:  0x1303,  // nav
++      0x40:  0x17704, // kind
++      0x41:  0x35708, // readonly
++      0x42:  0x30806, // mglyph
++      0x44:  0xb202,  // li
++      0x46:  0x2d506, // hidden
++      0x47:  0x70e03, // svg
++      0x48:  0x58304, // step
++      0x49:  0x23f09, // integrity
++      0x4a:  0x58606, // public
++      0x4c:  0x1ab03, // col
++      0x4d:  0x1870a, // blockquote
++      0x4e:  0x34f02, // h5
++      0x50:  0x5b908, // progress
++      0x51:  0x5f505, // sizes
++      0x52:  0x34502, // h4
++      0x56:  0x33005, // thead
++      0x57:  0xd607,  // keytype
++      0x58:  0x5b70a, // onprogress
++      0x59:  0x44b09, // inputmode
++      0x5a:  0x3b109, // ondragend
++      0x5d:  0x3a205, // oncut
++      0x5e:  0x43706, // spacer
++      0x5f:  0x1ab08, // colgroup
++      0x62:  0x16502, // is
++      0x65:  0x3c02,  // as
++      0x66:  0x54809, // onoffline
++      0x67:  0x33706, // sorted
++      0x69:  0x48d10, // onlanguagechange
++      0x6c:  0x43d0c, // onhashchange
++      0x6d:  0x9604,  // name
++      0x6e:  0xf505,  // tfoot
++      0x6f:  0x56104, // desc
++      0x70:  0x33d03, // max
++      0x72:  0x1ea06, // coords
++      0x73:  0x30d02, // h3
++      0x74:  0x6e70e, // onbeforeunload
++      0x75:  0x9c04,  // rows
++      0x76:  0x63c06, // select
++      0x77:  0x9805,  // meter
++      0x78:  0x38b06, // itemid
++      0x79:  0x53c0c, // onmousewheel
++      0x7a:  0x5c006, // srcdoc
++      0x7d:  0x1ba05, // track
++      0x7f:  0x31f08, // itemtype
++      0x82:  0xa402,  // mo
++      0x83:  0x41b08, // onchange
++      0x84:  0x33107, // headers
++      0x85:  0x5cc0c, // onratechange
++      0x86:  0x60819, // onsecuritypolicyviolation
++      0x88:  0x4a508, // datalist
++      0x89:  0x4e80b, // onmousedown
++      0x8a:  0x1ef04, // slot
++      0x8b:  0x4b010, // onloadedmetadata
++      0x8c:  0x1a06,  // accept
++      0x8d:  0x26806, // object
++      0x91:  0x6b30e, // onvolumechange
++      0x92:  0x2107,  // charset
++      0x93:  0x27613, // onautocompleteerror
++      0x94:  0xc113,  // allowpaymentrequest
++      0x95:  0x2804,  // body
++      0x96:  0x10a07, // default
++      0x97:  0x63c08, // selected
++      0x98:  0x21e04, // face
++      0x99:  0x1e505, // shape
++      0x9b:  0x68408, // ontoggle
++      0x9e:  0x64b02, // dt
++      0x9f:  0xb604,  // mark
++      0xa1:  0xb01,   // u
++      0xa4:  0x6ab08, // onunload
++      0xa5:  0x5d04,  // loop
++      0xa6:  0x16408, // disabled
++      0xaa:  0x42307, // onended
++      0xab:  0xb00a,  // malignmark
++      0xad:  0x67b09, // onsuspend
++      0xae:  0x35105, // mtext
++      0xaf:  0x64f06, // onsort
++      0xb0:  0x19d08, // itemprop
++      0xb3:  0x67109, // itemscope
++      0xb4:  0x17305, // blink
++      0xb6:  0x3b106, // ondrag
++      0xb7:  0xa702,  // ul
++      0xb8:  0x26e04, // form
++      0xb9:  0x12907, // sandbox
++      0xba:  0x8b05,  // frame
++      0xbb:  0x1505,  // value
++      0xbc:  0x66209, // onstorage
++      0xbf:  0xaa07,  // acronym
++      0xc0:  0x19a02, // rt
++      0xc2:  0x202,   // br
++      0xc3:  0x22608, // fieldset
++      0xc4:  0x2900d, // typemustmatch
++      0xc5:  0xa208,  // nomodule
++      0xc6:  0x6c07,  // noembed
++      0xc7:  0x69e0d, // onbeforeprint
++      0xc8:  0x19106, // button
++      0xc9:  0x2f507, // onclick
++      0xca:  0x70407, // summary
++      0xcd:  0xfb04,  // ruby
++      0xce:  0x56405, // class
++      0xcf:  0x3f40b, // ondragstart
++      0xd0:  0x23107, // caption
++      0xd4:  0xdd0e,  // allowusermedia
++      0xd5:  0x4cf0b, // onloadstart
++      0xd9:  0x16b03, // div
++      0xda:  0x4a904, // list
++      0xdb:  0x32e04, // math
++      0xdc:  0x44b05, // input
++      0xdf:  0x3ea0a, // ondragover
++      0xe0:  0x2de02, // h2
++      0xe2:  0x1b209, // plaintext
++      0xe4:  0x4f30c, // onmouseenter
++      0xe7:  0x47907, // checked
++      0xe8:  0x47003, // pre
++      0xea:  0x35f08, // multiple
++      0xeb:  0xba03,  // bdi
++      0xec:  0x33d09, // maxlength
++      0xed:  0xcf01,  // q
++      0xee:  0x61f0a, // onauxclick
++      0xf0:  0x57c03, // wbr
++      0xf2:  0x3b04,  // base
++      0xf3:  0x6e306, // option
++      0xf5:  0x41310, // ondurationchange
++      0xf7:  0x8908,  // noframes
++      0xf9:  0x40508, // dropzone
++      0xfb:  0x67505, // scope
++      0xfc:  0x8008,  // reversed
++      0xfd:  0x3ba0b, // ondragenter
++      0xfe:  0x3fa05, // start
++      0xff:  0x12f03, // xmp
++      0x100: 0x5f907, // srclang
++      0x101: 0x30703, // img
++      0x104: 0x101,   // b
++      0x105: 0x25403, // for
++      0x106: 0x10705, // aside
++      0x107: 0x44907, // oninput
++      0x108: 0x35604, // area
++      0x109: 0x2a40a, // formmethod
++      0x10a: 0x72604, // wrap
++      0x10c: 0x23c02, // rp
++      0x10d: 0x46b0a, // onkeypress
++      0x10e: 0x6802,  // tt
++      0x110: 0x34702, // mi
++      0x111: 0x36705, // muted
++      0x112: 0xf303,  // alt
++      0x113: 0x5c504, // code
++      0x114: 0x6e02,  // em
++      0x115: 0x3c50a, // ondragexit
++      0x117: 0x9f04,  // span
++      0x119: 0x6d708, // manifest
++      0x11a: 0x38708, // menuitem
++      0x11b: 0x58b07, // content
++      0x11d: 0x6c109, // onwaiting
++      0x11f: 0x4c609, // onloadend
++      0x121: 0x37e0d, // oncontextmenu
++      0x123: 0x56d06, // onblur
++      0x124: 0x3fc07, // article
++      0x125: 0x9303,  // dir
++      0x126: 0xef04,  // ping
++      0x127: 0x24c08, // required
++      0x128: 0x45509, // oninvalid
++      0x129: 0xb105,  // align
++      0x12b: 0x58a04, // icon
++      0x12c: 0x64d02, // h6
++      0x12d: 0x1c404, // cols
++      0x12e: 0x22e0a, // figcaption
++      0x12f: 0x45e09, // onkeydown
++      0x130: 0x66b08, // onsubmit
++      0x131: 0x14d09, // oncanplay
++      0x132: 0x70b03, // sup
++      0x133: 0xc01,   // p
++      0x135: 0x40a09, // onemptied
++      0x136: 0x39106, // oncopy
++      0x137: 0x19c04, // cite
++      0x138: 0x3a70a, // ondblclick
++      0x13a: 0x50b0b, // onmousemove
++      0x13c: 0x66d03, // sub
++      0x13d: 0x48703, // rel
++      0x13e: 0x5f08,  // optgroup
++      0x142: 0x9c07,  // rowspan
++      0x143: 0x37806, // source
++      0x144: 0x21608, // noscript
++      0x145: 0x1a304, // open
++      0x146: 0x20403, // ins
++      0x147: 0x2540d, // foreignObject
++      0x148: 0x5ad0a, // onpopstate
++      0x14a: 0x28d07, // enctype
++      0x14b: 0x2760e, // onautocomplete
++      0x14c: 0x35208, // textarea
++      0x14e: 0x2780c, // autocomplete
++      0x14f: 0x15702, // hr
++      0x150: 0x1de08, // controls
++      0x151: 0x10902, // id
++      0x153: 0x2360c, // onafterprint
++      0x155: 0x2610d, // foreignobject
++      0x156: 0x32707, // marquee
++      0x157: 0x59a07, // onpause
++      0x158: 0x5e602, // dl
++      0x159: 0x5206,  // height
++      0x15a: 0x34703, // min
++      0x15b: 0x9307,  // dirname
++      0x15c: 0x1f209, // translate
++      0x15d: 0x5604,  // html
++      0x15e: 0x34709, // minlength
++      0x15f: 0x48607, // preload
++      0x160: 0x71408, // template
++      0x161: 0x3df0b, // ondragleave
++      0x162: 0x3a02,  // rb
++      0x164: 0x5c003, // src
++      0x165: 0x6dd06, // strong
++      0x167: 0x7804,  // samp
++      0x168: 0x6f307, // address
++      0x169: 0x55108, // ononline
++      0x16b: 0x1310b, // placeholder
++      0x16c: 0x2c406, // target
++      0x16d: 0x20605, // small
++      0x16e: 0x6ca07, // onwheel
++      0x16f: 0x1c90a, // annotation
++      0x170: 0x4740a, // spellcheck
++      0x171: 0x7207,  // details
++      0x172: 0x10306, // canvas
++      0x173: 0x12109, // autofocus
++      0x174: 0xc05,   // param
++      0x176: 0x46308, // download
++      0x177: 0x45203, // del
++      0x178: 0x36c07, // onclose
++      0x179: 0xb903,  // kbd
++      0x17a: 0x31906, // applet
++      0x17b: 0x2e004, // href
++      0x17c: 0x5f108, // onresize
++      0x17e: 0x49d0c, // onloadeddata
++      0x180: 0xcc02,  // tr
++      0x181: 0x2c00a, // formtarget
++      0x182: 0x11005, // title
++      0x183: 0x6ff05, // style
++      0x184: 0xd206,  // strike
++      0x185: 0x59e06, // usemap
++      0x186: 0x2fc06, // iframe
++      0x187: 0x1004,  // main
++      0x189: 0x7b07,  // picture
++      0x18c: 0x31605, // ismap
++      0x18e: 0x4a504, // data
++      0x18f: 0x5905,  // label
++      0x191: 0x3d10e, // referrerpolicy
++      0x192: 0x15602, // th
++      0x194: 0x53606, // prompt
++      0x195: 0x56807, // section
++      0x197: 0x6d107, // optimum
++      0x198: 0x2db04, // high
++      0x199: 0x15c02, // h1
++      0x19a: 0x65909, // onstalled
++      0x19b: 0x16d03, // var
++      0x19c: 0x4204,  // time
++      0x19e: 0x67402, // ms
++      0x19f: 0x33106, // header
++      0x1a0: 0x4da09, // onmessage
++      0x1a1: 0x1a605, // nonce
++      0x1a2: 0x26e0a, // formaction
++      0x1a3: 0x22006, // center
++      0x1a4: 0x3704,  // nobr
++      0x1a5: 0x59505, // table
++      0x1a6: 0x4a907, // listing
++      0x1a7: 0x18106, // legend
++      0x1a9: 0x29b09, // challenge
++      0x1aa: 0x24806, // figure
++      0x1ab: 0xe605,  // media
++      0x1ae: 0xd904,  // type
++      0x1af: 0x3f04,  // font
++      0x1b0: 0x4da0e, // onmessageerror
++      0x1b1: 0x37108, // seamless
++      0x1b2: 0x8703,  // dfn
++      0x1b3: 0x5c705, // defer
++      0x1b4: 0xc303,  // low
++      0x1b5: 0x19a03, // rtc
++      0x1b6: 0x5230b, // onmouseover
++      0x1b7: 0x2b20a, // novalidate
++      0x1b8: 0x71c0a, // workertype
++      0x1ba: 0x3cd07, // itemref
++      0x1bd: 0x1,     // a
++      0x1be: 0x31803, // map
++      0x1bf: 0x400c,  // ontimeupdate
++      0x1c0: 0x15e07, // bgsound
++      0x1c1: 0x3206,  // keygen
++      0x1c2: 0x2705,  // tbody
++      0x1c5: 0x64406, // onshow
++      0x1c7: 0x2501,  // s
++      0x1c8: 0x6607,  // pattern
++      0x1cc: 0x14d10, // oncanplaythrough
++      0x1ce: 0x2d702, // dd
++      0x1cf: 0x6f906, // srcset
++      0x1d0: 0x17003, // big
++      0x1d2: 0x65108, // sortable
++      0x1d3: 0x48007, // onkeyup
++      0x1d5: 0x5a406, // onplay
++      0x1d7: 0x4b804, // meta
++      0x1d8: 0x40306, // ondrop
++      0x1da: 0x60008, // onscroll
++      0x1db: 0x1fb0b, // crossorigin
++      0x1dc: 0x5730a, // onpageshow
++      0x1dd: 0x4,     // abbr
++      0x1de: 0x9202,  // td
++      0x1df: 0x58b0f, // contenteditable
++      0x1e0: 0x27206, // action
++      0x1e1: 0x1400b, // playsinline
++      0x1e2: 0x43107, // onfocus
++      0x1e3: 0x2e008, // hreflang
++      0x1e5: 0x5160a, // onmouseout
++      0x1e6: 0x5ea07, // onreset
++      0x1e7: 0x13c08, // autoplay
++      0x1e8: 0x63109, // onseeking
++      0x1ea: 0x67506, // scoped
++      0x1ec: 0x30a,   // radiogroup
++      0x1ee: 0x3800b, // contextmenu
++      0x1ef: 0x52e09, // onmouseup
++      0x1f1: 0x2ca06, // hgroup
++      0x1f2: 0x2080f, // allowfullscreen
++      0x1f3: 0x4be08, // tabindex
++      0x1f6: 0x30f07, // isindex
++      0x1f7: 0x1a0e,  // accept-charset
++      0x1f8: 0x2ae0e, // formnovalidate
++      0x1fb: 0x1c90e, // annotation-xml
++      0x1fc: 0x6e05,  // embed
++      0x1fd: 0x21806, // script
++      0x1fe: 0xbb06,  // dialog
++      0x1ff: 0x1d707, // command
++}
++
++const atomText = "abbradiogrouparamainavalueaccept-charsetbodyaccesskeygenobrb" +
++      "asefontimeupdateviacacheightmlabelooptgroupatternoembedetail" +
++      "sampictureversedfnoframesetdirnameterowspanomoduleacronymali" +
++      "gnmarkbdialogallowpaymentrequestrikeytypeallowusermediagroup" +
++      "ingaltfooterubyasyncanvasidefaultitleaudioncancelautofocusan" +
++      "dboxmplaceholderautoplaysinlinebdoncanplaythrough1bgsoundisa" +
++      "bledivarbigblinkindraggablegendblockquotebuttonabortcitempro" +
++      "penoncecolgrouplaintextrackcolorcolspannotation-xmlcommandco" +
++      "ntrolshapecoordslotranslatecrossoriginsmallowfullscreenoscri" +
++      "ptfacenterfieldsetfigcaptionafterprintegrityfigurequiredfore" +
++      "ignObjectforeignobjectformactionautocompleteerrorformenctype" +
++      "mustmatchallengeformmethodformnovalidatetimeformtargethgroup" +
++      "osterhiddenhigh2hreflanghttp-equivideonclickiframeimageimgly" +
++      "ph3isindexismappletitemtypemarqueematheadersortedmaxlength4m" +
++      "inlength5mtextareadonlymultiplemutedoncloseamlessourceoncont" +
++      "extmenuitemidoncopyoncuechangeoncutondblclickondragendondrag" +
++      "enterondragexitemreferrerpolicyondragleaveondragoverondragst" +
++      "articleondropzonemptiedondurationchangeonendedonerroronfocus" +
++      "paceronhashchangeoninputmodeloninvalidonkeydownloadonkeypres" +
++      "spellcheckedonkeyupreloadonlanguagechangeonloadeddatalisting" +
++      "onloadedmetadatabindexonloadendonloadstartonmessageerroronmo" +
++      "usedownonmouseenteronmouseleaveonmousemoveonmouseoutputonmou" +
++      "seoveronmouseupromptonmousewheelonofflineononlineonpagehides" +
++      "classectionbluronpageshowbronpastepublicontenteditableonpaus" +
++      "emaponplayingonpopstateonprogressrcdocodeferonratechangeonre" +
++      "jectionhandledonresetonresizesrclangonscrollonsecuritypolicy" +
++      "violationauxclickonseekedonseekingonselectedonshowidth6onsor" +
++      "tableonstalledonstorageonsubmitemscopedonsuspendontoggleonun" +
++      "handledrejectionbeforeprintonunloadonvolumechangeonwaitingon" +
++      "wheeloptimumanifestrongoptionbeforeunloaddressrcsetstylesumm" +
++      "arysupsvgsystemplateworkertypewrap"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8a30762ec27a76d2738c31981fb69a314f90528e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,376 @@@
++// Code generated by go generate gen.go; DO NOT EDIT.
++
++//go:generate go run gen.go -test
++
++package atom
++
++var testAtomList = []string{
++      "a",
++      "abbr",
++      "accept",
++      "accept-charset",
++      "accesskey",
++      "acronym",
++      "action",
++      "address",
++      "align",
++      "allowfullscreen",
++      "allowpaymentrequest",
++      "allowusermedia",
++      "alt",
++      "annotation",
++      "annotation-xml",
++      "applet",
++      "area",
++      "article",
++      "as",
++      "aside",
++      "async",
++      "audio",
++      "autocomplete",
++      "autofocus",
++      "autoplay",
++      "b",
++      "base",
++      "basefont",
++      "bdi",
++      "bdo",
++      "bgsound",
++      "big",
++      "blink",
++      "blockquote",
++      "body",
++      "br",
++      "button",
++      "canvas",
++      "caption",
++      "center",
++      "challenge",
++      "charset",
++      "checked",
++      "cite",
++      "class",
++      "code",
++      "col",
++      "colgroup",
++      "color",
++      "cols",
++      "colspan",
++      "command",
++      "content",
++      "contenteditable",
++      "contextmenu",
++      "controls",
++      "coords",
++      "crossorigin",
++      "data",
++      "datalist",
++      "datetime",
++      "dd",
++      "default",
++      "defer",
++      "del",
++      "desc",
++      "details",
++      "dfn",
++      "dialog",
++      "dir",
++      "dirname",
++      "disabled",
++      "div",
++      "dl",
++      "download",
++      "draggable",
++      "dropzone",
++      "dt",
++      "em",
++      "embed",
++      "enctype",
++      "face",
++      "fieldset",
++      "figcaption",
++      "figure",
++      "font",
++      "footer",
++      "for",
++      "foreignObject",
++      "foreignobject",
++      "form",
++      "formaction",
++      "formenctype",
++      "formmethod",
++      "formnovalidate",
++      "formtarget",
++      "frame",
++      "frameset",
++      "h1",
++      "h2",
++      "h3",
++      "h4",
++      "h5",
++      "h6",
++      "head",
++      "header",
++      "headers",
++      "height",
++      "hgroup",
++      "hidden",
++      "high",
++      "hr",
++      "href",
++      "hreflang",
++      "html",
++      "http-equiv",
++      "i",
++      "icon",
++      "id",
++      "iframe",
++      "image",
++      "img",
++      "input",
++      "inputmode",
++      "ins",
++      "integrity",
++      "is",
++      "isindex",
++      "ismap",
++      "itemid",
++      "itemprop",
++      "itemref",
++      "itemscope",
++      "itemtype",
++      "kbd",
++      "keygen",
++      "keytype",
++      "kind",
++      "label",
++      "lang",
++      "legend",
++      "li",
++      "link",
++      "list",
++      "listing",
++      "loop",
++      "low",
++      "main",
++      "malignmark",
++      "manifest",
++      "map",
++      "mark",
++      "marquee",
++      "math",
++      "max",
++      "maxlength",
++      "media",
++      "mediagroup",
++      "menu",
++      "menuitem",
++      "meta",
++      "meter",
++      "method",
++      "mglyph",
++      "mi",
++      "min",
++      "minlength",
++      "mn",
++      "mo",
++      "ms",
++      "mtext",
++      "multiple",
++      "muted",
++      "name",
++      "nav",
++      "nobr",
++      "noembed",
++      "noframes",
++      "nomodule",
++      "nonce",
++      "noscript",
++      "novalidate",
++      "object",
++      "ol",
++      "onabort",
++      "onafterprint",
++      "onautocomplete",
++      "onautocompleteerror",
++      "onauxclick",
++      "onbeforeprint",
++      "onbeforeunload",
++      "onblur",
++      "oncancel",
++      "oncanplay",
++      "oncanplaythrough",
++      "onchange",
++      "onclick",
++      "onclose",
++      "oncontextmenu",
++      "oncopy",
++      "oncuechange",
++      "oncut",
++      "ondblclick",
++      "ondrag",
++      "ondragend",
++      "ondragenter",
++      "ondragexit",
++      "ondragleave",
++      "ondragover",
++      "ondragstart",
++      "ondrop",
++      "ondurationchange",
++      "onemptied",
++      "onended",
++      "onerror",
++      "onfocus",
++      "onhashchange",
++      "oninput",
++      "oninvalid",
++      "onkeydown",
++      "onkeypress",
++      "onkeyup",
++      "onlanguagechange",
++      "onload",
++      "onloadeddata",
++      "onloadedmetadata",
++      "onloadend",
++      "onloadstart",
++      "onmessage",
++      "onmessageerror",
++      "onmousedown",
++      "onmouseenter",
++      "onmouseleave",
++      "onmousemove",
++      "onmouseout",
++      "onmouseover",
++      "onmouseup",
++      "onmousewheel",
++      "onoffline",
++      "ononline",
++      "onpagehide",
++      "onpageshow",
++      "onpaste",
++      "onpause",
++      "onplay",
++      "onplaying",
++      "onpopstate",
++      "onprogress",
++      "onratechange",
++      "onrejectionhandled",
++      "onreset",
++      "onresize",
++      "onscroll",
++      "onsecuritypolicyviolation",
++      "onseeked",
++      "onseeking",
++      "onselect",
++      "onshow",
++      "onsort",
++      "onstalled",
++      "onstorage",
++      "onsubmit",
++      "onsuspend",
++      "ontimeupdate",
++      "ontoggle",
++      "onunhandledrejection",
++      "onunload",
++      "onvolumechange",
++      "onwaiting",
++      "onwheel",
++      "open",
++      "optgroup",
++      "optimum",
++      "option",
++      "output",
++      "p",
++      "param",
++      "pattern",
++      "picture",
++      "ping",
++      "placeholder",
++      "plaintext",
++      "playsinline",
++      "poster",
++      "pre",
++      "preload",
++      "progress",
++      "prompt",
++      "public",
++      "q",
++      "radiogroup",
++      "rb",
++      "readonly",
++      "referrerpolicy",
++      "rel",
++      "required",
++      "reversed",
++      "rows",
++      "rowspan",
++      "rp",
++      "rt",
++      "rtc",
++      "ruby",
++      "s",
++      "samp",
++      "sandbox",
++      "scope",
++      "scoped",
++      "script",
++      "seamless",
++      "section",
++      "select",
++      "selected",
++      "shape",
++      "size",
++      "sizes",
++      "slot",
++      "small",
++      "sortable",
++      "sorted",
++      "source",
++      "spacer",
++      "span",
++      "spellcheck",
++      "src",
++      "srcdoc",
++      "srclang",
++      "srcset",
++      "start",
++      "step",
++      "strike",
++      "strong",
++      "style",
++      "sub",
++      "summary",
++      "sup",
++      "svg",
++      "system",
++      "tabindex",
++      "table",
++      "target",
++      "tbody",
++      "td",
++      "template",
++      "textarea",
++      "tfoot",
++      "th",
++      "thead",
++      "time",
++      "title",
++      "tr",
++      "track",
++      "translate",
++      "tt",
++      "type",
++      "typemustmatch",
++      "u",
++      "ul",
++      "updateviacache",
++      "usemap",
++      "value",
++      "var",
++      "video",
++      "wbr",
++      "width",
++      "workertype",
++      "wrap",
++      "xmp",
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f61c6c30bd3d962deb704e2a548602db2833e4f1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,257 @@@
++// Copyright 2013 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// Package charset provides common text encodings for HTML documents.
++//
++// The mapping from encoding labels to encodings is defined at
++// https://encoding.spec.whatwg.org/.
++package charset // import "git.earlybird.gay/today-engine/internal/html/charset"
++
++import (
++      "bytes"
++      "fmt"
++      "io"
++      "mime"
++      "strings"
++      "unicode/utf8"
++
++      "git.earlybird.gay/today-engine/internal/html"
++      "golang.org/x/text/encoding"
++      "golang.org/x/text/encoding/charmap"
++      "golang.org/x/text/encoding/htmlindex"
++      "golang.org/x/text/transform"
++)
++
++// Lookup returns the encoding with the specified label, and its canonical
++// name. It returns nil and the empty string if label is not one of the
++// standard encodings for HTML. Matching is case-insensitive and ignores
++// leading and trailing whitespace. Encoders will use HTML escape sequences for
++// runes that are not supported by the character set.
++func Lookup(label string) (e encoding.Encoding, name string) {
++      e, err := htmlindex.Get(label)
++      if err != nil {
++              return nil, ""
++      }
++      name, _ = htmlindex.Name(e)
++      return &htmlEncoding{e}, name
++}
++
++type htmlEncoding struct{ encoding.Encoding }
++
++func (h *htmlEncoding) NewEncoder() *encoding.Encoder {
++      // HTML requires a non-terminating legacy encoder. We use HTML escapes to
++      // substitute unsupported code points.
++      return encoding.HTMLEscapeUnsupported(h.Encoding.NewEncoder())
++}
++
++// DetermineEncoding determines the encoding of an HTML document by examining
++// up to the first 1024 bytes of content and the declared Content-Type.
++//
++// See http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html#determining-the-character-encoding
++func DetermineEncoding(content []byte, contentType string) (e encoding.Encoding, name string, certain bool) {
++      if len(content) > 1024 {
++              content = content[:1024]
++      }
++
++      for _, b := range boms {
++              if bytes.HasPrefix(content, b.bom) {
++                      e, name = Lookup(b.enc)
++                      return e, name, true
++              }
++      }
++
++      if _, params, err := mime.ParseMediaType(contentType); err == nil {
++              if cs, ok := params["charset"]; ok {
++                      if e, name = Lookup(cs); e != nil {
++                              return e, name, true
++                      }
++              }
++      }
++
++      if len(content) > 0 {
++              e, name = prescan(content)
++              if e != nil {
++                      return e, name, false
++              }
++      }
++
++      // Try to detect UTF-8.
++      // First eliminate any partial rune at the end.
++      for i := len(content) - 1; i >= 0 && i > len(content)-4; i-- {
++              b := content[i]
++              if b < 0x80 {
++                      break
++              }
++              if utf8.RuneStart(b) {
++                      content = content[:i]
++                      break
++              }
++      }
++      hasHighBit := false
++      for _, c := range content {
++              if c >= 0x80 {
++                      hasHighBit = true
++                      break
++              }
++      }
++      if hasHighBit && utf8.Valid(content) {
++              return encoding.Nop, "utf-8", false
++      }
++
++      // TODO: change default depending on user's locale?
++      return charmap.Windows1252, "windows-1252", false
++}
++
++// NewReader returns an io.Reader that converts the content of r to UTF-8.
++// It calls DetermineEncoding to find out what r's encoding is.
++func NewReader(r io.Reader, contentType string) (io.Reader, error) {
++      preview := make([]byte, 1024)
++      n, err := io.ReadFull(r, preview)
++      switch {
++      case err == io.ErrUnexpectedEOF:
++              preview = preview[:n]
++              r = bytes.NewReader(preview)
++      case err != nil:
++              return nil, err
++      default:
++              r = io.MultiReader(bytes.NewReader(preview), r)
++      }
++
++      if e, _, _ := DetermineEncoding(preview, contentType); e != encoding.Nop {
++              r = transform.NewReader(r, e.NewDecoder())
++      }
++      return r, nil
++}
++
++// NewReaderLabel returns a reader that converts from the specified charset to
++// UTF-8. It uses Lookup to find the encoding that corresponds to label, and
++// returns an error if Lookup returns nil. It is suitable for use as
++// encoding/xml.Decoder's CharsetReader function.
++func NewReaderLabel(label string, input io.Reader) (io.Reader, error) {
++      e, _ := Lookup(label)
++      if e == nil {
++              return nil, fmt.Errorf("unsupported charset: %q", label)
++      }
++      return transform.NewReader(input, e.NewDecoder()), nil
++}
++
++func prescan(content []byte) (e encoding.Encoding, name string) {
++      z := html.NewTokenizer(bytes.NewReader(content))
++      for {
++              switch z.Next() {
++              case html.ErrorToken:
++                      return nil, ""
++
++              case html.StartTagToken, html.SelfClosingTagToken:
++                      tagName, hasAttr := z.TagName()
++                      if !bytes.Equal(tagName, []byte("meta")) {
++                              continue
++                      }
++                      attrList := make(map[string]bool)
++                      gotPragma := false
++
++                      const (
++                              dontKnow = iota
++                              doNeedPragma
++                              doNotNeedPragma
++                      )
++                      needPragma := dontKnow
++
++                      name = ""
++                      e = nil
++                      for hasAttr {
++                              var key, val []byte
++                              key, val, hasAttr = z.TagAttr()
++                              ks := string(key)
++                              if attrList[ks] {
++                                      continue
++                              }
++                              attrList[ks] = true
++                              for i, c := range val {
++                                      if 'A' <= c && c <= 'Z' {
++                                              val[i] = c + 0x20
++                                      }
++                              }
++
++                              switch ks {
++                              case "http-equiv":
++                                      if bytes.Equal(val, []byte("content-type")) {
++                                              gotPragma = true
++                                      }
++
++                              case "content":
++                                      if e == nil {
++                                              name = fromMetaElement(string(val))
++                                              if name != "" {
++                                                      e, name = Lookup(name)
++                                                      if e != nil {
++                                                              needPragma = doNeedPragma
++                                                      }
++                                              }
++                                      }
++
++                              case "charset":
++                                      e, name = Lookup(string(val))
++                                      needPragma = doNotNeedPragma
++                              }
++                      }
++
++                      if needPragma == dontKnow || needPragma == doNeedPragma && !gotPragma {
++                              continue
++                      }
++
++                      if strings.HasPrefix(name, "utf-16") {
++                              name = "utf-8"
++                              e = encoding.Nop
++                      }
++
++                      if e != nil {
++                              return e, name
++                      }
++              }
++      }
++}
++
++func fromMetaElement(s string) string {
++      for s != "" {
++              csLoc := strings.Index(s, "charset")
++              if csLoc == -1 {
++                      return ""
++              }
++              s = s[csLoc+len("charset"):]
++              s = strings.TrimLeft(s, " \t\n\f\r")
++              if !strings.HasPrefix(s, "=") {
++                      continue
++              }
++              s = s[1:]
++              s = strings.TrimLeft(s, " \t\n\f\r")
++              if s == "" {
++                      return ""
++              }
++              if q := s[0]; q == '"' || q == '\'' {
++                      s = s[1:]
++                      closeQuote := strings.IndexRune(s, rune(q))
++                      if closeQuote == -1 {
++                              return ""
++                      }
++                      return s[:closeQuote]
++              }
++
++              end := strings.IndexAny(s, "; \t\n\f\r")
++              if end == -1 {
++                      end = len(s)
++              }
++              return s[:end]
++      }
++      return ""
++}
++
++var boms = []struct {
++      bom []byte
++      enc string
++}{
++      {[]byte{0xfe, 0xff}, "utf-16be"},
++      {[]byte{0xff, 0xfe}, "utf-16le"},
++      {[]byte{0xef, 0xbb, 0xbf}, "utf-8"},
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c2f62445c7f070f58e99e4a99b0f80f28b4befaa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,237 @@@
++// Copyright 2013 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package charset
++
++import (
++      "bytes"
++      "encoding/xml"
++      "io"
++      "os"
++      "runtime"
++      "strings"
++      "testing"
++
++      "golang.org/x/text/transform"
++)
++
++func transformString(t transform.Transformer, s string) (string, error) {
++      r := transform.NewReader(strings.NewReader(s), t)
++      b, err := io.ReadAll(r)
++      return string(b), err
++}
++
++type testCase struct {
++      utf8, other, otherEncoding string
++}
++
++// testCases for encoding and decoding.
++var testCases = []testCase{
++      {"Résumé", "Résumé", "utf8"},
++      {"Résumé", "R\xe9sum\xe9", "latin1"},
++      {"これは漢字です。", "S0\x8c0o0\"oW[g0Y0\x020", "UTF-16LE"},
++      {"これは漢字です。", "0S0\x8c0oo\"[W0g0Y0\x02", "UTF-16BE"},
++      {"Hello, world", "Hello, world", "ASCII"},
++      {"Gdańsk", "Gda\xf1sk", "ISO-8859-2"},
++      {"Ââ Čč Đđ Ŋŋ Õõ Šš Žž Åå Ää", "\xc2\xe2 \xc8\xe8 \xa9\xb9 \xaf\xbf \xd5\xf5 \xaa\xba \xac\xbc \xc5\xe5 \xc4\xe4", "ISO-8859-10"},
++      {"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "ISO-8859-11"},
++      {"latviešu", "latvie\xf0u", "ISO-8859-13"},
++      {"Seònaid", "Se\xf2naid", "ISO-8859-14"},
++      {"€1 is cheap", "\xa41 is cheap", "ISO-8859-15"},
++      {"românește", "rom\xe2ne\xbate", "ISO-8859-16"},
++      {"nutraĵo", "nutra\xbco", "ISO-8859-3"},
++      {"Kalâdlit", "Kal\xe2dlit", "ISO-8859-4"},
++      {"русский", "\xe0\xe3\xe1\xe1\xda\xd8\xd9", "ISO-8859-5"},
++      {"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "ISO-8859-7"},
++      {"Kağan", "Ka\xf0an", "ISO-8859-9"},
++      {"Résumé", "R\x8esum\x8e", "macintosh"},
++      {"Gdańsk", "Gda\xf1sk", "windows-1250"},
++      {"русский", "\xf0\xf3\xf1\xf1\xea\xe8\xe9", "windows-1251"},
++      {"Résumé", "R\xe9sum\xe9", "windows-1252"},
++      {"ελληνικά", "\xe5\xeb\xeb\xe7\xed\xe9\xea\xdc", "windows-1253"},
++      {"Kağan", "Ka\xf0an", "windows-1254"},
++      {"עִבְרִית", "\xf2\xc4\xe1\xc0\xf8\xc4\xe9\xfa", "windows-1255"},
++      {"العربية", "\xc7\xe1\xda\xd1\xc8\xed\xc9", "windows-1256"},
++      {"latviešu", "latvie\xf0u", "windows-1257"},
++      {"Việt", "Vi\xea\xf2t", "windows-1258"},
++      {"สำหรับ", "\xca\xd3\xcb\xc3\u047a", "windows-874"},
++      {"русский", "\xd2\xd5\xd3\xd3\xcb\xc9\xca", "KOI8-R"},
++      {"українська", "\xd5\xcb\xd2\xc1\xa7\xce\xd3\xd8\xcb\xc1", "KOI8-U"},
++      {"Hello 常用國字標準字體表", "Hello \xb1`\xa5\u03b0\xea\xa6r\xbc\u0437\u01e6r\xc5\xe9\xaa\xed", "big5"},
++      {"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gbk"},
++      {"Hello 常用國字標準字體表", "Hello \xb3\xa3\xd3\xc3\x87\xf8\xd7\xd6\x98\xcb\x9c\xca\xd7\xd6\xf3\x77\xb1\xed", "gb18030"},
++      {"עִבְרִית", "\x81\x30\xfb\x30\x81\x30\xf6\x34\x81\x30\xf9\x33\x81\x30\xf6\x30\x81\x30\xfb\x36\x81\x30\xf6\x34\x81\x30\xfa\x31\x81\x30\xfb\x38", "gb18030"},
++      {"㧯", "\x82\x31\x89\x38", "gb18030"},
++      {"これは漢字です。", "\x82\xb1\x82\xea\x82\xcd\x8a\xbf\x8e\x9a\x82\xc5\x82\xb7\x81B", "SJIS"},
++      {"Hello, 世界!", "Hello, \x90\xa2\x8aE!", "SJIS"},
++      {"イウエオカ", "\xb2\xb3\xb4\xb5\xb6", "SJIS"},
++      {"これは漢字です。", "\xa4\xb3\xa4\xec\xa4\u03f4\xc1\xbb\xfa\xa4\u01e4\xb9\xa1\xa3", "EUC-JP"},
++      {"Hello, 世界!", "Hello, \x1b$B@$3&\x1b(B!", "ISO-2022-JP"},
++      {"다음과 같은 조건을 따라야 합니다: 저작자표시", "\xb4\xd9\xc0\xbd\xb0\xfa \xb0\xb0\xc0\xba \xc1\xb6\xb0\xc7\xc0\xbb \xb5\xfb\xb6\xf3\xbe\xdf \xc7մϴ\xd9: \xc0\xfa\xc0\xdb\xc0\xdaǥ\xbd\xc3", "EUC-KR"},
++}
++
++func TestDecode(t *testing.T) {
++      testCases := append(testCases, []testCase{
++              // Replace multi-byte maximum subpart of ill-formed subsequence with
++              // single replacement character (WhatWG requirement).
++              {"Rés\ufffdumé", "Rés\xe1\x80umé", "utf8"},
++      }...)
++      for _, tc := range testCases {
++              e, _ := Lookup(tc.otherEncoding)
++              if e == nil {
++                      t.Errorf("%s: not found", tc.otherEncoding)
++                      continue
++              }
++              s, err := transformString(e.NewDecoder(), tc.other)
++              if err != nil {
++                      t.Errorf("%s: decode %q: %v", tc.otherEncoding, tc.other, err)
++                      continue
++              }
++              if s != tc.utf8 {
++                      t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.utf8)
++              }
++      }
++}
++
++func TestEncode(t *testing.T) {
++      testCases := append(testCases, []testCase{
++              // Use Go-style replacement.
++              {"Rés\xe1\x80umé", "Rés\ufffd\ufffdumé", "utf8"},
++              // U+0144 LATIN SMALL LETTER N WITH ACUTE not supported by encoding.
++              {"Gdańsk", "Gda&#324;sk", "ISO-8859-11"},
++              {"\ufffd", "&#65533;", "ISO-8859-11"},
++              {"a\xe1\x80b", "a&#65533;&#65533;b", "ISO-8859-11"},
++      }...)
++      for _, tc := range testCases {
++              e, _ := Lookup(tc.otherEncoding)
++              if e == nil {
++                      t.Errorf("%s: not found", tc.otherEncoding)
++                      continue
++              }
++              s, err := transformString(e.NewEncoder(), tc.utf8)
++              if err != nil {
++                      t.Errorf("%s: encode %q: %s", tc.otherEncoding, tc.utf8, err)
++                      continue
++              }
++              if s != tc.other {
++                      t.Errorf("%s: got %q, want %q", tc.otherEncoding, s, tc.other)
++              }
++      }
++}
++
++var sniffTestCases = []struct {
++      filename, declared, want string
++}{
++      {"HTTP-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
++      {"UTF-16LE-BOM.html", "", "utf-16le"},
++      {"UTF-16BE-BOM.html", "", "utf-16be"},
++      {"meta-content-attribute.html", "text/html", "iso-8859-15"},
++      {"meta-charset-attribute.html", "text/html", "iso-8859-15"},
++      {"No-encoding-declaration.html", "text/html", "utf-8"},
++      {"HTTP-vs-UTF-8-BOM.html", "text/html; charset=iso-8859-15", "utf-8"},
++      {"HTTP-vs-meta-content.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
++      {"HTTP-vs-meta-charset.html", "text/html; charset=iso-8859-15", "iso-8859-15"},
++      {"UTF-8-BOM-vs-meta-content.html", "text/html", "utf-8"},
++      {"UTF-8-BOM-vs-meta-charset.html", "text/html", "utf-8"},
++}
++
++func TestSniff(t *testing.T) {
++      switch runtime.GOOS {
++      case "nacl": // platforms that don't permit direct file system access
++              t.Skipf("not supported on %q", runtime.GOOS)
++      }
++
++      for _, tc := range sniffTestCases {
++              content, err := os.ReadFile("testdata/" + tc.filename)
++              if err != nil {
++                      t.Errorf("%s: error reading file: %v", tc.filename, err)
++                      continue
++              }
++
++              _, name, _ := DetermineEncoding(content, tc.declared)
++              if name != tc.want {
++                      t.Errorf("%s: got %q, want %q", tc.filename, name, tc.want)
++                      continue
++              }
++      }
++}
++
++func TestReader(t *testing.T) {
++      switch runtime.GOOS {
++      case "nacl": // platforms that don't permit direct file system access
++              t.Skipf("not supported on %q", runtime.GOOS)
++      }
++
++      for _, tc := range sniffTestCases {
++              content, err := os.ReadFile("testdata/" + tc.filename)
++              if err != nil {
++                      t.Errorf("%s: error reading file: %v", tc.filename, err)
++                      continue
++              }
++
++              r, err := NewReader(bytes.NewReader(content), tc.declared)
++              if err != nil {
++                      t.Errorf("%s: error creating reader: %v", tc.filename, err)
++                      continue
++              }
++
++              got, err := io.ReadAll(r)
++              if err != nil {
++                      t.Errorf("%s: error reading from charset.NewReader: %v", tc.filename, err)
++                      continue
++              }
++
++              e, _ := Lookup(tc.want)
++              want, err := io.ReadAll(transform.NewReader(bytes.NewReader(content), e.NewDecoder()))
++              if err != nil {
++                      t.Errorf("%s: error decoding with hard-coded charset name: %v", tc.filename, err)
++                      continue
++              }
++
++              if !bytes.Equal(got, want) {
++                      t.Errorf("%s: got %q, want %q", tc.filename, got, want)
++                      continue
++              }
++      }
++}
++
++var metaTestCases = []struct {
++      meta, want string
++}{
++      {"", ""},
++      {"text/html", ""},
++      {"text/html; charset utf-8", ""},
++      {"text/html; charset=latin-2", "latin-2"},
++      {"text/html; charset; charset = utf-8", "utf-8"},
++      {`charset="big5"`, "big5"},
++      {"charset='shift_jis'", "shift_jis"},
++}
++
++func TestFromMeta(t *testing.T) {
++      for _, tc := range metaTestCases {
++              got := fromMetaElement(tc.meta)
++              if got != tc.want {
++                      t.Errorf("%q: got %q, want %q", tc.meta, got, tc.want)
++              }
++      }
++}
++
++func TestXML(t *testing.T) {
++      const s = "<?xml version=\"1.0\" encoding=\"windows-1252\"?><a><Word>r\xe9sum\xe9</Word></a>"
++
++      d := xml.NewDecoder(strings.NewReader(s))
++      d.CharsetReader = NewReaderLabel
++
++      var a struct {
++              Word string
++      }
++      if err := d.Decode(&a); err != nil {
++              t.Fatalf("Decode: %v", err)
++      }
++
++      want := "résumé"
++      if a.Word != want {
++              t.Errorf("got %q, want %q", a.Word, want)
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9915fa0ee4f59b680eecd47a8cb4fc33b278b5e6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,48 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++  <title>HTTP charset</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="The character encoding of a page can be set using the HTTP header charset declaration.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
++</head>
++<body>
++<p class='title'>HTTP charset</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">The character encoding of a page can be set using the HTTP header charset declaration.</p>
++<div class="notes"><p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p><p>The only character encoding declaration for this HTML file is in the HTTP header, which sets the encoding to ISO 8859-15.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-003">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-001<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-001" target="_blank">Detailed results for this test</a><br/>      <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..26e5d8b4ebf6b7b9b19b8a29645913a3888dab40
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,48 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++  <title>HTTP vs UTF-8 BOM</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
++</head>
++<body>
++<p class='title'>HTTP vs UTF-8 BOM</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">A character encoding set in the HTTP header has lower precedence than the UTF-8 signature.</p>
++<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p><p>If the test is unsuccessful, the characters &#x00EF;&#x00BB;&#x00BF; should appear at the top of the page.  These represent the bytes that make up the UTF-8 signature when encountered in the ISO 8859-15 encoding.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-022">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-034<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-034" target="_blank">Detailed results for this test</a><br/>  <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2f07e95158eae25debf22a2f7f1103655e2c0264
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta charset="iso-8859-1" > <title>HTTP vs meta charset</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.">
++<style type='text/css'>
++.test div { width: 50px; }.test div { width: 90px; }
++</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
++</head>
++<body>
++<p class='title'>HTTP vs meta charset</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta charset attribute.</p>
++<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-037">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-018<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-018" target="_blank">Detailed results for this test</a><br/>  <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6853cddecccbccc8236dd20d0543cd2bdc8c2ee8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta http-equiv="content-type" content="text/html;charset=iso-8859-1" > <title>HTTP vs meta content</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.">
++<style type='text/css'>
++.test div { width: 50px; }.test div { width: 90px; }
++</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
++</head>
++<body>
++<p class='title'>HTTP vs meta content</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">The HTTP header has a higher precedence than an encoding declaration in a meta content attribute.</p>
++<div class="notes"><p><p>The HTTP header attempts to set the character encoding to ISO 8859-15. The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-1.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-018">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-016<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-016" target="_blank">Detailed results for this test</a><br/>  <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..612e26c6c521a51366ca7ab5826f143609760628
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,47 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++  <title>No encoding declaration</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
++</head>
++<body>
++<p class='title'>No encoding declaration</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">A page with no encoding information in HTTP, BOM, XML declaration or meta element will be treated as UTF-8.</p>
++<div class="notes"><p><p>The test on this page contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-034">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-015<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-015" target="_blank">Detailed results for this test</a><br/>      <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..38ef0f9f121faa9918afa8b8b03091c6f97acfa2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,9 @@@
++These test cases come from
++http://www.w3.org/International/tests/repository/html5/the-input-byte-stream/results-basics
++
++Distributed under both the W3C Test Suite License
++(http://www.w3.org/Consortium/Legal/2008/04-testsuite-license)
++and the W3C 3-clause BSD License
++(http://www.w3.org/Consortium/Legal/2008/03-bsd-license).
++To contribute to a W3C Test Suite, see the policies and contribution
++forms (http://www.w3.org/2004/10/27-testcases).
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3abf7a9343c20518e57dfea58b374fb0f4fb58a1
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..76254c980c29954f1bbd96e145c79f64c43e3355
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..83de43338ecb121e82ab382f939bd8feb95dc912
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta charset="iso-8859-15"> <title>UTF-8 BOM vs meta charset</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.">
++<style type='text/css'>
++.test div { width: 50px; }.test div { width: 90px; }
++</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
++</head>
++<body>
++<p class='title'>UTF-8 BOM vs meta charset</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta charset attribute declares a different encoding.</p>
++<div class="notes"><p><p>The page contains an encoding declaration in a meta charset attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-024">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-038<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-038" target="_blank">Detailed results for this test</a><br/>  <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..501aac2d6a5d59bf59a60b0e452a7c0a90a9f8ec
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,48 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>UTF-8 BOM vs meta content</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-utf8.css">
++</head>
++<body>
++<p class='title'>UTF-8 BOM vs meta content</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">A page with a UTF-8 BOM will be recognized as UTF-8 even if the meta content attribute declares a different encoding.</p>
++<div class="notes"><p><p>The page contains an encoding declaration in a meta content attribute that attempts to set the character encoding to ISO 8859-15, but the file starts with a UTF-8 signature.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00FD;&#x00E4;&#x00E8;</code>. This matches the sequence of bytes above when they are interpreted as UTF-8. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-038">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-037<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#precedence" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-037" target="_blank">Detailed results for this test</a><br/>  <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2d7d25aba14dfb992b26b22be444c62db141123c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,48 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta charset="iso-8859-15"> <title>meta charset attribute</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="The character encoding of the page can be set by a meta element with charset attribute.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
++</head>
++<body>
++<p class='title'>meta charset attribute</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with charset attribute.</p>
++<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the charset attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-015">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-009<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-009" target="_blank">Detailed results for this test</a><br/>      <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1c3f228e7c999c56a73a8e570265ec845a1adb58
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,48 @@@
++<!DOCTYPE html>
++<html  lang="en" >
++<head>
++ <meta http-equiv="content-type" content="text/html; charset=iso-8859-15"> <title>meta content attribute</title>
++<link rel='author' title='Richard Ishida' href='mailto:ishida@w3.org'>
++<link rel='help' href='http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream'>
++<link rel="stylesheet" type="text/css" href="./generatedtests.css">
++<script src="http://w3c-test.org/resources/testharness.js"></script>
++<script src="http://w3c-test.org/resources/testharnessreport.js"></script>
++<meta name='flags' content='http'>
++<meta name="assert" content="The character encoding of the page can be set by a meta element with http-equiv and content attributes.">
++<style type='text/css'>
++.test div { width: 50px; }</style>
++<link rel="stylesheet" type="text/css" href="the-input-byte-stream/support/encodingtests-15.css">
++</head>
++<body>
++<p class='title'>meta content attribute</p>
++
++
++<div id='log'></div>
++
++
++<div class='test'><div id='box' class='ýäè'>&#xA0;</div></div>
++
++
++
++
++
++<div class='description'>
++<p class="assertion" title="Assertion">The character encoding of the page can be set by a meta element with http-equiv and content attributes.</p>
++<div class="notes"><p><p>The only character encoding declaration for this HTML file is in the content attribute of the meta element, which declares the encoding to be ISO 8859-15.</p><p>The test contains a div with a class name that contains the following sequence of bytes: 0xC3 0xBD 0xC3 0xA4 0xC3 0xA8. These represent different sequences of characters in ISO 8859-15, ISO 8859-1 and UTF-8. The external, UTF-8-encoded stylesheet contains a selector <code>.test div.&#x00C3;&#x0153;&#x00C3;&#x20AC;&#x00C3;&#x0161;</code>. This matches the sequence of bytes above when they are interpreted as ISO 8859-15. If the class name matches the selector then the test will pass.</p></p>
++</div>
++</div>
++<div class="nexttest"><div><a href="generate?test=the-input-byte-stream-009">Next test</a></div><div class="doctype">HTML5</div>
++<p class="jump">the-input-byte-stream-007<br /><a href="/International/tests/html5/the-input-byte-stream/results-basics#basics" target="_blank">Result summary &amp; related tests</a><br /><a href="http://w3c-test.org/framework/details/i18n-html5/the-input-byte-stream-007" target="_blank">Detailed results for this test</a><br/>      <a href="http://www.w3.org/TR/html5/syntax.html#the-input-byte-stream" target="_blank">Link to spec</a></p>
++<div class='prereq'>Assumptions: <ul><li>The default encoding for the browser you are testing is not set to ISO 8859-15.</li>
++                              <li>The test is read from a server that supports HTTP.</li></ul></div>
++</div>
++<script>
++test(function() {
++assert_equals(document.getElementById('box').offsetWidth, 100);
++}, " ");
++</script>
++
++</body>
++</html>
++
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fd47de877318c6c0ee9bddd398e62f5c0ab61930
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,291 @@@
++// Copyright 2023 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bytes"
++      "strings"
++      "testing"
++)
++
++// TestComments exhaustively tests every 'interesting' N-byte string is
++// correctly parsed as a comment. N ranges from 4+1 to 4+maxSuffixLen
++// inclusive. 4 is the length of the "<!--" prefix that starts an HTML comment.
++//
++// 'Interesting' means that the N-4 byte suffix consists entirely of bytes
++// sampled from the interestingCommentBytes const string, below. These cover
++// all of the possible state transitions from comment-related parser states, as
++// listed in the HTML spec (https://html.spec.whatwg.org/#comment-start-state
++// and subsequent sections).
++//
++// The spec is written as an explicit state machine that, as a side effect,
++// accumulates "the comment token's data" to a separate buffer.
++// Tokenizer.readComment in this package does not have an explicit state
++// machine and usually returns the comment text as a sub-slice of the input,
++// between the opening '<' and closing '>' or EOF. This test confirms that the
++// two algorithms match.
++func TestComments(t *testing.T) {
++      const prefix = "<!--"
++      const maxSuffixLen = 6
++      buffer := make([]byte, 0, len(prefix)+maxSuffixLen)
++      testAllComments(t, append(buffer, prefix...))
++}
++
++// NUL isn't in this list, even though the HTML spec sections 13.2.5.43 -
++// 13.2.5.52 mentions it. It's not interesting in terms of state transitions.
++// It's equivalent to any other non-interesting byte (other than being replaced
++// by U+FFFD REPLACEMENT CHARACTER).
++//
++// EOF isn't in this list. The HTML spec treats EOF as "an input character" but
++// testOneComment below breaks the loop instead.
++//
++// 'x' represents all other "non-interesting" comment bytes.
++var interestingCommentBytes = [...]byte{
++      '!', '-', '<', '>', 'x',
++}
++
++// testAllComments recursively fills in buffer[len(buffer):cap(buffer)] with
++// interesting bytes and then tests that this package's tokenization matches
++// the HTML spec.
++//
++// Precondition: len(buffer) < cap(buffer)
++// Precondition: string(buffer[:4]) == "<!--"
++func testAllComments(t *testing.T, buffer []byte) {
++      for _, interesting := range interestingCommentBytes {
++              b := append(buffer, interesting)
++              testOneComment(t, b)
++              if len(b) < cap(b) {
++                      testAllComments(t, b)
++              }
++      }
++}
++
++func testOneComment(t *testing.T, b []byte) {
++      z := NewTokenizer(bytes.NewReader(b))
++      if next := z.Next(); next != CommentToken {
++              t.Fatalf("Next(%q): got %v, want %v", b, next, CommentToken)
++      }
++      gotRemainder := string(b[len(z.Raw()):])
++      gotComment := string(z.Text())
++
++      i := len("<!--")
++      wantBuffer := []byte(nil)
++loop:
++      for state := 43; ; {
++              // Consume the next input character, handling EOF.
++              if i >= len(b) {
++                      break
++              }
++              nextInputCharacter := b[i]
++              i++
++
++              switch state {
++              case 43: // 13.2.5.43 Comment start state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 44
++                      case '>':
++                              break loop
++                      default:
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 44: // 13.2.5.44 Comment start dash state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 51
++                      case '>':
++                              break loop
++                      default:
++                              wantBuffer = append(wantBuffer, '-')
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 45: // 13.2.5.45 Comment state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 50
++                      case '<':
++                              wantBuffer = append(wantBuffer, '<')
++                              state = 46
++                      default:
++                              wantBuffer = append(wantBuffer, nextInputCharacter)
++                      }
++
++              case 46: // 13.2.5.46 Comment less-than sign state.
++                      switch nextInputCharacter {
++                      case '!':
++                              wantBuffer = append(wantBuffer, '!')
++                              state = 47
++                      case '<':
++                              wantBuffer = append(wantBuffer, '<')
++                              state = 46
++                      default:
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 47: // 13.2.5.47 Comment less-than sign bang state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 48
++                      default:
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 48: // 13.2.5.48 Comment less-than sign bang dash state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 49
++                      default:
++                              i-- // Reconsume.
++                              state = 50
++                      }
++
++              case 49: // 13.2.5.49 Comment less-than sign bang dash dash state.
++                      switch nextInputCharacter {
++                      case '>':
++                              break loop
++                      default:
++                              i-- // Reconsume.
++                              state = 51
++                      }
++
++              case 50: // 13.2.5.50 Comment end dash state.
++                      switch nextInputCharacter {
++                      case '-':
++                              state = 51
++                      default:
++                              wantBuffer = append(wantBuffer, '-')
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 51: // 13.2.5.51 Comment end state.
++                      switch nextInputCharacter {
++                      case '!':
++                              state = 52
++                      case '-':
++                              wantBuffer = append(wantBuffer, '-')
++                      case '>':
++                              break loop
++                      default:
++                              wantBuffer = append(wantBuffer, "--"...)
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              case 52: // 13.2.5.52 Comment end bang state.
++                      switch nextInputCharacter {
++                      case '-':
++                              wantBuffer = append(wantBuffer, "--!"...)
++                              state = 50
++                      case '>':
++                              break loop
++                      default:
++                              wantBuffer = append(wantBuffer, "--!"...)
++                              i-- // Reconsume.
++                              state = 45
++                      }
++
++              default:
++                      t.Fatalf("input=%q: unexpected state %d", b, state)
++              }
++      }
++
++      wantRemainder := ""
++      if i < len(b) {
++              wantRemainder = string(b[i:])
++      }
++      wantComment := string(wantBuffer)
++      if (gotComment != wantComment) || (gotRemainder != wantRemainder) {
++              t.Errorf("input=%q\ngot:  %q + %q\nwant: %q + %q",
++                      b, gotComment, gotRemainder, wantComment, wantRemainder)
++              return
++      }
++
++      // suffix is the "N-4 byte suffix" per the TestComments comment.
++      suffix := string(b[4:])
++
++      // Test that a round trip, rendering (escaped) and re-parsing, of a comment
++      // token (with that suffix as the Token.Data) preserves that string.
++      tok := Token{
++              Type: CommentToken,
++              Data: suffix,
++      }
++      z2 := NewTokenizer(strings.NewReader(tok.String()))
++      if next := z2.Next(); next != CommentToken {
++              t.Fatalf("round-trip Next(%q): got %v, want %v", suffix, next, CommentToken)
++      }
++      gotComment2 := string(z2.Text())
++      if gotComment2 != suffix {
++              t.Errorf("round-trip\ngot:  %q\nwant: %q", gotComment2, suffix)
++              return
++      }
++}
++
++// This table below summarizes the HTML-comment-related state machine from
++// 13.2.5.43 "Comment start state" and subsequent sections.
++// https://html.spec.whatwg.org/#comment-start-state
++//
++// Get to state 13.2.5.43 after seeing "<!--". Specifically, starting from the
++// initial 13.2.5.1 "Data state":
++//   - "<"  moves to 13.2.5.6  "Tag open state",
++//   - "!"  moves to 13.2.5.42 "Markup declaration open state",
++//   - "--" moves to 13.2.5.43 "Comment start state".
++// Each of these transitions are the only way to get to the 6/42/43 states.
++//
++// State   !         -         <         >         NUL       EOF       default   HTML spec section
++// 43      ...       s44       ...       s01.T.E0  ...       ...       r45       13.2.5.43 Comment start state
++// 44      ...       s51       ...       s01.T.E0  ...       T.Z.E1    r45.A-    13.2.5.44 Comment start dash state
++// 45      ...       s50       s46.A<    ...       t45.A?.E2 T.Z.E1    t45.Ax    13.2.5.45 Comment state
++// 46      s47.A!    ...       t46.A<    ...       ...       ...       r45       13.2.5.46 Comment less-than sign state
++// 47      ...       s48       ...       ...       ...       ...       r45       13.2.5.47 Comment less-than sign bang state
++// 48      ...       s49       ...       ...       ...       ...       r50       13.2.5.48 Comment less-than sign bang dash state
++// 49      ...       ...       ...       s01.T     ...       T.Z.E1    r51.E3    13.2.5.49 Comment less-than sign bang dash dash state
++// 50      ...       s51       ...       ...       ...       T.Z.E1    r45.A-    13.2.5.50 Comment end dash state
++// 51      s52       t51.A-    ...       s01.T     ...       T.Z.E1    r45.A--   13.2.5.51 Comment end state
++// 52      ...       s50.A--!  ...       s01.T.E4  ...       T.Z.E1    r45.A--!  13.2.5.52 Comment end bang state
++//
++// State 43 is the "Comment start state" meaning that we've only seen "<!--"
++// and nothing else. Similarly, state 44 means that we've only seen "<!---",
++// with three dashes, and nothing else. For the other states, we deduce
++// (working backwards) that the immediate prior input must be:
++//   - 45  something that's not '-'
++//   - 46  "<"
++//   - 47  "<!"
++//   - 48  "<!-"
++//   - 49  "<!--"  not including the opening "<!--"
++//   - 50  "-"     not including the opening "<!--" and also not "--"
++//   - 51  "--"    not including the opening "<!--"
++//   - 52  "--!"
++//
++// The table cell actions:
++//   - ...   do the default action
++//   - A!    append "!"      to the comment token's data.
++//   - A-    append "-"      to the comment token's data.
++//   - A--   append "--"     to the comment token's data.
++//   - A--!  append "--!"    to the comment token's data.
++//   - A<    append "<"      to the comment token's data.
++//   - A?    append "\uFFFD" to the comment token's data.
++//   - Ax    append the current input character to the comment token's data.
++//   - E0    parse error (abrupt-closing-of-empty-comment).
++//   - E1    parse error (eof-in-comment).
++//   - E2    parse error (unexpected-null-character).
++//   - E3    parse error (nested-comment).
++//   - E4    parse error (incorrectly-closed-comment).
++//   - T     emit the current comment token.
++//   - Z     emit an end-of-file token.
++//   - rNN   reconsume in the 13.2.5.NN     state (after any A* or E* operations).
++//   - s01   switch to the    13.2.5.1 Data state (after any A* or E* operations).
++//   - sNN   switch to the    13.2.5.NN     state (after any A* or E* operations).
++//   - tNN   stay in the      13.2.5.NN     state (after any A* or E* operations).
++//
++// The E* actions are called errors in the HTML spec but they are not fatal
++// (https://html.spec.whatwg.org/#parse-errors says "may [but not must] abort
++// the parser"). They are warnings that, in practice, browsers simply ignore.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ff7acf2d5b4b2d720b92b5dfc51b05894a36af31
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,111 @@@
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++// Section 12.2.4.2 of the HTML5 specification says "The following elements
++// have varying levels of special parsing rules".
++// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
++var isSpecialElementMap = map[string]bool{
++      "address":    true,
++      "applet":     true,
++      "area":       true,
++      "article":    true,
++      "aside":      true,
++      "base":       true,
++      "basefont":   true,
++      "bgsound":    true,
++      "blockquote": true,
++      "body":       true,
++      "br":         true,
++      "button":     true,
++      "caption":    true,
++      "center":     true,
++      "col":        true,
++      "colgroup":   true,
++      "dd":         true,
++      "details":    true,
++      "dir":        true,
++      "div":        true,
++      "dl":         true,
++      "dt":         true,
++      "embed":      true,
++      "fieldset":   true,
++      "figcaption": true,
++      "figure":     true,
++      "footer":     true,
++      "form":       true,
++      "frame":      true,
++      "frameset":   true,
++      "h1":         true,
++      "h2":         true,
++      "h3":         true,
++      "h4":         true,
++      "h5":         true,
++      "h6":         true,
++      "head":       true,
++      "header":     true,
++      "hgroup":     true,
++      "hr":         true,
++      "html":       true,
++      "iframe":     true,
++      "img":        true,
++      "input":      true,
++      "keygen":     true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility.
++      "li":         true,
++      "link":       true,
++      "listing":    true,
++      "main":       true,
++      "marquee":    true,
++      "menu":       true,
++      "meta":       true,
++      "nav":        true,
++      "noembed":    true,
++      "noframes":   true,
++      "noscript":   true,
++      "object":     true,
++      "ol":         true,
++      "p":          true,
++      "param":      true,
++      "plaintext":  true,
++      "pre":        true,
++      "script":     true,
++      "section":    true,
++      "select":     true,
++      "source":     true,
++      "style":      true,
++      "summary":    true,
++      "table":      true,
++      "tbody":      true,
++      "td":         true,
++      "template":   true,
++      "textarea":   true,
++      "tfoot":      true,
++      "th":         true,
++      "thead":      true,
++      "title":      true,
++      "tr":         true,
++      "track":      true,
++      "ul":         true,
++      "wbr":        true,
++      "xmp":        true,
++}
++
++func isSpecialElement(element *Node) bool {
++      switch element.Namespace {
++      case "", "html":
++              return isSpecialElementMap[element.Data]
++      case "math":
++              switch element.Data {
++              case "mi", "mo", "mn", "ms", "mtext", "annotation-xml":
++                      return true
++              }
++      case "svg":
++              switch element.Data {
++              case "foreignObject", "desc", "title":
++                      return true
++              }
++      }
++      return false
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..850c47fdbadedf59fba0a186dc192104d2c3ecda
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,127 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++/*
++Package html implements an HTML5-compliant tokenizer and parser.
++
++Tokenization is done by creating a Tokenizer for an io.Reader r. It is the
++caller's responsibility to ensure that r provides UTF-8 encoded HTML.
++
++      z := html.NewTokenizer(r)
++
++Given a Tokenizer z, the HTML is tokenized by repeatedly calling z.Next(),
++which parses the next token and returns its type, or an error:
++
++      for {
++              tt := z.Next()
++              if tt == html.ErrorToken {
++                      // ...
++                      return ...
++              }
++              // Process the current token.
++      }
++
++There are two APIs for retrieving the current token. The high-level API is to
++call Token; the low-level API is to call Text or TagName / TagAttr. Both APIs
++allow optionally calling Raw after Next but before Token, Text, TagName, or
++TagAttr. In EBNF notation, the valid call sequence per token is:
++
++      Next {Raw} [ Token | Text | TagName {TagAttr} ]
++
++Token returns an independent data structure that completely describes a token.
++Entities (such as "&lt;") are unescaped, tag names and attribute keys are
++lower-cased, and attributes are collected into a []Attribute. For example:
++
++      for {
++              if z.Next() == html.ErrorToken {
++                      // Returning io.EOF indicates success.
++                      return z.Err()
++              }
++              emitToken(z.Token())
++      }
++
++The low-level API performs fewer allocations and copies, but the contents of
++the []byte values returned by Text, TagName and TagAttr may change on the next
++call to Next. For example, to extract an HTML page's anchor text:
++
++      depth := 0
++      for {
++              tt := z.Next()
++              switch tt {
++              case html.ErrorToken:
++                      return z.Err()
++              case html.TextToken:
++                      if depth > 0 {
++                              // emitBytes should copy the []byte it receives,
++                              // if it doesn't process it immediately.
++                              emitBytes(z.Text())
++                      }
++              case html.StartTagToken, html.EndTagToken:
++                      tn, _ := z.TagName()
++                      if len(tn) == 1 && tn[0] == 'a' {
++                              if tt == html.StartTagToken {
++                                      depth++
++                              } else {
++                                      depth--
++                              }
++                      }
++              }
++      }
++
++Parsing is done by calling Parse with an io.Reader, which returns the root of
++the parse tree (the document element) as a *Node. It is the caller's
++responsibility to ensure that the Reader provides UTF-8 encoded HTML. For
++example, to process each anchor node in depth-first order:
++
++      doc, err := html.Parse(r)
++      if err != nil {
++              // ...
++      }
++      var f func(*html.Node)
++      f = func(n *html.Node) {
++              if n.Type == html.ElementNode && n.Data == "a" {
++                      // Do something with n...
++              }
++              for c := n.FirstChild; c != nil; c = c.NextSibling {
++                      f(c)
++              }
++      }
++      f(doc)
++
++The relevant specifications include:
++https://html.spec.whatwg.org/multipage/syntax.html and
++https://html.spec.whatwg.org/multipage/syntax.html#tokenization
++
++# Security Considerations
++
++Care should be taken when parsing and interpreting HTML, whether full documents
++or fragments, within the framework of the HTML specification, especially with
++regard to untrusted inputs.
++
++This package provides both a tokenizer and a parser, which implement the
++tokenization, and tokenization and tree construction stages of the WHATWG HTML
++parsing specification respectively. While the tokenizer parses and normalizes
++individual HTML tokens, only the parser constructs the DOM tree from the
++tokenized HTML, as described in the tree construction stage of the
++specification, dynamically modifying or extending the document's DOM tree.
++
++If your use case requires semantically well-formed HTML documents, as defined by
++the WHATWG specification, the parser should be used rather than the tokenizer.
++
++In security contexts, if trust decisions are being made using the tokenized or
++parsed content, the input must be re-serialized (for instance by using Render or
++Token.String) in order for those trust decisions to hold, as the process of
++tokenization or parsing may alter the content.
++*/
++package html // import "git.earlybird.gay/today-engine/internal/html"
++
++// The tokenization algorithm implemented by this package is not a line-by-line
++// transliteration of the relatively verbose state-machine in the WHATWG
++// specification. A more direct approach is used instead, where the program
++// counter implies the state, such as whether it is tokenizing a tag or a text
++// node. Specification compliance is verified by checking expected and actual
++// outputs over a test suite rather than aiming for algorithmic fidelity.
++
++// TODO(nigeltao): Does a DOM API belong in this package or a separate one?
++// TODO(nigeltao): How does parsing interact with a JavaScript engine?
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c484e5a94fbf0a38b9c1789356f9f152ccaec4d2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,156 @@@
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "strings"
++)
++
++// parseDoctype parses the data from a DoctypeToken into a name,
++// public identifier, and system identifier. It returns a Node whose Type
++// is DoctypeNode, whose Data is the name, and which has attributes
++// named "system" and "public" for the two identifiers if they were present.
++// quirks is whether the document should be parsed in "quirks mode".
++func parseDoctype(s string) (n *Node, quirks bool) {
++      n = &Node{Type: DoctypeNode}
++
++      // Find the name.
++      space := strings.IndexAny(s, whitespace)
++      if space == -1 {
++              space = len(s)
++      }
++      n.Data = s[:space]
++      // The comparison to "html" is case-sensitive.
++      if n.Data != "html" {
++              quirks = true
++      }
++      n.Data = strings.ToLower(n.Data)
++      s = strings.TrimLeft(s[space:], whitespace)
++
++      if len(s) < 6 {
++              // It can't start with "PUBLIC" or "SYSTEM".
++              // Ignore the rest of the string.
++              return n, quirks || s != ""
++      }
++
++      key := strings.ToLower(s[:6])
++      s = s[6:]
++      for key == "public" || key == "system" {
++              s = strings.TrimLeft(s, whitespace)
++              if s == "" {
++                      break
++              }
++              quote := s[0]
++              if quote != '"' && quote != '\'' {
++                      break
++              }
++              s = s[1:]
++              q := strings.IndexRune(s, rune(quote))
++              var id string
++              if q == -1 {
++                      id = s
++                      s = ""
++              } else {
++                      id = s[:q]
++                      s = s[q+1:]
++              }
++              n.Attr = append(n.Attr, Attribute{Key: key, Val: id})
++              if key == "public" {
++                      key = "system"
++              } else {
++                      key = ""
++              }
++      }
++
++      if key != "" || s != "" {
++              quirks = true
++      } else if len(n.Attr) > 0 {
++              if n.Attr[0].Key == "public" {
++                      public := strings.ToLower(n.Attr[0].Val)
++                      switch public {
++                      case "-//w3o//dtd w3 html strict 3.0//en//", "-/w3d/dtd html 4.0 transitional/en", "html":
++                              quirks = true
++                      default:
++                              for _, q := range quirkyIDs {
++                                      if strings.HasPrefix(public, q) {
++                                              quirks = true
++                                              break
++                                      }
++                              }
++                      }
++                      // The following two public IDs only cause quirks mode if there is no system ID.
++                      if len(n.Attr) == 1 && (strings.HasPrefix(public, "-//w3c//dtd html 4.01 frameset//") ||
++                              strings.HasPrefix(public, "-//w3c//dtd html 4.01 transitional//")) {
++                              quirks = true
++                      }
++              }
++              if lastAttr := n.Attr[len(n.Attr)-1]; lastAttr.Key == "system" &&
++                      strings.ToLower(lastAttr.Val) == "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd" {
++                      quirks = true
++              }
++      }
++
++      return n, quirks
++}
++
++// quirkyIDs is a list of public doctype identifiers that cause a document
++// to be interpreted in quirks mode. The identifiers should be in lower case.
++var quirkyIDs = []string{
++      "+//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//",
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b628880a014d865f22c5b2c15a2aaf63aa340ed7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2253 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++// All entities that do not end with ';' are 6 or fewer bytes long.
++const longestEntityWithoutSemicolon = 6
++
++// entity is a map from HTML entity names to their values. The semicolon matters:
++// https://html.spec.whatwg.org/multipage/syntax.html#named-character-references
++// lists both "amp" and "amp;" as two separate entries.
++//
++// Note that the HTML5 list is larger than the HTML4 list at
++// http://www.w3.org/TR/html4/sgml/entities.html
++var entity = map[string]rune{
++      "AElig;":                           '\U000000C6',
++      "AMP;":                             '\U00000026',
++      "Aacute;":                          '\U000000C1',
++      "Abreve;":                          '\U00000102',
++      "Acirc;":                           '\U000000C2',
++      "Acy;":                             '\U00000410',
++      "Afr;":                             '\U0001D504',
++      "Agrave;":                          '\U000000C0',
++      "Alpha;":                           '\U00000391',
++      "Amacr;":                           '\U00000100',
++      "And;":                             '\U00002A53',
++      "Aogon;":                           '\U00000104',
++      "Aopf;":                            '\U0001D538',
++      "ApplyFunction;":                   '\U00002061',
++      "Aring;":                           '\U000000C5',
++      "Ascr;":                            '\U0001D49C',
++      "Assign;":                          '\U00002254',
++      "Atilde;":                          '\U000000C3',
++      "Auml;":                            '\U000000C4',
++      "Backslash;":                       '\U00002216',
++      "Barv;":                            '\U00002AE7',
++      "Barwed;":                          '\U00002306',
++      "Bcy;":                             '\U00000411',
++      "Because;":                         '\U00002235',
++      "Bernoullis;":                      '\U0000212C',
++      "Beta;":                            '\U00000392',
++      "Bfr;":                             '\U0001D505',
++      "Bopf;":                            '\U0001D539',
++      "Breve;":                           '\U000002D8',
++      "Bscr;":                            '\U0000212C',
++      "Bumpeq;":                          '\U0000224E',
++      "CHcy;":                            '\U00000427',
++      "COPY;":                            '\U000000A9',
++      "Cacute;":                          '\U00000106',
++      "Cap;":                             '\U000022D2',
++      "CapitalDifferentialD;":            '\U00002145',
++      "Cayleys;":                         '\U0000212D',
++      "Ccaron;":                          '\U0000010C',
++      "Ccedil;":                          '\U000000C7',
++      "Ccirc;":                           '\U00000108',
++      "Cconint;":                         '\U00002230',
++      "Cdot;":                            '\U0000010A',
++      "Cedilla;":                         '\U000000B8',
++      "CenterDot;":                       '\U000000B7',
++      "Cfr;":                             '\U0000212D',
++      "Chi;":                             '\U000003A7',
++      "CircleDot;":                       '\U00002299',
++      "CircleMinus;":                     '\U00002296',
++      "CirclePlus;":                      '\U00002295',
++      "CircleTimes;":                     '\U00002297',
++      "ClockwiseContourIntegral;":        '\U00002232',
++      "CloseCurlyDoubleQuote;":           '\U0000201D',
++      "CloseCurlyQuote;":                 '\U00002019',
++      "Colon;":                           '\U00002237',
++      "Colone;":                          '\U00002A74',
++      "Congruent;":                       '\U00002261',
++      "Conint;":                          '\U0000222F',
++      "ContourIntegral;":                 '\U0000222E',
++      "Copf;":                            '\U00002102',
++      "Coproduct;":                       '\U00002210',
++      "CounterClockwiseContourIntegral;": '\U00002233',
++      "Cross;":                           '\U00002A2F',
++      "Cscr;":                            '\U0001D49E',
++      "Cup;":                             '\U000022D3',
++      "CupCap;":                          '\U0000224D',
++      "DD;":                              '\U00002145',
++      "DDotrahd;":                        '\U00002911',
++      "DJcy;":                            '\U00000402',
++      "DScy;":                            '\U00000405',
++      "DZcy;":                            '\U0000040F',
++      "Dagger;":                          '\U00002021',
++      "Darr;":                            '\U000021A1',
++      "Dashv;":                           '\U00002AE4',
++      "Dcaron;":                          '\U0000010E',
++      "Dcy;":                             '\U00000414',
++      "Del;":                             '\U00002207',
++      "Delta;":                           '\U00000394',
++      "Dfr;":                             '\U0001D507',
++      "DiacriticalAcute;":                '\U000000B4',
++      "DiacriticalDot;":                  '\U000002D9',
++      "DiacriticalDoubleAcute;":          '\U000002DD',
++      "DiacriticalGrave;":                '\U00000060',
++      "DiacriticalTilde;":                '\U000002DC',
++      "Diamond;":                         '\U000022C4',
++      "DifferentialD;":                   '\U00002146',
++      "Dopf;":                            '\U0001D53B',
++      "Dot;":                             '\U000000A8',
++      "DotDot;":                          '\U000020DC',
++      "DotEqual;":                        '\U00002250',
++      "DoubleContourIntegral;":           '\U0000222F',
++      "DoubleDot;":                       '\U000000A8',
++      "DoubleDownArrow;":                 '\U000021D3',
++      "DoubleLeftArrow;":                 '\U000021D0',
++      "DoubleLeftRightArrow;":            '\U000021D4',
++      "DoubleLeftTee;":                   '\U00002AE4',
++      "DoubleLongLeftArrow;":             '\U000027F8',
++      "DoubleLongLeftRightArrow;":        '\U000027FA',
++      "DoubleLongRightArrow;":            '\U000027F9',
++      "DoubleRightArrow;":                '\U000021D2',
++      "DoubleRightTee;":                  '\U000022A8',
++      "DoubleUpArrow;":                   '\U000021D1',
++      "DoubleUpDownArrow;":               '\U000021D5',
++      "DoubleVerticalBar;":               '\U00002225',
++      "DownArrow;":                       '\U00002193',
++      "DownArrowBar;":                    '\U00002913',
++      "DownArrowUpArrow;":                '\U000021F5',
++      "DownBreve;":                       '\U00000311',
++      "DownLeftRightVector;":             '\U00002950',
++      "DownLeftTeeVector;":               '\U0000295E',
++      "DownLeftVector;":                  '\U000021BD',
++      "DownLeftVectorBar;":               '\U00002956',
++      "DownRightTeeVector;":              '\U0000295F',
++      "DownRightVector;":                 '\U000021C1',
++      "DownRightVectorBar;":              '\U00002957',
++      "DownTee;":                         '\U000022A4',
++      "DownTeeArrow;":                    '\U000021A7',
++      "Downarrow;":                       '\U000021D3',
++      "Dscr;":                            '\U0001D49F',
++      "Dstrok;":                          '\U00000110',
++      "ENG;":                             '\U0000014A',
++      "ETH;":                             '\U000000D0',
++      "Eacute;":                          '\U000000C9',
++      "Ecaron;":                          '\U0000011A',
++      "Ecirc;":                           '\U000000CA',
++      "Ecy;":                             '\U0000042D',
++      "Edot;":                            '\U00000116',
++      "Efr;":                             '\U0001D508',
++      "Egrave;":                          '\U000000C8',
++      "Element;":                         '\U00002208',
++      "Emacr;":                           '\U00000112',
++      "EmptySmallSquare;":                '\U000025FB',
++      "EmptyVerySmallSquare;":            '\U000025AB',
++      "Eogon;":                           '\U00000118',
++      "Eopf;":                            '\U0001D53C',
++      "Epsilon;":                         '\U00000395',
++      "Equal;":                           '\U00002A75',
++      "EqualTilde;":                      '\U00002242',
++      "Equilibrium;":                     '\U000021CC',
++      "Escr;":                            '\U00002130',
++      "Esim;":                            '\U00002A73',
++      "Eta;":                             '\U00000397',
++      "Euml;":                            '\U000000CB',
++      "Exists;":                          '\U00002203',
++      "ExponentialE;":                    '\U00002147',
++      "Fcy;":                             '\U00000424',
++      "Ffr;":                             '\U0001D509',
++      "FilledSmallSquare;":               '\U000025FC',
++      "FilledVerySmallSquare;":           '\U000025AA',
++      "Fopf;":                            '\U0001D53D',
++      "ForAll;":                          '\U00002200',
++      "Fouriertrf;":                      '\U00002131',
++      "Fscr;":                            '\U00002131',
++      "GJcy;":                            '\U00000403',
++      "GT;":                              '\U0000003E',
++      "Gamma;":                           '\U00000393',
++      "Gammad;":                          '\U000003DC',
++      "Gbreve;":                          '\U0000011E',
++      "Gcedil;":                          '\U00000122',
++      "Gcirc;":                           '\U0000011C',
++      "Gcy;":                             '\U00000413',
++      "Gdot;":                            '\U00000120',
++      "Gfr;":                             '\U0001D50A',
++      "Gg;":                              '\U000022D9',
++      "Gopf;":                            '\U0001D53E',
++      "GreaterEqual;":                    '\U00002265',
++      "GreaterEqualLess;":                '\U000022DB',
++      "GreaterFullEqual;":                '\U00002267',
++      "GreaterGreater;":                  '\U00002AA2',
++      "GreaterLess;":                     '\U00002277',
++      "GreaterSlantEqual;":               '\U00002A7E',
++      "GreaterTilde;":                    '\U00002273',
++      "Gscr;":                            '\U0001D4A2',
++      "Gt;":                              '\U0000226B',
++      "HARDcy;":                          '\U0000042A',
++      "Hacek;":                           '\U000002C7',
++      "Hat;":                             '\U0000005E',
++      "Hcirc;":                           '\U00000124',
++      "Hfr;":                             '\U0000210C',
++      "HilbertSpace;":                    '\U0000210B',
++      "Hopf;":                            '\U0000210D',
++      "HorizontalLine;":                  '\U00002500',
++      "Hscr;":                            '\U0000210B',
++      "Hstrok;":                          '\U00000126',
++      "HumpDownHump;":                    '\U0000224E',
++      "HumpEqual;":                       '\U0000224F',
++      "IEcy;":                            '\U00000415',
++      "IJlig;":                           '\U00000132',
++      "IOcy;":                            '\U00000401',
++      "Iacute;":                          '\U000000CD',
++      "Icirc;":                           '\U000000CE',
++      "Icy;":                             '\U00000418',
++      "Idot;":                            '\U00000130',
++      "Ifr;":                             '\U00002111',
++      "Igrave;":                          '\U000000CC',
++      "Im;":                              '\U00002111',
++      "Imacr;":                           '\U0000012A',
++      "ImaginaryI;":                      '\U00002148',
++      "Implies;":                         '\U000021D2',
++      "Int;":                             '\U0000222C',
++      "Integral;":                        '\U0000222B',
++      "Intersection;":                    '\U000022C2',
++      "InvisibleComma;":                  '\U00002063',
++      "InvisibleTimes;":                  '\U00002062',
++      "Iogon;":                           '\U0000012E',
++      "Iopf;":                            '\U0001D540',
++      "Iota;":                            '\U00000399',
++      "Iscr;":                            '\U00002110',
++      "Itilde;":                          '\U00000128',
++      "Iukcy;":                           '\U00000406',
++      "Iuml;":                            '\U000000CF',
++      "Jcirc;":                           '\U00000134',
++      "Jcy;":                             '\U00000419',
++      "Jfr;":                             '\U0001D50D',
++      "Jopf;":                            '\U0001D541',
++      "Jscr;":                            '\U0001D4A5',
++      "Jsercy;":                          '\U00000408',
++      "Jukcy;":                           '\U00000404',
++      "KHcy;":                            '\U00000425',
++      "KJcy;":                            '\U0000040C',
++      "Kappa;":                           '\U0000039A',
++      "Kcedil;":                          '\U00000136',
++      "Kcy;":                             '\U0000041A',
++      "Kfr;":                             '\U0001D50E',
++      "Kopf;":                            '\U0001D542',
++      "Kscr;":                            '\U0001D4A6',
++      "LJcy;":                            '\U00000409',
++      "LT;":                              '\U0000003C',
++      "Lacute;":                          '\U00000139',
++      "Lambda;":                          '\U0000039B',
++      "Lang;":                            '\U000027EA',
++      "Laplacetrf;":                      '\U00002112',
++      "Larr;":                            '\U0000219E',
++      "Lcaron;":                          '\U0000013D',
++      "Lcedil;":                          '\U0000013B',
++      "Lcy;":                             '\U0000041B',
++      "LeftAngleBracket;":                '\U000027E8',
++      "LeftArrow;":                       '\U00002190',
++      "LeftArrowBar;":                    '\U000021E4',
++      "LeftArrowRightArrow;":             '\U000021C6',
++      "LeftCeiling;":                     '\U00002308',
++      "LeftDoubleBracket;":               '\U000027E6',
++      "LeftDownTeeVector;":               '\U00002961',
++      "LeftDownVector;":                  '\U000021C3',
++      "LeftDownVectorBar;":               '\U00002959',
++      "LeftFloor;":                       '\U0000230A',
++      "LeftRightArrow;":                  '\U00002194',
++      "LeftRightVector;":                 '\U0000294E',
++      "LeftTee;":                         '\U000022A3',
++      "LeftTeeArrow;":                    '\U000021A4',
++      "LeftTeeVector;":                   '\U0000295A',
++      "LeftTriangle;":                    '\U000022B2',
++      "LeftTriangleBar;":                 '\U000029CF',
++      "LeftTriangleEqual;":               '\U000022B4',
++      "LeftUpDownVector;":                '\U00002951',
++      "LeftUpTeeVector;":                 '\U00002960',
++      "LeftUpVector;":                    '\U000021BF',
++      "LeftUpVectorBar;":                 '\U00002958',
++      "LeftVector;":                      '\U000021BC',
++      "LeftVectorBar;":                   '\U00002952',
++      "Leftarrow;":                       '\U000021D0',
++      "Leftrightarrow;":                  '\U000021D4',
++      "LessEqualGreater;":                '\U000022DA',
++      "LessFullEqual;":                   '\U00002266',
++      "LessGreater;":                     '\U00002276',
++      "LessLess;":                        '\U00002AA1',
++      "LessSlantEqual;":                  '\U00002A7D',
++      "LessTilde;":                       '\U00002272',
++      "Lfr;":                             '\U0001D50F',
++      "Ll;":                              '\U000022D8',
++      "Lleftarrow;":                      '\U000021DA',
++      "Lmidot;":                          '\U0000013F',
++      "LongLeftArrow;":                   '\U000027F5',
++      "LongLeftRightArrow;":              '\U000027F7',
++      "LongRightArrow;":                  '\U000027F6',
++      "Longleftarrow;":                   '\U000027F8',
++      "Longleftrightarrow;":              '\U000027FA',
++      "Longrightarrow;":                  '\U000027F9',
++      "Lopf;":                            '\U0001D543',
++      "LowerLeftArrow;":                  '\U00002199',
++      "LowerRightArrow;":                 '\U00002198',
++      "Lscr;":                            '\U00002112',
++      "Lsh;":                             '\U000021B0',
++      "Lstrok;":                          '\U00000141',
++      "Lt;":                              '\U0000226A',
++      "Map;":                             '\U00002905',
++      "Mcy;":                             '\U0000041C',
++      "MediumSpace;":                     '\U0000205F',
++      "Mellintrf;":                       '\U00002133',
++      "Mfr;":                             '\U0001D510',
++      "MinusPlus;":                       '\U00002213',
++      "Mopf;":                            '\U0001D544',
++      "Mscr;":                            '\U00002133',
++      "Mu;":                              '\U0000039C',
++      "NJcy;":                            '\U0000040A',
++      "Nacute;":                          '\U00000143',
++      "Ncaron;":                          '\U00000147',
++      "Ncedil;":                          '\U00000145',
++      "Ncy;":                             '\U0000041D',
++      "NegativeMediumSpace;":             '\U0000200B',
++      "NegativeThickSpace;":              '\U0000200B',
++      "NegativeThinSpace;":               '\U0000200B',
++      "NegativeVeryThinSpace;":           '\U0000200B',
++      "NestedGreaterGreater;":            '\U0000226B',
++      "NestedLessLess;":                  '\U0000226A',
++      "NewLine;":                         '\U0000000A',
++      "Nfr;":                             '\U0001D511',
++      "NoBreak;":                         '\U00002060',
++      "NonBreakingSpace;":                '\U000000A0',
++      "Nopf;":                            '\U00002115',
++      "Not;":                             '\U00002AEC',
++      "NotCongruent;":                    '\U00002262',
++      "NotCupCap;":                       '\U0000226D',
++      "NotDoubleVerticalBar;":            '\U00002226',
++      "NotElement;":                      '\U00002209',
++      "NotEqual;":                        '\U00002260',
++      "NotExists;":                       '\U00002204',
++      "NotGreater;":                      '\U0000226F',
++      "NotGreaterEqual;":                 '\U00002271',
++      "NotGreaterLess;":                  '\U00002279',
++      "NotGreaterTilde;":                 '\U00002275',
++      "NotLeftTriangle;":                 '\U000022EA',
++      "NotLeftTriangleEqual;":            '\U000022EC',
++      "NotLess;":                         '\U0000226E',
++      "NotLessEqual;":                    '\U00002270',
++      "NotLessGreater;":                  '\U00002278',
++      "NotLessTilde;":                    '\U00002274',
++      "NotPrecedes;":                     '\U00002280',
++      "NotPrecedesSlantEqual;":           '\U000022E0',
++      "NotReverseElement;":               '\U0000220C',
++      "NotRightTriangle;":                '\U000022EB',
++      "NotRightTriangleEqual;":           '\U000022ED',
++      "NotSquareSubsetEqual;":            '\U000022E2',
++      "NotSquareSupersetEqual;":          '\U000022E3',
++      "NotSubsetEqual;":                  '\U00002288',
++      "NotSucceeds;":                     '\U00002281',
++      "NotSucceedsSlantEqual;":           '\U000022E1',
++      "NotSupersetEqual;":                '\U00002289',
++      "NotTilde;":                        '\U00002241',
++      "NotTildeEqual;":                   '\U00002244',
++      "NotTildeFullEqual;":               '\U00002247',
++      "NotTildeTilde;":                   '\U00002249',
++      "NotVerticalBar;":                  '\U00002224',
++      "Nscr;":                            '\U0001D4A9',
++      "Ntilde;":                          '\U000000D1',
++      "Nu;":                              '\U0000039D',
++      "OElig;":                           '\U00000152',
++      "Oacute;":                          '\U000000D3',
++      "Ocirc;":                           '\U000000D4',
++      "Ocy;":                             '\U0000041E',
++      "Odblac;":                          '\U00000150',
++      "Ofr;":                             '\U0001D512',
++      "Ograve;":                          '\U000000D2',
++      "Omacr;":                           '\U0000014C',
++      "Omega;":                           '\U000003A9',
++      "Omicron;":                         '\U0000039F',
++      "Oopf;":                            '\U0001D546',
++      "OpenCurlyDoubleQuote;":            '\U0000201C',
++      "OpenCurlyQuote;":                  '\U00002018',
++      "Or;":                              '\U00002A54',
++      "Oscr;":                            '\U0001D4AA',
++      "Oslash;":                          '\U000000D8',
++      "Otilde;":                          '\U000000D5',
++      "Otimes;":                          '\U00002A37',
++      "Ouml;":                            '\U000000D6',
++      "OverBar;":                         '\U0000203E',
++      "OverBrace;":                       '\U000023DE',
++      "OverBracket;":                     '\U000023B4',
++      "OverParenthesis;":                 '\U000023DC',
++      "PartialD;":                        '\U00002202',
++      "Pcy;":                             '\U0000041F',
++      "Pfr;":                             '\U0001D513',
++      "Phi;":                             '\U000003A6',
++      "Pi;":                              '\U000003A0',
++      "PlusMinus;":                       '\U000000B1',
++      "Poincareplane;":                   '\U0000210C',
++      "Popf;":                            '\U00002119',
++      "Pr;":                              '\U00002ABB',
++      "Precedes;":                        '\U0000227A',
++      "PrecedesEqual;":                   '\U00002AAF',
++      "PrecedesSlantEqual;":              '\U0000227C',
++      "PrecedesTilde;":                   '\U0000227E',
++      "Prime;":                           '\U00002033',
++      "Product;":                         '\U0000220F',
++      "Proportion;":                      '\U00002237',
++      "Proportional;":                    '\U0000221D',
++      "Pscr;":                            '\U0001D4AB',
++      "Psi;":                             '\U000003A8',
++      "QUOT;":                            '\U00000022',
++      "Qfr;":                             '\U0001D514',
++      "Qopf;":                            '\U0000211A',
++      "Qscr;":                            '\U0001D4AC',
++      "RBarr;":                           '\U00002910',
++      "REG;":                             '\U000000AE',
++      "Racute;":                          '\U00000154',
++      "Rang;":                            '\U000027EB',
++      "Rarr;":                            '\U000021A0',
++      "Rarrtl;":                          '\U00002916',
++      "Rcaron;":                          '\U00000158',
++      "Rcedil;":                          '\U00000156',
++      "Rcy;":                             '\U00000420',
++      "Re;":                              '\U0000211C',
++      "ReverseElement;":                  '\U0000220B',
++      "ReverseEquilibrium;":              '\U000021CB',
++      "ReverseUpEquilibrium;":            '\U0000296F',
++      "Rfr;":                             '\U0000211C',
++      "Rho;":                             '\U000003A1',
++      "RightAngleBracket;":               '\U000027E9',
++      "RightArrow;":                      '\U00002192',
++      "RightArrowBar;":                   '\U000021E5',
++      "RightArrowLeftArrow;":             '\U000021C4',
++      "RightCeiling;":                    '\U00002309',
++      "RightDoubleBracket;":              '\U000027E7',
++      "RightDownTeeVector;":              '\U0000295D',
++      "RightDownVector;":                 '\U000021C2',
++      "RightDownVectorBar;":              '\U00002955',
++      "RightFloor;":                      '\U0000230B',
++      "RightTee;":                        '\U000022A2',
++      "RightTeeArrow;":                   '\U000021A6',
++      "RightTeeVector;":                  '\U0000295B',
++      "RightTriangle;":                   '\U000022B3',
++      "RightTriangleBar;":                '\U000029D0',
++      "RightTriangleEqual;":              '\U000022B5',
++      "RightUpDownVector;":               '\U0000294F',
++      "RightUpTeeVector;":                '\U0000295C',
++      "RightUpVector;":                   '\U000021BE',
++      "RightUpVectorBar;":                '\U00002954',
++      "RightVector;":                     '\U000021C0',
++      "RightVectorBar;":                  '\U00002953',
++      "Rightarrow;":                      '\U000021D2',
++      "Ropf;":                            '\U0000211D',
++      "RoundImplies;":                    '\U00002970',
++      "Rrightarrow;":                     '\U000021DB',
++      "Rscr;":                            '\U0000211B',
++      "Rsh;":                             '\U000021B1',
++      "RuleDelayed;":                     '\U000029F4',
++      "SHCHcy;":                          '\U00000429',
++      "SHcy;":                            '\U00000428',
++      "SOFTcy;":                          '\U0000042C',
++      "Sacute;":                          '\U0000015A',
++      "Sc;":                              '\U00002ABC',
++      "Scaron;":                          '\U00000160',
++      "Scedil;":                          '\U0000015E',
++      "Scirc;":                           '\U0000015C',
++      "Scy;":                             '\U00000421',
++      "Sfr;":                             '\U0001D516',
++      "ShortDownArrow;":                  '\U00002193',
++      "ShortLeftArrow;":                  '\U00002190',
++      "ShortRightArrow;":                 '\U00002192',
++      "ShortUpArrow;":                    '\U00002191',
++      "Sigma;":                           '\U000003A3',
++      "SmallCircle;":                     '\U00002218',
++      "Sopf;":                            '\U0001D54A',
++      "Sqrt;":                            '\U0000221A',
++      "Square;":                          '\U000025A1',
++      "SquareIntersection;":              '\U00002293',
++      "SquareSubset;":                    '\U0000228F',
++      "SquareSubsetEqual;":               '\U00002291',
++      "SquareSuperset;":                  '\U00002290',
++      "SquareSupersetEqual;":             '\U00002292',
++      "SquareUnion;":                     '\U00002294',
++      "Sscr;":                            '\U0001D4AE',
++      "Star;":                            '\U000022C6',
++      "Sub;":                             '\U000022D0',
++      "Subset;":                          '\U000022D0',
++      "SubsetEqual;":                     '\U00002286',
++      "Succeeds;":                        '\U0000227B',
++      "SucceedsEqual;":                   '\U00002AB0',
++      "SucceedsSlantEqual;":              '\U0000227D',
++      "SucceedsTilde;":                   '\U0000227F',
++      "SuchThat;":                        '\U0000220B',
++      "Sum;":                             '\U00002211',
++      "Sup;":                             '\U000022D1',
++      "Superset;":                        '\U00002283',
++      "SupersetEqual;":                   '\U00002287',
++      "Supset;":                          '\U000022D1',
++      "THORN;":                           '\U000000DE',
++      "TRADE;":                           '\U00002122',
++      "TSHcy;":                           '\U0000040B',
++      "TScy;":                            '\U00000426',
++      "Tab;":                             '\U00000009',
++      "Tau;":                             '\U000003A4',
++      "Tcaron;":                          '\U00000164',
++      "Tcedil;":                          '\U00000162',
++      "Tcy;":                             '\U00000422',
++      "Tfr;":                             '\U0001D517',
++      "Therefore;":                       '\U00002234',
++      "Theta;":                           '\U00000398',
++      "ThinSpace;":                       '\U00002009',
++      "Tilde;":                           '\U0000223C',
++      "TildeEqual;":                      '\U00002243',
++      "TildeFullEqual;":                  '\U00002245',
++      "TildeTilde;":                      '\U00002248',
++      "Topf;":                            '\U0001D54B',
++      "TripleDot;":                       '\U000020DB',
++      "Tscr;":                            '\U0001D4AF',
++      "Tstrok;":                          '\U00000166',
++      "Uacute;":                          '\U000000DA',
++      "Uarr;":                            '\U0000219F',
++      "Uarrocir;":                        '\U00002949',
++      "Ubrcy;":                           '\U0000040E',
++      "Ubreve;":                          '\U0000016C',
++      "Ucirc;":                           '\U000000DB',
++      "Ucy;":                             '\U00000423',
++      "Udblac;":                          '\U00000170',
++      "Ufr;":                             '\U0001D518',
++      "Ugrave;":                          '\U000000D9',
++      "Umacr;":                           '\U0000016A',
++      "UnderBar;":                        '\U0000005F',
++      "UnderBrace;":                      '\U000023DF',
++      "UnderBracket;":                    '\U000023B5',
++      "UnderParenthesis;":                '\U000023DD',
++      "Union;":                           '\U000022C3',
++      "UnionPlus;":                       '\U0000228E',
++      "Uogon;":                           '\U00000172',
++      "Uopf;":                            '\U0001D54C',
++      "UpArrow;":                         '\U00002191',
++      "UpArrowBar;":                      '\U00002912',
++      "UpArrowDownArrow;":                '\U000021C5',
++      "UpDownArrow;":                     '\U00002195',
++      "UpEquilibrium;":                   '\U0000296E',
++      "UpTee;":                           '\U000022A5',
++      "UpTeeArrow;":                      '\U000021A5',
++      "Uparrow;":                         '\U000021D1',
++      "Updownarrow;":                     '\U000021D5',
++      "UpperLeftArrow;":                  '\U00002196',
++      "UpperRightArrow;":                 '\U00002197',
++      "Upsi;":                            '\U000003D2',
++      "Upsilon;":                         '\U000003A5',
++      "Uring;":                           '\U0000016E',
++      "Uscr;":                            '\U0001D4B0',
++      "Utilde;":                          '\U00000168',
++      "Uuml;":                            '\U000000DC',
++      "VDash;":                           '\U000022AB',
++      "Vbar;":                            '\U00002AEB',
++      "Vcy;":                             '\U00000412',
++      "Vdash;":                           '\U000022A9',
++      "Vdashl;":                          '\U00002AE6',
++      "Vee;":                             '\U000022C1',
++      "Verbar;":                          '\U00002016',
++      "Vert;":                            '\U00002016',
++      "VerticalBar;":                     '\U00002223',
++      "VerticalLine;":                    '\U0000007C',
++      "VerticalSeparator;":               '\U00002758',
++      "VerticalTilde;":                   '\U00002240',
++      "VeryThinSpace;":                   '\U0000200A',
++      "Vfr;":                             '\U0001D519',
++      "Vopf;":                            '\U0001D54D',
++      "Vscr;":                            '\U0001D4B1',
++      "Vvdash;":                          '\U000022AA',
++      "Wcirc;":                           '\U00000174',
++      "Wedge;":                           '\U000022C0',
++      "Wfr;":                             '\U0001D51A',
++      "Wopf;":                            '\U0001D54E',
++      "Wscr;":                            '\U0001D4B2',
++      "Xfr;":                             '\U0001D51B',
++      "Xi;":                              '\U0000039E',
++      "Xopf;":                            '\U0001D54F',
++      "Xscr;":                            '\U0001D4B3',
++      "YAcy;":                            '\U0000042F',
++      "YIcy;":                            '\U00000407',
++      "YUcy;":                            '\U0000042E',
++      "Yacute;":                          '\U000000DD',
++      "Ycirc;":                           '\U00000176',
++      "Ycy;":                             '\U0000042B',
++      "Yfr;":                             '\U0001D51C',
++      "Yopf;":                            '\U0001D550',
++      "Yscr;":                            '\U0001D4B4',
++      "Yuml;":                            '\U00000178',
++      "ZHcy;":                            '\U00000416',
++      "Zacute;":                          '\U00000179',
++      "Zcaron;":                          '\U0000017D',
++      "Zcy;":                             '\U00000417',
++      "Zdot;":                            '\U0000017B',
++      "ZeroWidthSpace;":                  '\U0000200B',
++      "Zeta;":                            '\U00000396',
++      "Zfr;":                             '\U00002128',
++      "Zopf;":                            '\U00002124',
++      "Zscr;":                            '\U0001D4B5',
++      "aacute;":                          '\U000000E1',
++      "abreve;":                          '\U00000103',
++      "ac;":                              '\U0000223E',
++      "acd;":                             '\U0000223F',
++      "acirc;":                           '\U000000E2',
++      "acute;":                           '\U000000B4',
++      "acy;":                             '\U00000430',
++      "aelig;":                           '\U000000E6',
++      "af;":                              '\U00002061',
++      "afr;":                             '\U0001D51E',
++      "agrave;":                          '\U000000E0',
++      "alefsym;":                         '\U00002135',
++      "aleph;":                           '\U00002135',
++      "alpha;":                           '\U000003B1',
++      "amacr;":                           '\U00000101',
++      "amalg;":                           '\U00002A3F',
++      "amp;":                             '\U00000026',
++      "and;":                             '\U00002227',
++      "andand;":                          '\U00002A55',
++      "andd;":                            '\U00002A5C',
++      "andslope;":                        '\U00002A58',
++      "andv;":                            '\U00002A5A',
++      "ang;":                             '\U00002220',
++      "ange;":                            '\U000029A4',
++      "angle;":                           '\U00002220',
++      "angmsd;":                          '\U00002221',
++      "angmsdaa;":                        '\U000029A8',
++      "angmsdab;":                        '\U000029A9',
++      "angmsdac;":                        '\U000029AA',
++      "angmsdad;":                        '\U000029AB',
++      "angmsdae;":                        '\U000029AC',
++      "angmsdaf;":                        '\U000029AD',
++      "angmsdag;":                        '\U000029AE',
++      "angmsdah;":                        '\U000029AF',
++      "angrt;":                           '\U0000221F',
++      "angrtvb;":                         '\U000022BE',
++      "angrtvbd;":                        '\U0000299D',
++      "angsph;":                          '\U00002222',
++      "angst;":                           '\U000000C5',
++      "angzarr;":                         '\U0000237C',
++      "aogon;":                           '\U00000105',
++      "aopf;":                            '\U0001D552',
++      "ap;":                              '\U00002248',
++      "apE;":                             '\U00002A70',
++      "apacir;":                          '\U00002A6F',
++      "ape;":                             '\U0000224A',
++      "apid;":                            '\U0000224B',
++      "apos;":                            '\U00000027',
++      "approx;":                          '\U00002248',
++      "approxeq;":                        '\U0000224A',
++      "aring;":                           '\U000000E5',
++      "ascr;":                            '\U0001D4B6',
++      "ast;":                             '\U0000002A',
++      "asymp;":                           '\U00002248',
++      "asympeq;":                         '\U0000224D',
++      "atilde;":                          '\U000000E3',
++      "auml;":                            '\U000000E4',
++      "awconint;":                        '\U00002233',
++      "awint;":                           '\U00002A11',
++      "bNot;":                            '\U00002AED',
++      "backcong;":                        '\U0000224C',
++      "backepsilon;":                     '\U000003F6',
++      "backprime;":                       '\U00002035',
++      "backsim;":                         '\U0000223D',
++      "backsimeq;":                       '\U000022CD',
++      "barvee;":                          '\U000022BD',
++      "barwed;":                          '\U00002305',
++      "barwedge;":                        '\U00002305',
++      "bbrk;":                            '\U000023B5',
++      "bbrktbrk;":                        '\U000023B6',
++      "bcong;":                           '\U0000224C',
++      "bcy;":                             '\U00000431',
++      "bdquo;":                           '\U0000201E',
++      "becaus;":                          '\U00002235',
++      "because;":                         '\U00002235',
++      "bemptyv;":                         '\U000029B0',
++      "bepsi;":                           '\U000003F6',
++      "bernou;":                          '\U0000212C',
++      "beta;":                            '\U000003B2',
++      "beth;":                            '\U00002136',
++      "between;":                         '\U0000226C',
++      "bfr;":                             '\U0001D51F',
++      "bigcap;":                          '\U000022C2',
++      "bigcirc;":                         '\U000025EF',
++      "bigcup;":                          '\U000022C3',
++      "bigodot;":                         '\U00002A00',
++      "bigoplus;":                        '\U00002A01',
++      "bigotimes;":                       '\U00002A02',
++      "bigsqcup;":                        '\U00002A06',
++      "bigstar;":                         '\U00002605',
++      "bigtriangledown;":                 '\U000025BD',
++      "bigtriangleup;":                   '\U000025B3',
++      "biguplus;":                        '\U00002A04',
++      "bigvee;":                          '\U000022C1',
++      "bigwedge;":                        '\U000022C0',
++      "bkarow;":                          '\U0000290D',
++      "blacklozenge;":                    '\U000029EB',
++      "blacksquare;":                     '\U000025AA',
++      "blacktriangle;":                   '\U000025B4',
++      "blacktriangledown;":               '\U000025BE',
++      "blacktriangleleft;":               '\U000025C2',
++      "blacktriangleright;":              '\U000025B8',
++      "blank;":                           '\U00002423',
++      "blk12;":                           '\U00002592',
++      "blk14;":                           '\U00002591',
++      "blk34;":                           '\U00002593',
++      "block;":                           '\U00002588',
++      "bnot;":                            '\U00002310',
++      "bopf;":                            '\U0001D553',
++      "bot;":                             '\U000022A5',
++      "bottom;":                          '\U000022A5',
++      "bowtie;":                          '\U000022C8',
++      "boxDL;":                           '\U00002557',
++      "boxDR;":                           '\U00002554',
++      "boxDl;":                           '\U00002556',
++      "boxDr;":                           '\U00002553',
++      "boxH;":                            '\U00002550',
++      "boxHD;":                           '\U00002566',
++      "boxHU;":                           '\U00002569',
++      "boxHd;":                           '\U00002564',
++      "boxHu;":                           '\U00002567',
++      "boxUL;":                           '\U0000255D',
++      "boxUR;":                           '\U0000255A',
++      "boxUl;":                           '\U0000255C',
++      "boxUr;":                           '\U00002559',
++      "boxV;":                            '\U00002551',
++      "boxVH;":                           '\U0000256C',
++      "boxVL;":                           '\U00002563',
++      "boxVR;":                           '\U00002560',
++      "boxVh;":                           '\U0000256B',
++      "boxVl;":                           '\U00002562',
++      "boxVr;":                           '\U0000255F',
++      "boxbox;":                          '\U000029C9',
++      "boxdL;":                           '\U00002555',
++      "boxdR;":                           '\U00002552',
++      "boxdl;":                           '\U00002510',
++      "boxdr;":                           '\U0000250C',
++      "boxh;":                            '\U00002500',
++      "boxhD;":                           '\U00002565',
++      "boxhU;":                           '\U00002568',
++      "boxhd;":                           '\U0000252C',
++      "boxhu;":                           '\U00002534',
++      "boxminus;":                        '\U0000229F',
++      "boxplus;":                         '\U0000229E',
++      "boxtimes;":                        '\U000022A0',
++      "boxuL;":                           '\U0000255B',
++      "boxuR;":                           '\U00002558',
++      "boxul;":                           '\U00002518',
++      "boxur;":                           '\U00002514',
++      "boxv;":                            '\U00002502',
++      "boxvH;":                           '\U0000256A',
++      "boxvL;":                           '\U00002561',
++      "boxvR;":                           '\U0000255E',
++      "boxvh;":                           '\U0000253C',
++      "boxvl;":                           '\U00002524',
++      "boxvr;":                           '\U0000251C',
++      "bprime;":                          '\U00002035',
++      "breve;":                           '\U000002D8',
++      "brvbar;":                          '\U000000A6',
++      "bscr;":                            '\U0001D4B7',
++      "bsemi;":                           '\U0000204F',
++      "bsim;":                            '\U0000223D',
++      "bsime;":                           '\U000022CD',
++      "bsol;":                            '\U0000005C',
++      "bsolb;":                           '\U000029C5',
++      "bsolhsub;":                        '\U000027C8',
++      "bull;":                            '\U00002022',
++      "bullet;":                          '\U00002022',
++      "bump;":                            '\U0000224E',
++      "bumpE;":                           '\U00002AAE',
++      "bumpe;":                           '\U0000224F',
++      "bumpeq;":                          '\U0000224F',
++      "cacute;":                          '\U00000107',
++      "cap;":                             '\U00002229',
++      "capand;":                          '\U00002A44',
++      "capbrcup;":                        '\U00002A49',
++      "capcap;":                          '\U00002A4B',
++      "capcup;":                          '\U00002A47',
++      "capdot;":                          '\U00002A40',
++      "caret;":                           '\U00002041',
++      "caron;":                           '\U000002C7',
++      "ccaps;":                           '\U00002A4D',
++      "ccaron;":                          '\U0000010D',
++      "ccedil;":                          '\U000000E7',
++      "ccirc;":                           '\U00000109',
++      "ccups;":                           '\U00002A4C',
++      "ccupssm;":                         '\U00002A50',
++      "cdot;":                            '\U0000010B',
++      "cedil;":                           '\U000000B8',
++      "cemptyv;":                         '\U000029B2',
++      "cent;":                            '\U000000A2',
++      "centerdot;":                       '\U000000B7',
++      "cfr;":                             '\U0001D520',
++      "chcy;":                            '\U00000447',
++      "check;":                           '\U00002713',
++      "checkmark;":                       '\U00002713',
++      "chi;":                             '\U000003C7',
++      "cir;":                             '\U000025CB',
++      "cirE;":                            '\U000029C3',
++      "circ;":                            '\U000002C6',
++      "circeq;":                          '\U00002257',
++      "circlearrowleft;":                 '\U000021BA',
++      "circlearrowright;":                '\U000021BB',
++      "circledR;":                        '\U000000AE',
++      "circledS;":                        '\U000024C8',
++      "circledast;":                      '\U0000229B',
++      "circledcirc;":                     '\U0000229A',
++      "circleddash;":                     '\U0000229D',
++      "cire;":                            '\U00002257',
++      "cirfnint;":                        '\U00002A10',
++      "cirmid;":                          '\U00002AEF',
++      "cirscir;":                         '\U000029C2',
++      "clubs;":                           '\U00002663',
++      "clubsuit;":                        '\U00002663',
++      "colon;":                           '\U0000003A',
++      "colone;":                          '\U00002254',
++      "coloneq;":                         '\U00002254',
++      "comma;":                           '\U0000002C',
++      "commat;":                          '\U00000040',
++      "comp;":                            '\U00002201',
++      "compfn;":                          '\U00002218',
++      "complement;":                      '\U00002201',
++      "complexes;":                       '\U00002102',
++      "cong;":                            '\U00002245',
++      "congdot;":                         '\U00002A6D',
++      "conint;":                          '\U0000222E',
++      "copf;":                            '\U0001D554',
++      "coprod;":                          '\U00002210',
++      "copy;":                            '\U000000A9',
++      "copysr;":                          '\U00002117',
++      "crarr;":                           '\U000021B5',
++      "cross;":                           '\U00002717',
++      "cscr;":                            '\U0001D4B8',
++      "csub;":                            '\U00002ACF',
++      "csube;":                           '\U00002AD1',
++      "csup;":                            '\U00002AD0',
++      "csupe;":                           '\U00002AD2',
++      "ctdot;":                           '\U000022EF',
++      "cudarrl;":                         '\U00002938',
++      "cudarrr;":                         '\U00002935',
++      "cuepr;":                           '\U000022DE',
++      "cuesc;":                           '\U000022DF',
++      "cularr;":                          '\U000021B6',
++      "cularrp;":                         '\U0000293D',
++      "cup;":                             '\U0000222A',
++      "cupbrcap;":                        '\U00002A48',
++      "cupcap;":                          '\U00002A46',
++      "cupcup;":                          '\U00002A4A',
++      "cupdot;":                          '\U0000228D',
++      "cupor;":                           '\U00002A45',
++      "curarr;":                          '\U000021B7',
++      "curarrm;":                         '\U0000293C',
++      "curlyeqprec;":                     '\U000022DE',
++      "curlyeqsucc;":                     '\U000022DF',
++      "curlyvee;":                        '\U000022CE',
++      "curlywedge;":                      '\U000022CF',
++      "curren;":                          '\U000000A4',
++      "curvearrowleft;":                  '\U000021B6',
++      "curvearrowright;":                 '\U000021B7',
++      "cuvee;":                           '\U000022CE',
++      "cuwed;":                           '\U000022CF',
++      "cwconint;":                        '\U00002232',
++      "cwint;":                           '\U00002231',
++      "cylcty;":                          '\U0000232D',
++      "dArr;":                            '\U000021D3',
++      "dHar;":                            '\U00002965',
++      "dagger;":                          '\U00002020',
++      "daleth;":                          '\U00002138',
++      "darr;":                            '\U00002193',
++      "dash;":                            '\U00002010',
++      "dashv;":                           '\U000022A3',
++      "dbkarow;":                         '\U0000290F',
++      "dblac;":                           '\U000002DD',
++      "dcaron;":                          '\U0000010F',
++      "dcy;":                             '\U00000434',
++      "dd;":                              '\U00002146',
++      "ddagger;":                         '\U00002021',
++      "ddarr;":                           '\U000021CA',
++      "ddotseq;":                         '\U00002A77',
++      "deg;":                             '\U000000B0',
++      "delta;":                           '\U000003B4',
++      "demptyv;":                         '\U000029B1',
++      "dfisht;":                          '\U0000297F',
++      "dfr;":                             '\U0001D521',
++      "dharl;":                           '\U000021C3',
++      "dharr;":                           '\U000021C2',
++      "diam;":                            '\U000022C4',
++      "diamond;":                         '\U000022C4',
++      "diamondsuit;":                     '\U00002666',
++      "diams;":                           '\U00002666',
++      "die;":                             '\U000000A8',
++      "digamma;":                         '\U000003DD',
++      "disin;":                           '\U000022F2',
++      "div;":                             '\U000000F7',
++      "divide;":                          '\U000000F7',
++      "divideontimes;":                   '\U000022C7',
++      "divonx;":                          '\U000022C7',
++      "djcy;":                            '\U00000452',
++      "dlcorn;":                          '\U0000231E',
++      "dlcrop;":                          '\U0000230D',
++      "dollar;":                          '\U00000024',
++      "dopf;":                            '\U0001D555',
++      "dot;":                             '\U000002D9',
++      "doteq;":                           '\U00002250',
++      "doteqdot;":                        '\U00002251',
++      "dotminus;":                        '\U00002238',
++      "dotplus;":                         '\U00002214',
++      "dotsquare;":                       '\U000022A1',
++      "doublebarwedge;":                  '\U00002306',
++      "downarrow;":                       '\U00002193',
++      "downdownarrows;":                  '\U000021CA',
++      "downharpoonleft;":                 '\U000021C3',
++      "downharpoonright;":                '\U000021C2',
++      "drbkarow;":                        '\U00002910',
++      "drcorn;":                          '\U0000231F',
++      "drcrop;":                          '\U0000230C',
++      "dscr;":                            '\U0001D4B9',
++      "dscy;":                            '\U00000455',
++      "dsol;":                            '\U000029F6',
++      "dstrok;":                          '\U00000111',
++      "dtdot;":                           '\U000022F1',
++      "dtri;":                            '\U000025BF',
++      "dtrif;":                           '\U000025BE',
++      "duarr;":                           '\U000021F5',
++      "duhar;":                           '\U0000296F',
++      "dwangle;":                         '\U000029A6',
++      "dzcy;":                            '\U0000045F',
++      "dzigrarr;":                        '\U000027FF',
++      "eDDot;":                           '\U00002A77',
++      "eDot;":                            '\U00002251',
++      "eacute;":                          '\U000000E9',
++      "easter;":                          '\U00002A6E',
++      "ecaron;":                          '\U0000011B',
++      "ecir;":                            '\U00002256',
++      "ecirc;":                           '\U000000EA',
++      "ecolon;":                          '\U00002255',
++      "ecy;":                             '\U0000044D',
++      "edot;":                            '\U00000117',
++      "ee;":                              '\U00002147',
++      "efDot;":                           '\U00002252',
++      "efr;":                             '\U0001D522',
++      "eg;":                              '\U00002A9A',
++      "egrave;":                          '\U000000E8',
++      "egs;":                             '\U00002A96',
++      "egsdot;":                          '\U00002A98',
++      "el;":                              '\U00002A99',
++      "elinters;":                        '\U000023E7',
++      "ell;":                             '\U00002113',
++      "els;":                             '\U00002A95',
++      "elsdot;":                          '\U00002A97',
++      "emacr;":                           '\U00000113',
++      "empty;":                           '\U00002205',
++      "emptyset;":                        '\U00002205',
++      "emptyv;":                          '\U00002205',
++      "emsp;":                            '\U00002003',
++      "emsp13;":                          '\U00002004',
++      "emsp14;":                          '\U00002005',
++      "eng;":                             '\U0000014B',
++      "ensp;":                            '\U00002002',
++      "eogon;":                           '\U00000119',
++      "eopf;":                            '\U0001D556',
++      "epar;":                            '\U000022D5',
++      "eparsl;":                          '\U000029E3',
++      "eplus;":                           '\U00002A71',
++      "epsi;":                            '\U000003B5',
++      "epsilon;":                         '\U000003B5',
++      "epsiv;":                           '\U000003F5',
++      "eqcirc;":                          '\U00002256',
++      "eqcolon;":                         '\U00002255',
++      "eqsim;":                           '\U00002242',
++      "eqslantgtr;":                      '\U00002A96',
++      "eqslantless;":                     '\U00002A95',
++      "equals;":                          '\U0000003D',
++      "equest;":                          '\U0000225F',
++      "equiv;":                           '\U00002261',
++      "equivDD;":                         '\U00002A78',
++      "eqvparsl;":                        '\U000029E5',
++      "erDot;":                           '\U00002253',
++      "erarr;":                           '\U00002971',
++      "escr;":                            '\U0000212F',
++      "esdot;":                           '\U00002250',
++      "esim;":                            '\U00002242',
++      "eta;":                             '\U000003B7',
++      "eth;":                             '\U000000F0',
++      "euml;":                            '\U000000EB',
++      "euro;":                            '\U000020AC',
++      "excl;":                            '\U00000021',
++      "exist;":                           '\U00002203',
++      "expectation;":                     '\U00002130',
++      "exponentiale;":                    '\U00002147',
++      "fallingdotseq;":                   '\U00002252',
++      "fcy;":                             '\U00000444',
++      "female;":                          '\U00002640',
++      "ffilig;":                          '\U0000FB03',
++      "fflig;":                           '\U0000FB00',
++      "ffllig;":                          '\U0000FB04',
++      "ffr;":                             '\U0001D523',
++      "filig;":                           '\U0000FB01',
++      "flat;":                            '\U0000266D',
++      "fllig;":                           '\U0000FB02',
++      "fltns;":                           '\U000025B1',
++      "fnof;":                            '\U00000192',
++      "fopf;":                            '\U0001D557',
++      "forall;":                          '\U00002200',
++      "fork;":                            '\U000022D4',
++      "forkv;":                           '\U00002AD9',
++      "fpartint;":                        '\U00002A0D',
++      "frac12;":                          '\U000000BD',
++      "frac13;":                          '\U00002153',
++      "frac14;":                          '\U000000BC',
++      "frac15;":                          '\U00002155',
++      "frac16;":                          '\U00002159',
++      "frac18;":                          '\U0000215B',
++      "frac23;":                          '\U00002154',
++      "frac25;":                          '\U00002156',
++      "frac34;":                          '\U000000BE',
++      "frac35;":                          '\U00002157',
++      "frac38;":                          '\U0000215C',
++      "frac45;":                          '\U00002158',
++      "frac56;":                          '\U0000215A',
++      "frac58;":                          '\U0000215D',
++      "frac78;":                          '\U0000215E',
++      "frasl;":                           '\U00002044',
++      "frown;":                           '\U00002322',
++      "fscr;":                            '\U0001D4BB',
++      "gE;":                              '\U00002267',
++      "gEl;":                             '\U00002A8C',
++      "gacute;":                          '\U000001F5',
++      "gamma;":                           '\U000003B3',
++      "gammad;":                          '\U000003DD',
++      "gap;":                             '\U00002A86',
++      "gbreve;":                          '\U0000011F',
++      "gcirc;":                           '\U0000011D',
++      "gcy;":                             '\U00000433',
++      "gdot;":                            '\U00000121',
++      "ge;":                              '\U00002265',
++      "gel;":                             '\U000022DB',
++      "geq;":                             '\U00002265',
++      "geqq;":                            '\U00002267',
++      "geqslant;":                        '\U00002A7E',
++      "ges;":                             '\U00002A7E',
++      "gescc;":                           '\U00002AA9',
++      "gesdot;":                          '\U00002A80',
++      "gesdoto;":                         '\U00002A82',
++      "gesdotol;":                        '\U00002A84',
++      "gesles;":                          '\U00002A94',
++      "gfr;":                             '\U0001D524',
++      "gg;":                              '\U0000226B',
++      "ggg;":                             '\U000022D9',
++      "gimel;":                           '\U00002137',
++      "gjcy;":                            '\U00000453',
++      "gl;":                              '\U00002277',
++      "glE;":                             '\U00002A92',
++      "gla;":                             '\U00002AA5',
++      "glj;":                             '\U00002AA4',
++      "gnE;":                             '\U00002269',
++      "gnap;":                            '\U00002A8A',
++      "gnapprox;":                        '\U00002A8A',
++      "gne;":                             '\U00002A88',
++      "gneq;":                            '\U00002A88',
++      "gneqq;":                           '\U00002269',
++      "gnsim;":                           '\U000022E7',
++      "gopf;":                            '\U0001D558',
++      "grave;":                           '\U00000060',
++      "gscr;":                            '\U0000210A',
++      "gsim;":                            '\U00002273',
++      "gsime;":                           '\U00002A8E',
++      "gsiml;":                           '\U00002A90',
++      "gt;":                              '\U0000003E',
++      "gtcc;":                            '\U00002AA7',
++      "gtcir;":                           '\U00002A7A',
++      "gtdot;":                           '\U000022D7',
++      "gtlPar;":                          '\U00002995',
++      "gtquest;":                         '\U00002A7C',
++      "gtrapprox;":                       '\U00002A86',
++      "gtrarr;":                          '\U00002978',
++      "gtrdot;":                          '\U000022D7',
++      "gtreqless;":                       '\U000022DB',
++      "gtreqqless;":                      '\U00002A8C',
++      "gtrless;":                         '\U00002277',
++      "gtrsim;":                          '\U00002273',
++      "hArr;":                            '\U000021D4',
++      "hairsp;":                          '\U0000200A',
++      "half;":                            '\U000000BD',
++      "hamilt;":                          '\U0000210B',
++      "hardcy;":                          '\U0000044A',
++      "harr;":                            '\U00002194',
++      "harrcir;":                         '\U00002948',
++      "harrw;":                           '\U000021AD',
++      "hbar;":                            '\U0000210F',
++      "hcirc;":                           '\U00000125',
++      "hearts;":                          '\U00002665',
++      "heartsuit;":                       '\U00002665',
++      "hellip;":                          '\U00002026',
++      "hercon;":                          '\U000022B9',
++      "hfr;":                             '\U0001D525',
++      "hksearow;":                        '\U00002925',
++      "hkswarow;":                        '\U00002926',
++      "hoarr;":                           '\U000021FF',
++      "homtht;":                          '\U0000223B',
++      "hookleftarrow;":                   '\U000021A9',
++      "hookrightarrow;":                  '\U000021AA',
++      "hopf;":                            '\U0001D559',
++      "horbar;":                          '\U00002015',
++      "hscr;":                            '\U0001D4BD',
++      "hslash;":                          '\U0000210F',
++      "hstrok;":                          '\U00000127',
++      "hybull;":                          '\U00002043',
++      "hyphen;":                          '\U00002010',
++      "iacute;":                          '\U000000ED',
++      "ic;":                              '\U00002063',
++      "icirc;":                           '\U000000EE',
++      "icy;":                             '\U00000438',
++      "iecy;":                            '\U00000435',
++      "iexcl;":                           '\U000000A1',
++      "iff;":                             '\U000021D4',
++      "ifr;":                             '\U0001D526',
++      "igrave;":                          '\U000000EC',
++      "ii;":                              '\U00002148',
++      "iiiint;":                          '\U00002A0C',
++      "iiint;":                           '\U0000222D',
++      "iinfin;":                          '\U000029DC',
++      "iiota;":                           '\U00002129',
++      "ijlig;":                           '\U00000133',
++      "imacr;":                           '\U0000012B',
++      "image;":                           '\U00002111',
++      "imagline;":                        '\U00002110',
++      "imagpart;":                        '\U00002111',
++      "imath;":                           '\U00000131',
++      "imof;":                            '\U000022B7',
++      "imped;":                           '\U000001B5',
++      "in;":                              '\U00002208',
++      "incare;":                          '\U00002105',
++      "infin;":                           '\U0000221E',
++      "infintie;":                        '\U000029DD',
++      "inodot;":                          '\U00000131',
++      "int;":                             '\U0000222B',
++      "intcal;":                          '\U000022BA',
++      "integers;":                        '\U00002124',
++      "intercal;":                        '\U000022BA',
++      "intlarhk;":                        '\U00002A17',
++      "intprod;":                         '\U00002A3C',
++      "iocy;":                            '\U00000451',
++      "iogon;":                           '\U0000012F',
++      "iopf;":                            '\U0001D55A',
++      "iota;":                            '\U000003B9',
++      "iprod;":                           '\U00002A3C',
++      "iquest;":                          '\U000000BF',
++      "iscr;":                            '\U0001D4BE',
++      "isin;":                            '\U00002208',
++      "isinE;":                           '\U000022F9',
++      "isindot;":                         '\U000022F5',
++      "isins;":                           '\U000022F4',
++      "isinsv;":                          '\U000022F3',
++      "isinv;":                           '\U00002208',
++      "it;":                              '\U00002062',
++      "itilde;":                          '\U00000129',
++      "iukcy;":                           '\U00000456',
++      "iuml;":                            '\U000000EF',
++      "jcirc;":                           '\U00000135',
++      "jcy;":                             '\U00000439',
++      "jfr;":                             '\U0001D527',
++      "jmath;":                           '\U00000237',
++      "jopf;":                            '\U0001D55B',
++      "jscr;":                            '\U0001D4BF',
++      "jsercy;":                          '\U00000458',
++      "jukcy;":                           '\U00000454',
++      "kappa;":                           '\U000003BA',
++      "kappav;":                          '\U000003F0',
++      "kcedil;":                          '\U00000137',
++      "kcy;":                             '\U0000043A',
++      "kfr;":                             '\U0001D528',
++      "kgreen;":                          '\U00000138',
++      "khcy;":                            '\U00000445',
++      "kjcy;":                            '\U0000045C',
++      "kopf;":                            '\U0001D55C',
++      "kscr;":                            '\U0001D4C0',
++      "lAarr;":                           '\U000021DA',
++      "lArr;":                            '\U000021D0',
++      "lAtail;":                          '\U0000291B',
++      "lBarr;":                           '\U0000290E',
++      "lE;":                              '\U00002266',
++      "lEg;":                             '\U00002A8B',
++      "lHar;":                            '\U00002962',
++      "lacute;":                          '\U0000013A',
++      "laemptyv;":                        '\U000029B4',
++      "lagran;":                          '\U00002112',
++      "lambda;":                          '\U000003BB',
++      "lang;":                            '\U000027E8',
++      "langd;":                           '\U00002991',
++      "langle;":                          '\U000027E8',
++      "lap;":                             '\U00002A85',
++      "laquo;":                           '\U000000AB',
++      "larr;":                            '\U00002190',
++      "larrb;":                           '\U000021E4',
++      "larrbfs;":                         '\U0000291F',
++      "larrfs;":                          '\U0000291D',
++      "larrhk;":                          '\U000021A9',
++      "larrlp;":                          '\U000021AB',
++      "larrpl;":                          '\U00002939',
++      "larrsim;":                         '\U00002973',
++      "larrtl;":                          '\U000021A2',
++      "lat;":                             '\U00002AAB',
++      "latail;":                          '\U00002919',
++      "late;":                            '\U00002AAD',
++      "lbarr;":                           '\U0000290C',
++      "lbbrk;":                           '\U00002772',
++      "lbrace;":                          '\U0000007B',
++      "lbrack;":                          '\U0000005B',
++      "lbrke;":                           '\U0000298B',
++      "lbrksld;":                         '\U0000298F',
++      "lbrkslu;":                         '\U0000298D',
++      "lcaron;":                          '\U0000013E',
++      "lcedil;":                          '\U0000013C',
++      "lceil;":                           '\U00002308',
++      "lcub;":                            '\U0000007B',
++      "lcy;":                             '\U0000043B',
++      "ldca;":                            '\U00002936',
++      "ldquo;":                           '\U0000201C',
++      "ldquor;":                          '\U0000201E',
++      "ldrdhar;":                         '\U00002967',
++      "ldrushar;":                        '\U0000294B',
++      "ldsh;":                            '\U000021B2',
++      "le;":                              '\U00002264',
++      "leftarrow;":                       '\U00002190',
++      "leftarrowtail;":                   '\U000021A2',
++      "leftharpoondown;":                 '\U000021BD',
++      "leftharpoonup;":                   '\U000021BC',
++      "leftleftarrows;":                  '\U000021C7',
++      "leftrightarrow;":                  '\U00002194',
++      "leftrightarrows;":                 '\U000021C6',
++      "leftrightharpoons;":               '\U000021CB',
++      "leftrightsquigarrow;":             '\U000021AD',
++      "leftthreetimes;":                  '\U000022CB',
++      "leg;":                             '\U000022DA',
++      "leq;":                             '\U00002264',
++      "leqq;":                            '\U00002266',
++      "leqslant;":                        '\U00002A7D',
++      "les;":                             '\U00002A7D',
++      "lescc;":                           '\U00002AA8',
++      "lesdot;":                          '\U00002A7F',
++      "lesdoto;":                         '\U00002A81',
++      "lesdotor;":                        '\U00002A83',
++      "lesges;":                          '\U00002A93',
++      "lessapprox;":                      '\U00002A85',
++      "lessdot;":                         '\U000022D6',
++      "lesseqgtr;":                       '\U000022DA',
++      "lesseqqgtr;":                      '\U00002A8B',
++      "lessgtr;":                         '\U00002276',
++      "lesssim;":                         '\U00002272',
++      "lfisht;":                          '\U0000297C',
++      "lfloor;":                          '\U0000230A',
++      "lfr;":                             '\U0001D529',
++      "lg;":                              '\U00002276',
++      "lgE;":                             '\U00002A91',
++      "lhard;":                           '\U000021BD',
++      "lharu;":                           '\U000021BC',
++      "lharul;":                          '\U0000296A',
++      "lhblk;":                           '\U00002584',
++      "ljcy;":                            '\U00000459',
++      "ll;":                              '\U0000226A',
++      "llarr;":                           '\U000021C7',
++      "llcorner;":                        '\U0000231E',
++      "llhard;":                          '\U0000296B',
++      "lltri;":                           '\U000025FA',
++      "lmidot;":                          '\U00000140',
++      "lmoust;":                          '\U000023B0',
++      "lmoustache;":                      '\U000023B0',
++      "lnE;":                             '\U00002268',
++      "lnap;":                            '\U00002A89',
++      "lnapprox;":                        '\U00002A89',
++      "lne;":                             '\U00002A87',
++      "lneq;":                            '\U00002A87',
++      "lneqq;":                           '\U00002268',
++      "lnsim;":                           '\U000022E6',
++      "loang;":                           '\U000027EC',
++      "loarr;":                           '\U000021FD',
++      "lobrk;":                           '\U000027E6',
++      "longleftarrow;":                   '\U000027F5',
++      "longleftrightarrow;":              '\U000027F7',
++      "longmapsto;":                      '\U000027FC',
++      "longrightarrow;":                  '\U000027F6',
++      "looparrowleft;":                   '\U000021AB',
++      "looparrowright;":                  '\U000021AC',
++      "lopar;":                           '\U00002985',
++      "lopf;":                            '\U0001D55D',
++      "loplus;":                          '\U00002A2D',
++      "lotimes;":                         '\U00002A34',
++      "lowast;":                          '\U00002217',
++      "lowbar;":                          '\U0000005F',
++      "loz;":                             '\U000025CA',
++      "lozenge;":                         '\U000025CA',
++      "lozf;":                            '\U000029EB',
++      "lpar;":                            '\U00000028',
++      "lparlt;":                          '\U00002993',
++      "lrarr;":                           '\U000021C6',
++      "lrcorner;":                        '\U0000231F',
++      "lrhar;":                           '\U000021CB',
++      "lrhard;":                          '\U0000296D',
++      "lrm;":                             '\U0000200E',
++      "lrtri;":                           '\U000022BF',
++      "lsaquo;":                          '\U00002039',
++      "lscr;":                            '\U0001D4C1',
++      "lsh;":                             '\U000021B0',
++      "lsim;":                            '\U00002272',
++      "lsime;":                           '\U00002A8D',
++      "lsimg;":                           '\U00002A8F',
++      "lsqb;":                            '\U0000005B',
++      "lsquo;":                           '\U00002018',
++      "lsquor;":                          '\U0000201A',
++      "lstrok;":                          '\U00000142',
++      "lt;":                              '\U0000003C',
++      "ltcc;":                            '\U00002AA6',
++      "ltcir;":                           '\U00002A79',
++      "ltdot;":                           '\U000022D6',
++      "lthree;":                          '\U000022CB',
++      "ltimes;":                          '\U000022C9',
++      "ltlarr;":                          '\U00002976',
++      "ltquest;":                         '\U00002A7B',
++      "ltrPar;":                          '\U00002996',
++      "ltri;":                            '\U000025C3',
++      "ltrie;":                           '\U000022B4',
++      "ltrif;":                           '\U000025C2',
++      "lurdshar;":                        '\U0000294A',
++      "luruhar;":                         '\U00002966',
++      "mDDot;":                           '\U0000223A',
++      "macr;":                            '\U000000AF',
++      "male;":                            '\U00002642',
++      "malt;":                            '\U00002720',
++      "maltese;":                         '\U00002720',
++      "map;":                             '\U000021A6',
++      "mapsto;":                          '\U000021A6',
++      "mapstodown;":                      '\U000021A7',
++      "mapstoleft;":                      '\U000021A4',
++      "mapstoup;":                        '\U000021A5',
++      "marker;":                          '\U000025AE',
++      "mcomma;":                          '\U00002A29',
++      "mcy;":                             '\U0000043C',
++      "mdash;":                           '\U00002014',
++      "measuredangle;":                   '\U00002221',
++      "mfr;":                             '\U0001D52A',
++      "mho;":                             '\U00002127',
++      "micro;":                           '\U000000B5',
++      "mid;":                             '\U00002223',
++      "midast;":                          '\U0000002A',
++      "midcir;":                          '\U00002AF0',
++      "middot;":                          '\U000000B7',
++      "minus;":                           '\U00002212',
++      "minusb;":                          '\U0000229F',
++      "minusd;":                          '\U00002238',
++      "minusdu;":                         '\U00002A2A',
++      "mlcp;":                            '\U00002ADB',
++      "mldr;":                            '\U00002026',
++      "mnplus;":                          '\U00002213',
++      "models;":                          '\U000022A7',
++      "mopf;":                            '\U0001D55E',
++      "mp;":                              '\U00002213',
++      "mscr;":                            '\U0001D4C2',
++      "mstpos;":                          '\U0000223E',
++      "mu;":                              '\U000003BC',
++      "multimap;":                        '\U000022B8',
++      "mumap;":                           '\U000022B8',
++      "nLeftarrow;":                      '\U000021CD',
++      "nLeftrightarrow;":                 '\U000021CE',
++      "nRightarrow;":                     '\U000021CF',
++      "nVDash;":                          '\U000022AF',
++      "nVdash;":                          '\U000022AE',
++      "nabla;":                           '\U00002207',
++      "nacute;":                          '\U00000144',
++      "nap;":                             '\U00002249',
++      "napos;":                           '\U00000149',
++      "napprox;":                         '\U00002249',
++      "natur;":                           '\U0000266E',
++      "natural;":                         '\U0000266E',
++      "naturals;":                        '\U00002115',
++      "nbsp;":                            '\U000000A0',
++      "ncap;":                            '\U00002A43',
++      "ncaron;":                          '\U00000148',
++      "ncedil;":                          '\U00000146',
++      "ncong;":                           '\U00002247',
++      "ncup;":                            '\U00002A42',
++      "ncy;":                             '\U0000043D',
++      "ndash;":                           '\U00002013',
++      "ne;":                              '\U00002260',
++      "neArr;":                           '\U000021D7',
++      "nearhk;":                          '\U00002924',
++      "nearr;":                           '\U00002197',
++      "nearrow;":                         '\U00002197',
++      "nequiv;":                          '\U00002262',
++      "nesear;":                          '\U00002928',
++      "nexist;":                          '\U00002204',
++      "nexists;":                         '\U00002204',
++      "nfr;":                             '\U0001D52B',
++      "nge;":                             '\U00002271',
++      "ngeq;":                            '\U00002271',
++      "ngsim;":                           '\U00002275',
++      "ngt;":                             '\U0000226F',
++      "ngtr;":                            '\U0000226F',
++      "nhArr;":                           '\U000021CE',
++      "nharr;":                           '\U000021AE',
++      "nhpar;":                           '\U00002AF2',
++      "ni;":                              '\U0000220B',
++      "nis;":                             '\U000022FC',
++      "nisd;":                            '\U000022FA',
++      "niv;":                             '\U0000220B',
++      "njcy;":                            '\U0000045A',
++      "nlArr;":                           '\U000021CD',
++      "nlarr;":                           '\U0000219A',
++      "nldr;":                            '\U00002025',
++      "nle;":                             '\U00002270',
++      "nleftarrow;":                      '\U0000219A',
++      "nleftrightarrow;":                 '\U000021AE',
++      "nleq;":                            '\U00002270',
++      "nless;":                           '\U0000226E',
++      "nlsim;":                           '\U00002274',
++      "nlt;":                             '\U0000226E',
++      "nltri;":                           '\U000022EA',
++      "nltrie;":                          '\U000022EC',
++      "nmid;":                            '\U00002224',
++      "nopf;":                            '\U0001D55F',
++      "not;":                             '\U000000AC',
++      "notin;":                           '\U00002209',
++      "notinva;":                         '\U00002209',
++      "notinvb;":                         '\U000022F7',
++      "notinvc;":                         '\U000022F6',
++      "notni;":                           '\U0000220C',
++      "notniva;":                         '\U0000220C',
++      "notnivb;":                         '\U000022FE',
++      "notnivc;":                         '\U000022FD',
++      "npar;":                            '\U00002226',
++      "nparallel;":                       '\U00002226',
++      "npolint;":                         '\U00002A14',
++      "npr;":                             '\U00002280',
++      "nprcue;":                          '\U000022E0',
++      "nprec;":                           '\U00002280',
++      "nrArr;":                           '\U000021CF',
++      "nrarr;":                           '\U0000219B',
++      "nrightarrow;":                     '\U0000219B',
++      "nrtri;":                           '\U000022EB',
++      "nrtrie;":                          '\U000022ED',
++      "nsc;":                             '\U00002281',
++      "nsccue;":                          '\U000022E1',
++      "nscr;":                            '\U0001D4C3',
++      "nshortmid;":                       '\U00002224',
++      "nshortparallel;":                  '\U00002226',
++      "nsim;":                            '\U00002241',
++      "nsime;":                           '\U00002244',
++      "nsimeq;":                          '\U00002244',
++      "nsmid;":                           '\U00002224',
++      "nspar;":                           '\U00002226',
++      "nsqsube;":                         '\U000022E2',
++      "nsqsupe;":                         '\U000022E3',
++      "nsub;":                            '\U00002284',
++      "nsube;":                           '\U00002288',
++      "nsubseteq;":                       '\U00002288',
++      "nsucc;":                           '\U00002281',
++      "nsup;":                            '\U00002285',
++      "nsupe;":                           '\U00002289',
++      "nsupseteq;":                       '\U00002289',
++      "ntgl;":                            '\U00002279',
++      "ntilde;":                          '\U000000F1',
++      "ntlg;":                            '\U00002278',
++      "ntriangleleft;":                   '\U000022EA',
++      "ntrianglelefteq;":                 '\U000022EC',
++      "ntriangleright;":                  '\U000022EB',
++      "ntrianglerighteq;":                '\U000022ED',
++      "nu;":                              '\U000003BD',
++      "num;":                             '\U00000023',
++      "numero;":                          '\U00002116',
++      "numsp;":                           '\U00002007',
++      "nvDash;":                          '\U000022AD',
++      "nvHarr;":                          '\U00002904',
++      "nvdash;":                          '\U000022AC',
++      "nvinfin;":                         '\U000029DE',
++      "nvlArr;":                          '\U00002902',
++      "nvrArr;":                          '\U00002903',
++      "nwArr;":                           '\U000021D6',
++      "nwarhk;":                          '\U00002923',
++      "nwarr;":                           '\U00002196',
++      "nwarrow;":                         '\U00002196',
++      "nwnear;":                          '\U00002927',
++      "oS;":                              '\U000024C8',
++      "oacute;":                          '\U000000F3',
++      "oast;":                            '\U0000229B',
++      "ocir;":                            '\U0000229A',
++      "ocirc;":                           '\U000000F4',
++      "ocy;":                             '\U0000043E',
++      "odash;":                           '\U0000229D',
++      "odblac;":                          '\U00000151',
++      "odiv;":                            '\U00002A38',
++      "odot;":                            '\U00002299',
++      "odsold;":                          '\U000029BC',
++      "oelig;":                           '\U00000153',
++      "ofcir;":                           '\U000029BF',
++      "ofr;":                             '\U0001D52C',
++      "ogon;":                            '\U000002DB',
++      "ograve;":                          '\U000000F2',
++      "ogt;":                             '\U000029C1',
++      "ohbar;":                           '\U000029B5',
++      "ohm;":                             '\U000003A9',
++      "oint;":                            '\U0000222E',
++      "olarr;":                           '\U000021BA',
++      "olcir;":                           '\U000029BE',
++      "olcross;":                         '\U000029BB',
++      "oline;":                           '\U0000203E',
++      "olt;":                             '\U000029C0',
++      "omacr;":                           '\U0000014D',
++      "omega;":                           '\U000003C9',
++      "omicron;":                         '\U000003BF',
++      "omid;":                            '\U000029B6',
++      "ominus;":                          '\U00002296',
++      "oopf;":                            '\U0001D560',
++      "opar;":                            '\U000029B7',
++      "operp;":                           '\U000029B9',
++      "oplus;":                           '\U00002295',
++      "or;":                              '\U00002228',
++      "orarr;":                           '\U000021BB',
++      "ord;":                             '\U00002A5D',
++      "order;":                           '\U00002134',
++      "orderof;":                         '\U00002134',
++      "ordf;":                            '\U000000AA',
++      "ordm;":                            '\U000000BA',
++      "origof;":                          '\U000022B6',
++      "oror;":                            '\U00002A56',
++      "orslope;":                         '\U00002A57',
++      "orv;":                             '\U00002A5B',
++      "oscr;":                            '\U00002134',
++      "oslash;":                          '\U000000F8',
++      "osol;":                            '\U00002298',
++      "otilde;":                          '\U000000F5',
++      "otimes;":                          '\U00002297',
++      "otimesas;":                        '\U00002A36',
++      "ouml;":                            '\U000000F6',
++      "ovbar;":                           '\U0000233D',
++      "par;":                             '\U00002225',
++      "para;":                            '\U000000B6',
++      "parallel;":                        '\U00002225',
++      "parsim;":                          '\U00002AF3',
++      "parsl;":                           '\U00002AFD',
++      "part;":                            '\U00002202',
++      "pcy;":                             '\U0000043F',
++      "percnt;":                          '\U00000025',
++      "period;":                          '\U0000002E',
++      "permil;":                          '\U00002030',
++      "perp;":                            '\U000022A5',
++      "pertenk;":                         '\U00002031',
++      "pfr;":                             '\U0001D52D',
++      "phi;":                             '\U000003C6',
++      "phiv;":                            '\U000003D5',
++      "phmmat;":                          '\U00002133',
++      "phone;":                           '\U0000260E',
++      "pi;":                              '\U000003C0',
++      "pitchfork;":                       '\U000022D4',
++      "piv;":                             '\U000003D6',
++      "planck;":                          '\U0000210F',
++      "planckh;":                         '\U0000210E',
++      "plankv;":                          '\U0000210F',
++      "plus;":                            '\U0000002B',
++      "plusacir;":                        '\U00002A23',
++      "plusb;":                           '\U0000229E',
++      "pluscir;":                         '\U00002A22',
++      "plusdo;":                          '\U00002214',
++      "plusdu;":                          '\U00002A25',
++      "pluse;":                           '\U00002A72',
++      "plusmn;":                          '\U000000B1',
++      "plussim;":                         '\U00002A26',
++      "plustwo;":                         '\U00002A27',
++      "pm;":                              '\U000000B1',
++      "pointint;":                        '\U00002A15',
++      "popf;":                            '\U0001D561',
++      "pound;":                           '\U000000A3',
++      "pr;":                              '\U0000227A',
++      "prE;":                             '\U00002AB3',
++      "prap;":                            '\U00002AB7',
++      "prcue;":                           '\U0000227C',
++      "pre;":                             '\U00002AAF',
++      "prec;":                            '\U0000227A',
++      "precapprox;":                      '\U00002AB7',
++      "preccurlyeq;":                     '\U0000227C',
++      "preceq;":                          '\U00002AAF',
++      "precnapprox;":                     '\U00002AB9',
++      "precneqq;":                        '\U00002AB5',
++      "precnsim;":                        '\U000022E8',
++      "precsim;":                         '\U0000227E',
++      "prime;":                           '\U00002032',
++      "primes;":                          '\U00002119',
++      "prnE;":                            '\U00002AB5',
++      "prnap;":                           '\U00002AB9',
++      "prnsim;":                          '\U000022E8',
++      "prod;":                            '\U0000220F',
++      "profalar;":                        '\U0000232E',
++      "profline;":                        '\U00002312',
++      "profsurf;":                        '\U00002313',
++      "prop;":                            '\U0000221D',
++      "propto;":                          '\U0000221D',
++      "prsim;":                           '\U0000227E',
++      "prurel;":                          '\U000022B0',
++      "pscr;":                            '\U0001D4C5',
++      "psi;":                             '\U000003C8',
++      "puncsp;":                          '\U00002008',
++      "qfr;":                             '\U0001D52E',
++      "qint;":                            '\U00002A0C',
++      "qopf;":                            '\U0001D562',
++      "qprime;":                          '\U00002057',
++      "qscr;":                            '\U0001D4C6',
++      "quaternions;":                     '\U0000210D',
++      "quatint;":                         '\U00002A16',
++      "quest;":                           '\U0000003F',
++      "questeq;":                         '\U0000225F',
++      "quot;":                            '\U00000022',
++      "rAarr;":                           '\U000021DB',
++      "rArr;":                            '\U000021D2',
++      "rAtail;":                          '\U0000291C',
++      "rBarr;":                           '\U0000290F',
++      "rHar;":                            '\U00002964',
++      "racute;":                          '\U00000155',
++      "radic;":                           '\U0000221A',
++      "raemptyv;":                        '\U000029B3',
++      "rang;":                            '\U000027E9',
++      "rangd;":                           '\U00002992',
++      "range;":                           '\U000029A5',
++      "rangle;":                          '\U000027E9',
++      "raquo;":                           '\U000000BB',
++      "rarr;":                            '\U00002192',
++      "rarrap;":                          '\U00002975',
++      "rarrb;":                           '\U000021E5',
++      "rarrbfs;":                         '\U00002920',
++      "rarrc;":                           '\U00002933',
++      "rarrfs;":                          '\U0000291E',
++      "rarrhk;":                          '\U000021AA',
++      "rarrlp;":                          '\U000021AC',
++      "rarrpl;":                          '\U00002945',
++      "rarrsim;":                         '\U00002974',
++      "rarrtl;":                          '\U000021A3',
++      "rarrw;":                           '\U0000219D',
++      "ratail;":                          '\U0000291A',
++      "ratio;":                           '\U00002236',
++      "rationals;":                       '\U0000211A',
++      "rbarr;":                           '\U0000290D',
++      "rbbrk;":                           '\U00002773',
++      "rbrace;":                          '\U0000007D',
++      "rbrack;":                          '\U0000005D',
++      "rbrke;":                           '\U0000298C',
++      "rbrksld;":                         '\U0000298E',
++      "rbrkslu;":                         '\U00002990',
++      "rcaron;":                          '\U00000159',
++      "rcedil;":                          '\U00000157',
++      "rceil;":                           '\U00002309',
++      "rcub;":                            '\U0000007D',
++      "rcy;":                             '\U00000440',
++      "rdca;":                            '\U00002937',
++      "rdldhar;":                         '\U00002969',
++      "rdquo;":                           '\U0000201D',
++      "rdquor;":                          '\U0000201D',
++      "rdsh;":                            '\U000021B3',
++      "real;":                            '\U0000211C',
++      "realine;":                         '\U0000211B',
++      "realpart;":                        '\U0000211C',
++      "reals;":                           '\U0000211D',
++      "rect;":                            '\U000025AD',
++      "reg;":                             '\U000000AE',
++      "rfisht;":                          '\U0000297D',
++      "rfloor;":                          '\U0000230B',
++      "rfr;":                             '\U0001D52F',
++      "rhard;":                           '\U000021C1',
++      "rharu;":                           '\U000021C0',
++      "rharul;":                          '\U0000296C',
++      "rho;":                             '\U000003C1',
++      "rhov;":                            '\U000003F1',
++      "rightarrow;":                      '\U00002192',
++      "rightarrowtail;":                  '\U000021A3',
++      "rightharpoondown;":                '\U000021C1',
++      "rightharpoonup;":                  '\U000021C0',
++      "rightleftarrows;":                 '\U000021C4',
++      "rightleftharpoons;":               '\U000021CC',
++      "rightrightarrows;":                '\U000021C9',
++      "rightsquigarrow;":                 '\U0000219D',
++      "rightthreetimes;":                 '\U000022CC',
++      "ring;":                            '\U000002DA',
++      "risingdotseq;":                    '\U00002253',
++      "rlarr;":                           '\U000021C4',
++      "rlhar;":                           '\U000021CC',
++      "rlm;":                             '\U0000200F',
++      "rmoust;":                          '\U000023B1',
++      "rmoustache;":                      '\U000023B1',
++      "rnmid;":                           '\U00002AEE',
++      "roang;":                           '\U000027ED',
++      "roarr;":                           '\U000021FE',
++      "robrk;":                           '\U000027E7',
++      "ropar;":                           '\U00002986',
++      "ropf;":                            '\U0001D563',
++      "roplus;":                          '\U00002A2E',
++      "rotimes;":                         '\U00002A35',
++      "rpar;":                            '\U00000029',
++      "rpargt;":                          '\U00002994',
++      "rppolint;":                        '\U00002A12',
++      "rrarr;":                           '\U000021C9',
++      "rsaquo;":                          '\U0000203A',
++      "rscr;":                            '\U0001D4C7',
++      "rsh;":                             '\U000021B1',
++      "rsqb;":                            '\U0000005D',
++      "rsquo;":                           '\U00002019',
++      "rsquor;":                          '\U00002019',
++      "rthree;":                          '\U000022CC',
++      "rtimes;":                          '\U000022CA',
++      "rtri;":                            '\U000025B9',
++      "rtrie;":                           '\U000022B5',
++      "rtrif;":                           '\U000025B8',
++      "rtriltri;":                        '\U000029CE',
++      "ruluhar;":                         '\U00002968',
++      "rx;":                              '\U0000211E',
++      "sacute;":                          '\U0000015B',
++      "sbquo;":                           '\U0000201A',
++      "sc;":                              '\U0000227B',
++      "scE;":                             '\U00002AB4',
++      "scap;":                            '\U00002AB8',
++      "scaron;":                          '\U00000161',
++      "sccue;":                           '\U0000227D',
++      "sce;":                             '\U00002AB0',
++      "scedil;":                          '\U0000015F',
++      "scirc;":                           '\U0000015D',
++      "scnE;":                            '\U00002AB6',
++      "scnap;":                           '\U00002ABA',
++      "scnsim;":                          '\U000022E9',
++      "scpolint;":                        '\U00002A13',
++      "scsim;":                           '\U0000227F',
++      "scy;":                             '\U00000441',
++      "sdot;":                            '\U000022C5',
++      "sdotb;":                           '\U000022A1',
++      "sdote;":                           '\U00002A66',
++      "seArr;":                           '\U000021D8',
++      "searhk;":                          '\U00002925',
++      "searr;":                           '\U00002198',
++      "searrow;":                         '\U00002198',
++      "sect;":                            '\U000000A7',
++      "semi;":                            '\U0000003B',
++      "seswar;":                          '\U00002929',
++      "setminus;":                        '\U00002216',
++      "setmn;":                           '\U00002216',
++      "sext;":                            '\U00002736',
++      "sfr;":                             '\U0001D530',
++      "sfrown;":                          '\U00002322',
++      "sharp;":                           '\U0000266F',
++      "shchcy;":                          '\U00000449',
++      "shcy;":                            '\U00000448',
++      "shortmid;":                        '\U00002223',
++      "shortparallel;":                   '\U00002225',
++      "shy;":                             '\U000000AD',
++      "sigma;":                           '\U000003C3',
++      "sigmaf;":                          '\U000003C2',
++      "sigmav;":                          '\U000003C2',
++      "sim;":                             '\U0000223C',
++      "simdot;":                          '\U00002A6A',
++      "sime;":                            '\U00002243',
++      "simeq;":                           '\U00002243',
++      "simg;":                            '\U00002A9E',
++      "simgE;":                           '\U00002AA0',
++      "siml;":                            '\U00002A9D',
++      "simlE;":                           '\U00002A9F',
++      "simne;":                           '\U00002246',
++      "simplus;":                         '\U00002A24',
++      "simrarr;":                         '\U00002972',
++      "slarr;":                           '\U00002190',
++      "smallsetminus;":                   '\U00002216',
++      "smashp;":                          '\U00002A33',
++      "smeparsl;":                        '\U000029E4',
++      "smid;":                            '\U00002223',
++      "smile;":                           '\U00002323',
++      "smt;":                             '\U00002AAA',
++      "smte;":                            '\U00002AAC',
++      "softcy;":                          '\U0000044C',
++      "sol;":                             '\U0000002F',
++      "solb;":                            '\U000029C4',
++      "solbar;":                          '\U0000233F',
++      "sopf;":                            '\U0001D564',
++      "spades;":                          '\U00002660',
++      "spadesuit;":                       '\U00002660',
++      "spar;":                            '\U00002225',
++      "sqcap;":                           '\U00002293',
++      "sqcup;":                           '\U00002294',
++      "sqsub;":                           '\U0000228F',
++      "sqsube;":                          '\U00002291',
++      "sqsubset;":                        '\U0000228F',
++      "sqsubseteq;":                      '\U00002291',
++      "sqsup;":                           '\U00002290',
++      "sqsupe;":                          '\U00002292',
++      "sqsupset;":                        '\U00002290',
++      "sqsupseteq;":                      '\U00002292',
++      "squ;":                             '\U000025A1',
++      "square;":                          '\U000025A1',
++      "squarf;":                          '\U000025AA',
++      "squf;":                            '\U000025AA',
++      "srarr;":                           '\U00002192',
++      "sscr;":                            '\U0001D4C8',
++      "ssetmn;":                          '\U00002216',
++      "ssmile;":                          '\U00002323',
++      "sstarf;":                          '\U000022C6',
++      "star;":                            '\U00002606',
++      "starf;":                           '\U00002605',
++      "straightepsilon;":                 '\U000003F5',
++      "straightphi;":                     '\U000003D5',
++      "strns;":                           '\U000000AF',
++      "sub;":                             '\U00002282',
++      "subE;":                            '\U00002AC5',
++      "subdot;":                          '\U00002ABD',
++      "sube;":                            '\U00002286',
++      "subedot;":                         '\U00002AC3',
++      "submult;":                         '\U00002AC1',
++      "subnE;":                           '\U00002ACB',
++      "subne;":                           '\U0000228A',
++      "subplus;":                         '\U00002ABF',
++      "subrarr;":                         '\U00002979',
++      "subset;":                          '\U00002282',
++      "subseteq;":                        '\U00002286',
++      "subseteqq;":                       '\U00002AC5',
++      "subsetneq;":                       '\U0000228A',
++      "subsetneqq;":                      '\U00002ACB',
++      "subsim;":                          '\U00002AC7',
++      "subsub;":                          '\U00002AD5',
++      "subsup;":                          '\U00002AD3',
++      "succ;":                            '\U0000227B',
++      "succapprox;":                      '\U00002AB8',
++      "succcurlyeq;":                     '\U0000227D',
++      "succeq;":                          '\U00002AB0',
++      "succnapprox;":                     '\U00002ABA',
++      "succneqq;":                        '\U00002AB6',
++      "succnsim;":                        '\U000022E9',
++      "succsim;":                         '\U0000227F',
++      "sum;":                             '\U00002211',
++      "sung;":                            '\U0000266A',
++      "sup;":                             '\U00002283',
++      "sup1;":                            '\U000000B9',
++      "sup2;":                            '\U000000B2',
++      "sup3;":                            '\U000000B3',
++      "supE;":                            '\U00002AC6',
++      "supdot;":                          '\U00002ABE',
++      "supdsub;":                         '\U00002AD8',
++      "supe;":                            '\U00002287',
++      "supedot;":                         '\U00002AC4',
++      "suphsol;":                         '\U000027C9',
++      "suphsub;":                         '\U00002AD7',
++      "suplarr;":                         '\U0000297B',
++      "supmult;":                         '\U00002AC2',
++      "supnE;":                           '\U00002ACC',
++      "supne;":                           '\U0000228B',
++      "supplus;":                         '\U00002AC0',
++      "supset;":                          '\U00002283',
++      "supseteq;":                        '\U00002287',
++      "supseteqq;":                       '\U00002AC6',
++      "supsetneq;":                       '\U0000228B',
++      "supsetneqq;":                      '\U00002ACC',
++      "supsim;":                          '\U00002AC8',
++      "supsub;":                          '\U00002AD4',
++      "supsup;":                          '\U00002AD6',
++      "swArr;":                           '\U000021D9',
++      "swarhk;":                          '\U00002926',
++      "swarr;":                           '\U00002199',
++      "swarrow;":                         '\U00002199',
++      "swnwar;":                          '\U0000292A',
++      "szlig;":                           '\U000000DF',
++      "target;":                          '\U00002316',
++      "tau;":                             '\U000003C4',
++      "tbrk;":                            '\U000023B4',
++      "tcaron;":                          '\U00000165',
++      "tcedil;":                          '\U00000163',
++      "tcy;":                             '\U00000442',
++      "tdot;":                            '\U000020DB',
++      "telrec;":                          '\U00002315',
++      "tfr;":                             '\U0001D531',
++      "there4;":                          '\U00002234',
++      "therefore;":                       '\U00002234',
++      "theta;":                           '\U000003B8',
++      "thetasym;":                        '\U000003D1',
++      "thetav;":                          '\U000003D1',
++      "thickapprox;":                     '\U00002248',
++      "thicksim;":                        '\U0000223C',
++      "thinsp;":                          '\U00002009',
++      "thkap;":                           '\U00002248',
++      "thksim;":                          '\U0000223C',
++      "thorn;":                           '\U000000FE',
++      "tilde;":                           '\U000002DC',
++      "times;":                           '\U000000D7',
++      "timesb;":                          '\U000022A0',
++      "timesbar;":                        '\U00002A31',
++      "timesd;":                          '\U00002A30',
++      "tint;":                            '\U0000222D',
++      "toea;":                            '\U00002928',
++      "top;":                             '\U000022A4',
++      "topbot;":                          '\U00002336',
++      "topcir;":                          '\U00002AF1',
++      "topf;":                            '\U0001D565',
++      "topfork;":                         '\U00002ADA',
++      "tosa;":                            '\U00002929',
++      "tprime;":                          '\U00002034',
++      "trade;":                           '\U00002122',
++      "triangle;":                        '\U000025B5',
++      "triangledown;":                    '\U000025BF',
++      "triangleleft;":                    '\U000025C3',
++      "trianglelefteq;":                  '\U000022B4',
++      "triangleq;":                       '\U0000225C',
++      "triangleright;":                   '\U000025B9',
++      "trianglerighteq;":                 '\U000022B5',
++      "tridot;":                          '\U000025EC',
++      "trie;":                            '\U0000225C',
++      "triminus;":                        '\U00002A3A',
++      "triplus;":                         '\U00002A39',
++      "trisb;":                           '\U000029CD',
++      "tritime;":                         '\U00002A3B',
++      "trpezium;":                        '\U000023E2',
++      "tscr;":                            '\U0001D4C9',
++      "tscy;":                            '\U00000446',
++      "tshcy;":                           '\U0000045B',
++      "tstrok;":                          '\U00000167',
++      "twixt;":                           '\U0000226C',
++      "twoheadleftarrow;":                '\U0000219E',
++      "twoheadrightarrow;":               '\U000021A0',
++      "uArr;":                            '\U000021D1',
++      "uHar;":                            '\U00002963',
++      "uacute;":                          '\U000000FA',
++      "uarr;":                            '\U00002191',
++      "ubrcy;":                           '\U0000045E',
++      "ubreve;":                          '\U0000016D',
++      "ucirc;":                           '\U000000FB',
++      "ucy;":                             '\U00000443',
++      "udarr;":                           '\U000021C5',
++      "udblac;":                          '\U00000171',
++      "udhar;":                           '\U0000296E',
++      "ufisht;":                          '\U0000297E',
++      "ufr;":                             '\U0001D532',
++      "ugrave;":                          '\U000000F9',
++      "uharl;":                           '\U000021BF',
++      "uharr;":                           '\U000021BE',
++      "uhblk;":                           '\U00002580',
++      "ulcorn;":                          '\U0000231C',
++      "ulcorner;":                        '\U0000231C',
++      "ulcrop;":                          '\U0000230F',
++      "ultri;":                           '\U000025F8',
++      "umacr;":                           '\U0000016B',
++      "uml;":                             '\U000000A8',
++      "uogon;":                           '\U00000173',
++      "uopf;":                            '\U0001D566',
++      "uparrow;":                         '\U00002191',
++      "updownarrow;":                     '\U00002195',
++      "upharpoonleft;":                   '\U000021BF',
++      "upharpoonright;":                  '\U000021BE',
++      "uplus;":                           '\U0000228E',
++      "upsi;":                            '\U000003C5',
++      "upsih;":                           '\U000003D2',
++      "upsilon;":                         '\U000003C5',
++      "upuparrows;":                      '\U000021C8',
++      "urcorn;":                          '\U0000231D',
++      "urcorner;":                        '\U0000231D',
++      "urcrop;":                          '\U0000230E',
++      "uring;":                           '\U0000016F',
++      "urtri;":                           '\U000025F9',
++      "uscr;":                            '\U0001D4CA',
++      "utdot;":                           '\U000022F0',
++      "utilde;":                          '\U00000169',
++      "utri;":                            '\U000025B5',
++      "utrif;":                           '\U000025B4',
++      "uuarr;":                           '\U000021C8',
++      "uuml;":                            '\U000000FC',
++      "uwangle;":                         '\U000029A7',
++      "vArr;":                            '\U000021D5',
++      "vBar;":                            '\U00002AE8',
++      "vBarv;":                           '\U00002AE9',
++      "vDash;":                           '\U000022A8',
++      "vangrt;":                          '\U0000299C',
++      "varepsilon;":                      '\U000003F5',
++      "varkappa;":                        '\U000003F0',
++      "varnothing;":                      '\U00002205',
++      "varphi;":                          '\U000003D5',
++      "varpi;":                           '\U000003D6',
++      "varpropto;":                       '\U0000221D',
++      "varr;":                            '\U00002195',
++      "varrho;":                          '\U000003F1',
++      "varsigma;":                        '\U000003C2',
++      "vartheta;":                        '\U000003D1',
++      "vartriangleleft;":                 '\U000022B2',
++      "vartriangleright;":                '\U000022B3',
++      "vcy;":                             '\U00000432',
++      "vdash;":                           '\U000022A2',
++      "vee;":                             '\U00002228',
++      "veebar;":                          '\U000022BB',
++      "veeeq;":                           '\U0000225A',
++      "vellip;":                          '\U000022EE',
++      "verbar;":                          '\U0000007C',
++      "vert;":                            '\U0000007C',
++      "vfr;":                             '\U0001D533',
++      "vltri;":                           '\U000022B2',
++      "vopf;":                            '\U0001D567',
++      "vprop;":                           '\U0000221D',
++      "vrtri;":                           '\U000022B3',
++      "vscr;":                            '\U0001D4CB',
++      "vzigzag;":                         '\U0000299A',
++      "wcirc;":                           '\U00000175',
++      "wedbar;":                          '\U00002A5F',
++      "wedge;":                           '\U00002227',
++      "wedgeq;":                          '\U00002259',
++      "weierp;":                          '\U00002118',
++      "wfr;":                             '\U0001D534',
++      "wopf;":                            '\U0001D568',
++      "wp;":                              '\U00002118',
++      "wr;":                              '\U00002240',
++      "wreath;":                          '\U00002240',
++      "wscr;":                            '\U0001D4CC',
++      "xcap;":                            '\U000022C2',
++      "xcirc;":                           '\U000025EF',
++      "xcup;":                            '\U000022C3',
++      "xdtri;":                           '\U000025BD',
++      "xfr;":                             '\U0001D535',
++      "xhArr;":                           '\U000027FA',
++      "xharr;":                           '\U000027F7',
++      "xi;":                              '\U000003BE',
++      "xlArr;":                           '\U000027F8',
++      "xlarr;":                           '\U000027F5',
++      "xmap;":                            '\U000027FC',
++      "xnis;":                            '\U000022FB',
++      "xodot;":                           '\U00002A00',
++      "xopf;":                            '\U0001D569',
++      "xoplus;":                          '\U00002A01',
++      "xotime;":                          '\U00002A02',
++      "xrArr;":                           '\U000027F9',
++      "xrarr;":                           '\U000027F6',
++      "xscr;":                            '\U0001D4CD',
++      "xsqcup;":                          '\U00002A06',
++      "xuplus;":                          '\U00002A04',
++      "xutri;":                           '\U000025B3',
++      "xvee;":                            '\U000022C1',
++      "xwedge;":                          '\U000022C0',
++      "yacute;":                          '\U000000FD',
++      "yacy;":                            '\U0000044F',
++      "ycirc;":                           '\U00000177',
++      "ycy;":                             '\U0000044B',
++      "yen;":                             '\U000000A5',
++      "yfr;":                             '\U0001D536',
++      "yicy;":                            '\U00000457',
++      "yopf;":                            '\U0001D56A',
++      "yscr;":                            '\U0001D4CE',
++      "yucy;":                            '\U0000044E',
++      "yuml;":                            '\U000000FF',
++      "zacute;":                          '\U0000017A',
++      "zcaron;":                          '\U0000017E',
++      "zcy;":                             '\U00000437',
++      "zdot;":                            '\U0000017C',
++      "zeetrf;":                          '\U00002128',
++      "zeta;":                            '\U000003B6',
++      "zfr;":                             '\U0001D537',
++      "zhcy;":                            '\U00000436',
++      "zigrarr;":                         '\U000021DD',
++      "zopf;":                            '\U0001D56B',
++      "zscr;":                            '\U0001D4CF',
++      "zwj;":                             '\U0000200D',
++      "zwnj;":                            '\U0000200C',
++      "AElig":                            '\U000000C6',
++      "AMP":                              '\U00000026',
++      "Aacute":                           '\U000000C1',
++      "Acirc":                            '\U000000C2',
++      "Agrave":                           '\U000000C0',
++      "Aring":                            '\U000000C5',
++      "Atilde":                           '\U000000C3',
++      "Auml":                             '\U000000C4',
++      "COPY":                             '\U000000A9',
++      "Ccedil":                           '\U000000C7',
++      "ETH":                              '\U000000D0',
++      "Eacute":                           '\U000000C9',
++      "Ecirc":                            '\U000000CA',
++      "Egrave":                           '\U000000C8',
++      "Euml":                             '\U000000CB',
++      "GT":                               '\U0000003E',
++      "Iacute":                           '\U000000CD',
++      "Icirc":                            '\U000000CE',
++      "Igrave":                           '\U000000CC',
++      "Iuml":                             '\U000000CF',
++      "LT":                               '\U0000003C',
++      "Ntilde":                           '\U000000D1',
++      "Oacute":                           '\U000000D3',
++      "Ocirc":                            '\U000000D4',
++      "Ograve":                           '\U000000D2',
++      "Oslash":                           '\U000000D8',
++      "Otilde":                           '\U000000D5',
++      "Ouml":                             '\U000000D6',
++      "QUOT":                             '\U00000022',
++      "REG":                              '\U000000AE',
++      "THORN":                            '\U000000DE',
++      "Uacute":                           '\U000000DA',
++      "Ucirc":                            '\U000000DB',
++      "Ugrave":                           '\U000000D9',
++      "Uuml":                             '\U000000DC',
++      "Yacute":                           '\U000000DD',
++      "aacute":                           '\U000000E1',
++      "acirc":                            '\U000000E2',
++      "acute":                            '\U000000B4',
++      "aelig":                            '\U000000E6',
++      "agrave":                           '\U000000E0',
++      "amp":                              '\U00000026',
++      "aring":                            '\U000000E5',
++      "atilde":                           '\U000000E3',
++      "auml":                             '\U000000E4',
++      "brvbar":                           '\U000000A6',
++      "ccedil":                           '\U000000E7',
++      "cedil":                            '\U000000B8',
++      "cent":                             '\U000000A2',
++      "copy":                             '\U000000A9',
++      "curren":                           '\U000000A4',
++      "deg":                              '\U000000B0',
++      "divide":                           '\U000000F7',
++      "eacute":                           '\U000000E9',
++      "ecirc":                            '\U000000EA',
++      "egrave":                           '\U000000E8',
++      "eth":                              '\U000000F0',
++      "euml":                             '\U000000EB',
++      "frac12":                           '\U000000BD',
++      "frac14":                           '\U000000BC',
++      "frac34":                           '\U000000BE',
++      "gt":                               '\U0000003E',
++      "iacute":                           '\U000000ED',
++      "icirc":                            '\U000000EE',
++      "iexcl":                            '\U000000A1',
++      "igrave":                           '\U000000EC',
++      "iquest":                           '\U000000BF',
++      "iuml":                             '\U000000EF',
++      "laquo":                            '\U000000AB',
++      "lt":                               '\U0000003C',
++      "macr":                             '\U000000AF',
++      "micro":                            '\U000000B5',
++      "middot":                           '\U000000B7',
++      "nbsp":                             '\U000000A0',
++      "not":                              '\U000000AC',
++      "ntilde":                           '\U000000F1',
++      "oacute":                           '\U000000F3',
++      "ocirc":                            '\U000000F4',
++      "ograve":                           '\U000000F2',
++      "ordf":                             '\U000000AA',
++      "ordm":                             '\U000000BA',
++      "oslash":                           '\U000000F8',
++      "otilde":                           '\U000000F5',
++      "ouml":                             '\U000000F6',
++      "para":                             '\U000000B6',
++      "plusmn":                           '\U000000B1',
++      "pound":                            '\U000000A3',
++      "quot":                             '\U00000022',
++      "raquo":                            '\U000000BB',
++      "reg":                              '\U000000AE',
++      "sect":                             '\U000000A7',
++      "shy":                              '\U000000AD',
++      "sup1":                             '\U000000B9',
++      "sup2":                             '\U000000B2',
++      "sup3":                             '\U000000B3',
++      "szlig":                            '\U000000DF',
++      "thorn":                            '\U000000FE',
++      "times":                            '\U000000D7',
++      "uacute":                           '\U000000FA',
++      "ucirc":                            '\U000000FB',
++      "ugrave":                           '\U000000F9',
++      "uml":                              '\U000000A8',
++      "uuml":                             '\U000000FC',
++      "yacute":                           '\U000000FD',
++      "yen":                              '\U000000A5',
++      "yuml":                             '\U000000FF',
++}
++
++// HTML entities that are two unicode codepoints.
++var entity2 = map[string][2]rune{
++      // TODO(nigeltao): Handle replacements that are wider than their names.
++      // "nLt;":                     {'\u226A', '\u20D2'},
++      // "nGt;":                     {'\u226B', '\u20D2'},
++      "NotEqualTilde;":           {'\u2242', '\u0338'},
++      "NotGreaterFullEqual;":     {'\u2267', '\u0338'},
++      "NotGreaterGreater;":       {'\u226B', '\u0338'},
++      "NotGreaterSlantEqual;":    {'\u2A7E', '\u0338'},
++      "NotHumpDownHump;":         {'\u224E', '\u0338'},
++      "NotHumpEqual;":            {'\u224F', '\u0338'},
++      "NotLeftTriangleBar;":      {'\u29CF', '\u0338'},
++      "NotLessLess;":             {'\u226A', '\u0338'},
++      "NotLessSlantEqual;":       {'\u2A7D', '\u0338'},
++      "NotNestedGreaterGreater;": {'\u2AA2', '\u0338'},
++      "NotNestedLessLess;":       {'\u2AA1', '\u0338'},
++      "NotPrecedesEqual;":        {'\u2AAF', '\u0338'},
++      "NotRightTriangleBar;":     {'\u29D0', '\u0338'},
++      "NotSquareSubset;":         {'\u228F', '\u0338'},
++      "NotSquareSuperset;":       {'\u2290', '\u0338'},
++      "NotSubset;":               {'\u2282', '\u20D2'},
++      "NotSucceedsEqual;":        {'\u2AB0', '\u0338'},
++      "NotSucceedsTilde;":        {'\u227F', '\u0338'},
++      "NotSuperset;":             {'\u2283', '\u20D2'},
++      "ThickSpace;":              {'\u205F', '\u200A'},
++      "acE;":                     {'\u223E', '\u0333'},
++      "bne;":                     {'\u003D', '\u20E5'},
++      "bnequiv;":                 {'\u2261', '\u20E5'},
++      "caps;":                    {'\u2229', '\uFE00'},
++      "cups;":                    {'\u222A', '\uFE00'},
++      "fjlig;":                   {'\u0066', '\u006A'},
++      "gesl;":                    {'\u22DB', '\uFE00'},
++      "gvertneqq;":               {'\u2269', '\uFE00'},
++      "gvnE;":                    {'\u2269', '\uFE00'},
++      "lates;":                   {'\u2AAD', '\uFE00'},
++      "lesg;":                    {'\u22DA', '\uFE00'},
++      "lvertneqq;":               {'\u2268', '\uFE00'},
++      "lvnE;":                    {'\u2268', '\uFE00'},
++      "nGg;":                     {'\u22D9', '\u0338'},
++      "nGtv;":                    {'\u226B', '\u0338'},
++      "nLl;":                     {'\u22D8', '\u0338'},
++      "nLtv;":                    {'\u226A', '\u0338'},
++      "nang;":                    {'\u2220', '\u20D2'},
++      "napE;":                    {'\u2A70', '\u0338'},
++      "napid;":                   {'\u224B', '\u0338'},
++      "nbump;":                   {'\u224E', '\u0338'},
++      "nbumpe;":                  {'\u224F', '\u0338'},
++      "ncongdot;":                {'\u2A6D', '\u0338'},
++      "nedot;":                   {'\u2250', '\u0338'},
++      "nesim;":                   {'\u2242', '\u0338'},
++      "ngE;":                     {'\u2267', '\u0338'},
++      "ngeqq;":                   {'\u2267', '\u0338'},
++      "ngeqslant;":               {'\u2A7E', '\u0338'},
++      "nges;":                    {'\u2A7E', '\u0338'},
++      "nlE;":                     {'\u2266', '\u0338'},
++      "nleqq;":                   {'\u2266', '\u0338'},
++      "nleqslant;":               {'\u2A7D', '\u0338'},
++      "nles;":                    {'\u2A7D', '\u0338'},
++      "notinE;":                  {'\u22F9', '\u0338'},
++      "notindot;":                {'\u22F5', '\u0338'},
++      "nparsl;":                  {'\u2AFD', '\u20E5'},
++      "npart;":                   {'\u2202', '\u0338'},
++      "npre;":                    {'\u2AAF', '\u0338'},
++      "npreceq;":                 {'\u2AAF', '\u0338'},
++      "nrarrc;":                  {'\u2933', '\u0338'},
++      "nrarrw;":                  {'\u219D', '\u0338'},
++      "nsce;":                    {'\u2AB0', '\u0338'},
++      "nsubE;":                   {'\u2AC5', '\u0338'},
++      "nsubset;":                 {'\u2282', '\u20D2'},
++      "nsubseteqq;":              {'\u2AC5', '\u0338'},
++      "nsucceq;":                 {'\u2AB0', '\u0338'},
++      "nsupE;":                   {'\u2AC6', '\u0338'},
++      "nsupset;":                 {'\u2283', '\u20D2'},
++      "nsupseteqq;":              {'\u2AC6', '\u0338'},
++      "nvap;":                    {'\u224D', '\u20D2'},
++      "nvge;":                    {'\u2265', '\u20D2'},
++      "nvgt;":                    {'\u003E', '\u20D2'},
++      "nvle;":                    {'\u2264', '\u20D2'},
++      "nvlt;":                    {'\u003C', '\u20D2'},
++      "nvltrie;":                 {'\u22B4', '\u20D2'},
++      "nvrtrie;":                 {'\u22B5', '\u20D2'},
++      "nvsim;":                   {'\u223C', '\u20D2'},
++      "race;":                    {'\u223D', '\u0331'},
++      "smtes;":                   {'\u2AAC', '\uFE00'},
++      "sqcaps;":                  {'\u2293', '\uFE00'},
++      "sqcups;":                  {'\u2294', '\uFE00'},
++      "varsubsetneq;":            {'\u228A', '\uFE00'},
++      "varsubsetneqq;":           {'\u2ACB', '\uFE00'},
++      "varsupsetneq;":            {'\u228B', '\uFE00'},
++      "varsupsetneqq;":           {'\u2ACC', '\uFE00'},
++      "vnsub;":                   {'\u2282', '\u20D2'},
++      "vnsup;":                   {'\u2283', '\u20D2'},
++      "vsubnE;":                  {'\u2ACB', '\uFE00'},
++      "vsubne;":                  {'\u228A', '\uFE00'},
++      "vsupnE;":                  {'\u2ACC', '\uFE00'},
++      "vsupne;":                  {'\u228B', '\uFE00'},
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b53f866fa2ddff6f22e9c9c831c8eabb1d7197b2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,29 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "testing"
++      "unicode/utf8"
++)
++
++func TestEntityLength(t *testing.T) {
++      // We verify that the length of UTF-8 encoding of each value is <= 1 + len(key).
++      // The +1 comes from the leading "&". This property implies that the length of
++      // unescaped text is <= the length of escaped text.
++      for k, v := range entity {
++              if 1+len(k) < utf8.RuneLen(v) {
++                      t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v))
++              }
++              if len(k) > longestEntityWithoutSemicolon && k[len(k)-1] != ';' {
++                      t.Errorf("entity name %s is %d characters, but longestEntityWithoutSemicolon=%d", k, len(k), longestEntityWithoutSemicolon)
++              }
++      }
++      for k, v := range entity2 {
++              if 1+len(k) < utf8.RuneLen(v[0])+utf8.RuneLen(v[1]) {
++                      t.Error("escaped entity &" + k + " is shorter than its UTF-8 encoding " + string(v[0]) + string(v[1]))
++              }
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..04c6bec21073773d3e975f35d62b2c6599b709d0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,339 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bytes"
++      "strings"
++      "unicode/utf8"
++)
++
++// These replacements permit compatibility with old numeric entities that
++// assumed Windows-1252 encoding.
++// https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
++var replacementTable = [...]rune{
++      '\u20AC', // First entry is what 0x80 should be replaced with.
++      '\u0081',
++      '\u201A',
++      '\u0192',
++      '\u201E',
++      '\u2026',
++      '\u2020',
++      '\u2021',
++      '\u02C6',
++      '\u2030',
++      '\u0160',
++      '\u2039',
++      '\u0152',
++      '\u008D',
++      '\u017D',
++      '\u008F',
++      '\u0090',
++      '\u2018',
++      '\u2019',
++      '\u201C',
++      '\u201D',
++      '\u2022',
++      '\u2013',
++      '\u2014',
++      '\u02DC',
++      '\u2122',
++      '\u0161',
++      '\u203A',
++      '\u0153',
++      '\u009D',
++      '\u017E',
++      '\u0178', // Last entry is 0x9F.
++      // 0x00->'\uFFFD' is handled programmatically.
++      // 0x0D->'\u000D' is a no-op.
++}
++
++// unescapeEntity reads an entity like "&lt;" from b[src:] and writes the
++// corresponding "<" to b[dst:], returning the incremented dst and src cursors.
++// Precondition: b[src] == '&' && dst <= src.
++// attribute should be true if parsing an attribute value.
++func unescapeEntity(b []byte, dst, src int, attribute bool) (dst1, src1 int) {
++      // https://html.spec.whatwg.org/multipage/syntax.html#consume-a-character-reference
++
++      // i starts at 1 because we already know that s[0] == '&'.
++      i, s := 1, b[src:]
++
++      if len(s) <= 1 {
++              b[dst] = b[src]
++              return dst + 1, src + 1
++      }
++
++      if s[i] == '#' {
++              if len(s) <= 3 { // We need to have at least "&#.".
++                      b[dst] = b[src]
++                      return dst + 1, src + 1
++              }
++              i++
++              c := s[i]
++              hex := false
++              if c == 'x' || c == 'X' {
++                      hex = true
++                      i++
++              }
++
++              x := '\x00'
++              for i < len(s) {
++                      c = s[i]
++                      i++
++                      if hex {
++                              if '0' <= c && c <= '9' {
++                                      x = 16*x + rune(c) - '0'
++                                      continue
++                              } else if 'a' <= c && c <= 'f' {
++                                      x = 16*x + rune(c) - 'a' + 10
++                                      continue
++                              } else if 'A' <= c && c <= 'F' {
++                                      x = 16*x + rune(c) - 'A' + 10
++                                      continue
++                              }
++                      } else if '0' <= c && c <= '9' {
++                              x = 10*x + rune(c) - '0'
++                              continue
++                      }
++                      if c != ';' {
++                              i--
++                      }
++                      break
++              }
++
++              if i <= 3 { // No characters matched.
++                      b[dst] = b[src]
++                      return dst + 1, src + 1
++              }
++
++              if 0x80 <= x && x <= 0x9F {
++                      // Replace characters from Windows-1252 with UTF-8 equivalents.
++                      x = replacementTable[x-0x80]
++              } else if x == 0 || (0xD800 <= x && x <= 0xDFFF) || x > 0x10FFFF {
++                      // Replace invalid characters with the replacement character.
++                      x = '\uFFFD'
++              }
++
++              return dst + utf8.EncodeRune(b[dst:], x), src + i
++      }
++
++      // Consume the maximum number of characters possible, with the
++      // consumed characters matching one of the named references.
++
++      for i < len(s) {
++              c := s[i]
++              i++
++              // Lower-cased characters are more common in entities, so we check for them first.
++              if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' {
++                      continue
++              }
++              if c != ';' {
++                      i--
++              }
++              break
++      }
++
++      entityName := string(s[1:i])
++      if entityName == "" {
++              // No-op.
++      } else if attribute && entityName[len(entityName)-1] != ';' && len(s) > i && s[i] == '=' {
++              // No-op.
++      } else if x := entity[entityName]; x != 0 {
++              return dst + utf8.EncodeRune(b[dst:], x), src + i
++      } else if x := entity2[entityName]; x[0] != 0 {
++              dst1 := dst + utf8.EncodeRune(b[dst:], x[0])
++              return dst1 + utf8.EncodeRune(b[dst1:], x[1]), src + i
++      } else if !attribute {
++              maxLen := len(entityName) - 1
++              if maxLen > longestEntityWithoutSemicolon {
++                      maxLen = longestEntityWithoutSemicolon
++              }
++              for j := maxLen; j > 1; j-- {
++                      if x := entity[entityName[:j]]; x != 0 {
++                              return dst + utf8.EncodeRune(b[dst:], x), src + j + 1
++                      }
++              }
++      }
++
++      dst1, src1 = dst+i, src+i
++      copy(b[dst:dst1], b[src:src1])
++      return dst1, src1
++}
++
++// unescape unescapes b's entities in-place, so that "a&lt;b" becomes "a<b".
++// attribute should be true if parsing an attribute value.
++func unescape(b []byte, attribute bool) []byte {
++      for i, c := range b {
++              if c == '&' {
++                      dst, src := unescapeEntity(b, i, i, attribute)
++                      for src < len(b) {
++                              c := b[src]
++                              if c == '&' {
++                                      dst, src = unescapeEntity(b, dst, src, attribute)
++                              } else {
++                                      b[dst] = c
++                                      dst, src = dst+1, src+1
++                              }
++                      }
++                      return b[0:dst]
++              }
++      }
++      return b
++}
++
++// lower lower-cases the A-Z bytes in b in-place, so that "aBc" becomes "abc".
++func lower(b []byte) []byte {
++      for i, c := range b {
++              if 'A' <= c && c <= 'Z' {
++                      b[i] = c + 'a' - 'A'
++              }
++      }
++      return b
++}
++
++// escapeComment is like func escape but escapes its input bytes less often.
++// Per https://github.com/golang/go/issues/58246 some HTML comments are (1)
++// meaningful and (2) contain angle brackets that we'd like to avoid escaping
++// unless we have to.
++//
++// "We have to" includes the '&' byte, since that introduces other escapes.
++//
++// It also includes those bytes (not including EOF) that would otherwise end
++// the comment. Per the summary table at the bottom of comment_test.go, this is
++// the '>' byte that, per above, we'd like to avoid escaping unless we have to.
++//
++// Studying the summary table (and T actions in its '>' column) closely, we
++// only need to escape in states 43, 44, 49, 51 and 52. State 43 is at the
++// start of the comment data. State 52 is after a '!'. The other three states
++// are after a '-'.
++//
++// Our algorithm is thus to escape every '&' and to escape '>' if and only if:
++//   - The '>' is after a '!' or '-' (in the unescaped data) or
++//   - The '>' is at the start of the comment data (after the opening "<!--").
++func escapeComment(w writer, s string) error {
++      // When modifying this function, consider manually increasing the
++      // maxSuffixLen constant in func TestComments, from 6 to e.g. 9 or more.
++      // That increase should only be temporary, not committed, as it
++      // exponentially affects the test running time.
++
++      if len(s) == 0 {
++              return nil
++      }
++
++      // Loop:
++      //   - Grow j such that s[i:j] does not need escaping.
++      //   - If s[j] does need escaping, output s[i:j] and an escaped s[j],
++      //     resetting i and j to point past that s[j] byte.
++      i := 0
++      for j := 0; j < len(s); j++ {
++              escaped := ""
++              switch s[j] {
++              case '&':
++                      escaped = "&amp;"
++
++              case '>':
++                      if j > 0 {
++                              if prev := s[j-1]; (prev != '!') && (prev != '-') {
++                                      continue
++                              }
++                      }
++                      escaped = "&gt;"
++
++              default:
++                      continue
++              }
++
++              if i < j {
++                      if _, err := w.WriteString(s[i:j]); err != nil {
++                              return err
++                      }
++              }
++              if _, err := w.WriteString(escaped); err != nil {
++                      return err
++              }
++              i = j + 1
++      }
++
++      if i < len(s) {
++              if _, err := w.WriteString(s[i:]); err != nil {
++                      return err
++              }
++      }
++      return nil
++}
++
++// escapeCommentString is to EscapeString as escapeComment is to escape.
++func escapeCommentString(s string) string {
++      if strings.IndexAny(s, "&>") == -1 {
++              return s
++      }
++      var buf bytes.Buffer
++      escapeComment(&buf, s)
++      return buf.String()
++}
++
++const escapedChars = "&'<>\"\r"
++
++func escape(w writer, s string) error {
++      i := strings.IndexAny(s, escapedChars)
++      for i != -1 {
++              if _, err := w.WriteString(s[:i]); err != nil {
++                      return err
++              }
++              var esc string
++              switch s[i] {
++              case '&':
++                      esc = "&amp;"
++              case '\'':
++                      // "&#39;" is shorter than "&apos;" and apos was not in HTML until HTML5.
++                      esc = "&#39;"
++              case '<':
++                      esc = "&lt;"
++              case '>':
++                      esc = "&gt;"
++              case '"':
++                      // "&#34;" is shorter than "&quot;".
++                      esc = "&#34;"
++              case '\r':
++                      esc = "&#13;"
++              default:
++                      panic("unrecognized escape character")
++              }
++              s = s[i+1:]
++              if _, err := w.WriteString(esc); err != nil {
++                      return err
++              }
++              i = strings.IndexAny(s, escapedChars)
++      }
++      _, err := w.WriteString(s)
++      return err
++}
++
++// EscapeString escapes special characters like "<" to become "&lt;". It
++// escapes only five such characters: <, >, &, ' and ".
++// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
++// always true.
++func EscapeString(s string) string {
++      if strings.IndexAny(s, escapedChars) == -1 {
++              return s
++      }
++      var buf bytes.Buffer
++      escape(&buf, s)
++      return buf.String()
++}
++
++// UnescapeString unescapes entities like "&lt;" to become "<". It unescapes a
++// larger range of entities than EscapeString escapes. For example, "&aacute;"
++// unescapes to "á", as does "&#225;" and "&xE1;".
++// UnescapeString(EscapeString(s)) == s always holds, but the converse isn't
++// always true.
++func UnescapeString(s string) string {
++      for _, c := range s {
++              if c == '&' {
++                      return string(unescape([]byte(s), false))
++              }
++      }
++      return s
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b405d4b4a778cc65f29d0a679a91352d618ee360
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,97 @@@
++// Copyright 2013 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import "testing"
++
++type unescapeTest struct {
++      // A short description of the test case.
++      desc string
++      // The HTML text.
++      html string
++      // The unescaped text.
++      unescaped string
++}
++
++var unescapeTests = []unescapeTest{
++      // Handle no entities.
++      {
++              "copy",
++              "A\ttext\nstring",
++              "A\ttext\nstring",
++      },
++      // Handle simple named entities.
++      {
++              "simple",
++              "&amp; &gt; &lt;",
++              "& > <",
++      },
++      // Handle hitting the end of the string.
++      {
++              "stringEnd",
++              "&amp &amp",
++              "& &",
++      },
++      // Handle entities with two codepoints.
++      {
++              "multiCodepoint",
++              "text &gesl; blah",
++              "text \u22db\ufe00 blah",
++      },
++      // Handle decimal numeric entities.
++      {
++              "decimalEntity",
++              "Delta = &#916; ",
++              "Delta = Δ ",
++      },
++      // Handle hexadecimal numeric entities.
++      {
++              "hexadecimalEntity",
++              "Lambda = &#x3bb; = &#X3Bb ",
++              "Lambda = λ = λ ",
++      },
++      // Handle numeric early termination.
++      {
++              "numericEnds",
++              "&# &#x &#128;43 &copy = &#169f = &#xa9",
++              "&# &#x €43 © = ©f = ©",
++      },
++      // Handle numeric ISO-8859-1 entity replacements.
++      {
++              "numericReplacements",
++              "Footnote&#x87;",
++              "Footnote‡",
++      },
++}
++
++func TestUnescape(t *testing.T) {
++      for _, tt := range unescapeTests {
++              unescaped := UnescapeString(tt.html)
++              if unescaped != tt.unescaped {
++                      t.Errorf("TestUnescape %s: want %q, got %q", tt.desc, tt.unescaped, unescaped)
++              }
++      }
++}
++
++func TestUnescapeEscape(t *testing.T) {
++      ss := []string{
++              ``,
++              `abc def`,
++              `a & b`,
++              `a&amp;b`,
++              `a &amp b`,
++              `&quot;`,
++              `"`,
++              `"<&>"`,
++              `&quot;&lt;&amp;&gt;&quot;`,
++              `3&5==1 && 0<1, "0&lt;1", a+acute=&aacute;`,
++              `The special characters are: <, >, &, ' and "`,
++      }
++      for _, s := range ss {
++              if got := UnescapeString(EscapeString(s)); got != s {
++                      t.Errorf("got %q want %q", got, s)
++              }
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ebdd168a232c0b3352d5ce7c2bf1e63017f8c2b6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,40 @@@
++// Copyright 2012 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++// This example demonstrates parsing HTML data and walking the resulting tree.
++package html_test
++
++import (
++      "fmt"
++      "log"
++      "strings"
++
++      "git.earlybird.gay/today-engine/internal/html"
++)
++
++func ExampleParse() {
++      s := `<p>Links:</p><ul><li><a href="foo">Foo</a><li><a href="/bar/baz">BarBaz</a></ul>`
++      doc, err := html.Parse(strings.NewReader(s))
++      if err != nil {
++              log.Fatal(err)
++      }
++      var f func(*html.Node)
++      f = func(n *html.Node) {
++              if n.Type == html.ElementNode && n.Data == "a" {
++                      for _, a := range n.Attr {
++                              if a.Key == "href" {
++                                      fmt.Println(a.Val)
++                                      break
++                              }
++                      }
++              }
++              for c := n.FirstChild; c != nil; c = c.NextSibling {
++                      f(c)
++              }
++      }
++      f(doc)
++      // Output:
++      // foo
++      // /bar/baz
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9da9e9dc4246323836f27dca93d039732e88bd7d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,222 @@@
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "strings"
++)
++
++func adjustAttributeNames(aa []Attribute, nameMap map[string]string) {
++      for i := range aa {
++              if newName, ok := nameMap[aa[i].Key]; ok {
++                      aa[i].Key = newName
++              }
++      }
++}
++
++func adjustForeignAttributes(aa []Attribute) {
++      for i, a := range aa {
++              if a.Key == "" || a.Key[0] != 'x' {
++                      continue
++              }
++              switch a.Key {
++              case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
++                      "xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
++                      j := strings.Index(a.Key, ":")
++                      aa[i].Namespace = a.Key[:j]
++                      aa[i].Key = a.Key[j+1:]
++              }
++      }
++}
++
++func htmlIntegrationPoint(n *Node) bool {
++      if n.Type != ElementNode {
++              return false
++      }
++      switch n.Namespace {
++      case "math":
++              if n.Data == "annotation-xml" {
++                      for _, a := range n.Attr {
++                              if a.Key == "encoding" {
++                                      val := strings.ToLower(a.Val)
++                                      if val == "text/html" || val == "application/xhtml+xml" {
++                                              return true
++                                      }
++                              }
++                      }
++              }
++      case "svg":
++              switch n.Data {
++              case "desc", "foreignObject", "title":
++                      return true
++              }
++      }
++      return false
++}
++
++func mathMLTextIntegrationPoint(n *Node) bool {
++      if n.Namespace != "math" {
++              return false
++      }
++      switch n.Data {
++      case "mi", "mo", "mn", "ms", "mtext":
++              return true
++      }
++      return false
++}
++
++// Section 12.2.6.5.
++var breakout = map[string]bool{
++      "b":          true,
++      "big":        true,
++      "blockquote": true,
++      "body":       true,
++      "br":         true,
++      "center":     true,
++      "code":       true,
++      "dd":         true,
++      "div":        true,
++      "dl":         true,
++      "dt":         true,
++      "em":         true,
++      "embed":      true,
++      "h1":         true,
++      "h2":         true,
++      "h3":         true,
++      "h4":         true,
++      "h5":         true,
++      "h6":         true,
++      "head":       true,
++      "hr":         true,
++      "i":          true,
++      "img":        true,
++      "li":         true,
++      "listing":    true,
++      "menu":       true,
++      "meta":       true,
++      "nobr":       true,
++      "ol":         true,
++      "p":          true,
++      "pre":        true,
++      "ruby":       true,
++      "s":          true,
++      "small":      true,
++      "span":       true,
++      "strong":     true,
++      "strike":     true,
++      "sub":        true,
++      "sup":        true,
++      "table":      true,
++      "tt":         true,
++      "u":          true,
++      "ul":         true,
++      "var":        true,
++}
++
++// Section 12.2.6.5.
++var svgTagNameAdjustments = map[string]string{
++      "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",
++}
++
++// Section 12.2.6.1
++var mathMLAttributeAdjustments = map[string]string{
++      "definitionurl": "definitionURL",
++}
++
++var svgAttributeAdjustments = map[string]string{
++      "attributename":       "attributeName",
++      "attributetype":       "attributeType",
++      "basefrequency":       "baseFrequency",
++      "baseprofile":         "baseProfile",
++      "calcmode":            "calcMode",
++      "clippathunits":       "clipPathUnits",
++      "diffuseconstant":     "diffuseConstant",
++      "edgemode":            "edgeMode",
++      "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",
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bb1624b7ccfed4bde882320b2c96f33b4c6956b2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,225 @@@
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "git.earlybird.gay/today-engine/internal/html/atom"
++)
++
++// A NodeType is the type of a Node.
++type NodeType uint32
++
++const (
++      ErrorNode NodeType = iota
++      TextNode
++      DocumentNode
++      ElementNode
++      CommentNode
++      DoctypeNode
++      // RawNode nodes are not returned by the parser, but can be part of the
++      // Node tree passed to func Render to insert raw HTML (without escaping).
++      // If so, this package makes no guarantee that the rendered HTML is secure
++      // (from e.g. Cross Site Scripting attacks) or well-formed.
++      RawNode
++      scopeMarkerNode
++)
++
++// Section 12.2.4.3 says "The markers are inserted when entering applet,
++// object, marquee, template, td, th, and caption elements, and are used
++// to prevent formatting from "leaking" into applet, object, marquee,
++// template, td, th, and caption elements".
++var scopeMarker = Node{Type: scopeMarkerNode}
++
++// A Node consists of a NodeType and some Data (tag name for element nodes,
++// content for text) and are part of a tree of Nodes. Element nodes may also
++// have a Namespace and contain a slice of Attributes. Data is unescaped, so
++// that it looks like "a<b" rather than "a&lt;b". For element nodes, DataAtom
++// is the atom for Data, or zero if Data is not a known tag name.
++//
++// An empty Namespace implies a "http://www.w3.org/1999/xhtml" namespace.
++// Similarly, "math" is short for "http://www.w3.org/1998/Math/MathML", and
++// "svg" is short for "http://www.w3.org/2000/svg".
++type Node struct {
++      Parent, FirstChild, LastChild, PrevSibling, NextSibling *Node
++
++      Type      NodeType
++      DataAtom  atom.Atom
++      Data      string
++      Namespace string
++      Attr      []Attribute
++}
++
++// InsertBefore inserts newChild as a child of n, immediately before oldChild
++// in the sequence of n's children. oldChild may be nil, in which case newChild
++// is appended to the end of n's children.
++//
++// It will panic if newChild already has a parent or siblings.
++func (n *Node) InsertBefore(newChild, oldChild *Node) {
++      if newChild.Parent != nil || newChild.PrevSibling != nil || newChild.NextSibling != nil {
++              panic("html: InsertBefore called for an attached child Node")
++      }
++      var prev, next *Node
++      if oldChild != nil {
++              prev, next = oldChild.PrevSibling, oldChild
++      } else {
++              prev = n.LastChild
++      }
++      if prev != nil {
++              prev.NextSibling = newChild
++      } else {
++              n.FirstChild = newChild
++      }
++      if next != nil {
++              next.PrevSibling = newChild
++      } else {
++              n.LastChild = newChild
++      }
++      newChild.Parent = n
++      newChild.PrevSibling = prev
++      newChild.NextSibling = next
++}
++
++// AppendChild adds a node c as a child of n.
++//
++// It will panic if c already has a parent or siblings.
++func (n *Node) AppendChild(c *Node) {
++      if c.Parent != nil || c.PrevSibling != nil || c.NextSibling != nil {
++              panic("html: AppendChild called for an attached child Node")
++      }
++      last := n.LastChild
++      if last != nil {
++              last.NextSibling = c
++      } else {
++              n.FirstChild = c
++      }
++      n.LastChild = c
++      c.Parent = n
++      c.PrevSibling = last
++}
++
++// RemoveChild removes a node c that is a child of n. Afterwards, c will have
++// no parent and no siblings.
++//
++// It will panic if c's parent is not n.
++func (n *Node) RemoveChild(c *Node) {
++      if c.Parent != n {
++              panic("html: RemoveChild called for a non-child Node")
++      }
++      if n.FirstChild == c {
++              n.FirstChild = c.NextSibling
++      }
++      if c.NextSibling != nil {
++              c.NextSibling.PrevSibling = c.PrevSibling
++      }
++      if n.LastChild == c {
++              n.LastChild = c.PrevSibling
++      }
++      if c.PrevSibling != nil {
++              c.PrevSibling.NextSibling = c.NextSibling
++      }
++      c.Parent = nil
++      c.PrevSibling = nil
++      c.NextSibling = nil
++}
++
++// reparentChildren reparents all of src's child nodes to dst.
++func reparentChildren(dst, src *Node) {
++      for {
++              child := src.FirstChild
++              if child == nil {
++                      break
++              }
++              src.RemoveChild(child)
++              dst.AppendChild(child)
++      }
++}
++
++// clone returns a new node with the same type, data and attributes.
++// The clone has no parent, no siblings and no children.
++func (n *Node) clone() *Node {
++      m := &Node{
++              Type:     n.Type,
++              DataAtom: n.DataAtom,
++              Data:     n.Data,
++              Attr:     make([]Attribute, len(n.Attr)),
++      }
++      copy(m.Attr, n.Attr)
++      return m
++}
++
++// nodeStack is a stack of nodes.
++type nodeStack []*Node
++
++// pop pops the stack. It will panic if s is empty.
++func (s *nodeStack) pop() *Node {
++      i := len(*s)
++      n := (*s)[i-1]
++      *s = (*s)[:i-1]
++      return n
++}
++
++// top returns the most recently pushed node, or nil if s is empty.
++func (s *nodeStack) top() *Node {
++      if i := len(*s); i > 0 {
++              return (*s)[i-1]
++      }
++      return nil
++}
++
++// index returns the index of the top-most occurrence of n in the stack, or -1
++// if n is not present.
++func (s *nodeStack) index(n *Node) int {
++      for i := len(*s) - 1; i >= 0; i-- {
++              if (*s)[i] == n {
++                      return i
++              }
++      }
++      return -1
++}
++
++// contains returns whether a is within s.
++func (s *nodeStack) contains(a atom.Atom) bool {
++      for _, n := range *s {
++              if n.DataAtom == a && n.Namespace == "" {
++                      return true
++              }
++      }
++      return false
++}
++
++// insert inserts a node at the given index.
++func (s *nodeStack) insert(i int, n *Node) {
++      (*s) = append(*s, nil)
++      copy((*s)[i+1:], (*s)[i:])
++      (*s)[i] = n
++}
++
++// remove removes a node from the stack. It is a no-op if n is not present.
++func (s *nodeStack) remove(n *Node) {
++      i := s.index(n)
++      if i == -1 {
++              return
++      }
++      copy((*s)[i:], (*s)[i+1:])
++      j := len(*s) - 1
++      (*s)[j] = nil
++      *s = (*s)[:j]
++}
++
++type insertionModeStack []insertionMode
++
++func (s *insertionModeStack) pop() (im insertionMode) {
++      i := len(*s)
++      im = (*s)[i-1]
++      *s = (*s)[:i-1]
++      return im
++}
++
++func (s *insertionModeStack) top() insertionMode {
++      if i := len(*s); i > 0 {
++              return (*s)[i-1]
++      }
++      return nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..471102f3a2218e2d19c882fbc94e0c7d7b1fb046
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,146 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "fmt"
++)
++
++// checkTreeConsistency checks that a node and its descendants are all
++// consistent in their parent/child/sibling relationships.
++func checkTreeConsistency(n *Node) error {
++      return checkTreeConsistency1(n, 0)
++}
++
++func checkTreeConsistency1(n *Node, depth int) error {
++      if depth == 1e4 {
++              return fmt.Errorf("html: tree looks like it contains a cycle")
++      }
++      if err := checkNodeConsistency(n); err != nil {
++              return err
++      }
++      for c := n.FirstChild; c != nil; c = c.NextSibling {
++              if err := checkTreeConsistency1(c, depth+1); err != nil {
++                      return err
++              }
++      }
++      return nil
++}
++
++// checkNodeConsistency checks that a node's parent/child/sibling relationships
++// are consistent.
++func checkNodeConsistency(n *Node) error {
++      if n == nil {
++              return nil
++      }
++
++      nParent := 0
++      for p := n.Parent; p != nil; p = p.Parent {
++              nParent++
++              if nParent == 1e4 {
++                      return fmt.Errorf("html: parent list looks like an infinite loop")
++              }
++      }
++
++      nForward := 0
++      for c := n.FirstChild; c != nil; c = c.NextSibling {
++              nForward++
++              if nForward == 1e6 {
++                      return fmt.Errorf("html: forward list of children looks like an infinite loop")
++              }
++              if c.Parent != n {
++                      return fmt.Errorf("html: inconsistent child/parent relationship")
++              }
++      }
++
++      nBackward := 0
++      for c := n.LastChild; c != nil; c = c.PrevSibling {
++              nBackward++
++              if nBackward == 1e6 {
++                      return fmt.Errorf("html: backward list of children looks like an infinite loop")
++              }
++              if c.Parent != n {
++                      return fmt.Errorf("html: inconsistent child/parent relationship")
++              }
++      }
++
++      if n.Parent != nil {
++              if n.Parent == n {
++                      return fmt.Errorf("html: inconsistent parent relationship")
++              }
++              if n.Parent == n.FirstChild {
++                      return fmt.Errorf("html: inconsistent parent/first relationship")
++              }
++              if n.Parent == n.LastChild {
++                      return fmt.Errorf("html: inconsistent parent/last relationship")
++              }
++              if n.Parent == n.PrevSibling {
++                      return fmt.Errorf("html: inconsistent parent/prev relationship")
++              }
++              if n.Parent == n.NextSibling {
++                      return fmt.Errorf("html: inconsistent parent/next relationship")
++              }
++
++              parentHasNAsAChild := false
++              for c := n.Parent.FirstChild; c != nil; c = c.NextSibling {
++                      if c == n {
++                              parentHasNAsAChild = true
++                              break
++                      }
++              }
++              if !parentHasNAsAChild {
++                      return fmt.Errorf("html: inconsistent parent/child relationship")
++              }
++      }
++
++      if n.PrevSibling != nil && n.PrevSibling.NextSibling != n {
++              return fmt.Errorf("html: inconsistent prev/next relationship")
++      }
++      if n.NextSibling != nil && n.NextSibling.PrevSibling != n {
++              return fmt.Errorf("html: inconsistent next/prev relationship")
++      }
++
++      if (n.FirstChild == nil) != (n.LastChild == nil) {
++              return fmt.Errorf("html: inconsistent first/last relationship")
++      }
++      if n.FirstChild != nil && n.FirstChild == n.LastChild {
++              // We have a sole child.
++              if n.FirstChild.PrevSibling != nil || n.FirstChild.NextSibling != nil {
++                      return fmt.Errorf("html: inconsistent sole child's sibling relationship")
++              }
++      }
++
++      seen := map[*Node]bool{}
++
++      var last *Node
++      for c := n.FirstChild; c != nil; c = c.NextSibling {
++              if seen[c] {
++                      return fmt.Errorf("html: inconsistent repeated child")
++              }
++              seen[c] = true
++              last = c
++      }
++      if last != n.LastChild {
++              return fmt.Errorf("html: inconsistent last relationship")
++      }
++
++      var first *Node
++      for c := n.LastChild; c != nil; c = c.PrevSibling {
++              if !seen[c] {
++                      return fmt.Errorf("html: inconsistent missing child")
++              }
++              delete(seen, c)
++              first = c
++      }
++      if first != n.FirstChild {
++              return fmt.Errorf("html: inconsistent first relationship")
++      }
++
++      if len(seen) != 0 {
++              return fmt.Errorf("html: inconsistent forwards/backwards child list")
++      }
++
++      return nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8c1131b78f432650e6b6adfdd1d132bcc052cdc5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2454 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "errors"
++      "fmt"
++      "io"
++      "strings"
++
++      a "git.earlybird.gay/today-engine/internal/html/atom"
++)
++
++// A parser implements the HTML5 parsing algorithm:
++// https://html.spec.whatwg.org/multipage/syntax.html#tree-construction
++type parser struct {
++      // tokenizer provides the tokens for the parser.
++      tokenizer *Tokenizer
++      // tok is the most recently read token.
++      tok Token
++      // Self-closing tags like <hr/> are treated as start tags, except that
++      // hasSelfClosingToken is set while they are being processed.
++      hasSelfClosingToken bool
++      // doc is the document root element.
++      doc *Node
++      // The stack of open elements (section 12.2.4.2) and active formatting
++      // elements (section 12.2.4.3).
++      oe, afe nodeStack
++      // Element pointers (section 12.2.4.4).
++      head, form *Node
++      // Other parsing state flags (section 12.2.4.5).
++      scripting, framesetOK bool
++      // The stack of template insertion modes
++      templateStack insertionModeStack
++      // im is the current insertion mode.
++      im insertionMode
++      // originalIM is the insertion mode to go back to after completing a text
++      // or inTableText insertion mode.
++      originalIM insertionMode
++      // fosterParenting is whether new elements should be inserted according to
++      // the foster parenting rules (section 12.2.6.1).
++      fosterParenting bool
++      // quirks is whether the parser is operating in "quirks mode."
++      quirks bool
++      // fragment is whether the parser is parsing an HTML fragment.
++      fragment bool
++      // context is the context element when parsing an HTML fragment
++      // (section 12.4).
++      context *Node
++}
++
++func (p *parser) top() *Node {
++      if n := p.oe.top(); n != nil {
++              return n
++      }
++      return p.doc
++}
++
++// Stop tags for use in popUntil. These come from section 12.2.4.2.
++var (
++      defaultScopeStopTags = map[string][]a.Atom{
++              "":     {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
++              "math": {a.AnnotationXml, a.Mi, a.Mn, a.Mo, a.Ms, a.Mtext},
++              "svg":  {a.Desc, a.ForeignObject, a.Title},
++      }
++)
++
++type scope int
++
++const (
++      defaultScope scope = iota
++      listItemScope
++      buttonScope
++      tableScope
++      tableRowScope
++      tableBodyScope
++      selectScope
++)
++
++// popUntil pops the stack of open elements at the highest element whose tag
++// is in matchTags, provided there is no higher element in the scope's stop
++// tags (as defined in section 12.2.4.2). It returns whether or not there was
++// such an element. If there was not, popUntil leaves the stack unchanged.
++//
++// For example, the set of stop tags for table scope is: "html", "table". If
++// the stack was:
++// ["html", "body", "font", "table", "b", "i", "u"]
++// then popUntil(tableScope, "font") would return false, but
++// popUntil(tableScope, "i") would return true and the stack would become:
++// ["html", "body", "font", "table", "b"]
++//
++// If an element's tag is in both the stop tags and matchTags, then the stack
++// will be popped and the function returns true (provided, of course, there was
++// no higher element in the stack that was also in the stop tags). For example,
++// popUntil(tableScope, "table") returns true and leaves:
++// ["html", "body", "font"]
++func (p *parser) popUntil(s scope, matchTags ...a.Atom) bool {
++      if i := p.indexOfElementInScope(s, matchTags...); i != -1 {
++              p.oe = p.oe[:i]
++              return true
++      }
++      return false
++}
++
++// indexOfElementInScope returns the index in p.oe of the highest element whose
++// tag is in matchTags that is in scope. If no matching element is in scope, it
++// returns -1.
++func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
++      for i := len(p.oe) - 1; i >= 0; i-- {
++              tagAtom := p.oe[i].DataAtom
++              if p.oe[i].Namespace == "" {
++                      for _, t := range matchTags {
++                              if t == tagAtom {
++                                      return i
++                              }
++                      }
++                      switch s {
++                      case defaultScope:
++                              // No-op.
++                      case listItemScope:
++                              if tagAtom == a.Ol || tagAtom == a.Ul {
++                                      return -1
++                              }
++                      case buttonScope:
++                              if tagAtom == a.Button {
++                                      return -1
++                              }
++                      case tableScope:
++                              if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
++                                      return -1
++                              }
++                      case selectScope:
++                              if tagAtom != a.Optgroup && tagAtom != a.Option {
++                                      return -1
++                              }
++                      default:
++                              panic("unreachable")
++                      }
++              }
++              switch s {
++              case defaultScope, listItemScope, buttonScope:
++                      for _, t := range defaultScopeStopTags[p.oe[i].Namespace] {
++                              if t == tagAtom {
++                                      return -1
++                              }
++                      }
++              }
++      }
++      return -1
++}
++
++// elementInScope is like popUntil, except that it doesn't modify the stack of
++// open elements.
++func (p *parser) elementInScope(s scope, matchTags ...a.Atom) bool {
++      return p.indexOfElementInScope(s, matchTags...) != -1
++}
++
++// clearStackToContext pops elements off the stack of open elements until a
++// scope-defined element is found.
++func (p *parser) clearStackToContext(s scope) {
++      for i := len(p.oe) - 1; i >= 0; i-- {
++              tagAtom := p.oe[i].DataAtom
++              switch s {
++              case tableScope:
++                      if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
++                              p.oe = p.oe[:i+1]
++                              return
++                      }
++              case tableRowScope:
++                      if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template {
++                              p.oe = p.oe[:i+1]
++                              return
++                      }
++              case tableBodyScope:
++                      if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template {
++                              p.oe = p.oe[:i+1]
++                              return
++                      }
++              default:
++                      panic("unreachable")
++              }
++      }
++}
++
++// parseGenericRawTextElement implements the generic raw text element parsing
++// algorithm defined in 12.2.6.2.
++// https://html.spec.whatwg.org/multipage/parsing.html#parsing-elements-that-contain-only-text
++// TODO: Since both RAWTEXT and RCDATA states are treated as tokenizer's part
++// officially, need to make tokenizer consider both states.
++func (p *parser) parseGenericRawTextElement() {
++      p.addElement()
++      p.originalIM = p.im
++      p.im = textIM
++}
++
++// generateImpliedEndTags pops nodes off the stack of open elements as long as
++// the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc.
++// If exceptions are specified, nodes with that name will not be popped off.
++func (p *parser) generateImpliedEndTags(exceptions ...string) {
++      var i int
++loop:
++      for i = len(p.oe) - 1; i >= 0; i-- {
++              n := p.oe[i]
++              if n.Type != ElementNode {
++                      break
++              }
++              switch n.DataAtom {
++              case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc:
++                      for _, except := range exceptions {
++                              if n.Data == except {
++                                      break loop
++                              }
++                      }
++                      continue
++              }
++              break
++      }
++
++      p.oe = p.oe[:i+1]
++}
++
++// addChild adds a child node n to the top element, and pushes n onto the stack
++// of open elements if it is an element node.
++func (p *parser) addChild(n *Node) {
++      if p.shouldFosterParent() {
++              p.fosterParent(n)
++      } else {
++              p.top().AppendChild(n)
++      }
++
++      if n.Type == ElementNode {
++              p.oe = append(p.oe, n)
++      }
++}
++
++// shouldFosterParent returns whether the next node to be added should be
++// foster parented.
++func (p *parser) shouldFosterParent() bool {
++      return false
++}
++
++// fosterParent adds a child node according to the foster parenting rules.
++// Section 12.2.6.1, "foster parenting".
++func (p *parser) fosterParent(n *Node) {
++      var table, parent, prev, template *Node
++      var i int
++      for i = len(p.oe) - 1; i >= 0; i-- {
++              if p.oe[i].DataAtom == a.Table {
++                      table = p.oe[i]
++                      break
++              }
++      }
++
++      var j int
++      for j = len(p.oe) - 1; j >= 0; j-- {
++              if p.oe[j].DataAtom == a.Template {
++                      template = p.oe[j]
++                      break
++              }
++      }
++
++      if template != nil && (table == nil || j > i) {
++              template.AppendChild(n)
++              return
++      }
++
++      if table == nil {
++              // The foster parent is the html element.
++              parent = p.oe[0]
++      } else {
++              parent = table.Parent
++      }
++      if parent == nil {
++              parent = p.oe[i-1]
++      }
++
++      if table != nil {
++              prev = table.PrevSibling
++      } else {
++              prev = parent.LastChild
++      }
++      if prev != nil && prev.Type == TextNode && n.Type == TextNode {
++              prev.Data += n.Data
++              return
++      }
++
++      parent.InsertBefore(n, table)
++}
++
++// addText adds text to the preceding node if it is a text node, or else it
++// calls addChild with a new text node.
++func (p *parser) addText(text string) {
++      if text == "" {
++              return
++      }
++
++      if p.shouldFosterParent() {
++              p.fosterParent(&Node{
++                      Type: TextNode,
++                      Data: text,
++              })
++              return
++      }
++
++      t := p.top()
++      if n := t.LastChild; n != nil && n.Type == TextNode {
++              n.Data += text
++              return
++      }
++      p.addChild(&Node{
++              Type: TextNode,
++              Data: text,
++      })
++}
++
++// addElement adds a child element based on the current token.
++func (p *parser) addElement() {
++      p.addChild(&Node{
++              Type:     ElementNode,
++              DataAtom: p.tok.DataAtom,
++              Data:     p.tok.Data,
++              Attr:     p.tok.Attr,
++      })
++}
++
++// Section 12.2.4.3.
++func (p *parser) addFormattingElement() {
++      tagAtom, attr := p.tok.DataAtom, p.tok.Attr
++      p.addElement()
++
++      // Implement the Noah's Ark clause, but with three per family instead of two.
++      identicalElements := 0
++findIdenticalElements:
++      for i := len(p.afe) - 1; i >= 0; i-- {
++              n := p.afe[i]
++              if n.Type == scopeMarkerNode {
++                      break
++              }
++              if n.Type != ElementNode {
++                      continue
++              }
++              if n.Namespace != "" {
++                      continue
++              }
++              if n.DataAtom != tagAtom {
++                      continue
++              }
++              if len(n.Attr) != len(attr) {
++                      continue
++              }
++      compareAttributes:
++              for _, t0 := range n.Attr {
++                      for _, t1 := range attr {
++                              if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
++                                      // Found a match for this attribute, continue with the next attribute.
++                                      continue compareAttributes
++                              }
++                      }
++                      // If we get here, there is no attribute that matches a.
++                      // Therefore the element is not identical to the new one.
++                      continue findIdenticalElements
++              }
++
++              identicalElements++
++              if identicalElements >= 3 {
++                      p.afe.remove(n)
++              }
++      }
++
++      p.afe = append(p.afe, p.top())
++}
++
++// Section 12.2.4.3.
++func (p *parser) clearActiveFormattingElements() {
++      for {
++              if n := p.afe.pop(); len(p.afe) == 0 || n.Type == scopeMarkerNode {
++                      return
++              }
++      }
++}
++
++// Section 12.2.4.3.
++func (p *parser) reconstructActiveFormattingElements() {
++      n := p.afe.top()
++      if n == nil {
++              return
++      }
++      if n.Type == scopeMarkerNode || p.oe.index(n) != -1 {
++              return
++      }
++      i := len(p.afe) - 1
++      for n.Type != scopeMarkerNode && p.oe.index(n) == -1 {
++              if i == 0 {
++                      i = -1
++                      break
++              }
++              i--
++              n = p.afe[i]
++      }
++      for {
++              i++
++              clone := p.afe[i].clone()
++              p.addChild(clone)
++              p.afe[i] = clone
++              if i == len(p.afe)-1 {
++                      break
++              }
++      }
++}
++
++// Section 12.2.5.
++func (p *parser) acknowledgeSelfClosingTag() {
++      p.hasSelfClosingToken = false
++}
++
++// An insertion mode (section 12.2.4.1) is the state transition function from
++// a particular state in the HTML5 parser's state machine. It updates the
++// parser's fields depending on parser.tok (where ErrorToken means EOF).
++// It returns whether the token was consumed.
++type insertionMode func(*parser) bool
++
++// setOriginalIM sets the insertion mode to return to after completing a text or
++// inTableText insertion mode.
++// Section 12.2.4.1, "using the rules for".
++func (p *parser) setOriginalIM() {
++      if p.originalIM != nil {
++              panic("html: bad parser state: originalIM was set twice")
++      }
++      p.originalIM = p.im
++}
++
++// Section 12.2.4.1, "reset the insertion mode".
++func (p *parser) resetInsertionMode() {
++      for i := len(p.oe) - 1; i >= 0; i-- {
++              n := p.oe[i]
++              last := i == 0
++              if last && p.context != nil {
++                      n = p.context
++              }
++
++              switch n.DataAtom {
++              case a.Select:
++                      if !last {
++                              for ancestor, first := n, p.oe[0]; ancestor != first; {
++                                      ancestor = p.oe[p.oe.index(ancestor)-1]
++                                      switch ancestor.DataAtom {
++                                      case a.Template:
++                                              p.im = inSelectIM
++                                              return
++                                      case a.Table:
++                                              p.im = inSelectInTableIM
++                                              return
++                                      }
++                              }
++                      }
++                      p.im = inSelectIM
++              case a.Td, a.Th:
++                      // TODO: remove this divergence from the HTML5 spec.
++                      //
++                      // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
++                      p.im = inCellIM
++              case a.Tr:
++                      p.im = inRowIM
++              case a.Tbody, a.Thead, a.Tfoot:
++                      p.im = inTableBodyIM
++              case a.Caption:
++                      p.im = inCaptionIM
++              case a.Colgroup:
++                      p.im = inColumnGroupIM
++              case a.Table:
++                      p.im = inTableIM
++              case a.Template:
++                      // TODO: remove this divergence from the HTML5 spec.
++                      if n.Namespace != "" {
++                              continue
++                      }
++                      p.im = p.templateStack.top()
++              case a.Head:
++                      // TODO: remove this divergence from the HTML5 spec.
++                      //
++                      // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
++                      p.im = inHeadIM
++              case a.Body:
++                      p.im = inBodyIM
++              case a.Frameset:
++                      p.im = inFramesetIM
++              case a.Html:
++                      if p.head == nil {
++                              p.im = beforeHeadIM
++                      } else {
++                              p.im = afterHeadIM
++                      }
++              default:
++                      if last {
++                              p.im = inBodyIM
++                              return
++                      }
++                      continue
++              }
++              return
++      }
++}
++
++const whitespace = " \t\r\n\f"
++
++// Section 12.2.6.4.1.
++func initialIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
++              if len(p.tok.Data) == 0 {
++                      // It was all whitespace, so ignore it.
++                      return true
++              }
++      case CommentToken:
++              p.doc.AppendChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              n, quirks := parseDoctype(p.tok.Data)
++              p.doc.AppendChild(n)
++              p.quirks = quirks
++              p.im = beforeHTMLIM
++              return true
++      }
++      p.quirks = true
++      p.im = beforeHTMLIM
++      return false
++}
++
++// Section 12.2.6.4.2.
++func beforeHTMLIM(p *parser) bool {
++      switch p.tok.Type {
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      case TextToken:
++              p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
++              if len(p.tok.Data) == 0 {
++                      // It was all whitespace, so ignore it.
++                      return true
++              }
++      case StartTagToken:
++              if p.tok.DataAtom == a.Html {
++                      p.addElement()
++                      p.im = beforeHeadIM
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Head, a.Body, a.Html, a.Br:
++                      p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
++                      return false
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case CommentToken:
++              p.doc.AppendChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      }
++      p.parseImpliedToken(StartTagToken, a.Html, a.Html.String())
++      return false
++}
++
++// Section 12.2.6.4.3.
++func beforeHeadIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              p.tok.Data = strings.TrimLeft(p.tok.Data, whitespace)
++              if len(p.tok.Data) == 0 {
++                      // It was all whitespace, so ignore it.
++                      return true
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Head:
++                      p.addElement()
++                      p.head = p.top()
++                      p.im = inHeadIM
++                      return true
++              case a.Html:
++                      return inBodyIM(p)
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Head, a.Body, a.Html, a.Br:
++                      p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
++                      return false
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      }
++
++      p.parseImpliedToken(StartTagToken, a.Head, a.Head.String())
++      return false
++}
++
++// Section 12.2.6.4.4.
++func inHeadIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) < len(p.tok.Data) {
++                      // Add the initial whitespace to the current node.
++                      p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
++                      if s == "" {
++                              return true
++                      }
++                      p.tok.Data = s
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta:
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++                      return true
++              case a.Noscript:
++                      if p.scripting {
++                              p.parseGenericRawTextElement()
++                              return true
++                      }
++                      p.addElement()
++                      p.im = inHeadNoscriptIM
++                      // Don't let the tokenizer go into raw text mode when scripting is disabled.
++                      p.tokenizer.NextIsNotRawText()
++                      return true
++              case a.Script, a.Title:
++                      p.addElement()
++                      p.setOriginalIM()
++                      p.im = textIM
++                      return true
++              case a.Noframes, a.Style:
++                      p.parseGenericRawTextElement()
++                      return true
++              case a.Head:
++                      // Ignore the token.
++                      return true
++              case a.Template:
++                      // TODO: remove this divergence from the HTML5 spec.
++                      //
++                      // We don't handle all of the corner cases when mixing foreign
++                      // content (i.e. <math> or <svg>) with <template>. Without this
++                      // early return, we can get into an infinite loop, possibly because
++                      // of the "TODO... further divergence" a little below.
++                      //
++                      // As a workaround, if we are mixing foreign content and templates,
++                      // just ignore the rest of the HTML. Foreign content is rare and a
++                      // relatively old HTML feature. Templates are also rare and a
++                      // relatively new HTML feature. Their combination is very rare.
++                      for _, e := range p.oe {
++                              if e.Namespace != "" {
++                                      p.im = ignoreTheRemainingTokens
++                                      return true
++                              }
++                      }
++
++                      p.addElement()
++                      p.afe = append(p.afe, &scopeMarker)
++                      p.framesetOK = false
++                      p.im = inTemplateIM
++                      p.templateStack = append(p.templateStack, inTemplateIM)
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Head:
++                      p.oe.pop()
++                      p.im = afterHeadIM
++                      return true
++              case a.Body, a.Html, a.Br:
++                      p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
++                      return false
++              case a.Template:
++                      if !p.oe.contains(a.Template) {
++                              return true
++                      }
++                      // TODO: remove this further divergence from the HTML5 spec.
++                      //
++                      // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
++                      p.generateImpliedEndTags()
++                      for i := len(p.oe) - 1; i >= 0; i-- {
++                              if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
++                                      p.oe = p.oe[:i]
++                                      break
++                              }
++                      }
++                      p.clearActiveFormattingElements()
++                      p.templateStack.pop()
++                      p.resetInsertionMode()
++                      return true
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      }
++
++      p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
++      return false
++}
++
++// Section 12.2.6.4.5.
++func inHeadNoscriptIM(p *parser) bool {
++      switch p.tok.Type {
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Style:
++                      return inHeadIM(p)
++              case a.Head:
++                      // Ignore the token.
++                      return true
++              case a.Noscript:
++                      // Don't let the tokenizer go into raw text mode even when a <noscript>
++                      // tag is in "in head noscript" insertion mode.
++                      p.tokenizer.NextIsNotRawText()
++                      // Ignore the token.
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Noscript, a.Br:
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) == 0 {
++                      // It was all whitespace.
++                      return inHeadIM(p)
++              }
++      case CommentToken:
++              return inHeadIM(p)
++      }
++      p.oe.pop()
++      if p.top().DataAtom != a.Head {
++              panic("html: the new current node will be a head element.")
++      }
++      p.im = inHeadIM
++      if p.tok.DataAtom == a.Noscript {
++              return true
++      }
++      return false
++}
++
++// Section 12.2.6.4.6.
++func afterHeadIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) < len(p.tok.Data) {
++                      // Add the initial whitespace to the current node.
++                      p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
++                      if s == "" {
++                              return true
++                      }
++                      p.tok.Data = s
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Body:
++                      p.addElement()
++                      p.framesetOK = false
++                      p.im = inBodyIM
++                      return true
++              case a.Frameset:
++                      p.addElement()
++                      p.im = inFramesetIM
++                      return true
++              case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
++                      p.oe = append(p.oe, p.head)
++                      defer p.oe.remove(p.head)
++                      return inHeadIM(p)
++              case a.Head:
++                      // Ignore the token.
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Body, a.Html, a.Br:
++                      // Drop down to creating an implied <body> tag.
++              case a.Template:
++                      return inHeadIM(p)
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      }
++
++      p.parseImpliedToken(StartTagToken, a.Body, a.Body.String())
++      p.framesetOK = true
++      return false
++}
++
++// copyAttributes copies attributes of src not found on dst to dst.
++func copyAttributes(dst *Node, src Token) {
++      if len(src.Attr) == 0 {
++              return
++      }
++      attr := map[string]string{}
++      for _, t := range dst.Attr {
++              attr[t.Key] = t.Val
++      }
++      for _, t := range src.Attr {
++              if _, ok := attr[t.Key]; !ok {
++                      dst.Attr = append(dst.Attr, t)
++                      attr[t.Key] = t.Val
++              }
++      }
++}
++
++// Section 12.2.6.4.7.
++func inBodyIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              d := p.tok.Data
++              switch n := p.oe.top(); n.DataAtom {
++              case a.Pre, a.Listing:
++                      if n.FirstChild == nil {
++                              // Ignore a newline at the start of a <pre> block.
++                              if d != "" && d[0] == '\r' {
++                                      d = d[1:]
++                              }
++                              if d != "" && d[0] == '\n' {
++                                      d = d[1:]
++                              }
++                      }
++              }
++              d = strings.Replace(d, "\x00", "", -1)
++              if d == "" {
++                      return true
++              }
++              p.reconstructActiveFormattingElements()
++              p.addText(d)
++              if p.framesetOK && strings.TrimLeft(d, whitespace) != "" {
++                      // There were non-whitespace characters inserted.
++                      p.framesetOK = false
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      if p.oe.contains(a.Template) {
++                              return true
++                      }
++                      copyAttributes(p.oe[0], p.tok)
++              case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
++                      return inHeadIM(p)
++              case a.Body:
++                      if p.oe.contains(a.Template) {
++                              return true
++                      }
++                      if len(p.oe) >= 2 {
++                              body := p.oe[1]
++                              if body.Type == ElementNode && body.DataAtom == a.Body {
++                                      p.framesetOK = false
++                                      copyAttributes(body, p.tok)
++                              }
++                      }
++              case a.Frameset:
++                      if !p.framesetOK || len(p.oe) < 2 || p.oe[1].DataAtom != a.Body {
++                              // Ignore the token.
++                              return true
++                      }
++                      body := p.oe[1]
++                      if body.Parent != nil {
++                              body.Parent.RemoveChild(body)
++                      }
++                      p.oe = p.oe[:1]
++                      p.addElement()
++                      p.im = inFramesetIM
++                      return true
++              case a.Address, a.Article, a.Aside, a.Blockquote, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Main, a.Menu, a.Nav, a.Ol, a.P, a.Section, a.Summary, a.Ul:
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++              case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
++                      p.popUntil(buttonScope, a.P)
++                      switch n := p.top(); n.DataAtom {
++                      case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
++                              p.oe.pop()
++                      }
++                      p.addElement()
++              case a.Pre, a.Listing:
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++                      // The newline, if any, will be dealt with by the TextToken case.
++                      p.framesetOK = false
++              case a.Form:
++                      if p.form != nil && !p.oe.contains(a.Template) {
++                              // Ignore the token
++                              return true
++                      }
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++                      if !p.oe.contains(a.Template) {
++                              p.form = p.top()
++                      }
++              case a.Li:
++                      p.framesetOK = false
++                      for i := len(p.oe) - 1; i >= 0; i-- {
++                              node := p.oe[i]
++                              switch node.DataAtom {
++                              case a.Li:
++                                      p.oe = p.oe[:i]
++                              case a.Address, a.Div, a.P:
++                                      continue
++                              default:
++                                      if !isSpecialElement(node) {
++                                              continue
++                                      }
++                              }
++                              break
++                      }
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++              case a.Dd, a.Dt:
++                      p.framesetOK = false
++                      for i := len(p.oe) - 1; i >= 0; i-- {
++                              node := p.oe[i]
++                              switch node.DataAtom {
++                              case a.Dd, a.Dt:
++                                      p.oe = p.oe[:i]
++                              case a.Address, a.Div, a.P:
++                                      continue
++                              default:
++                                      if !isSpecialElement(node) {
++                                              continue
++                                      }
++                              }
++                              break
++                      }
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++              case a.Plaintext:
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++              case a.Button:
++                      p.popUntil(defaultScope, a.Button)
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.framesetOK = false
++              case a.A:
++                      for i := len(p.afe) - 1; i >= 0 && p.afe[i].Type != scopeMarkerNode; i-- {
++                              if n := p.afe[i]; n.Type == ElementNode && n.DataAtom == a.A {
++                                      p.inBodyEndTagFormatting(a.A, "a")
++                                      p.oe.remove(n)
++                                      p.afe.remove(n)
++                                      break
++                              }
++                      }
++                      p.reconstructActiveFormattingElements()
++                      p.addFormattingElement()
++              case a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
++                      p.reconstructActiveFormattingElements()
++                      p.addFormattingElement()
++              case a.Nobr:
++                      p.reconstructActiveFormattingElements()
++                      if p.elementInScope(defaultScope, a.Nobr) {
++                              p.inBodyEndTagFormatting(a.Nobr, "nobr")
++                              p.reconstructActiveFormattingElements()
++                      }
++                      p.addFormattingElement()
++              case a.Applet, a.Marquee, a.Object:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.afe = append(p.afe, &scopeMarker)
++                      p.framesetOK = false
++              case a.Table:
++                      if !p.quirks {
++                              p.popUntil(buttonScope, a.P)
++                      }
++                      p.addElement()
++                      p.framesetOK = false
++                      p.im = inTableIM
++                      return true
++              case a.Area, a.Br, a.Embed, a.Img, a.Input, a.Keygen, a.Wbr:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++                      if p.tok.DataAtom == a.Input {
++                              for _, t := range p.tok.Attr {
++                                      if t.Key == "type" {
++                                              if strings.ToLower(t.Val) == "hidden" {
++                                                      // Skip setting framesetOK = false
++                                                      return true
++                                              }
++                                      }
++                              }
++                      }
++                      p.framesetOK = false
++              case a.Param, a.Source, a.Track:
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++              case a.Hr:
++                      p.popUntil(buttonScope, a.P)
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++                      p.framesetOK = false
++              case a.Image:
++                      p.tok.DataAtom = a.Img
++                      p.tok.Data = a.Img.String()
++                      return false
++              case a.Textarea:
++                      p.addElement()
++                      p.setOriginalIM()
++                      p.framesetOK = false
++                      p.im = textIM
++              case a.Xmp:
++                      p.popUntil(buttonScope, a.P)
++                      p.reconstructActiveFormattingElements()
++                      p.framesetOK = false
++                      p.parseGenericRawTextElement()
++              case a.Iframe:
++                      p.framesetOK = false
++                      p.parseGenericRawTextElement()
++              case a.Noembed:
++                      p.parseGenericRawTextElement()
++              case a.Noscript:
++                      if p.scripting {
++                              p.parseGenericRawTextElement()
++                              return true
++                      }
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      // Don't let the tokenizer go into raw text mode when scripting is disabled.
++                      p.tokenizer.NextIsNotRawText()
++              case a.Select:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.framesetOK = false
++                      p.im = inSelectIM
++                      return true
++              case a.Optgroup, a.Option:
++                      if p.top().DataAtom == a.Option {
++                              p.oe.pop()
++                      }
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++              case a.Rb, a.Rtc:
++                      if p.elementInScope(defaultScope, a.Ruby) {
++                              p.generateImpliedEndTags()
++                      }
++                      p.addElement()
++              case a.Rp, a.Rt:
++                      if p.elementInScope(defaultScope, a.Ruby) {
++                              p.generateImpliedEndTags("rtc")
++                      }
++                      p.addElement()
++              case a.Math, a.Svg:
++                      p.reconstructActiveFormattingElements()
++                      if p.tok.DataAtom == a.Math {
++                              adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
++                      } else {
++                              adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
++                      }
++                      adjustForeignAttributes(p.tok.Attr)
++                      p.addElement()
++                      p.top().Namespace = p.tok.Data
++                      if p.hasSelfClosingToken {
++                              p.oe.pop()
++                              p.acknowledgeSelfClosingTag()
++                      }
++                      return true
++              case a.Caption, a.Col, a.Colgroup, a.Frame, a.Head, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
++                      // Ignore the token.
++              default:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Body:
++                      if p.elementInScope(defaultScope, a.Body) {
++                              p.im = afterBodyIM
++                      }
++              case a.Html:
++                      if p.elementInScope(defaultScope, a.Body) {
++                              p.parseImpliedToken(EndTagToken, a.Body, a.Body.String())
++                              return false
++                      }
++                      return true
++              case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dialog, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Main, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
++                      p.popUntil(defaultScope, p.tok.DataAtom)
++              case a.Form:
++                      if p.oe.contains(a.Template) {
++                              i := p.indexOfElementInScope(defaultScope, a.Form)
++                              if i == -1 {
++                                      // Ignore the token.
++                                      return true
++                              }
++                              p.generateImpliedEndTags()
++                              if p.oe[i].DataAtom != a.Form {
++                                      // Ignore the token.
++                                      return true
++                              }
++                              p.popUntil(defaultScope, a.Form)
++                      } else {
++                              node := p.form
++                              p.form = nil
++                              i := p.indexOfElementInScope(defaultScope, a.Form)
++                              if node == nil || i == -1 || p.oe[i] != node {
++                                      // Ignore the token.
++                                      return true
++                              }
++                              p.generateImpliedEndTags()
++                              p.oe.remove(node)
++                      }
++              case a.P:
++                      if !p.elementInScope(buttonScope, a.P) {
++                              p.parseImpliedToken(StartTagToken, a.P, a.P.String())
++                      }
++                      p.popUntil(buttonScope, a.P)
++              case a.Li:
++                      p.popUntil(listItemScope, a.Li)
++              case a.Dd, a.Dt:
++                      p.popUntil(defaultScope, p.tok.DataAtom)
++              case a.H1, a.H2, a.H3, a.H4, a.H5, a.H6:
++                      p.popUntil(defaultScope, a.H1, a.H2, a.H3, a.H4, a.H5, a.H6)
++              case a.A, a.B, a.Big, a.Code, a.Em, a.Font, a.I, a.Nobr, a.S, a.Small, a.Strike, a.Strong, a.Tt, a.U:
++                      p.inBodyEndTagFormatting(p.tok.DataAtom, p.tok.Data)
++              case a.Applet, a.Marquee, a.Object:
++                      if p.popUntil(defaultScope, p.tok.DataAtom) {
++                              p.clearActiveFormattingElements()
++                      }
++              case a.Br:
++                      p.tok.Type = StartTagToken
++                      return false
++              case a.Template:
++                      return inHeadIM(p)
++              default:
++                      p.inBodyEndTagOther(p.tok.DataAtom, p.tok.Data)
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case ErrorToken:
++              // TODO: remove this divergence from the HTML5 spec.
++              if len(p.templateStack) > 0 {
++                      p.im = inTemplateIM
++                      return false
++              }
++              for _, e := range p.oe {
++                      switch e.DataAtom {
++                      case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th,
++                              a.Thead, a.Tr, a.Body, a.Html:
++                      default:
++                              return true
++                      }
++              }
++      }
++
++      return true
++}
++
++func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
++      // This is the "adoption agency" algorithm, described at
++      // https://html.spec.whatwg.org/multipage/syntax.html#adoptionAgency
++
++      // TODO: this is a fairly literal line-by-line translation of that algorithm.
++      // Once the code successfully parses the comprehensive test suite, we should
++      // refactor this code to be more idiomatic.
++
++      // Steps 1-2
++      if current := p.oe.top(); current.Data == tagName && p.afe.index(current) == -1 {
++              p.oe.pop()
++              return
++      }
++
++      // Steps 3-5. The outer loop.
++      for i := 0; i < 8; i++ {
++              // Step 6. Find the formatting element.
++              var formattingElement *Node
++              for j := len(p.afe) - 1; j >= 0; j-- {
++                      if p.afe[j].Type == scopeMarkerNode {
++                              break
++                      }
++                      if p.afe[j].DataAtom == tagAtom {
++                              formattingElement = p.afe[j]
++                              break
++                      }
++              }
++              if formattingElement == nil {
++                      p.inBodyEndTagOther(tagAtom, tagName)
++                      return
++              }
++
++              // Step 7. Ignore the tag if formatting element is not in the stack of open elements.
++              feIndex := p.oe.index(formattingElement)
++              if feIndex == -1 {
++                      p.afe.remove(formattingElement)
++                      return
++              }
++              // Step 8. Ignore the tag if formatting element is not in the scope.
++              if !p.elementInScope(defaultScope, tagAtom) {
++                      // Ignore the tag.
++                      return
++              }
++
++              // Step 9. This step is omitted because it's just a parse error but no need to return.
++
++              // Steps 10-11. Find the furthest block.
++              var furthestBlock *Node
++              for _, e := range p.oe[feIndex:] {
++                      if isSpecialElement(e) {
++                              furthestBlock = e
++                              break
++                      }
++              }
++              if furthestBlock == nil {
++                      e := p.oe.pop()
++                      for e != formattingElement {
++                              e = p.oe.pop()
++                      }
++                      p.afe.remove(e)
++                      return
++              }
++
++              // Steps 12-13. Find the common ancestor and bookmark node.
++              commonAncestor := p.oe[feIndex-1]
++              bookmark := p.afe.index(formattingElement)
++
++              // Step 14. The inner loop. Find the lastNode to reparent.
++              lastNode := furthestBlock
++              node := furthestBlock
++              x := p.oe.index(node)
++              // Step 14.1.
++              j := 0
++              for {
++                      // Step 14.2.
++                      j++
++                      // Step. 14.3.
++                      x--
++                      node = p.oe[x]
++                      // Step 14.4. Go to the next step if node is formatting element.
++                      if node == formattingElement {
++                              break
++                      }
++                      // Step 14.5. Remove node from the list of active formatting elements if
++                      // inner loop counter is greater than three and node is in the list of
++                      // active formatting elements.
++                      if ni := p.afe.index(node); j > 3 && ni > -1 {
++                              p.afe.remove(node)
++                              // If any element of the list of active formatting elements is removed,
++                              // we need to take care whether bookmark should be decremented or not.
++                              // This is because the value of bookmark may exceed the size of the
++                              // list by removing elements from the list.
++                              if ni <= bookmark {
++                                      bookmark--
++                              }
++                              continue
++                      }
++                      // Step 14.6. Continue the next inner loop if node is not in the list of
++                      // active formatting elements.
++                      if p.afe.index(node) == -1 {
++                              p.oe.remove(node)
++                              continue
++                      }
++                      // Step 14.7.
++                      clone := node.clone()
++                      p.afe[p.afe.index(node)] = clone
++                      p.oe[p.oe.index(node)] = clone
++                      node = clone
++                      // Step 14.8.
++                      if lastNode == furthestBlock {
++                              bookmark = p.afe.index(node) + 1
++                      }
++                      // Step 14.9.
++                      if lastNode.Parent != nil {
++                              lastNode.Parent.RemoveChild(lastNode)
++                      }
++                      node.AppendChild(lastNode)
++                      // Step 14.10.
++                      lastNode = node
++              }
++
++              // Step 15. Reparent lastNode to the common ancestor,
++              // or for misnested table nodes, to the foster parent.
++              if lastNode.Parent != nil {
++                      lastNode.Parent.RemoveChild(lastNode)
++              }
++              switch commonAncestor.DataAtom {
++              case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
++                      p.fosterParent(lastNode)
++              default:
++                      commonAncestor.AppendChild(lastNode)
++              }
++
++              // Steps 16-18. Reparent nodes from the furthest block's children
++              // to a clone of the formatting element.
++              clone := formattingElement.clone()
++              reparentChildren(clone, furthestBlock)
++              furthestBlock.AppendChild(clone)
++
++              // Step 19. Fix up the list of active formatting elements.
++              if oldLoc := p.afe.index(formattingElement); oldLoc != -1 && oldLoc < bookmark {
++                      // Move the bookmark with the rest of the list.
++                      bookmark--
++              }
++              p.afe.remove(formattingElement)
++              p.afe.insert(bookmark, clone)
++
++              // Step 20. Fix up the stack of open elements.
++              p.oe.remove(formattingElement)
++              p.oe.insert(p.oe.index(furthestBlock)+1, clone)
++      }
++}
++
++// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
++// "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
++// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
++func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
++      for i := len(p.oe) - 1; i >= 0; i-- {
++              // Two element nodes have the same tag if they have the same Data (a
++              // string-typed field). As an optimization, for common HTML tags, each
++              // Data string is assigned a unique, non-zero DataAtom (a uint32-typed
++              // field), since integer comparison is faster than string comparison.
++              // Uncommon (custom) tags get a zero DataAtom.
++              //
++              // The if condition here is equivalent to (p.oe[i].Data == tagName).
++              if (p.oe[i].DataAtom == tagAtom) &&
++                      ((tagAtom != 0) || (p.oe[i].Data == tagName)) {
++                      p.oe = p.oe[:i]
++                      break
++              }
++              if isSpecialElement(p.oe[i]) {
++                      break
++              }
++      }
++}
++
++// Section 12.2.6.4.8.
++func textIM(p *parser) bool {
++      switch p.tok.Type {
++      case ErrorToken:
++              p.oe.pop()
++      case TextToken:
++              d := p.tok.Data
++              if n := p.oe.top(); n.DataAtom == a.Textarea && n.FirstChild == nil {
++                      // Ignore a newline at the start of a <textarea> block.
++                      if d != "" && d[0] == '\r' {
++                              d = d[1:]
++                      }
++                      if d != "" && d[0] == '\n' {
++                              d = d[1:]
++                      }
++              }
++              if d == "" {
++                      return true
++              }
++              p.addText(d)
++              return true
++      case EndTagToken:
++              p.oe.pop()
++      }
++      p.im = p.originalIM
++      p.originalIM = nil
++      return p.tok.Type == EndTagToken
++}
++
++// Section 12.2.6.4.9.
++func inTableIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
++              switch p.oe.top().DataAtom {
++              case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
++                      if strings.Trim(p.tok.Data, whitespace) == "" {
++                              p.addText(p.tok.Data)
++                              return true
++                      }
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Caption:
++                      p.clearStackToContext(tableScope)
++                      p.afe = append(p.afe, &scopeMarker)
++                      p.addElement()
++                      p.im = inCaptionIM
++                      return true
++              case a.Colgroup:
++                      p.clearStackToContext(tableScope)
++                      p.addElement()
++                      p.im = inColumnGroupIM
++                      return true
++              case a.Col:
++                      p.parseImpliedToken(StartTagToken, a.Colgroup, a.Colgroup.String())
++                      return false
++              case a.Tbody, a.Tfoot, a.Thead:
++                      p.clearStackToContext(tableScope)
++                      p.addElement()
++                      p.im = inTableBodyIM
++                      return true
++              case a.Td, a.Th, a.Tr:
++                      p.parseImpliedToken(StartTagToken, a.Tbody, a.Tbody.String())
++                      return false
++              case a.Table:
++                      if p.popUntil(tableScope, a.Table) {
++                              p.resetInsertionMode()
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Style, a.Script, a.Template:
++                      return inHeadIM(p)
++              case a.Input:
++                      for _, t := range p.tok.Attr {
++                              if t.Key == "type" && strings.ToLower(t.Val) == "hidden" {
++                                      p.addElement()
++                                      p.oe.pop()
++                                      return true
++                              }
++                      }
++                      // Otherwise drop down to the default action.
++              case a.Form:
++                      if p.oe.contains(a.Template) || p.form != nil {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.addElement()
++                      p.form = p.oe.pop()
++              case a.Select:
++                      p.reconstructActiveFormattingElements()
++                      switch p.top().DataAtom {
++                      case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
++                              p.fosterParenting = true
++                      }
++                      p.addElement()
++                      p.fosterParenting = false
++                      p.framesetOK = false
++                      p.im = inSelectInTableIM
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Table:
++                      if p.popUntil(tableScope, a.Table) {
++                              p.resetInsertionMode()
++                              return true
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
++                      // Ignore the token.
++                      return true
++              case a.Template:
++                      return inHeadIM(p)
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      case ErrorToken:
++              return inBodyIM(p)
++      }
++
++      p.fosterParenting = true
++      defer func() { p.fosterParenting = false }()
++
++      return inBodyIM(p)
++}
++
++// Section 12.2.6.4.11.
++func inCaptionIM(p *parser) bool {
++      switch p.tok.Type {
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Thead, a.Tr:
++                      if !p.popUntil(tableScope, a.Caption) {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.clearActiveFormattingElements()
++                      p.im = inTableIM
++                      return false
++              case a.Select:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.framesetOK = false
++                      p.im = inSelectInTableIM
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Caption:
++                      if p.popUntil(tableScope, a.Caption) {
++                              p.clearActiveFormattingElements()
++                              p.im = inTableIM
++                      }
++                      return true
++              case a.Table:
++                      if !p.popUntil(tableScope, a.Caption) {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.clearActiveFormattingElements()
++                      p.im = inTableIM
++                      return false
++              case a.Body, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
++                      // Ignore the token.
++                      return true
++              }
++      }
++      return inBodyIM(p)
++}
++
++// Section 12.2.6.4.12.
++func inColumnGroupIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) < len(p.tok.Data) {
++                      // Add the initial whitespace to the current node.
++                      p.addText(p.tok.Data[:len(p.tok.Data)-len(s)])
++                      if s == "" {
++                              return true
++                      }
++                      p.tok.Data = s
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Col:
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++                      return true
++              case a.Template:
++                      return inHeadIM(p)
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Colgroup:
++                      if p.oe.top().DataAtom == a.Colgroup {
++                              p.oe.pop()
++                              p.im = inTableIM
++                      }
++                      return true
++              case a.Col:
++                      // Ignore the token.
++                      return true
++              case a.Template:
++                      return inHeadIM(p)
++              }
++      case ErrorToken:
++              return inBodyIM(p)
++      }
++      if p.oe.top().DataAtom != a.Colgroup {
++              return true
++      }
++      p.oe.pop()
++      p.im = inTableIM
++      return false
++}
++
++// Section 12.2.6.4.13.
++func inTableBodyIM(p *parser) bool {
++      switch p.tok.Type {
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Tr:
++                      p.clearStackToContext(tableBodyScope)
++                      p.addElement()
++                      p.im = inRowIM
++                      return true
++              case a.Td, a.Th:
++                      p.parseImpliedToken(StartTagToken, a.Tr, a.Tr.String())
++                      return false
++              case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
++                      if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
++                              p.im = inTableIM
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Tbody, a.Tfoot, a.Thead:
++                      if p.elementInScope(tableScope, p.tok.DataAtom) {
++                              p.clearStackToContext(tableBodyScope)
++                              p.oe.pop()
++                              p.im = inTableIM
++                      }
++                      return true
++              case a.Table:
++                      if p.popUntil(tableScope, a.Tbody, a.Thead, a.Tfoot) {
++                              p.im = inTableIM
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th, a.Tr:
++                      // Ignore the token.
++                      return true
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      }
++
++      return inTableIM(p)
++}
++
++// Section 12.2.6.4.14.
++func inRowIM(p *parser) bool {
++      switch p.tok.Type {
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Td, a.Th:
++                      p.clearStackToContext(tableRowScope)
++                      p.addElement()
++                      p.afe = append(p.afe, &scopeMarker)
++                      p.im = inCellIM
++                      return true
++              case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Tfoot, a.Thead, a.Tr:
++                      if p.popUntil(tableScope, a.Tr) {
++                              p.im = inTableBodyIM
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Tr:
++                      if p.popUntil(tableScope, a.Tr) {
++                              p.im = inTableBodyIM
++                              return true
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Table:
++                      if p.popUntil(tableScope, a.Tr) {
++                              p.im = inTableBodyIM
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Tbody, a.Tfoot, a.Thead:
++                      if p.elementInScope(tableScope, p.tok.DataAtom) {
++                              p.parseImpliedToken(EndTagToken, a.Tr, a.Tr.String())
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Td, a.Th:
++                      // Ignore the token.
++                      return true
++              }
++      }
++
++      return inTableIM(p)
++}
++
++// Section 12.2.6.4.15.
++func inCellIM(p *parser) bool {
++      switch p.tok.Type {
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Caption, a.Col, a.Colgroup, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
++                      if p.popUntil(tableScope, a.Td, a.Th) {
++                              // Close the cell and reprocess.
++                              p.clearActiveFormattingElements()
++                              p.im = inRowIM
++                              return false
++                      }
++                      // Ignore the token.
++                      return true
++              case a.Select:
++                      p.reconstructActiveFormattingElements()
++                      p.addElement()
++                      p.framesetOK = false
++                      p.im = inSelectInTableIM
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Td, a.Th:
++                      if !p.popUntil(tableScope, p.tok.DataAtom) {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.clearActiveFormattingElements()
++                      p.im = inRowIM
++                      return true
++              case a.Body, a.Caption, a.Col, a.Colgroup, a.Html:
++                      // Ignore the token.
++                      return true
++              case a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr:
++                      if !p.elementInScope(tableScope, p.tok.DataAtom) {
++                              // Ignore the token.
++                              return true
++                      }
++                      // Close the cell and reprocess.
++                      if p.popUntil(tableScope, a.Td, a.Th) {
++                              p.clearActiveFormattingElements()
++                      }
++                      p.im = inRowIM
++                      return false
++              }
++      }
++      return inBodyIM(p)
++}
++
++// Section 12.2.6.4.16.
++func inSelectIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Option:
++                      if p.top().DataAtom == a.Option {
++                              p.oe.pop()
++                      }
++                      p.addElement()
++              case a.Optgroup:
++                      if p.top().DataAtom == a.Option {
++                              p.oe.pop()
++                      }
++                      if p.top().DataAtom == a.Optgroup {
++                              p.oe.pop()
++                      }
++                      p.addElement()
++              case a.Select:
++                      if !p.popUntil(selectScope, a.Select) {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.resetInsertionMode()
++              case a.Input, a.Keygen, a.Textarea:
++                      if p.elementInScope(selectScope, a.Select) {
++                              p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
++                              return false
++                      }
++                      // In order to properly ignore <textarea>, we need to change the tokenizer mode.
++                      p.tokenizer.NextIsNotRawText()
++                      // Ignore the token.
++                      return true
++              case a.Script, a.Template:
++                      return inHeadIM(p)
++              case a.Iframe, a.Noembed, a.Noframes, a.Noscript, a.Plaintext, a.Style, a.Title, a.Xmp:
++                      // Don't let the tokenizer go into raw text mode when there are raw tags
++                      // to be ignored. These tags should be ignored from the tokenizer
++                      // properly.
++                      p.tokenizer.NextIsNotRawText()
++                      // Ignore the token.
++                      return true
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Option:
++                      if p.top().DataAtom == a.Option {
++                              p.oe.pop()
++                      }
++              case a.Optgroup:
++                      i := len(p.oe) - 1
++                      if p.oe[i].DataAtom == a.Option {
++                              i--
++                      }
++                      if p.oe[i].DataAtom == a.Optgroup {
++                              p.oe = p.oe[:i]
++                      }
++              case a.Select:
++                      if !p.popUntil(selectScope, a.Select) {
++                              // Ignore the token.
++                              return true
++                      }
++                      p.resetInsertionMode()
++              case a.Template:
++                      return inHeadIM(p)
++              }
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case DoctypeToken:
++              // Ignore the token.
++              return true
++      case ErrorToken:
++              return inBodyIM(p)
++      }
++
++      return true
++}
++
++// Section 12.2.6.4.17.
++func inSelectInTableIM(p *parser) bool {
++      switch p.tok.Type {
++      case StartTagToken, EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
++                      if p.tok.Type == EndTagToken && !p.elementInScope(tableScope, p.tok.DataAtom) {
++                              // Ignore the token.
++                              return true
++                      }
++                      // This is like p.popUntil(selectScope, a.Select), but it also
++                      // matches <math select>, not just <select>. Matching the MathML
++                      // tag is arguably incorrect (conceptually), but it mimics what
++                      // Chromium does.
++                      for i := len(p.oe) - 1; i >= 0; i-- {
++                              if n := p.oe[i]; n.DataAtom == a.Select {
++                                      p.oe = p.oe[:i]
++                                      break
++                              }
++                      }
++                      p.resetInsertionMode()
++                      return false
++              }
++      }
++      return inSelectIM(p)
++}
++
++// Section 12.2.6.4.18.
++func inTemplateIM(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken, CommentToken, DoctypeToken:
++              return inBodyIM(p)
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
++                      return inHeadIM(p)
++              case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
++                      p.templateStack.pop()
++                      p.templateStack = append(p.templateStack, inTableIM)
++                      p.im = inTableIM
++                      return false
++              case a.Col:
++                      p.templateStack.pop()
++                      p.templateStack = append(p.templateStack, inColumnGroupIM)
++                      p.im = inColumnGroupIM
++                      return false
++              case a.Tr:
++                      p.templateStack.pop()
++                      p.templateStack = append(p.templateStack, inTableBodyIM)
++                      p.im = inTableBodyIM
++                      return false
++              case a.Td, a.Th:
++                      p.templateStack.pop()
++                      p.templateStack = append(p.templateStack, inRowIM)
++                      p.im = inRowIM
++                      return false
++              default:
++                      p.templateStack.pop()
++                      p.templateStack = append(p.templateStack, inBodyIM)
++                      p.im = inBodyIM
++                      return false
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Template:
++                      return inHeadIM(p)
++              default:
++                      // Ignore the token.
++                      return true
++              }
++      case ErrorToken:
++              if !p.oe.contains(a.Template) {
++                      // Ignore the token.
++                      return true
++              }
++              // TODO: remove this divergence from the HTML5 spec.
++              //
++              // See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
++              p.generateImpliedEndTags()
++              for i := len(p.oe) - 1; i >= 0; i-- {
++                      if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
++                              p.oe = p.oe[:i]
++                              break
++                      }
++              }
++              p.clearActiveFormattingElements()
++              p.templateStack.pop()
++              p.resetInsertionMode()
++              return false
++      }
++      return false
++}
++
++// Section 12.2.6.4.19.
++func afterBodyIM(p *parser) bool {
++      switch p.tok.Type {
++      case ErrorToken:
++              // Stop parsing.
++              return true
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) == 0 {
++                      // It was all whitespace.
++                      return inBodyIM(p)
++              }
++      case StartTagToken:
++              if p.tok.DataAtom == a.Html {
++                      return inBodyIM(p)
++              }
++      case EndTagToken:
++              if p.tok.DataAtom == a.Html {
++                      if !p.fragment {
++                              p.im = afterAfterBodyIM
++                      }
++                      return true
++              }
++      case CommentToken:
++              // The comment is attached to the <html> element.
++              if len(p.oe) < 1 || p.oe[0].DataAtom != a.Html {
++                      panic("html: bad parser state: <html> element not found, in the after-body insertion mode")
++              }
++              p.oe[0].AppendChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      }
++      p.im = inBodyIM
++      return false
++}
++
++// Section 12.2.6.4.20.
++func inFramesetIM(p *parser) bool {
++      switch p.tok.Type {
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case TextToken:
++              // Ignore all text but whitespace.
++              s := strings.Map(func(c rune) rune {
++                      switch c {
++                      case ' ', '\t', '\n', '\f', '\r':
++                              return c
++                      }
++                      return -1
++              }, p.tok.Data)
++              if s != "" {
++                      p.addText(s)
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Frameset:
++                      p.addElement()
++              case a.Frame:
++                      p.addElement()
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++              case a.Noframes:
++                      return inHeadIM(p)
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Frameset:
++                      if p.oe.top().DataAtom != a.Html {
++                              p.oe.pop()
++                              if p.oe.top().DataAtom != a.Frameset {
++                                      p.im = afterFramesetIM
++                                      return true
++                              }
++                      }
++              }
++      default:
++              // Ignore the token.
++      }
++      return true
++}
++
++// Section 12.2.6.4.21.
++func afterFramesetIM(p *parser) bool {
++      switch p.tok.Type {
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case TextToken:
++              // Ignore all text but whitespace.
++              s := strings.Map(func(c rune) rune {
++                      switch c {
++                      case ' ', '\t', '\n', '\f', '\r':
++                              return c
++                      }
++                      return -1
++              }, p.tok.Data)
++              if s != "" {
++                      p.addText(s)
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Noframes:
++                      return inHeadIM(p)
++              }
++      case EndTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      p.im = afterAfterFramesetIM
++                      return true
++              }
++      default:
++              // Ignore the token.
++      }
++      return true
++}
++
++// Section 12.2.6.4.22.
++func afterAfterBodyIM(p *parser) bool {
++      switch p.tok.Type {
++      case ErrorToken:
++              // Stop parsing.
++              return true
++      case TextToken:
++              s := strings.TrimLeft(p.tok.Data, whitespace)
++              if len(s) == 0 {
++                      // It was all whitespace.
++                      return inBodyIM(p)
++              }
++      case StartTagToken:
++              if p.tok.DataAtom == a.Html {
++                      return inBodyIM(p)
++              }
++      case CommentToken:
++              p.doc.AppendChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++              return true
++      case DoctypeToken:
++              return inBodyIM(p)
++      }
++      p.im = inBodyIM
++      return false
++}
++
++// Section 12.2.6.4.23.
++func afterAfterFramesetIM(p *parser) bool {
++      switch p.tok.Type {
++      case CommentToken:
++              p.doc.AppendChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case TextToken:
++              // Ignore all text but whitespace.
++              s := strings.Map(func(c rune) rune {
++                      switch c {
++                      case ' ', '\t', '\n', '\f', '\r':
++                              return c
++                      }
++                      return -1
++              }, p.tok.Data)
++              if s != "" {
++                      p.tok.Data = s
++                      return inBodyIM(p)
++              }
++      case StartTagToken:
++              switch p.tok.DataAtom {
++              case a.Html:
++                      return inBodyIM(p)
++              case a.Noframes:
++                      return inHeadIM(p)
++              }
++      case DoctypeToken:
++              return inBodyIM(p)
++      default:
++              // Ignore the token.
++      }
++      return true
++}
++
++func ignoreTheRemainingTokens(p *parser) bool {
++      return true
++}
++
++const whitespaceOrNUL = whitespace + "\x00"
++
++// Section 12.2.6.5
++func parseForeignContent(p *parser) bool {
++      switch p.tok.Type {
++      case TextToken:
++              if p.framesetOK {
++                      p.framesetOK = strings.TrimLeft(p.tok.Data, whitespaceOrNUL) == ""
++              }
++              p.tok.Data = strings.Replace(p.tok.Data, "\x00", "\ufffd", -1)
++              p.addText(p.tok.Data)
++      case CommentToken:
++              p.addChild(&Node{
++                      Type: CommentNode,
++                      Data: p.tok.Data,
++              })
++      case StartTagToken:
++              if !p.fragment {
++                      b := breakout[p.tok.Data]
++                      if p.tok.DataAtom == a.Font {
++                      loop:
++                              for _, attr := range p.tok.Attr {
++                                      switch attr.Key {
++                                      case "color", "face", "size":
++                                              b = true
++                                              break loop
++                                      }
++                              }
++                      }
++                      if b {
++                              for i := len(p.oe) - 1; i >= 0; i-- {
++                                      n := p.oe[i]
++                                      if n.Namespace == "" || htmlIntegrationPoint(n) || mathMLTextIntegrationPoint(n) {
++                                              p.oe = p.oe[:i+1]
++                                              break
++                                      }
++                              }
++                              return false
++                      }
++              }
++              current := p.adjustedCurrentNode()
++              switch current.Namespace {
++              case "math":
++                      adjustAttributeNames(p.tok.Attr, mathMLAttributeAdjustments)
++              case "svg":
++                      // Adjust SVG tag names. The tokenizer lower-cases tag names, but
++                      // SVG wants e.g. "foreignObject" with a capital second "O".
++                      if x := svgTagNameAdjustments[p.tok.Data]; x != "" {
++                              p.tok.DataAtom = a.Lookup([]byte(x))
++                              p.tok.Data = x
++                      }
++                      adjustAttributeNames(p.tok.Attr, svgAttributeAdjustments)
++              default:
++                      panic("html: bad parser state: unexpected namespace")
++              }
++              adjustForeignAttributes(p.tok.Attr)
++              namespace := current.Namespace
++              p.addElement()
++              p.top().Namespace = namespace
++              if namespace != "" {
++                      // Don't let the tokenizer go into raw text mode in foreign content
++                      // (e.g. in an SVG <title> tag).
++                      p.tokenizer.NextIsNotRawText()
++              }
++              if p.hasSelfClosingToken {
++                      p.oe.pop()
++                      p.acknowledgeSelfClosingTag()
++              }
++      case EndTagToken:
++              for i := len(p.oe) - 1; i >= 0; i-- {
++                      if p.oe[i].Namespace == "" {
++                              return p.im(p)
++                      }
++                      if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
++                              p.oe = p.oe[:i]
++                              break
++                      }
++              }
++              return true
++      default:
++              // Ignore the token.
++      }
++      return true
++}
++
++// Section 12.2.4.2.
++func (p *parser) adjustedCurrentNode() *Node {
++      if len(p.oe) == 1 && p.fragment && p.context != nil {
++              return p.context
++      }
++      return p.oe.top()
++}
++
++// Section 12.2.6.
++func (p *parser) inForeignContent() bool {
++      if len(p.oe) == 0 {
++              return false
++      }
++      n := p.adjustedCurrentNode()
++      if n.Namespace == "" {
++              return false
++      }
++      if mathMLTextIntegrationPoint(n) {
++              if p.tok.Type == StartTagToken && p.tok.DataAtom != a.Mglyph && p.tok.DataAtom != a.Malignmark {
++                      return false
++              }
++              if p.tok.Type == TextToken {
++                      return false
++              }
++      }
++      if n.Namespace == "math" && n.DataAtom == a.AnnotationXml && p.tok.Type == StartTagToken && p.tok.DataAtom == a.Svg {
++              return false
++      }
++      if htmlIntegrationPoint(n) && (p.tok.Type == StartTagToken || p.tok.Type == TextToken) {
++              return false
++      }
++      if p.tok.Type == ErrorToken {
++              return false
++      }
++      return true
++}
++
++// parseImpliedToken parses a token as though it had appeared in the parser's
++// input.
++func (p *parser) parseImpliedToken(t TokenType, dataAtom a.Atom, data string) {
++      realToken, selfClosing := p.tok, p.hasSelfClosingToken
++      p.tok = Token{
++              Type:     t,
++              DataAtom: dataAtom,
++              Data:     data,
++      }
++      p.hasSelfClosingToken = false
++      p.parseCurrentToken()
++      p.tok, p.hasSelfClosingToken = realToken, selfClosing
++}
++
++// parseCurrentToken runs the current token through the parsing routines
++// until it is consumed.
++func (p *parser) parseCurrentToken() {
++      if p.tok.Type == SelfClosingTagToken {
++              p.hasSelfClosingToken = true
++              p.tok.Type = StartTagToken
++      }
++
++      consumed := false
++      for !consumed {
++              if p.inForeignContent() {
++                      consumed = parseForeignContent(p)
++              } else {
++                      consumed = p.im(p)
++              }
++      }
++
++      if p.hasSelfClosingToken {
++              // This is a parse error, but ignore it.
++              p.hasSelfClosingToken = false
++      }
++}
++
++func (p *parser) parse() error {
++      // Iterate until EOF. Any other error will cause an early return.
++      var err error
++      for err != io.EOF {
++              // CDATA sections are allowed only in foreign content.
++              n := p.oe.top()
++              p.tokenizer.AllowCDATA(n != nil && n.Namespace != "")
++              // Read and parse the next token.
++              p.tokenizer.Next()
++              p.tok = p.tokenizer.Token()
++              if p.tok.Type == ErrorToken {
++                      err = p.tokenizer.Err()
++                      if err != nil && err != io.EOF {
++                              return err
++                      }
++              }
++              p.parseCurrentToken()
++      }
++      return nil
++}
++
++// Parse returns the parse tree for the HTML from the given Reader.
++//
++// It implements the HTML5 parsing algorithm
++// (https://html.spec.whatwg.org/multipage/syntax.html#tree-construction),
++// which is very complicated. The resultant tree can contain implicitly created
++// nodes that have no explicit <tag> listed in r's data, and nodes' parents can
++// differ from the nesting implied by a naive processing of start and end
++// <tag>s. Conversely, explicit <tag>s in r's data can be silently dropped,
++// with no corresponding node in the resulting tree.
++//
++// The input is assumed to be UTF-8 encoded.
++func Parse(r io.Reader) (*Node, error) {
++      return ParseWithOptions(r)
++}
++
++// ParseFragment parses a fragment of HTML and returns the nodes that were
++// found. If the fragment is the InnerHTML for an existing element, pass that
++// element in context.
++//
++// It has the same intricacies as Parse.
++func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
++      return ParseFragmentWithOptions(r, context)
++}
++
++// ParseOption configures a parser.
++type ParseOption func(p *parser)
++
++// ParseOptionEnableScripting configures the scripting flag.
++// https://html.spec.whatwg.org/multipage/webappapis.html#enabling-and-disabling-scripting
++//
++// By default, scripting is enabled.
++func ParseOptionEnableScripting(enable bool) ParseOption {
++      return func(p *parser) {
++              p.scripting = enable
++      }
++}
++
++// ParseWithOptions is like Parse, with options.
++func ParseWithOptions(r io.Reader, opts ...ParseOption) (*Node, error) {
++      p := &parser{
++              tokenizer: NewTokenizer(r),
++              doc: &Node{
++                      Type: DocumentNode,
++              },
++              scripting:  true,
++              framesetOK: true,
++              im:         initialIM,
++      }
++
++      for _, f := range opts {
++              f(p)
++      }
++
++      if err := p.parse(); err != nil {
++              return nil, err
++      }
++      return p.doc, nil
++}
++
++// ParseFragmentWithOptions is like ParseFragment, with options.
++func ParseFragmentWithOptions(r io.Reader, context *Node, opts ...ParseOption) ([]*Node, error) {
++      contextTag := ""
++      if context != nil {
++              if context.Type != ElementNode {
++                      return nil, errors.New("html: ParseFragment of non-element Node")
++              }
++              // The next check isn't just context.DataAtom.String() == context.Data because
++              // it is valid to pass an element whose tag isn't a known atom. For example,
++              // DataAtom == 0 and Data = "tagfromthefuture" is perfectly consistent.
++              if context.DataAtom != a.Lookup([]byte(context.Data)) {
++                      return nil, fmt.Errorf("html: inconsistent Node: DataAtom=%q, Data=%q", context.DataAtom, context.Data)
++              }
++              contextTag = context.DataAtom.String()
++      }
++      p := &parser{
++              doc: &Node{
++                      Type: DocumentNode,
++              },
++              scripting: true,
++              fragment:  true,
++              context:   context,
++      }
++      if context != nil && context.Namespace != "" {
++              p.tokenizer = NewTokenizer(r)
++      } else {
++              p.tokenizer = NewTokenizerFragment(r, contextTag)
++      }
++
++      for _, f := range opts {
++              f(p)
++      }
++
++      root := &Node{
++              Type:     ElementNode,
++              DataAtom: a.Html,
++              Data:     a.Html.String(),
++      }
++      p.doc.AppendChild(root)
++      p.oe = nodeStack{root}
++      if context != nil && context.DataAtom == a.Template {
++              p.templateStack = append(p.templateStack, inTemplateIM)
++      }
++      p.resetInsertionMode()
++
++      for n := context; n != nil; n = n.Parent {
++              if n.Type == ElementNode && n.DataAtom == a.Form {
++                      p.form = n
++                      break
++              }
++      }
++
++      if err := p.parse(); err != nil {
++              return nil, err
++      }
++
++      parent := p.doc
++      if context != nil {
++              parent = root
++      }
++
++      var result []*Node
++      for c := parent.FirstChild; c != nil; {
++              next := c.NextSibling
++              parent.RemoveChild(c)
++              result = append(result, c)
++              c = next
++      }
++      return result, nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b2b7fdc5f0b3fae4af402fc338017f303f55bd19
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,490 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bufio"
++      "bytes"
++      "errors"
++      "fmt"
++      "io"
++      "os"
++      "path/filepath"
++      "runtime"
++      "sort"
++      "strings"
++      "testing"
++
++      "git.earlybird.gay/today-engine/internal/html/atom"
++)
++
++type testAttrs struct {
++      text, want, context string
++      scripting           bool
++}
++
++// readParseTest reads a single test case from r.
++func readParseTest(r *bufio.Reader) (*testAttrs, error) {
++      ta := &testAttrs{scripting: true}
++      line, err := r.ReadSlice('\n')
++      if err != nil {
++              return nil, err
++      }
++      var b []byte
++
++      // Read the HTML.
++      if string(line) != "#data\n" {
++              return nil, fmt.Errorf(`got %q want "#data\n"`, line)
++      }
++      for {
++              line, err = r.ReadSlice('\n')
++              if err != nil {
++                      return nil, err
++              }
++              if line[0] == '#' {
++                      break
++              }
++              b = append(b, line...)
++      }
++      ta.text = strings.TrimSuffix(string(b), "\n")
++      b = b[:0]
++
++      // Skip the error list.
++      if string(line) != "#errors\n" {
++              return nil, fmt.Errorf(`got %q want "#errors\n"`, line)
++      }
++      for {
++              line, err = r.ReadSlice('\n')
++              if err != nil {
++                      return nil, err
++              }
++              if line[0] == '#' {
++                      break
++              }
++      }
++
++      // Skip the new-errors list.
++      if string(line) == "#new-errors\n" {
++              for {
++                      line, err = r.ReadSlice('\n')
++                      if err != nil {
++                              return nil, err
++                      }
++                      if line[0] == '#' {
++                              break
++                      }
++              }
++      }
++
++      if ls := string(line); strings.HasPrefix(ls, "#script-") {
++              switch {
++              case strings.HasSuffix(ls, "-on\n"):
++                      ta.scripting = true
++              case strings.HasSuffix(ls, "-off\n"):
++                      ta.scripting = false
++              default:
++                      return nil, fmt.Errorf(`got %q, want "#script-on" or "#script-off"`, line)
++              }
++              for {
++                      line, err = r.ReadSlice('\n')
++                      if err != nil {
++                              return nil, err
++                      }
++                      if line[0] == '#' {
++                              break
++                      }
++              }
++      }
++
++      if string(line) == "#document-fragment\n" {
++              line, err = r.ReadSlice('\n')
++              if err != nil {
++                      return nil, err
++              }
++              ta.context = strings.TrimSpace(string(line))
++              line, err = r.ReadSlice('\n')
++              if err != nil {
++                      return nil, err
++              }
++      }
++
++      // Read the dump of what the parse tree should be.
++      if string(line) != "#document\n" {
++              return nil, fmt.Errorf(`got %q want "#document\n"`, line)
++      }
++      inQuote := false
++      for {
++              line, err = r.ReadSlice('\n')
++              if err != nil && err != io.EOF {
++                      return nil, err
++              }
++              trimmed := bytes.Trim(line, "| \n")
++              if len(trimmed) > 0 {
++                      if line[0] == '|' && trimmed[0] == '"' {
++                              inQuote = true
++                      }
++                      if trimmed[len(trimmed)-1] == '"' && !(line[0] == '|' && len(trimmed) == 1) {
++                              inQuote = false
++                      }
++              }
++              if len(line) == 0 || len(line) == 1 && line[0] == '\n' && !inQuote {
++                      break
++              }
++              b = append(b, line...)
++      }
++      ta.want = string(b)
++      return ta, nil
++}
++
++func dumpIndent(w io.Writer, level int) {
++      io.WriteString(w, "| ")
++      for i := 0; i < level; i++ {
++              io.WriteString(w, "  ")
++      }
++}
++
++type sortedAttributes []Attribute
++
++func (a sortedAttributes) Len() int {
++      return len(a)
++}
++
++func (a sortedAttributes) Less(i, j int) bool {
++      if a[i].Namespace != a[j].Namespace {
++              return a[i].Namespace < a[j].Namespace
++      }
++      return a[i].Key < a[j].Key
++}
++
++func (a sortedAttributes) Swap(i, j int) {
++      a[i], a[j] = a[j], a[i]
++}
++
++func dumpLevel(w io.Writer, n *Node, level int) error {
++      dumpIndent(w, level)
++      level++
++      switch n.Type {
++      case ErrorNode:
++              return errors.New("unexpected ErrorNode")
++      case DocumentNode:
++              return errors.New("unexpected DocumentNode")
++      case ElementNode:
++              if n.Namespace != "" {
++                      fmt.Fprintf(w, "<%s %s>", n.Namespace, n.Data)
++              } else {
++                      fmt.Fprintf(w, "<%s>", n.Data)
++              }
++              attr := sortedAttributes(n.Attr)
++              sort.Sort(attr)
++              for _, a := range attr {
++                      io.WriteString(w, "\n")
++                      dumpIndent(w, level)
++                      if a.Namespace != "" {
++                              fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
++                      } else {
++                              fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
++                      }
++              }
++              if n.Namespace == "" && n.DataAtom == atom.Template {
++                      io.WriteString(w, "\n")
++                      dumpIndent(w, level)
++                      level++
++                      io.WriteString(w, "content")
++              }
++      case TextNode:
++              fmt.Fprintf(w, `"%s"`, n.Data)
++      case CommentNode:
++              fmt.Fprintf(w, "<!-- %s -->", n.Data)
++      case DoctypeNode:
++              fmt.Fprintf(w, "<!DOCTYPE %s", n.Data)
++              if n.Attr != nil {
++                      var p, s string
++                      for _, a := range n.Attr {
++                              switch a.Key {
++                              case "public":
++                                      p = a.Val
++                              case "system":
++                                      s = a.Val
++                              }
++                      }
++                      if p != "" || s != "" {
++                              fmt.Fprintf(w, ` "%s"`, p)
++                              fmt.Fprintf(w, ` "%s"`, s)
++                      }
++              }
++              io.WriteString(w, ">")
++      case scopeMarkerNode:
++              return errors.New("unexpected scopeMarkerNode")
++      default:
++              return errors.New("unknown node type")
++      }
++      io.WriteString(w, "\n")
++      for c := n.FirstChild; c != nil; c = c.NextSibling {
++              if err := dumpLevel(w, c, level); err != nil {
++                      return err
++              }
++      }
++      return nil
++}
++
++func dump(n *Node) (string, error) {
++      if n == nil || n.FirstChild == nil {
++              return "", nil
++      }
++      var b bytes.Buffer
++      for c := n.FirstChild; c != nil; c = c.NextSibling {
++              if err := dumpLevel(&b, c, 0); err != nil {
++                      return "", err
++              }
++      }
++      return b.String(), nil
++}
++
++var testDataDirs = []string{"testdata/webkit/", "testdata/go/"}
++
++func TestParser(t *testing.T) {
++      for _, testDataDir := range testDataDirs {
++              testFiles, err := filepath.Glob(testDataDir + "*.dat")
++              if err != nil {
++                      t.Fatal(err)
++              }
++              for _, tf := range testFiles {
++                      f, err := os.Open(tf)
++                      if err != nil {
++                              t.Fatal(err)
++                      }
++                      defer f.Close()
++                      r := bufio.NewReader(f)
++
++                      for i := 0; ; i++ {
++                              ta, err := readParseTest(r)
++                              if err == io.EOF {
++                                      break
++                              }
++                              if err != nil {
++                                      t.Fatal(err)
++                              }
++                              if parseTestBlacklist[ta.text] {
++                                      continue
++                              }
++
++                              err = testParseCase(ta.text, ta.want, ta.context, ParseOptionEnableScripting(ta.scripting))
++
++                              if err != nil {
++                                      t.Errorf("%s test #%d %q, %s", tf, i, ta.text, err)
++                              }
++                      }
++              }
++      }
++}
++
++// Issue 16318
++func TestParserWithoutScripting(t *testing.T) {
++      text := `<noscript><img src='https://golang.org/doc/gopher/frontpage.png' /></noscript><p><img src='https://golang.org/doc/gopher/doc.png' /></p>`
++      want := `| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <img>
++|       src="https://golang.org/doc/gopher/frontpage.png"
++|     <p>
++|       <img>
++|         src="https://golang.org/doc/gopher/doc.png"
++`
++
++      if err := testParseCase(text, want, "", ParseOptionEnableScripting(false)); err != nil {
++              t.Errorf("test with scripting is disabled, %q, %s", text, err)
++      }
++}
++
++// testParseCase tests one test case from the test files. If the test does not
++// pass, it returns an error that explains the failure.
++// text is the HTML to be parsed, want is a dump of the correct parse tree,
++// and context is the name of the context node, if any.
++func testParseCase(text, want, context string, opts ...ParseOption) (err error) {
++      defer func() {
++              if x := recover(); x != nil {
++                      switch e := x.(type) {
++                      case error:
++                              err = e
++                      default:
++                              err = fmt.Errorf("%v", e)
++                      }
++              }
++      }()
++
++      var doc *Node
++      if context == "" {
++              doc, err = ParseWithOptions(strings.NewReader(text), opts...)
++              if err != nil {
++                      return err
++              }
++      } else {
++              namespace := ""
++              if i := strings.IndexByte(context, ' '); i >= 0 {
++                      namespace, context = context[:i], context[i+1:]
++              }
++              contextNode := &Node{
++                      Data:      context,
++                      DataAtom:  atom.Lookup([]byte(context)),
++                      Namespace: namespace,
++                      Type:      ElementNode,
++              }
++              nodes, err := ParseFragmentWithOptions(strings.NewReader(text), contextNode, opts...)
++              if err != nil {
++                      return err
++              }
++              doc = &Node{
++                      Type: DocumentNode,
++              }
++              for _, n := range nodes {
++                      doc.AppendChild(n)
++              }
++      }
++
++      if err := checkTreeConsistency(doc); err != nil {
++              return err
++      }
++
++      got, err := dump(doc)
++      if err != nil {
++              return err
++      }
++      // Compare the parsed tree to the #document section.
++      if got != want {
++              return fmt.Errorf("got vs want:\n----\n%s----\n%s----", got, want)
++      }
++
++      if renderTestBlacklist[text] || context != "" {
++              return nil
++      }
++
++      // Check that rendering and re-parsing results in an identical tree.
++      pr, pw := io.Pipe()
++      go func() {
++              pw.CloseWithError(Render(pw, doc))
++      }()
++      doc1, err := ParseWithOptions(pr, opts...)
++      if err != nil {
++              return err
++      }
++      got1, err := dump(doc1)
++      if err != nil {
++              return err
++      }
++      if got != got1 {
++              return fmt.Errorf("got vs got1:\n----\n%s----\n%s----", got, got1)
++      }
++
++      return nil
++}
++
++// Some test inputs are simply skipped - we would otherwise fail the test. We
++// blacklist such inputs from the parse test.
++var parseTestBlacklist = map[string]bool{
++      // See the a.Template TODO in inHeadIM.
++      `<math><template><mo><template>`:                                     true,
++      `<template><svg><foo><template><foreignObject><div></template><div>`: true,
++}
++
++// Some test input result in parse trees are not 'well-formed' despite
++// following the HTML5 recovery algorithms. Rendering and re-parsing such a
++// tree will not result in an exact clone of that tree. We blacklist such
++// inputs from the render test.
++var renderTestBlacklist = map[string]bool{
++      // The second <a> will be reparented to the first <table>'s parent. This
++      // results in an <a> whose parent is an <a>, which is not 'well-formed'.
++      `<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y`: true,
++      // The same thing with a <p>:
++      `<p><table></p>`: true,
++      // More cases of <a> being reparented:
++      `<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe`: true,
++      `<a><table><a></table><p><a><div><a>`:                                     true,
++      `<a><table><td><a><table></table><a></tr><a></table><a>`:                  true,
++      `<template><a><table><a>`:                                                 true,
++      // A similar reparenting situation involving <nobr>:
++      `<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3`: true,
++      // A <plaintext> element is reparented, putting it before a table.
++      // A <plaintext> element can't have anything after it in HTML.
++      `<table><plaintext><td>`:                                   true,
++      `<!doctype html><table><plaintext></plaintext>`:            true,
++      `<!doctype html><table><tbody><plaintext></plaintext>`:     true,
++      `<!doctype html><table><tbody><tr><plaintext></plaintext>`: true,
++      // A form inside a table inside a form doesn't work either.
++      `<!doctype html><form><table></form><form></table></form>`: true,
++      // A script that ends at EOF may escape its own closing tag when rendered.
++      `<!doctype html><script><!--<script `:          true,
++      `<!doctype html><script><!--<script <`:         true,
++      `<!doctype html><script><!--<script <a`:        true,
++      `<!doctype html><script><!--<script </`:        true,
++      `<!doctype html><script><!--<script </s`:       true,
++      `<!doctype html><script><!--<script </script`:  true,
++      `<!doctype html><script><!--<script </scripta`: true,
++      `<!doctype html><script><!--<script -`:         true,
++      `<!doctype html><script><!--<script -a`:        true,
++      `<!doctype html><script><!--<script -<`:        true,
++      `<!doctype html><script><!--<script --`:        true,
++      `<!doctype html><script><!--<script --a`:       true,
++      `<!doctype html><script><!--<script --<`:       true,
++      `<script><!--<script `:                         true,
++      `<script><!--<script <a`:                       true,
++      `<script><!--<script </script`:                 true,
++      `<script><!--<script </scripta`:                true,
++      `<script><!--<script -`:                        true,
++      `<script><!--<script -a`:                       true,
++      `<script><!--<script --`:                       true,
++      `<script><!--<script --a`:                      true,
++      `<script><!--<script <`:                        true,
++      `<script><!--<script </`:                       true,
++      `<script><!--<script </s`:                      true,
++      // Reconstructing the active formatting elements results in a <plaintext>
++      // element that contains an <a> element.
++      `<!doctype html><p><a><plaintext>b`:                       true,
++      `<table><math><select><mi><select></table>`:               true,
++      `<!doctype html><table><colgroup><plaintext></plaintext>`: true,
++      `<!doctype html><svg><plaintext>a</plaintext>b`:           true,
++}
++
++func TestNodeConsistency(t *testing.T) {
++      // inconsistentNode is a Node whose DataAtom and Data do not agree.
++      inconsistentNode := &Node{
++              Type:     ElementNode,
++              DataAtom: atom.Frameset,
++              Data:     "table",
++      }
++      if _, err := ParseFragment(strings.NewReader("<p>hello</p>"), inconsistentNode); err == nil {
++              t.Errorf("got nil error, want non-nil")
++      }
++}
++
++func TestParseFragmentWithNilContext(t *testing.T) {
++      // This shouldn't panic.
++      ParseFragment(strings.NewReader("<p>hello</p>"), nil)
++}
++
++func TestParseFragmentForeignContentTemplates(t *testing.T) {
++      srcs := []string{
++              "<math><html><template><mn><template></template></template>",
++              "<math><math><head><mi><template>",
++      }
++      for _, src := range srcs {
++              // The next line shouldn't infinite-loop.
++              ParseFragment(strings.NewReader(src), nil)
++      }
++}
++
++func BenchmarkParser(b *testing.B) {
++      buf, err := os.ReadFile("testdata/go1.html")
++      if err != nil {
++              b.Fatalf("could not read testdata/go1.html: %v", err)
++      }
++      b.SetBytes(int64(len(buf)))
++      runtime.GC()
++      b.ReportAllocs()
++      b.ResetTimer()
++      for i := 0; i < b.N; i++ {
++              Parse(bytes.NewBuffer(buf))
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e8c12334553d5bd5a9a48e07562aa0889b9f653b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,293 @@@
++// Copyright 2011 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bufio"
++      "errors"
++      "fmt"
++      "io"
++      "strings"
++)
++
++type writer interface {
++      io.Writer
++      io.ByteWriter
++      WriteString(string) (int, error)
++}
++
++// Render renders the parse tree n to the given writer.
++//
++// Rendering is done on a 'best effort' basis: calling Parse on the output of
++// Render will always result in something similar to the original tree, but it
++// is not necessarily an exact clone unless the original tree was 'well-formed'.
++// 'Well-formed' is not easily specified; the HTML5 specification is
++// complicated.
++//
++// Calling Parse on arbitrary input typically results in a 'well-formed' parse
++// tree. However, it is possible for Parse to yield a 'badly-formed' parse tree.
++// For example, in a 'well-formed' parse tree, no <a> element is a child of
++// another <a> element: parsing "<a><a>" results in two sibling elements.
++// Similarly, in a 'well-formed' parse tree, no <a> element is a child of a
++// <table> element: parsing "<p><table><a>" results in a <p> with two sibling
++// children; the <a> is reparented to the <table>'s parent. However, calling
++// Parse on "<a><table><a>" does not return an error, but the result has an <a>
++// element with an <a> child, and is therefore not 'well-formed'.
++//
++// Programmatically constructed trees are typically also 'well-formed', but it
++// is possible to construct a tree that looks innocuous but, when rendered and
++// re-parsed, results in a different tree. A simple example is that a solitary
++// text node would become a tree containing <html>, <head> and <body> elements.
++// Another example is that the programmatic equivalent of "a<head>b</head>c"
++// becomes "<html><head><head/><body>abc</body></html>".
++func Render(w io.Writer, n *Node) error {
++      if x, ok := w.(writer); ok {
++              return render(x, n)
++      }
++      buf := bufio.NewWriter(w)
++      if err := render(buf, n); err != nil {
++              return err
++      }
++      return buf.Flush()
++}
++
++// plaintextAbort is returned from render1 when a <plaintext> element
++// has been rendered. No more end tags should be rendered after that.
++var plaintextAbort = errors.New("html: internal error (plaintext abort)")
++
++func render(w writer, n *Node) error {
++      err := render1(w, n)
++      if err == plaintextAbort {
++              err = nil
++      }
++      return err
++}
++
++func render1(w writer, n *Node) error {
++      // Render non-element nodes; these are the easy cases.
++      switch n.Type {
++      case ErrorNode:
++              return errors.New("html: cannot render an ErrorNode node")
++      case TextNode:
++              return escape(w, n.Data)
++      case DocumentNode:
++              for c := n.FirstChild; c != nil; c = c.NextSibling {
++                      if err := render1(w, c); err != nil {
++                              return err
++                      }
++              }
++              return nil
++      case ElementNode:
++              // No-op.
++      case CommentNode:
++              if _, err := w.WriteString("<!--"); err != nil {
++                      return err
++              }
++              if err := escapeComment(w, n.Data); err != nil {
++                      return err
++              }
++              if _, err := w.WriteString("-->"); err != nil {
++                      return err
++              }
++              return nil
++      case DoctypeNode:
++              if _, err := w.WriteString("<!DOCTYPE "); err != nil {
++                      return err
++              }
++              if err := escape(w, n.Data); err != nil {
++                      return err
++              }
++              if n.Attr != nil {
++                      var p, s string
++                      for _, a := range n.Attr {
++                              switch a.Key {
++                              case "public":
++                                      p = a.Val
++                              case "system":
++                                      s = a.Val
++                              }
++                      }
++                      if p != "" {
++                              if _, err := w.WriteString(" PUBLIC "); err != nil {
++                                      return err
++                              }
++                              if err := writeQuoted(w, p); err != nil {
++                                      return err
++                              }
++                              if s != "" {
++                                      if err := w.WriteByte(' '); err != nil {
++                                              return err
++                                      }
++                                      if err := writeQuoted(w, s); err != nil {
++                                              return err
++                                      }
++                              }
++                      } else if s != "" {
++                              if _, err := w.WriteString(" SYSTEM "); err != nil {
++                                      return err
++                              }
++                              if err := writeQuoted(w, s); err != nil {
++                                      return err
++                              }
++                      }
++              }
++              return w.WriteByte('>')
++      case RawNode:
++              _, err := w.WriteString(n.Data)
++              return err
++      default:
++              return errors.New("html: unknown node type")
++      }
++
++      // Render the <xxx> opening tag.
++      if err := w.WriteByte('<'); err != nil {
++              return err
++      }
++      if _, err := w.WriteString(n.Data); err != nil {
++              return err
++      }
++      for _, a := range n.Attr {
++              if err := w.WriteByte(' '); err != nil {
++                      return err
++              }
++              if a.Namespace != "" {
++                      if _, err := w.WriteString(a.Namespace); err != nil {
++                              return err
++                      }
++                      if err := w.WriteByte(':'); err != nil {
++                              return err
++                      }
++              }
++              if _, err := w.WriteString(a.Key); err != nil {
++                      return err
++              }
++              if _, err := w.WriteString(`="`); err != nil {
++                      return err
++              }
++              if err := escape(w, a.Val); err != nil {
++                      return err
++              }
++              if err := w.WriteByte('"'); err != nil {
++                      return err
++              }
++      }
++      if voidElements[n.Data] {
++              if n.FirstChild != nil {
++                      return fmt.Errorf("html: void element <%s> has child nodes", n.Data)
++              }
++              _, err := w.WriteString("/>")
++              return err
++      }
++      if err := w.WriteByte('>'); err != nil {
++              return err
++      }
++
++      // Add initial newline where there is danger of a newline beging ignored.
++      if c := n.FirstChild; c != nil && c.Type == TextNode && strings.HasPrefix(c.Data, "\n") {
++              switch n.Data {
++              case "pre", "listing", "textarea":
++                      if err := w.WriteByte('\n'); err != nil {
++                              return err
++                      }
++              }
++      }
++
++      // Render any child nodes
++      if childTextNodesAreLiteral(n) {
++              for c := n.FirstChild; c != nil; c = c.NextSibling {
++                      if c.Type == TextNode {
++                              if _, err := w.WriteString(c.Data); err != nil {
++                                      return err
++                              }
++                      } else {
++                              if err := render1(w, c); err != nil {
++                                      return err
++                              }
++                      }
++              }
++              if n.Data == "plaintext" {
++                      // Don't render anything else. <plaintext> must be the
++                      // last element in the file, with no closing tag.
++                      return plaintextAbort
++              }
++      } else {
++              for c := n.FirstChild; c != nil; c = c.NextSibling {
++                      if err := render1(w, c); err != nil {
++                              return err
++                      }
++              }
++      }
++
++      // Render the </xxx> closing tag.
++      if _, err := w.WriteString("</"); err != nil {
++              return err
++      }
++      if _, err := w.WriteString(n.Data); err != nil {
++              return err
++      }
++      return w.WriteByte('>')
++}
++
++func childTextNodesAreLiteral(n *Node) bool {
++      // Per WHATWG HTML 13.3, if the parent of the current node is a style,
++      // script, xmp, iframe, noembed, noframes, or plaintext element, and the
++      // current node is a text node, append the value of the node's data
++      // literally. The specification is not explicit about it, but we only
++      // enforce this if we are in the HTML namespace (i.e. when the namespace is
++      // "").
++      // NOTE: we also always include noscript elements, although the
++      // specification states that they should only be rendered as such if
++      // scripting is enabled for the node (which is not something we track).
++      if n.Namespace != "" {
++              return false
++      }
++      switch n.Data {
++      case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
++              return true
++      default:
++              return false
++      }
++}
++
++// writeQuoted writes s to w surrounded by quotes. Normally it will use double
++// quotes, but if s contains a double quote, it will use single quotes.
++// It is used for writing the identifiers in a doctype declaration.
++// In valid HTML, they can't contain both types of quotes.
++func writeQuoted(w writer, s string) error {
++      var q byte = '"'
++      if strings.Contains(s, `"`) {
++              q = '\''
++      }
++      if err := w.WriteByte(q); err != nil {
++              return err
++      }
++      if _, err := w.WriteString(s); err != nil {
++              return err
++      }
++      if err := w.WriteByte(q); err != nil {
++              return err
++      }
++      return nil
++}
++
++// Section 12.1.2, "Elements", gives this list of void elements. Void elements
++// are those that can't have any contents.
++var voidElements = map[string]bool{
++      "area":   true,
++      "base":   true,
++      "br":     true,
++      "col":    true,
++      "embed":  true,
++      "hr":     true,
++      "img":    true,
++      "input":  true,
++      "keygen": true, // "keygen" has been removed from the spec, but are kept here for backwards compatibility.
++      "link":   true,
++      "meta":   true,
++      "param":  true,
++      "source": true,
++      "track":  true,
++      "wbr":    true,
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..22d08641a01c3e4e18fc7428fb5e0c162d5e2e96
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,207 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bytes"
++      "fmt"
++      "strings"
++      "testing"
++)
++
++func TestRenderer(t *testing.T) {
++      nodes := [...]*Node{
++              0: {
++                      Type: ElementNode,
++                      Data: "html",
++              },
++              1: {
++                      Type: ElementNode,
++                      Data: "head",
++              },
++              2: {
++                      Type: ElementNode,
++                      Data: "body",
++              },
++              3: {
++                      Type: TextNode,
++                      Data: "0<1",
++              },
++              4: {
++                      Type: ElementNode,
++                      Data: "p",
++                      Attr: []Attribute{
++                              {
++                                      Key: "id",
++                                      Val: "A",
++                              },
++                              {
++                                      Key: "foo",
++                                      Val: `abc"def`,
++                              },
++                      },
++              },
++              5: {
++                      Type: TextNode,
++                      Data: "2",
++              },
++              6: {
++                      Type: ElementNode,
++                      Data: "b",
++                      Attr: []Attribute{
++                              {
++                                      Key: "empty",
++                                      Val: "",
++                              },
++                      },
++              },
++              7: {
++                      Type: TextNode,
++                      Data: "3",
++              },
++              8: {
++                      Type: ElementNode,
++                      Data: "i",
++                      Attr: []Attribute{
++                              {
++                                      Key: "backslash",
++                                      Val: `\`,
++                              },
++                      },
++              },
++              9: {
++                      Type: TextNode,
++                      Data: "&4",
++              },
++              10: {
++                      Type: TextNode,
++                      Data: "5",
++              },
++              11: {
++                      Type: ElementNode,
++                      Data: "blockquote",
++              },
++              12: {
++                      Type: ElementNode,
++                      Data: "br",
++              },
++              13: {
++                      Type: TextNode,
++                      Data: "6",
++              },
++              14: {
++                      Type: CommentNode,
++                      Data: "comm",
++              },
++              15: {
++                      Type: CommentNode,
++                      Data: "x-->y", // Needs escaping.
++              },
++              16: {
++                      Type: RawNode,
++                      Data: "7<pre>8</pre>9",
++              },
++      }
++
++      // Build a tree out of those nodes, based on a textual representation.
++      // Only the ".\t"s are significant. The trailing HTML-like text is
++      // just commentary. The "0:" prefixes are for easy cross-reference with
++      // the nodes array.
++      treeAsText := [...]string{
++              0:  `<html>`,
++              1:  `.  <head>`,
++              2:  `.  <body>`,
++              3:  `.  .       "0&lt;1"`,
++              4:  `.  .       <p id="A" foo="abc&#34;def">`,
++              5:  `.  .       .       "2"`,
++              6:  `.  .       .       <b empty="">`,
++              7:  `.  .       .       .       "3"`,
++              8:  `.  .       .       <i backslash="\">`,
++              9:  `.  .       .       .       "&amp;4"`,
++              10: `.  .       "5"`,
++              11: `.  .       <blockquote>`,
++              12: `.  .       <br>`,
++              13: `.  .       "6"`,
++              14: `.  .       "<!--comm-->"`,
++              15: `.  .       "<!--x--&gt;y-->"`,
++              16: `.  .       "7<pre>8</pre>9"`,
++      }
++      if len(nodes) != len(treeAsText) {
++              t.Fatal("len(nodes) != len(treeAsText)")
++      }
++      var stack [8]*Node
++      for i, line := range treeAsText {
++              level := 0
++              for line[0] == '.' {
++                      // Strip a leading ".\t".
++                      line = line[2:]
++                      level++
++              }
++              n := nodes[i]
++              if level == 0 {
++                      if stack[0] != nil {
++                              t.Fatal("multiple root nodes")
++                      }
++                      stack[0] = n
++              } else {
++                      stack[level-1].AppendChild(n)
++                      stack[level] = n
++                      for i := level + 1; i < len(stack); i++ {
++                              stack[i] = nil
++                      }
++              }
++              // At each stage of tree construction, we check all nodes for consistency.
++              for j, m := range nodes {
++                      if err := checkNodeConsistency(m); err != nil {
++                              t.Fatalf("i=%d, j=%d: %v", i, j, err)
++                      }
++              }
++      }
++
++      want := `<html><head></head><body>0&lt;1<p id="A" foo="abc&#34;def">` +
++              `2<b empty="">3</b><i backslash="\">&amp;4</i></p>` +
++              `5<blockquote></blockquote><br/>6<!--comm--><!--x--&gt;y-->7<pre>8</pre>9</body></html>`
++      b := new(bytes.Buffer)
++      if err := Render(b, nodes[0]); err != nil {
++              t.Fatal(err)
++      }
++      if got := b.String(); got != want {
++              t.Errorf("got vs want:\n%s\n%s\n", got, want)
++      }
++}
++
++func TestRenderTextNodes(t *testing.T) {
++      elements := []string{"style", "script", "xmp", "iframe", "noembed", "noframes", "plaintext", "noscript"}
++      for _, namespace := range []string{
++              "", // html
++              "svg",
++              "math",
++      } {
++              for _, e := range elements {
++                      var namespaceOpen, namespaceClose string
++                      if namespace != "" {
++                              namespaceOpen, namespaceClose = fmt.Sprintf("<%s>", namespace), fmt.Sprintf("</%s>", namespace)
++                      }
++                      doc := fmt.Sprintf(`<html><head></head><body>%s<%s>&</%s>%s</body></html>`, namespaceOpen, e, e, namespaceClose)
++                      n, err := Parse(strings.NewReader(doc))
++                      if err != nil {
++                              t.Fatal(err)
++                      }
++                      b := bytes.NewBuffer(nil)
++                      if err := Render(b, n); err != nil {
++                              t.Fatal(err)
++                      }
++
++                      expected := doc
++                      if namespace != "" {
++                              expected = strings.Replace(expected, "&", "&amp;", 1)
++                      }
++
++                      if b.String() != expected {
++                              t.Errorf("unexpected output: got %q, want %q", b.String(), expected)
++                      }
++              }
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..741f4b1ae8d77e3d5898a0a353b59a3db090b7fb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,12 @@@
++#data
++<table><math><th><mo><select></table>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math th>
++|         <math mo>
++|           <select>
++|     <table>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e31496443cd917a260713ba2a1308843d67dea0d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,11 @@@
++#data
++<html><head></head><body><tag1><tag2 /><p></p></tag1><div></div></body></html>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <tag1>
++|       <tag2>
++|         <p>
++|     <div>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..50bac597d4fea8dcd5fc69773e60ebcf71be4b5d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,97 @@@
++#data
++<!doctype html><table><select><iframe>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><noembed>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><noframes>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><noscript>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><style>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><title>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><table><select><xmp>a<caption>b
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..684554c8afb1db3ee6c6874091a19c42c3a35f05
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,12 @@@
++#data
++<table><math><select><mi><select></table>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math select>
++|         <math mi>
++|           <select>
++|     <table>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b923b0ff0b69afc0af694bee23df464b92a42547
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,64 @@@
++#data
++<body><template><yt-icon-button></yt-icon-button><form><paper-input></paper-input></form><style></style></template>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <yt-icon-button>
++|         <form>
++|           <paper-input>
++|         <style>
++
++#data
++<template><tBody><isindex/action=0>
++#errors
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <tbody>
++|         <isindex>
++|           action="0"
++|   <body>
++
++#data
++<math><template><mo><template>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math template>
++|         <math mo>
++|           <template>
++|             content
++
++#data
++<svg><template><desc><t><svg></template>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg template>
++|         <svg desc>
++|           <t>
++|             <svg svg>
++
++#data
++<math><template><mn><b></template>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math template>
++|         <math mn>
++|           <b>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..086c011cb14e078ef028ec7d2f04c633e94fb8aa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2237 @@@
++<!DOCTYPE html>
++<html>
++<head>
++<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
++
++  <title>Go 1 Release Notes - The Go Programming Language</title>
++
++<link type="text/css" rel="stylesheet" href="/doc/style.css">
++<script type="text/javascript" src="/doc/godocs.js"></script>
++
++<link rel="search" type="application/opensearchdescription+xml" title="godoc" href="/opensearch.xml" />
++
++<script type="text/javascript">
++var _gaq = _gaq || [];
++_gaq.push(["_setAccount", "UA-11222381-2"]);
++_gaq.push(["_trackPageview"]);
++</script>
++</head>
++<body>
++
++<div id="topbar"><div class="container wide">
++
++<form method="GET" action="/search">
++<div id="menu">
++<a href="/doc/">Documents</a>
++<a href="/ref/">References</a>
++<a href="/pkg/">Packages</a>
++<a href="/project/">The Project</a>
++<a href="/help/">Help</a>
++<input type="text" id="search" name="q" class="inactive" value="Search">
++</div>
++<div id="heading"><a href="/">The Go Programming Language</a></div>
++</form>
++
++</div></div>
++
++<div id="page" class="wide">
++
++
++  <div id="minusone"><g:minusone size="small" annotation="none"></g:minusone></div>
++  <h1>Go 1 Release Notes</h1>
++
++
++
++
++<div id="nav"></div>
++
++
++
++
++<h2 id="introduction">Introduction to Go 1</h2>
++
++<p>
++Go version 1, Go 1 for short, defines a language and a set of core libraries
++that provide a stable foundation for creating reliable products, projects, and
++publications.
++</p>
++
++<p>
++The driving motivation for Go 1 is stability for its users. People should be able to
++write Go programs and expect that they will continue to compile and run without
++change, on a time scale of years, including in production environments such as
++Google App Engine. Similarly, people should be able to write books about Go, be
++able to say which version of Go the book is describing, and have that version
++number still be meaningful much later.
++</p>
++
++<p>
++Code that compiles in Go 1 should, with few exceptions, continue to compile and
++run throughout the lifetime of that version, even as we issue updates and bug
++fixes such as Go version 1.1, 1.2, and so on. Other than critical fixes, changes
++made to the language and library for subsequent releases of Go 1 may
++add functionality but will not break existing Go 1 programs.
++<a href="go1compat.html">The Go 1 compatibility document</a>
++explains the compatibility guidelines in more detail.
++</p>
++
++<p>
++Go 1 is a representation of Go as it used today, not a wholesale rethinking of
++the language. We avoided designing new features and instead focused on cleaning
++up problems and inconsistencies and improving portability. There are a number
++changes to the Go language and packages that we had considered for some time and
++prototyped but not released primarily because they are significant and
++backwards-incompatible. Go 1 was an opportunity to get them out, which is
++helpful for the long term, but also means that Go 1 introduces incompatibilities
++for old programs. Fortunately, the <code>go</code> <code>fix</code> tool can
++automate much of the work needed to bring programs up to the Go 1 standard.
++</p>
++
++<p>
++This document outlines the major changes in Go 1 that will affect programmers
++updating existing code; its reference point is the prior release, r60 (tagged as
++r60.3). It also explains how to update code from r60 to run under Go 1.
++</p>
++
++<h2 id="language">Changes to the language</h2>
++
++<h3 id="append">Append</h3>
++
++<p>
++The <code>append</code> predeclared variadic function makes it easy to grow a slice
++by adding elements to the end.
++A common use is to add bytes to the end of a byte slice when generating output.
++However, <code>append</code> did not provide a way to append a string to a <code>[]byte</code>,
++which is another common case.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/greeting := ..byte/` `/append.*hello/`}}
++-->    greeting := []byte{}
++    greeting = append(greeting, []byte(&#34;hello &#34;)...)</pre>
++
++<p>
++By analogy with the similar property of <code>copy</code>, Go 1
++permits a string to be appended (byte-wise) directly to a byte
++slice, reducing the friction between strings and byte slices.
++The conversion is no longer necessary:
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/append.*world/`}}
++-->    greeting = append(greeting, &#34;world&#34;...)</pre>
++
++<p>
++<em>Updating</em>:
++This is a new feature, so existing code needs no changes.
++</p>
++
++<h3 id="close">Close</h3>
++
++<p>
++The <code>close</code> predeclared function provides a mechanism
++for a sender to signal that no more values will be sent.
++It is important to the implementation of <code>for</code> <code>range</code>
++loops over channels and is helpful in other situations.
++Partly by design and partly because of race conditions that can occur otherwise,
++it is intended for use only by the goroutine sending on the channel,
++not by the goroutine receiving data.
++However, before Go 1 there was no compile-time checking that <code>close</code>
++was being used correctly.
++</p>
++
++<p>
++To close this gap, at least in part, Go 1 disallows <code>close</code> on receive-only channels.
++Attempting to close such a channel is a compile-time error.
++</p>
++
++<pre>
++    var c chan int
++    var csend chan&lt;- int = c
++    var crecv &lt;-chan int = c
++    close(c)     // legal
++    close(csend) // legal
++    close(crecv) // illegal
++</pre>
++
++<p>
++<em>Updating</em>:
++Existing code that attempts to close a receive-only channel was
++erroneous even before Go 1 and should be fixed.  The compiler will
++now reject such code.
++</p>
++
++<h3 id="literals">Composite literals</h3>
++
++<p>
++In Go 1, a composite literal of array, slice, or map type can elide the
++type specification for the elements' initializers if they are of pointer type.
++All four of the initializations in this example are legal; the last one was illegal before Go 1.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/type Date struct/` `/STOP/`}}
++-->    type Date struct {
++        month string
++        day   int
++    }
++    <span class="comment">// Struct values, fully qualified; always legal.</span>
++    holiday1 := []Date{
++        Date{&#34;Feb&#34;, 14},
++        Date{&#34;Nov&#34;, 11},
++        Date{&#34;Dec&#34;, 25},
++    }
++    <span class="comment">// Struct values, type name elided; always legal.</span>
++    holiday2 := []Date{
++        {&#34;Feb&#34;, 14},
++        {&#34;Nov&#34;, 11},
++        {&#34;Dec&#34;, 25},
++    }
++    <span class="comment">// Pointers, fully qualified, always legal.</span>
++    holiday3 := []*Date{
++        &amp;Date{&#34;Feb&#34;, 14},
++        &amp;Date{&#34;Nov&#34;, 11},
++        &amp;Date{&#34;Dec&#34;, 25},
++    }
++    <span class="comment">// Pointers, type name elided; legal in Go 1.</span>
++    holiday4 := []*Date{
++        {&#34;Feb&#34;, 14},
++        {&#34;Nov&#34;, 11},
++        {&#34;Dec&#34;, 25},
++    }</pre>
++
++<p>
++<em>Updating</em>:
++This change has no effect on existing code, but the command
++<code>gofmt</code> <code>-s</code> applied to existing source
++will, among other things, elide explicit element types wherever permitted.
++</p>
++
++
++<h3 id="init">Goroutines during init</h3>
++
++<p>
++The old language defined that <code>go</code> statements executed during initialization created goroutines but that they did not begin to run until initialization of the entire program was complete.
++This introduced clumsiness in many places and, in effect, limited the utility
++of the <code>init</code> construct:
++if it was possible for another package to use the library during initialization, the library
++was forced to avoid goroutines.
++This design was done for reasons of simplicity and safety but,
++as our confidence in the language grew, it seemed unnecessary.
++Running goroutines during initialization is no more complex or unsafe than running them during normal execution.
++</p>
++
++<p>
++In Go 1, code that uses goroutines can be called from
++<code>init</code> routines and global initialization expressions
++without introducing a deadlock.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/PackageGlobal/` `/^}/`}}
++-->var PackageGlobal int
++
++func init() {
++    c := make(chan int)
++    go initializationFunction(c)
++    PackageGlobal = &lt;-c
++}</pre>
++
++<p>
++<em>Updating</em>:
++This is a new feature, so existing code needs no changes,
++although it's possible that code that depends on goroutines not starting before <code>main</code> will break.
++There was no such code in the standard repository.
++</p>
++
++<h3 id="rune">The rune type</h3>
++
++<p>
++The language spec allows the <code>int</code> type to be 32 or 64 bits wide, but current implementations set <code>int</code> to 32 bits even on 64-bit platforms.
++It would be preferable to have <code>int</code> be 64 bits on 64-bit platforms.
++(There are important consequences for indexing large slices.)
++However, this change would waste space when processing Unicode characters with
++the old language because the <code>int</code> type was also used to hold Unicode code points: each code point would waste an extra 32 bits of storage if <code>int</code> grew from 32 bits to 64.
++</p>
++
++<p>
++To make changing to 64-bit <code>int</code> feasible,
++Go 1 introduces a new basic type, <code>rune</code>, to represent
++individual Unicode code points.
++It is an alias for <code>int32</code>, analogous to <code>byte</code>
++as an alias for <code>uint8</code>.
++</p>
++
++<p>
++Character literals such as <code>'a'</code>, <code>'語'</code>, and <code>'\u0345'</code>
++now have default type <code>rune</code>,
++analogous to <code>1.0</code> having default type <code>float64</code>.
++A variable initialized to a character constant will therefore
++have type <code>rune</code> unless otherwise specified.
++</p>
++
++<p>
++Libraries have been updated to use <code>rune</code> rather than <code>int</code>
++when appropriate. For instance, the functions <code>unicode.ToLower</code> and
++relatives now take and return a <code>rune</code>.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/STARTRUNE/` `/ENDRUNE/`}}
++-->    delta := &#39;δ&#39; <span class="comment">// delta has type rune.</span>
++    var DELTA rune
++    DELTA = unicode.ToUpper(delta)
++    epsilon := unicode.ToLower(DELTA + 1)
++    if epsilon != &#39;δ&#39;+1 {
++        log.Fatal(&#34;inconsistent casing for Greek&#34;)
++    }</pre>
++
++<p>
++<em>Updating</em>:
++Most source code will be unaffected by this because the type inference from
++<code>:=</code> initializers introduces the new type silently, and it propagates
++from there.
++Some code may get type errors that a trivial conversion will resolve.
++</p>
++
++<h3 id="error">The error type</h3>
++
++<p>
++Go 1 introduces a new built-in type, <code>error</code>, which has the following definition:
++</p>
++
++<pre>
++    type error interface {
++        Error() string
++    }
++</pre>
++
++<p>
++Since the consequences of this type are all in the package library,
++it is discussed <a href="#errors">below</a>.
++</p>
++
++<h3 id="delete">Deleting from maps</h3>
++
++<p>
++In the old language, to delete the entry with key <code>k</code> from map <code>m</code>, one wrote the statement,
++</p>
++
++<pre>
++    m[k] = value, false
++</pre>
++
++<p>
++This syntax was a peculiar special case, the only two-to-one assignment.
++It required passing a value (usually ignored) that is evaluated but discarded,
++plus a boolean that was nearly always the constant <code>false</code>.
++It did the job but was odd and a point of contention.
++</p>
++
++<p>
++In Go 1, that syntax has gone; instead there is a new built-in
++function, <code>delete</code>.  The call
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/delete\(m, k\)/`}}
++-->    delete(m, k)</pre>
++
++<p>
++will delete the map entry retrieved by the expression <code>m[k]</code>.
++There is no return value. Deleting a non-existent entry is a no-op.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will convert expressions of the form <code>m[k] = value,
++false</code> into <code>delete(m, k)</code> when it is clear that
++the ignored value can be safely discarded from the program and
++<code>false</code> refers to the predefined boolean constant.
++The fix tool
++will flag other uses of the syntax for inspection by the programmer.
++</p>
++
++<h3 id="iteration">Iterating in maps</h3>
++
++<p>
++The old language specification did not define the order of iteration for maps,
++and in practice it differed across hardware platforms.
++This caused tests that iterated over maps to be fragile and non-portable, with the
++unpleasant property that a test might always pass on one machine but break on another.
++</p>
++
++<p>
++In Go 1, the order in which elements are visited when iterating
++over a map using a <code>for</code> <code>range</code> statement
++is defined to be unpredictable, even if the same loop is run multiple
++times with the same map.
++Code should not assume that the elements are visited in any particular order.
++</p>
++
++<p>
++This change means that code that depends on iteration order is very likely to break early and be fixed long before it becomes a problem.
++Just as important, it allows the map implementation to ensure better map balancing even when programs are using range loops to select an element from a map.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/Sunday/` `/^    }/`}}
++-->    m := map[string]int{&#34;Sunday&#34;: 0, &#34;Monday&#34;: 1}
++    for name, value := range m {
++        <span class="comment">// This loop should not assume Sunday will be visited first.</span>
++        f(name, value)
++    }</pre>
++
++<p>
++<em>Updating</em>:
++This is one change where tools cannot help.  Most existing code
++will be unaffected, but some programs may break or misbehave; we
++recommend manual checking of all range statements over maps to
++verify they do not depend on iteration order. There were a few such
++examples in the standard repository; they have been fixed.
++Note that it was already incorrect to depend on the iteration order, which
++was unspecified. This change codifies the unpredictability.
++</p>
++
++<h3 id="multiple_assignment">Multiple assignment</h3>
++
++<p>
++The language specification has long guaranteed that in assignments
++the right-hand-side expressions are all evaluated before any left-hand-side expressions are assigned.
++To guarantee predictable behavior,
++Go 1 refines the specification further.
++</p>
++
++<p>
++If the left-hand side of the assignment
++statement contains expressions that require evaluation, such as
++function calls or array indexing operations, these will all be done
++using the usual left-to-right rule before any variables are assigned
++their value.  Once everything is evaluated, the actual assignments
++proceed in left-to-right order.
++</p>
++
++<p>
++These examples illustrate the behavior.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/sa :=/` `/then sc.0. = 2/`}}
++-->    sa := []int{1, 2, 3}
++    i := 0
++    i, sa[i] = 1, 2 <span class="comment">// sets i = 1, sa[0] = 2</span>
++
++    sb := []int{1, 2, 3}
++    j := 0
++    sb[j], j = 2, 1 <span class="comment">// sets sb[0] = 2, j = 1</span>
++
++    sc := []int{1, 2, 3}
++    sc[0], sc[0] = 1, 2 <span class="comment">// sets sc[0] = 1, then sc[0] = 2 (so sc[0] = 2 at end)</span></pre>
++
++<p>
++<em>Updating</em>:
++This is one change where tools cannot help, but breakage is unlikely.
++No code in the standard repository was broken by this change, and code
++that depended on the previous unspecified behavior was already incorrect.
++</p>
++
++<h3 id="shadowing">Returns and shadowed variables</h3>
++
++<p>
++A common mistake is to use <code>return</code> (without arguments) after an assignment to a variable that has the same name as a result variable but is not the same variable.
++This situation is called <em>shadowing</em>: the result variable has been shadowed by another variable with the same name declared in an inner scope.
++</p>
++
++<p>
++In functions with named return values,
++the Go 1 compilers disallow return statements without arguments if any of the named return values is shadowed at the point of the return statement.
++(It isn't part of the specification, because this is one area we are still exploring;
++the situation is analogous to the compilers rejecting functions that do not end with an explicit return statement.)
++</p>
++
++<p>
++This function implicitly returns a shadowed return value and will be rejected by the compiler:
++</p>
++
++<pre>
++    func Bug() (i, j, k int) {
++        for i = 0; i &lt; 5; i++ {
++            for j := 0; j &lt; 5; j++ { // Redeclares j.
++                k += i*j
++                if k > 100 {
++                    return // Rejected: j is shadowed here.
++                }
++            }
++        }
++        return // OK: j is not shadowed here.
++    }
++</pre>
++
++<p>
++<em>Updating</em>:
++Code that shadows return values in this way will be rejected by the compiler and will need to be fixed by hand.
++The few cases that arose in the standard repository were mostly bugs.
++</p>
++
++<h3 id="unexported">Copying structs with unexported fields</h3>
++
++<p>
++The old language did not allow a package to make a copy of a struct value containing unexported fields belonging to a different package.
++There was, however, a required exception for a method receiver;
++also, the implementations of <code>copy</code> and <code>append</code> have never honored the restriction.
++</p>
++
++<p>
++Go 1 will allow packages to copy struct values containing unexported fields from other packages.
++Besides resolving the inconsistency,
++this change admits a new kind of API: a package can return an opaque value without resorting to a pointer or interface.
++The new implementations of <code>time.Time</code> and
++<code>reflect.Value</code> are examples of types taking advantage of this new property.
++</p>
++
++<p>
++As an example, if package <code>p</code> includes the definitions,
++</p>
++
++<pre>
++    type Struct struct {
++        Public int
++        secret int
++    }
++    func NewStruct(a int) Struct {  // Note: not a pointer.
++        return Struct{a, f(a)}
++    }
++    func (s Struct) String() string {
++        return fmt.Sprintf("{%d (secret %d)}", s.Public, s.secret)
++    }
++</pre>
++
++<p>
++a package that imports <code>p</code> can assign and copy values of type
++<code>p.Struct</code> at will.
++Behind the scenes the unexported fields will be assigned and copied just
++as if they were exported,
++but the client code will never be aware of them. The code
++</p>
++
++<pre>
++    import "p"
++
++    myStruct := p.NewStruct(23)
++    copyOfMyStruct := myStruct
++    fmt.Println(myStruct, copyOfMyStruct)
++</pre>
++
++<p>
++will show that the secret field of the struct has been copied to the new value.
++</p>
++
++<p>
++<em>Updating</em>:
++This is a new feature, so existing code needs no changes.
++</p>
++
++<h3 id="equality">Equality</h3>
++
++<p>
++Before Go 1, the language did not define equality on struct and array values.
++This meant,
++among other things, that structs and arrays could not be used as map keys.
++On the other hand, Go did define equality on function and map values.
++Function equality was problematic in the presence of closures
++(when are two closures equal?)
++while map equality compared pointers, not the maps' content, which was usually
++not what the user would want.
++</p>
++
++<p>
++Go 1 addressed these issues.
++First, structs and arrays can be compared for equality and inequality
++(<code>==</code> and <code>!=</code>),
++and therefore be used as map keys,
++provided they are composed from elements for which equality is also defined,
++using element-wise comparison.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/type Day struct/` `/Printf/`}}
++-->    type Day struct {
++        long  string
++        short string
++    }
++    Christmas := Day{&#34;Christmas&#34;, &#34;XMas&#34;}
++    Thanksgiving := Day{&#34;Thanksgiving&#34;, &#34;Turkey&#34;}
++    holiday := map[Day]bool{
++        Christmas:    true,
++        Thanksgiving: true,
++    }
++    fmt.Printf(&#34;Christmas is a holiday: %t\n&#34;, holiday[Christmas])</pre>
++
++<p>
++Second, Go 1 removes the definition of equality for function values,
++except for comparison with <code>nil</code>.
++Finally, map equality is gone too, also except for comparison with <code>nil</code>.
++</p>
++
++<p>
++Note that equality is still undefined for slices, for which the
++calculation is in general infeasible.  Also note that the ordered
++comparison operators (<code>&lt;</code> <code>&lt;=</code>
++<code>&gt;</code> <code>&gt;=</code>) are still undefined for
++structs and arrays.
++
++<p>
++<em>Updating</em>:
++Struct and array equality is a new feature, so existing code needs no changes.
++Existing code that depends on function or map equality will be
++rejected by the compiler and will need to be fixed by hand.
++Few programs will be affected, but the fix may require some
++redesign.
++</p>
++
++<h2 id="packages">The package hierarchy</h2>
++
++<p>
++Go 1 addresses many deficiencies in the old standard library and
++cleans up a number of packages, making them more internally consistent
++and portable.
++</p>
++
++<p>
++This section describes how the packages have been rearranged in Go 1.
++Some have moved, some have been renamed, some have been deleted.
++New packages are described in later sections.
++</p>
++
++<h3 id="hierarchy">The package hierarchy</h3>
++
++<p>
++Go 1 has a rearranged package hierarchy that groups related items
++into subdirectories. For instance, <code>utf8</code> and
++<code>utf16</code> now occupy subdirectories of <code>unicode</code>.
++Also, <a href="#subrepo">some packages</a> have moved into
++subrepositories of
++<a href="http://code.google.com/p/go"><code>code.google.com/p/go</code></a>
++while <a href="#deleted">others</a> have been deleted outright.
++</p>
++
++<table class="codetable" frame="border" summary="Moved packages">
++<colgroup align="left" width="60%"></colgroup>
++<colgroup align="left" width="40%"></colgroup>
++<tr>
++<th align="left">Old path</th>
++<th align="left">New path</th>
++</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>asn1</td> <td>encoding/asn1</td></tr>
++<tr><td>csv</td> <td>encoding/csv</td></tr>
++<tr><td>gob</td> <td>encoding/gob</td></tr>
++<tr><td>json</td> <td>encoding/json</td></tr>
++<tr><td>xml</td> <td>encoding/xml</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>exp/template/html</td> <td>html/template</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>big</td> <td>math/big</td></tr>
++<tr><td>cmath</td> <td>math/cmplx</td></tr>
++<tr><td>rand</td> <td>math/rand</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>http</td> <td>net/http</td></tr>
++<tr><td>http/cgi</td> <td>net/http/cgi</td></tr>
++<tr><td>http/fcgi</td> <td>net/http/fcgi</td></tr>
++<tr><td>http/httptest</td> <td>net/http/httptest</td></tr>
++<tr><td>http/pprof</td> <td>net/http/pprof</td></tr>
++<tr><td>mail</td> <td>net/mail</td></tr>
++<tr><td>rpc</td> <td>net/rpc</td></tr>
++<tr><td>rpc/jsonrpc</td> <td>net/rpc/jsonrpc</td></tr>
++<tr><td>smtp</td> <td>net/smtp</td></tr>
++<tr><td>url</td> <td>net/url</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>exec</td> <td>os/exec</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>scanner</td> <td>text/scanner</td></tr>
++<tr><td>tabwriter</td> <td>text/tabwriter</td></tr>
++<tr><td>template</td> <td>text/template</td></tr>
++<tr><td>template/parse</td> <td>text/template/parse</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>utf8</td> <td>unicode/utf8</td></tr>
++<tr><td>utf16</td> <td>unicode/utf16</td></tr>
++</table>
++
++<p>
++Note that the package names for the old <code>cmath</code> and
++<code>exp/template/html</code> packages have changed to <code>cmplx</code>
++and <code>template</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update all imports and package renames for packages that
++remain inside the standard repository.  Programs that import packages
++that are no longer in the standard repository will need to be edited
++by hand.
++</p>
++
++<h3 id="exp">The package tree exp</h3>
++
++<p>
++Because they are not standardized, the packages under the <code>exp</code> directory will not be available in the
++standard Go 1 release distributions, although they will be available in source code form
++in <a href="http://code.google.com/p/go/">the repository</a> for
++developers who wish to use them.
++</p>
++
++<p>
++Several packages have moved under <code>exp</code> at the time of Go 1's release:
++</p>
++
++<ul>
++<li><code>ebnf</code></li>
++<li><code>html</code><sup>&#8224;</sup></li>
++<li><code>go/types</code></li>
++</ul>
++
++<p>
++(<sup>&#8224;</sup>The <code>EscapeString</code> and <code>UnescapeString</code> types remain
++in package <code>html</code>.)
++</p>
++
++<p>
++All these packages are available under the same names, with the prefix <code>exp/</code>: <code>exp/ebnf</code> etc.
++</p>
++
++<p>
++Also, the <code>utf8.String</code> type has been moved to its own package, <code>exp/utf8string</code>.
++</p>
++
++<p>
++Finally, the <code>gotype</code> command now resides in <code>exp/gotype</code>, while
++<code>ebnflint</code> is now in <code>exp/ebnflint</code>.
++If they are installed, they now reside in <code>$GOROOT/bin/tool</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses packages in <code>exp</code> will need to be updated by hand,
++or else compiled from an installation that has <code>exp</code> available.
++The <code>go</code> <code>fix</code> tool or the compiler will complain about such uses.
++</p>
++
++<h3 id="old">The package tree old</h3>
++
++<p>
++Because they are deprecated, the packages under the <code>old</code> directory will not be available in the
++standard Go 1 release distributions, although they will be available in source code form for
++developers who wish to use them.
++</p>
++
++<p>
++The packages in their new locations are:
++</p>
++
++<ul>
++<li><code>old/netchan</code></li>
++<li><code>old/regexp</code></li>
++<li><code>old/template</code></li>
++</ul>
++
++<p>
++<em>Updating</em>:
++Code that uses packages now in <code>old</code> will need to be updated by hand,
++or else compiled from an installation that has <code>old</code> available.
++The <code>go</code> <code>fix</code> tool will warn about such uses.
++</p>
++
++<h3 id="deleted">Deleted packages</h3>
++
++<p>
++Go 1 deletes several packages outright:
++</p>
++
++<ul>
++<li><code>container/vector</code></li>
++<li><code>exp/datafmt</code></li>
++<li><code>go/typechecker</code></li>
++<li><code>try</code></li>
++</ul>
++
++<p>
++and also the command <code>gotry</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses <code>container/vector</code> should be updated to use
++slices directly.  See
++<a href="http://code.google.com/p/go-wiki/wiki/SliceTricks">the Go
++Language Community Wiki</a> for some suggestions.
++Code that uses the other packages (there should be almost zero) will need to be rethought.
++</p>
++
++<h3 id="subrepo">Packages moving to subrepositories</h3>
++
++<p>
++Go 1 has moved a number of packages into other repositories, usually sub-repositories of
++<a href="http://code.google.com/p/go/">the main Go repository</a>.
++This table lists the old and new import paths:
++
++<table class="codetable" frame="border" summary="Sub-repositories">
++<colgroup align="left" width="40%"></colgroup>
++<colgroup align="left" width="60%"></colgroup>
++<tr>
++<th align="left">Old</th>
++<th align="left">New</th>
++</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>crypto/bcrypt</td> <td>code.google.com/p/go.crypto/bcrypt</tr>
++<tr><td>crypto/blowfish</td> <td>code.google.com/p/go.crypto/blowfish</tr>
++<tr><td>crypto/cast5</td> <td>code.google.com/p/go.crypto/cast5</tr>
++<tr><td>crypto/md4</td> <td>code.google.com/p/go.crypto/md4</tr>
++<tr><td>crypto/ocsp</td> <td>code.google.com/p/go.crypto/ocsp</tr>
++<tr><td>crypto/openpgp</td> <td>code.google.com/p/go.crypto/openpgp</tr>
++<tr><td>crypto/openpgp/armor</td> <td>code.google.com/p/go.crypto/openpgp/armor</tr>
++<tr><td>crypto/openpgp/elgamal</td> <td>code.google.com/p/go.crypto/openpgp/elgamal</tr>
++<tr><td>crypto/openpgp/errors</td> <td>code.google.com/p/go.crypto/openpgp/errors</tr>
++<tr><td>crypto/openpgp/packet</td> <td>code.google.com/p/go.crypto/openpgp/packet</tr>
++<tr><td>crypto/openpgp/s2k</td> <td>code.google.com/p/go.crypto/openpgp/s2k</tr>
++<tr><td>crypto/ripemd160</td> <td>code.google.com/p/go.crypto/ripemd160</tr>
++<tr><td>crypto/twofish</td> <td>code.google.com/p/go.crypto/twofish</tr>
++<tr><td>crypto/xtea</td> <td>code.google.com/p/go.crypto/xtea</tr>
++<tr><td>exp/ssh</td> <td>code.google.com/p/go.crypto/ssh</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>image/bmp</td> <td>code.google.com/p/go.image/bmp</tr>
++<tr><td>image/tiff</td> <td>code.google.com/p/go.image/tiff</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>net/dict</td> <td>code.google.com/p/go.net/dict</tr>
++<tr><td>net/websocket</td> <td>code.google.com/p/go.net/websocket</tr>
++<tr><td>exp/spdy</td> <td>code.google.com/p/go.net/spdy</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>encoding/git85</td> <td>code.google.com/p/go.codereview/git85</tr>
++<tr><td>patch</td> <td>code.google.com/p/go.codereview/patch</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>exp/wingui</td> <td>code.google.com/p/gowingui</tr>
++</table>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update imports of these packages to use the new import paths.
++Installations that depend on these packages will need to install them using
++a <code>go get</code> command.
++</p>
++
++<h2 id="major">Major changes to the library</h2>
++
++<p>
++This section describes significant changes to the core libraries, the ones that
++affect the most programs.
++</p>
++
++<h3 id="errors">The error type and errors package</h3>
++
++<p>
++The placement of <code>os.Error</code> in package <code>os</code> is mostly historical: errors first came up when implementing package <code>os</code>, and they seemed system-related at the time.
++Since then it has become clear that errors are more fundamental than the operating system.  For example, it would be nice to use <code>Errors</code> in packages that <code>os</code> depends on, like <code>syscall</code>.
++Also, having <code>Error</code> in <code>os</code> introduces many dependencies on <code>os</code> that would otherwise not exist.
++</p>
++
++<p>
++Go 1 solves these problems by introducing a built-in <code>error</code> interface type and a separate <code>errors</code> package (analogous to <code>bytes</code> and <code>strings</code>) that contains utility functions.
++It replaces <code>os.NewError</code> with
++<a href="/pkg/errors/#New"><code>errors.New</code></a>,
++giving errors a more central place in the environment.
++</p>
++
++<p>
++So the widely-used <code>String</code> method does not cause accidental satisfaction
++of the <code>error</code> interface, the <code>error</code> interface uses instead
++the name <code>Error</code> for that method:
++</p>
++
++<pre>
++    type error interface {
++        Error() string
++    }
++</pre>
++
++<p>
++The <code>fmt</code> library automatically invokes <code>Error</code>, as it already
++does for <code>String</code>, for easy printing of error values.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/START ERROR EXAMPLE/` `/END ERROR EXAMPLE/`}}
++-->type SyntaxError struct {
++    File    string
++    Line    int
++    Message string
++}
++
++func (se *SyntaxError) Error() string {
++    return fmt.Sprintf(&#34;%s:%d: %s&#34;, se.File, se.Line, se.Message)
++}</pre>
++
++<p>
++All standard packages have been updated to use the new interface; the old <code>os.Error</code> is gone.
++</p>
++
++<p>
++A new package, <a href="/pkg/errors/"><code>errors</code></a>, contains the function
++</p>
++
++<pre>
++func New(text string) error
++</pre>
++
++<p>
++to turn a string into an error. It replaces the old <code>os.NewError</code>.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/ErrSyntax/`}}
++-->    var ErrSyntax = errors.New(&#34;syntax error&#34;)</pre>
++              
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
++Code that defines error types with a <code>String</code> method will need to be updated
++by hand to rename the methods to <code>Error</code>.
++</p>
++
++<h3 id="errno">System call errors</h3>
++
++<p>
++The old <code>syscall</code> package, which predated <code>os.Error</code>
++(and just about everything else),
++returned errors as <code>int</code> values.
++In turn, the <code>os</code> package forwarded many of these errors, such
++as <code>EINVAL</code>, but using a different set of errors on each platform.
++This behavior was unpleasant and unportable.
++</p>
++
++<p>
++In Go 1, the
++<a href="/pkg/syscall/"><code>syscall</code></a>
++package instead returns an <code>error</code> for system call errors.
++On Unix, the implementation is done by a
++<a href="/pkg/syscall/#Errno"><code>syscall.Errno</code></a> type
++that satisfies <code>error</code> and replaces the old <code>os.Errno</code>.
++</p>
++
++<p>
++The changes affecting <code>os.EINVAL</code> and relatives are
++described <a href="#os">elsewhere</a>.
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
++Regardless, most code should use the <code>os</code> package
++rather than <code>syscall</code> and so will be unaffected.
++</p>
++
++<h3 id="time">Time</h3>
++
++<p>
++Time is always a challenge to support well in a programming language.
++The old Go <code>time</code> package had <code>int64</code> units, no
++real type safety,
++and no distinction between absolute times and durations.
++</p>
++
++<p>
++One of the most sweeping changes in the Go 1 library is therefore a
++complete redesign of the
++<a href="/pkg/time/"><code>time</code></a> package.
++Instead of an integer number of nanoseconds as an <code>int64</code>,
++and a separate <code>*time.Time</code> type to deal with human
++units such as hours and years,
++there are now two fundamental types:
++<a href="/pkg/time/#Time"><code>time.Time</code></a>
++(a value, so the <code>*</code> is gone), which represents a moment in time;
++and <a href="/pkg/time/#Duration"><code>time.Duration</code></a>,
++which represents an interval.
++Both have nanosecond resolution.
++A <code>Time</code> can represent any time into the ancient
++past and remote future, while a <code>Duration</code> can
++span plus or minus only about 290 years.
++There are methods on these types, plus a number of helpful
++predefined constant durations such as <code>time.Second</code>.
++</p>
++
++<p>
++Among the new methods are things like
++<a href="/pkg/time/#Time.Add"><code>Time.Add</code></a>,
++which adds a <code>Duration</code> to a <code>Time</code>, and
++<a href="/pkg/time/#Time.Sub"><code>Time.Sub</code></a>,
++which subtracts two <code>Times</code> to yield a <code>Duration</code>.
++</p>
++
++<p>
++The most important semantic change is that the Unix epoch (Jan 1, 1970) is now
++relevant only for those functions and methods that mention Unix:
++<a href="/pkg/time/#Unix"><code>time.Unix</code></a>
++and the <a href="/pkg/time/#Time.Unix"><code>Unix</code></a>
++and <a href="/pkg/time/#Time.UnixNano"><code>UnixNano</code></a> methods
++of the <code>Time</code> type.
++In particular,
++<a href="/pkg/time/#Now"><code>time.Now</code></a>
++returns a <code>time.Time</code> value rather than, in the old
++API, an integer nanosecond count since the Unix epoch.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/sleepUntil/` `/^}/`}}
++--><span class="comment">// sleepUntil sleeps until the specified time. It returns immediately if it&#39;s too late.</span>
++func sleepUntil(wakeup time.Time) {
++    now := time.Now() <span class="comment">// A Time.</span>
++    if !wakeup.After(now) {
++        return
++    }
++    delta := wakeup.Sub(now) <span class="comment">// A Duration.</span>
++    fmt.Printf(&#34;Sleeping for %.3fs\n&#34;, delta.Seconds())
++    time.Sleep(delta)
++}</pre>
++
++<p>
++The new types, methods, and constants have been propagated through
++all the standard packages that use time, such as <code>os</code> and
++its representation of file time stamps.
++</p>
++
++<p>
++<em>Updating</em>:
++The <code>go</code> <code>fix</code> tool will update many uses of the old <code>time</code> package to use the new
++types and methods, although it does not replace values such as <code>1e9</code>
++representing nanoseconds per second.
++Also, because of type changes in some of the values that arise,
++some of the expressions rewritten by the fix tool may require
++further hand editing; in such cases the rewrite will include
++the correct function or method for the old functionality, but
++may have the wrong type or require further analysis.
++</p>
++
++<h2 id="minor">Minor changes to the library</h2>
++
++<p>
++This section describes smaller changes, such as those to less commonly
++used packages or that affect
++few programs beyond the need to run <code>go</code> <code>fix</code>.
++This category includes packages that are new in Go 1.
++Collectively they improve portability, regularize behavior, and
++make the interfaces more modern and Go-like.
++</p>
++
++<h3 id="archive_zip">The archive/zip package</h3>
++
++<p>
++In Go 1, <a href="/pkg/archive/zip/#Writer"><code>*zip.Writer</code></a> no
++longer has a <code>Write</code> method. Its presence was a mistake.
++</p>
++
++<p>
++<em>Updating</em>:
++What little code is affected will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="bufio">The bufio package</h3>
++
++<p>
++In Go 1, <a href="/pkg/bufio/#NewReaderSize"><code>bufio.NewReaderSize</code></a>
++and
++<a href="/pkg/bufio/#NewWriterSize"><code>bufio.NewWriterSize</code></a>
++functions no longer return an error for invalid sizes.
++If the argument size is too small or invalid, it is adjusted.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update calls that assign the error to _.
++Calls that aren't fixed will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="compress">The compress/flate, compress/gzip and compress/zlib packages</h3>
++
++<p>
++In Go 1, the <code>NewWriterXxx</code> functions in
++<a href="/pkg/compress/flate"><code>compress/flate</code></a>,
++<a href="/pkg/compress/gzip"><code>compress/gzip</code></a> and
++<a href="/pkg/compress/zlib"><code>compress/zlib</code></a>
++all return <code>(*Writer, error)</code> if they take a compression level,
++and <code>*Writer</code> otherwise. Package <code>gzip</code>'s
++<code>Compressor</code> and <code>Decompressor</code> types have been renamed
++to <code>Writer</code> and <code>Reader</code>. Package <code>flate</code>'s
++<code>WrongValueError</code> type has been removed.
++</p>
++
++<p>
++<em>Updating</em>
++Running <code>go</code> <code>fix</code> will update old names and calls that assign the error to _.
++Calls that aren't fixed will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="crypto_aes_des">The crypto/aes and crypto/des packages</h3>
++
++<p>
++In Go 1, the <code>Reset</code> method has been removed. Go does not guarantee
++that memory is not copied and therefore this method was misleading.
++</p>
++
++<p>
++The cipher-specific types <code>*aes.Cipher</code>, <code>*des.Cipher</code>,
++and <code>*des.TripleDESCipher</code> have been removed in favor of
++<code>cipher.Block</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Remove the calls to Reset. Replace uses of the specific cipher types with
++cipher.Block.
++</p>
++
++<h3 id="crypto_elliptic">The crypto/elliptic package</h3>
++
++<p>
++In Go 1, <a href="/pkg/crypto/elliptic/#Curve"><code>elliptic.Curve</code></a>
++has been made an interface to permit alternative implementations. The curve
++parameters have been moved to the
++<a href="/pkg/crypto/elliptic/#CurveParams"><code>elliptic.CurveParams</code></a>
++structure.
++</p>
++
++<p>
++<em>Updating</em>:
++Existing users of <code>*elliptic.Curve</code> will need to change to
++simply <code>elliptic.Curve</code>. Calls to <code>Marshal</code>,
++<code>Unmarshal</code> and <code>GenerateKey</code> are now functions
++in <code>crypto/elliptic</code> that take an <code>elliptic.Curve</code>
++as their first argument.
++</p>
++
++<h3 id="crypto_hmac">The crypto/hmac package</h3>
++
++<p>
++In Go 1, the hash-specific functions, such as <code>hmac.NewMD5</code>, have
++been removed from <code>crypto/hmac</code>. Instead, <code>hmac.New</code> takes
++a function that returns a <code>hash.Hash</code>, such as <code>md5.New</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will perform the needed changes.
++</p>
++
++<h3 id="crypto_x509">The crypto/x509 package</h3>
++
++<p>
++In Go 1, the
++<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
++and
++<a href="/pkg/crypto/x509/#CreateCRL"><code>CreateCRL</code></a>
++functions in <code>crypto/x509</code> have been altered to take an
++<code>interface{}</code> where they previously took a <code>*rsa.PublicKey</code>
++or <code>*rsa.PrivateKey</code>. This will allow other public key algorithms
++to be implemented in the future.
++</p>
++
++<p>
++<em>Updating</em>:
++No changes will be needed.
++</p>
++
++<h3 id="encoding_binary">The encoding/binary package</h3>
++
++<p>
++In Go 1, the <code>binary.TotalSize</code> function has been replaced by
++<a href="/pkg/encoding/binary/#Size"><code>Size</code></a>,
++which takes an <code>interface{}</code> argument rather than
++a <code>reflect.Value</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++What little code is affected will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="encoding_xml">The encoding/xml package</h3>
++
++<p>
++In Go 1, the <a href="/pkg/encoding/xml/"><code>xml</code></a> package
++has been brought closer in design to the other marshaling packages such
++as <a href="/pkg/encoding/gob/"><code>encoding/gob</code></a>.
++</p>
++
++<p>
++The old <code>Parser</code> type is renamed
++<a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> and has a new
++<a href="/pkg/encoding/xml/#Decoder.Decode"><code>Decode</code></a> method. An
++<a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a> type was also introduced.
++</p>
++
++<p>
++The functions <a href="/pkg/encoding/xml/#Marshal"><code>Marshal</code></a>
++and <a href="/pkg/encoding/xml/#Unmarshal"><code>Unmarshal</code></a>
++work with <code>[]byte</code> values now. To work with streams,
++use the new <a href="/pkg/encoding/xml/#Encoder"><code>Encoder</code></a>
++and <a href="/pkg/encoding/xml/#Decoder"><code>Decoder</code></a> types.
++</p>
++
++<p>
++When marshaling or unmarshaling values, the format of supported flags in
++field tags has changed to be closer to the
++<a href="/pkg/encoding/json"><code>json</code></a> package
++(<code>`xml:"name,flag"`</code>). The matching done between field tags, field
++names, and the XML attribute and element names is now case-sensitive.
++The <code>XMLName</code> field tag, if present, must also match the name
++of the XML element being marshaled.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update most uses of the package except for some calls to
++<code>Unmarshal</code>. Special care must be taken with field tags,
++since the fix tool will not update them and if not fixed by hand they will
++misbehave silently in some cases. For example, the old
++<code>"attr"</code> is now written <code>",attr"</code> while plain
++<code>"attr"</code> remains valid but with a different meaning.
++</p>
++
++<h3 id="expvar">The expvar package</h3>
++
++<p>
++In Go 1, the <code>RemoveAll</code> function has been removed.
++The <code>Iter</code> function and Iter method on <code>*Map</code> have
++been replaced by
++<a href="/pkg/expvar/#Do"><code>Do</code></a>
++and
++<a href="/pkg/expvar/#Map.Do"><code>(*Map).Do</code></a>.
++</p>
++
++<p>
++<em>Updating</em>:
++Most code using <code>expvar</code> will not need changing. The rare code that used
++<code>Iter</code> can be updated to pass a closure to <code>Do</code> to achieve the same effect.
++</p>
++
++<h3 id="flag">The flag package</h3>
++
++<p>
++In Go 1, the interface <a href="/pkg/flag/#Value"><code>flag.Value</code></a> has changed slightly.
++The <code>Set</code> method now returns an <code>error</code> instead of
++a <code>bool</code> to indicate success or failure.
++</p>
++
++<p>
++There is also a new kind of flag, <code>Duration</code>, to support argument
++values specifying time intervals.
++Values for such flags must be given units, just as <code>time.Duration</code>
++formats them: <code>10s</code>, <code>1h30m</code>, etc.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/timeout/`}}
++-->var timeout = flag.Duration(&#34;timeout&#34;, 30*time.Second, &#34;how long to wait for completion&#34;)</pre>
++
++<p>
++<em>Updating</em>:
++Programs that implement their own flags will need minor manual fixes to update their
++<code>Set</code> methods.
++The <code>Duration</code> flag is new and affects no existing code.
++</p>
++
++
++<h3 id="go">The go/* packages</h3>
++
++<p>
++Several packages under <code>go</code> have slightly revised APIs.
++</p>
++
++<p>
++A concrete <code>Mode</code> type was introduced for configuration mode flags
++in the packages
++<a href="/pkg/go/scanner/"><code>go/scanner</code></a>,
++<a href="/pkg/go/parser/"><code>go/parser</code></a>,
++<a href="/pkg/go/printer/"><code>go/printer</code></a>, and
++<a href="/pkg/go/doc/"><code>go/doc</code></a>.
++</p>
++
++<p>
++The modes <code>AllowIllegalChars</code> and <code>InsertSemis</code> have been removed
++from the <a href="/pkg/go/scanner/"><code>go/scanner</code></a> package. They were mostly
++useful for scanning text other then Go source files. Instead, the
++<a href="/pkg/text/scanner/"><code>text/scanner</code></a> package should be used
++for that purpose.
++</p>
++
++<p>
++The <a href="/pkg/go/scanner/#ErrorHandler"><code>ErrorHandler</code></a> provided
++to the scanner's <a href="/pkg/go/scanner/#Scanner.Init"><code>Init</code></a> method is
++now simply a function rather than an interface. The <code>ErrorVector</code> type has
++been removed in favor of the (existing) <a href="/pkg/go/scanner/#ErrorList"><code>ErrorList</code></a>
++type, and the <code>ErrorVector</code> methods have been migrated. Instead of embedding
++an <code>ErrorVector</code> in a client of the scanner, now a client should maintain
++an <code>ErrorList</code>.
++</p>
++
++<p>
++The set of parse functions provided by the <a href="/pkg/go/parser/"><code>go/parser</code></a>
++package has been reduced to the primary parse function
++<a href="/pkg/go/parser/#ParseFile"><code>ParseFile</code></a>, and a couple of
++convenience functions <a href="/pkg/go/parser/#ParseDir"><code>ParseDir</code></a>
++and <a href="/pkg/go/parser/#ParseExpr"><code>ParseExpr</code></a>.
++</p>
++
++<p>
++The <a href="/pkg/go/printer/"><code>go/printer</code></a> package supports an additional
++configuration mode <a href="/pkg/go/printer/#Mode"><code>SourcePos</code></a>;
++if set, the printer will emit <code>//line</code> comments such that the generated
++output contains the original source code position information. The new type
++<a href="/pkg/go/printer/#CommentedNode"><code>CommentedNode</code></a> can be
++used to provide comments associated with an arbitrary
++<a href="/pkg/go/ast/#Node"><code>ast.Node</code></a> (until now only
++<a href="/pkg/go/ast/#File"><code>ast.File</code></a> carried comment information).
++</p>
++
++<p>
++The type names of the <a href="/pkg/go/doc/"><code>go/doc</code></a> package have been
++streamlined by removing the <code>Doc</code> suffix: <code>PackageDoc</code>
++is now <code>Package</code>, <code>ValueDoc</code> is <code>Value</code>, etc.
++Also, all types now consistently have a <code>Name</code> field (or <code>Names</code>,
++in the case of type <code>Value</code>) and <code>Type.Factories</code> has become
++<code>Type.Funcs</code>.
++Instead of calling <code>doc.NewPackageDoc(pkg, importpath)</code>,
++documentation for a package is created with:
++</p>
++
++<pre>
++    doc.New(pkg, importpath, mode)
++</pre>
++
++<p>
++where the new <code>mode</code> parameter specifies the operation mode:
++if set to <a href="/pkg/go/doc/#AllDecls"><code>AllDecls</code></a>, all declarations
++(not just exported ones) are considered.
++The function <code>NewFileDoc</code> was removed, and the function
++<code>CommentText</code> has become the method
++<a href="/pkg/go/ast/#Text"><code>Text</code></a> of
++<a href="/pkg/go/ast/#CommentGroup"><code>ast.CommentGroup</code></a>.
++</p>
++
++<p>
++In package <a href="/pkg/go/token/"><code>go/token</code></a>, the
++<a href="/pkg/go/token/#FileSet"><code>token.FileSet</code></a> method <code>Files</code>
++(which originally returned a channel of <code>*token.File</code>s) has been replaced
++with the iterator <a href="/pkg/go/token/#FileSet.Iterate"><code>Iterate</code></a> that
++accepts a function argument instead.
++</p>
++
++<p>
++In package <a href="/pkg/go/build/"><code>go/build</code></a>, the API
++has been nearly completely replaced.
++The package still computes Go package information
++but it does not run the build: the <code>Cmd</code> and <code>Script</code>
++types are gone.
++(To build code, use the new
++<a href="/cmd/go/"><code>go</code></a> command instead.)
++The <code>DirInfo</code> type is now named
++<a href="/pkg/go/build/#Package"><code>Package</code></a>.
++<code>FindTree</code> and <code>ScanDir</code> are replaced by
++<a href="/pkg/go/build/#Import"><code>Import</code></a>
++and
++<a href="/pkg/go/build/#ImportDir"><code>ImportDir</code></a>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses packages in <code>go</code> will have to be updated by hand; the
++compiler will reject incorrect uses. Templates used in conjunction with any of the
++<code>go/doc</code> types may need manual fixes; the renamed fields will lead
++to run-time errors.
++</p>
++
++<h3 id="hash">The hash package</h3>
++
++<p>
++In Go 1, the definition of <a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> includes
++a new method, <code>BlockSize</code>.  This new method is used primarily in the
++cryptographic libraries.
++</p>
++
++<p>
++The <code>Sum</code> method of the
++<a href="/pkg/hash/#Hash"><code>hash.Hash</code></a> interface now takes a
++<code>[]byte</code> argument, to which the hash value will be appended.
++The previous behavior can be recreated by adding a <code>nil</code> argument to the call.
++</p>
++
++<p>
++<em>Updating</em>:
++Existing implementations of <code>hash.Hash</code> will need to add a
++<code>BlockSize</code> method.  Hashes that process the input one byte at
++a time can implement <code>BlockSize</code> to return 1.
++Running <code>go</code> <code>fix</code> will update calls to the <code>Sum</code> methods of the various
++implementations of <code>hash.Hash</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Since the package's functionality is new, no updating is necessary.
++</p>
++
++<h3 id="http">The http package</h3>
++
++<p>
++In Go 1 the <a href="/pkg/net/http/"><code>http</code></a> package is refactored,
++putting some of the utilities into a
++<a href="/pkg/net/http/httputil/"><code>httputil</code></a> subdirectory.
++These pieces are only rarely needed by HTTP clients.
++The affected items are:
++</p>
++
++<ul>
++<li>ClientConn</li>
++<li>DumpRequest</li>
++<li>DumpRequestOut</li>
++<li>DumpResponse</li>
++<li>NewChunkedReader</li>
++<li>NewChunkedWriter</li>
++<li>NewClientConn</li>
++<li>NewProxyClientConn</li>
++<li>NewServerConn</li>
++<li>NewSingleHostReverseProxy</li>
++<li>ReverseProxy</li>
++<li>ServerConn</li>
++</ul>
++
++<p>
++The <code>Request.RawURL</code> field has been removed; it was a
++historical artifact.
++</p>
++
++<p>
++The <code>Handle</code> and <code>HandleFunc</code>
++functions, and the similarly-named methods of <code>ServeMux</code>,
++now panic if an attempt is made to register the same pattern twice.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update the few programs that are affected except for
++uses of <code>RawURL</code>, which must be fixed by hand.
++</p>
++
++<h3 id="image">The image package</h3>
++
++<p>
++The <a href="/pkg/image/"><code>image</code></a> package has had a number of
++minor changes, rearrangements and renamings.
++</p>
++
++<p>
++Most of the color handling code has been moved into its own package,
++<a href="/pkg/image/color/"><code>image/color</code></a>.
++For the elements that moved, a symmetry arises; for instance,
++each pixel of an
++<a href="/pkg/image/#RGBA"><code>image.RGBA</code></a>
++is a
++<a href="/pkg/image/color/#RGBA"><code>color.RGBA</code></a>.
++</p>
++
++<p>
++The old <code>image/ycbcr</code> package has been folded, with some
++renamings, into the
++<a href="/pkg/image/"><code>image</code></a>
++and
++<a href="/pkg/image/color/"><code>image/color</code></a>
++packages.
++</p>
++
++<p>
++The old <code>image.ColorImage</code> type is still in the <code>image</code>
++package but has been renamed
++<a href="/pkg/image/#Uniform"><code>image.Uniform</code></a>,
++while <code>image.Tiled</code> has been removed.
++</p>
++
++<p>
++This table lists the renamings.
++</p>
++
++<table class="codetable" frame="border" summary="image renames">
++<colgroup align="left" width="50%"></colgroup>
++<colgroup align="left" width="50%"></colgroup>
++<tr>
++<th align="left">Old</th>
++<th align="left">New</th>
++</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>image.Color</td> <td>color.Color</td></tr>
++<tr><td>image.ColorModel</td> <td>color.Model</td></tr>
++<tr><td>image.ColorModelFunc</td> <td>color.ModelFunc</td></tr>
++<tr><td>image.PalettedColorModel</td> <td>color.Palette</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>image.RGBAColor</td> <td>color.RGBA</td></tr>
++<tr><td>image.RGBA64Color</td> <td>color.RGBA64</td></tr>
++<tr><td>image.NRGBAColor</td> <td>color.NRGBA</td></tr>
++<tr><td>image.NRGBA64Color</td> <td>color.NRGBA64</td></tr>
++<tr><td>image.AlphaColor</td> <td>color.Alpha</td></tr>
++<tr><td>image.Alpha16Color</td> <td>color.Alpha16</td></tr>
++<tr><td>image.GrayColor</td> <td>color.Gray</td></tr>
++<tr><td>image.Gray16Color</td> <td>color.Gray16</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>image.RGBAColorModel</td> <td>color.RGBAModel</td></tr>
++<tr><td>image.RGBA64ColorModel</td> <td>color.RGBA64Model</td></tr>
++<tr><td>image.NRGBAColorModel</td> <td>color.NRGBAModel</td></tr>
++<tr><td>image.NRGBA64ColorModel</td> <td>color.NRGBA64Model</td></tr>
++<tr><td>image.AlphaColorModel</td> <td>color.AlphaModel</td></tr>
++<tr><td>image.Alpha16ColorModel</td> <td>color.Alpha16Model</td></tr>
++<tr><td>image.GrayColorModel</td> <td>color.GrayModel</td></tr>
++<tr><td>image.Gray16ColorModel</td> <td>color.Gray16Model</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>ycbcr.RGBToYCbCr</td> <td>color.RGBToYCbCr</td></tr>
++<tr><td>ycbcr.YCbCrToRGB</td> <td>color.YCbCrToRGB</td></tr>
++<tr><td>ycbcr.YCbCrColorModel</td> <td>color.YCbCrModel</td></tr>
++<tr><td>ycbcr.YCbCrColor</td> <td>color.YCbCr</td></tr>
++<tr><td>ycbcr.YCbCr</td> <td>image.YCbCr</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>ycbcr.SubsampleRatio444</td> <td>image.YCbCrSubsampleRatio444</td></tr>
++<tr><td>ycbcr.SubsampleRatio422</td> <td>image.YCbCrSubsampleRatio422</td></tr>
++<tr><td>ycbcr.SubsampleRatio420</td> <td>image.YCbCrSubsampleRatio420</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>image.ColorImage</td> <td>image.Uniform</td></tr>
++</table>
++
++<p>
++The image package's <code>New</code> functions
++(<a href="/pkg/image/#NewRGBA"><code>NewRGBA</code></a>,
++<a href="/pkg/image/#NewRGBA64"><code>NewRGBA64</code></a>, etc.)
++take an <a href="/pkg/image/#Rectangle"><code>image.Rectangle</code></a> as an argument
++instead of four integers.
++</p>
++
++<p>
++Finally, there are new predefined <code>color.Color</code> variables
++<a href="/pkg/image/color/#Black"><code>color.Black</code></a>,
++<a href="/pkg/image/color/#White"><code>color.White</code></a>,
++<a href="/pkg/image/color/#Opaque"><code>color.Opaque</code></a>
++and
++<a href="/pkg/image/color/#Transparent"><code>color.Transparent</code></a>.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
++</p>
++
++<h3 id="log_syslog">The log/syslog package</h3>
++
++<p>
++In Go 1, the <a href="/pkg/log/syslog/#NewLogger"><code>syslog.NewLogger</code></a>
++function returns an error as well as a <code>log.Logger</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++What little code is affected will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="mime">The mime package</h3>
++
++<p>
++In Go 1, the <a href="/pkg/mime/#FormatMediaType"><code>FormatMediaType</code></a> function
++of the <code>mime</code> package has  been simplified to make it
++consistent with
++<a href="/pkg/mime/#ParseMediaType"><code>ParseMediaType</code></a>.
++It now takes <code>"text/html"</code> rather than <code>"text"</code> and <code>"html"</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++What little code is affected will be caught by the compiler and must be updated by hand.
++</p>
++
++<h3 id="net">The net package</h3>
++
++<p>
++In Go 1, the various <code>SetTimeout</code>,
++<code>SetReadTimeout</code>, and <code>SetWriteTimeout</code> methods
++have been replaced with
++<a href="/pkg/net/#IPConn.SetDeadline"><code>SetDeadline</code></a>,
++<a href="/pkg/net/#IPConn.SetReadDeadline"><code>SetReadDeadline</code></a>, and
++<a href="/pkg/net/#IPConn.SetWriteDeadline"><code>SetWriteDeadline</code></a>,
++respectively.  Rather than taking a timeout value in nanoseconds that
++apply to any activity on the connection, the new methods set an
++absolute deadline (as a <code>time.Time</code> value) after which
++reads and writes will time out and no longer block.
++</p>
++
++<p>
++There are also new functions
++<a href="/pkg/net/#DialTimeout"><code>net.DialTimeout</code></a>
++to simplify timing out dialing a network address and
++<a href="/pkg/net/#ListenMulticastUDP"><code>net.ListenMulticastUDP</code></a>
++to allow multicast UDP to listen concurrently across multiple listeners.
++The <code>net.ListenMulticastUDP</code> function replaces the old
++<code>JoinGroup</code> and <code>LeaveGroup</code> methods.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses the old methods will fail to compile and must be updated by hand.
++The semantic change makes it difficult for the fix tool to update automatically.
++</p>
++
++<h3 id="os">The os package</h3>
++
++<p>
++The <code>Time</code> function has been removed; callers should use
++the <a href="/pkg/time/#Time"><code>Time</code></a> type from the
++<code>time</code> package.
++</p>
++
++<p>
++The <code>Exec</code> function has been removed; callers should use
++<code>Exec</code> from the <code>syscall</code> package, where available.
++</p>
++
++<p>
++The <code>ShellExpand</code> function has been renamed to <a
++href="/pkg/os/#ExpandEnv"><code>ExpandEnv</code></a>.
++</p>
++
++<p>
++The <a href="/pkg/os/#NewFile"><code>NewFile</code></a> function
++now takes a <code>uintptr</code> fd, instead of an <code>int</code>.
++The <a href="/pkg/os/#File.Fd"><code>Fd</code></a> method on files now
++also returns a <code>uintptr</code>.
++</p>
++
++<p>
++There are no longer error constants such as <code>EINVAL</code>
++in the <code>os</code> package, since the set of values varied with
++the underlying operating system. There are new portable functions like
++<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>
++to test common error properties, plus a few new error values
++with more Go-like names, such as
++<a href="/pkg/os/#ErrPermission"><code>ErrPermission</code></a>
++and
++<a href="/pkg/os/#ErrNoEnv"><code>ErrNoEnv</code></a>.
++</p>
++
++<p>
++The <code>Getenverror</code> function has been removed. To distinguish
++between a non-existent environment variable and an empty string,
++use <a href="/pkg/os/#Environ"><code>os.Environ</code></a> or
++<a href="/pkg/syscall/#Getenv"><code>syscall.Getenv</code></a>.
++</p>
++
++
++<p>
++The <a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a> method has
++dropped its option argument and the associated constants are gone
++from the package.
++Also, the function <code>Wait</code> is gone; only the method of
++the <code>Process</code> type persists.
++</p>
++
++<p>
++The <code>Waitmsg</code> type returned by
++<a href="/pkg/os/#Process.Wait"><code>Process.Wait</code></a>
++has been replaced with a more portable
++<a href="/pkg/os/#ProcessState"><code>ProcessState</code></a>
++type with accessor methods to recover information about the
++process.
++Because of changes to <code>Wait</code>, the <code>ProcessState</code>
++value always describes an exited process.
++Portability concerns simplified the interface in other ways, but the values returned by the
++<a href="/pkg/os/#ProcessState.Sys"><code>ProcessState.Sys</code></a> and
++<a href="/pkg/os/#ProcessState.SysUsage"><code>ProcessState.SysUsage</code></a>
++methods can be type-asserted to underlying system-specific data structures such as
++<a href="/pkg/syscall/#WaitStatus"><code>syscall.WaitStatus</code></a> and
++<a href="/pkg/syscall/#Rusage"><code>syscall.Rusage</code></a> on Unix.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will drop a zero argument to <code>Process.Wait</code>.
++All other changes will be caught by the compiler and must be updated by hand.
++</p>
++
++<h4 id="os_fileinfo">The os.FileInfo type</h4>
++
++<p>
++Go 1 redefines the <a href="/pkg/os/#FileInfo"><code>os.FileInfo</code></a> type,
++changing it from a struct to an interface:
++</p>
++
++<pre>
++    type FileInfo interface {
++        Name() string       // base name of the file
++        Size() int64        // length in bytes
++        Mode() FileMode     // file mode bits
++        ModTime() time.Time // modification time
++        IsDir() bool        // abbreviation for Mode().IsDir()
++        Sys() interface{}   // underlying data source (can return nil)
++    }
++</pre>
++
++<p>
++The file mode information has been moved into a subtype called
++<a href="/pkg/os/#FileMode"><code>os.FileMode</code></a>,
++a simple integer type with <code>IsDir</code>, <code>Perm</code>, and <code>String</code>
++methods.
++</p>
++
++<p>
++The system-specific details of file modes and properties such as (on Unix)
++i-number have been removed from <code>FileInfo</code> altogether.
++Instead, each operating system's <code>os</code> package provides an
++implementation of the <code>FileInfo</code> interface, which
++has a <code>Sys</code> method that returns the
++system-specific representation of file metadata.
++For instance, to discover the i-number of a file on a Unix system, unpack
++the <code>FileInfo</code> like this:
++</p>
++
++<pre>
++    fi, err := os.Stat("hello.go")
++    if err != nil {
++        log.Fatal(err)
++    }
++    // Check that it's a Unix file.
++    unixStat, ok := fi.Sys().(*syscall.Stat_t)
++    if !ok {
++        log.Fatal("hello.go: not a Unix file")
++    }
++    fmt.Printf("file i-number: %d\n", unixStat.Ino)
++</pre>
++
++<p>
++Assuming (which is unwise) that <code>"hello.go"</code> is a Unix file,
++the i-number expression could be contracted to
++</p>
++
++<pre>
++    fi.Sys().(*syscall.Stat_t).Ino
++</pre>
++
++<p>
++The vast majority of uses of <code>FileInfo</code> need only the methods
++of the standard interface.
++</p>
++
++<p>
++The <code>os</code> package no longer contains wrappers for the POSIX errors
++such as <code>ENOENT</code>.
++For the few programs that need to verify particular error conditions, there are
++now the boolean functions
++<a href="/pkg/os/#IsExist"><code>IsExist</code></a>,
++<a href="/pkg/os/#IsNotExist"><code>IsNotExist</code></a>
++and
++<a href="/pkg/os/#IsPermission"><code>IsPermission</code></a>.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/os\.Open/` `/}/`}}
++-->    f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
++    if os.IsExist(err) {
++        log.Printf(&#34;%s already exists&#34;, name)
++    }</pre>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update code that uses the old equivalent of the current <code>os.FileInfo</code>
++and <code>os.FileMode</code> API.
++Code that needs system-specific file details will need to be updated by hand.
++Code that uses the old POSIX error values from the <code>os</code> package
++will fail to compile and will also need to be updated by hand.
++</p>
++
++<h3 id="os_signal">The os/signal package</h3>
++
++<p>
++The <code>os/signal</code> package in Go 1 replaces the
++<code>Incoming</code> function, which returned a channel
++that received all incoming signals,
++with the selective <code>Notify</code> function, which asks
++for delivery of specific signals on an existing channel.
++</p>
++
++<p>
++<em>Updating</em>:
++Code must be updated by hand.
++A literal translation of
++</p>
++<pre>
++c := signal.Incoming()
++</pre>
++<p>
++is
++</p>
++<pre>
++c := make(chan os.Signal)
++signal.Notify(c) // ask for all signals
++</pre>
++<p>
++but most code should list the specific signals it wants to handle instead:
++</p>
++<pre>
++c := make(chan os.Signal)
++signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT)
++</pre>
++
++<h3 id="path_filepath">The path/filepath package</h3>
++
++<p>
++In Go 1, the <a href="/pkg/path/filepath/#Walk"><code>Walk</code></a> function of the
++<code>path/filepath</code> package
++has been changed to take a function value of type
++<a href="/pkg/path/filepath/#WalkFunc"><code>WalkFunc</code></a>
++instead of a <code>Visitor</code> interface value.
++<code>WalkFunc</code> unifies the handling of both files and directories.
++</p>
++
++<pre>
++    type WalkFunc func(path string, info os.FileInfo, err error) error
++</pre>
++
++<p>
++The <code>WalkFunc</code> function will be called even for files or directories that could not be opened;
++in such cases the error argument will describe the failure.
++If a directory's contents are to be skipped,
++the function should return the value <a href="/pkg/path/filepath/#variables"><code>filepath.SkipDir</code></a>
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/STARTWALK/` `/ENDWALK/`}}
++-->    markFn := func(path string, info os.FileInfo, err error) error {
++        if path == &#34;pictures&#34; { <span class="comment">// Will skip walking of directory pictures and its contents.</span>
++            return filepath.SkipDir
++        }
++        if err != nil {
++            return err
++        }
++        log.Println(path)
++        return nil
++    }
++    err := filepath.Walk(&#34;.&#34;, markFn)
++    if err != nil {
++        log.Fatal(err)
++    }</pre>
++
++<p>
++<em>Updating</em>:
++The change simplifies most code but has subtle consequences, so affected programs
++will need to be updated by hand.
++The compiler will catch code using the old interface.
++</p>
++
++<h3 id="regexp">The regexp package</h3>
++
++<p>
++The <a href="/pkg/regexp/"><code>regexp</code></a> package has been rewritten.
++It has the same interface but the specification of the regular expressions
++it supports has changed from the old "egrep" form to that of
++<a href="http://code.google.com/p/re2/">RE2</a>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses the package should have its regular expressions checked by hand.
++</p>
++
++<h3 id="runtime">The runtime package</h3>
++
++<p>
++In Go 1, much of the API exported by package
++<code>runtime</code> has been removed in favor of
++functionality provided by other packages.
++Code using the <code>runtime.Type</code> interface
++or its specific concrete type implementations should
++now use package <a href="/pkg/reflect/"><code>reflect</code></a>.
++Code using <code>runtime.Semacquire</code> or <code>runtime.Semrelease</code>
++should use channels or the abstractions in package <a href="/pkg/sync/"><code>sync</code></a>.
++The <code>runtime.Alloc</code>, <code>runtime.Free</code>,
++and <code>runtime.Lookup</code> functions, an unsafe API created for
++debugging the memory allocator, have no replacement.
++</p>
++
++<p>
++Before, <code>runtime.MemStats</code> was a global variable holding
++statistics about memory allocation, and calls to <code>runtime.UpdateMemStats</code>
++ensured that it was up to date.
++In Go 1, <code>runtime.MemStats</code> is a struct type, and code should use
++<a href="/pkg/runtime/#ReadMemStats"><code>runtime.ReadMemStats</code></a>
++to obtain the current statistics.
++</p>
++
++<p>
++The package adds a new function,
++<a href="/pkg/runtime/#NumCPU"><code>runtime.NumCPU</code></a>, that returns the number of CPUs available
++for parallel execution, as reported by the operating system kernel.
++Its value can inform the setting of <code>GOMAXPROCS</code>.
++The <code>runtime.Cgocalls</code> and <code>runtime.Goroutines</code> functions
++have been renamed to <code>runtime.NumCgoCall</code> and <code>runtime.NumGoroutine</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update code for the function renamings.
++Other code will need to be updated by hand.
++</p>
++
++<h3 id="strconv">The strconv package</h3>
++
++<p>
++In Go 1, the
++<a href="/pkg/strconv/"><code>strconv</code></a>
++package has been significantly reworked to make it more Go-like and less C-like,
++although <code>Atoi</code> lives on (it's similar to
++<code>int(ParseInt(x, 10, 0))</code>, as does
++<code>Itoa(x)</code> (<code>FormatInt(int64(x), 10)</code>).
++There are also new variants of some of the functions that append to byte slices rather than
++return strings, to allow control over allocation.
++</p>
++
++<p>
++This table summarizes the renamings; see the
++<a href="/pkg/strconv/">package documentation</a>
++for full details.
++</p>
++
++<table class="codetable" frame="border" summary="strconv renames">
++<colgroup align="left" width="50%"></colgroup>
++<colgroup align="left" width="50%"></colgroup>
++<tr>
++<th align="left">Old call</th>
++<th align="left">New call</th>
++</tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Atob(x)</td> <td>ParseBool(x)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Atof32(x)</td> <td>ParseFloat(x, 32)§</td></tr>
++<tr><td>Atof64(x)</td> <td>ParseFloat(x, 64)</td></tr>
++<tr><td>AtofN(x, n)</td> <td>ParseFloat(x, n)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Atoi(x)</td> <td>Atoi(x)</td></tr>
++<tr><td>Atoi(x)</td> <td>ParseInt(x, 10, 0)§</td></tr>
++<tr><td>Atoi64(x)</td> <td>ParseInt(x, 10, 64)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Atoui(x)</td> <td>ParseUint(x, 10, 0)§</td></tr>
++<tr><td>Atoui64(x)</td> <td>ParseUint(x, 10, 64)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Btoi64(x, b)</td> <td>ParseInt(x, b, 64)</td></tr>
++<tr><td>Btoui64(x, b)</td> <td>ParseUint(x, b, 64)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Btoa(x)</td> <td>FormatBool(x)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Ftoa32(x, f, p)</td> <td>FormatFloat(float64(x), f, p, 32)</td></tr>
++<tr><td>Ftoa64(x, f, p)</td> <td>FormatFloat(x, f, p, 64)</td></tr>
++<tr><td>FtoaN(x, f, p, n)</td> <td>FormatFloat(x, f, p, n)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Itoa(x)</td> <td>Itoa(x)</td></tr>
++<tr><td>Itoa(x)</td> <td>FormatInt(int64(x), 10)</td></tr>
++<tr><td>Itoa64(x)</td> <td>FormatInt(x, 10)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Itob(x, b)</td> <td>FormatInt(int64(x), b)</td></tr>
++<tr><td>Itob64(x, b)</td> <td>FormatInt(x, b)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Uitoa(x)</td> <td>FormatUint(uint64(x), 10)</td></tr>
++<tr><td>Uitoa64(x)</td> <td>FormatUint(x, 10)</td></tr>
++<tr>
++<td colspan="2"><hr></td>
++</tr>
++<tr><td>Uitob(x, b)</td> <td>FormatUint(uint64(x), b)</td></tr>
++<tr><td>Uitob64(x, b)</td> <td>FormatUint(x, b)</td></tr>
++</table>
++              
++<p>
++<em>Updating</em>:
++Running <code>go</code> <code>fix</code> will update almost all code affected by the change.
++<br>
++§ <code>Atoi</code> persists but <code>Atoui</code> and <code>Atof32</code> do not, so
++they may require
++a cast that must be added by hand; the <code>go</code> <code>fix</code> tool will warn about it.
++</p>
++
++
++<h3 id="templates">The template packages</h3>
++
++<p>
++The <code>template</code> and <code>exp/template/html</code> packages have moved to 
++<a href="/pkg/text/template/"><code>text/template</code></a> and
++<a href="/pkg/html/template/"><code>html/template</code></a>.
++More significant, the interface to these packages has been simplified.
++The template language is the same, but the concept of "template set" is gone
++and the functions and methods of the packages have changed accordingly,
++often by elimination.
++</p>
++
++<p>
++Instead of sets, a <code>Template</code> object
++may contain multiple named template definitions,
++in effect constructing
++name spaces for template invocation.
++A template can invoke any other template associated with it, but only those
++templates associated with it.
++The simplest way to associate templates is to parse them together, something
++made easier with the new structure of the packages.
++</p>
++
++<p>
++<em>Updating</em>:
++The imports will be updated by fix tool.
++Single-template uses will be otherwise be largely unaffected.
++Code that uses multiple templates in concert will need to be updated by hand.
++The <a href="/pkg/text/template/#examples">examples</a> in
++the documentation for <code>text/template</code> can provide guidance.
++</p>
++
++<h3 id="testing">The testing package</h3>
++
++<p>
++The testing package has a type, <code>B</code>, passed as an argument to benchmark functions.
++In Go 1, <code>B</code> has new methods, analogous to those of <code>T</code>, enabling
++logging and failure reporting.
++</p>
++
++<pre><!--{{code "/doc/progs/go1.go" `/func.*Benchmark/` `/^}/`}}
++-->func BenchmarkSprintf(b *testing.B) {
++    <span class="comment">// Verify correctness before running benchmark.</span>
++    b.StopTimer()
++    got := fmt.Sprintf(&#34;%x&#34;, 23)
++    const expect = &#34;17&#34;
++    if expect != got {
++        b.Fatalf(&#34;expected %q; got %q&#34;, expect, got)
++    }
++    b.StartTimer()
++    for i := 0; i &lt; b.N; i++ {
++        fmt.Sprintf(&#34;%x&#34;, 23)
++    }
++}</pre>
++
++<p>
++<em>Updating</em>:
++Existing code is unaffected, although benchmarks that use <code>println</code>
++or <code>panic</code> should be updated to use the new methods.
++</p>
++
++<h3 id="testing_script">The testing/script package</h3>
++
++<p>
++The testing/script package has been deleted. It was a dreg.
++</p>
++
++<p>
++<em>Updating</em>:
++No code is likely to be affected.
++</p>
++
++<h3 id="unsafe">The unsafe package</h3>
++
++<p>
++In Go 1, the functions
++<code>unsafe.Typeof</code>, <code>unsafe.Reflect</code>,
++<code>unsafe.Unreflect</code>, <code>unsafe.New</code>, and
++<code>unsafe.NewArray</code> have been removed;
++they duplicated safer functionality provided by
++package <a href="/pkg/reflect/"><code>reflect</code></a>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code using these functions must be rewritten to use
++package <a href="/pkg/reflect/"><code>reflect</code></a>.
++The changes to <a href="http://code.google.com/p/go/source/detail?r=2646dc956207">encoding/gob</a> and the <a href="http://code.google.com/p/goprotobuf/source/detail?r=5340ad310031">protocol buffer library</a>
++may be helpful as examples.
++</p>
++
++<h3 id="url">The url package</h3>
++
++<p>
++In Go 1 several fields from the <a href="/pkg/net/url/#URL"><code>url.URL</code></a> type
++were removed or replaced.
++</p>
++
++<p>
++The <a href="/pkg/net/url/#URL.String"><code>String</code></a> method now
++predictably rebuilds an encoded URL string using all of <code>URL</code>'s
++fields as necessary. The resulting string will also no longer have
++passwords escaped.
++</p>
++
++<p>
++The <code>Raw</code> field has been removed. In most cases the <code>String</code>
++method may be used in its place.
++</p>
++
++<p>
++The old <code>RawUserinfo</code> field is replaced by the <code>User</code>
++field, of type <a href="/pkg/net/url/#Userinfo"><code>*net.Userinfo</code></a>.
++Values of this type may be created using the new <a href="/pkg/net/url/#User"><code>net.User</code></a>
++and <a href="/pkg/net/url/#UserPassword"><code>net.UserPassword</code></a>
++functions. The <code>EscapeUserinfo</code> and <code>UnescapeUserinfo</code>
++functions are also gone.
++</p>
++
++<p>
++The <code>RawAuthority</code> field has been removed. The same information is
++available in the <code>Host</code> and <code>User</code> fields.
++</p>
++
++<p>
++The <code>RawPath</code> field and the <code>EncodedPath</code> method have
++been removed. The path information in rooted URLs (with a slash following the
++schema) is now available only in decoded form in the <code>Path</code> field.
++Occasionally, the encoded data may be required to obtain information that
++was lost in the decoding process. These cases must be handled by accessing
++the data the URL was built from.
++</p>
++
++<p>
++URLs with non-rooted paths, such as <code>"mailto:dev@golang.org?subject=Hi"</code>,
++are also handled differently. The <code>OpaquePath</code> boolean field has been
++removed and a new <code>Opaque</code> string field introduced to hold the encoded
++path for such URLs. In Go 1, the cited URL parses as:
++</p>
++
++<pre>
++    URL{
++        Scheme: "mailto",
++        Opaque: "dev@golang.org",
++        RawQuery: "subject=Hi",
++    }
++</pre>
++
++<p>
++A new <a href="/pkg/net/url/#URL.RequestURI"><code>RequestURI</code></a> method was
++added to <code>URL</code>.
++</p>
++
++<p>
++The <code>ParseWithReference</code> function has been renamed to <code>ParseWithFragment</code>.
++</p>
++
++<p>
++<em>Updating</em>:
++Code that uses the old fields will fail to compile and must be updated by hand.
++The semantic changes make it difficult for the fix tool to update automatically.
++</p>
++
++<h2 id="cmd_go">The go command</h2>
++
++<p>
++Go 1 introduces the <a href="/cmd/go/">go command</a>, a tool for fetching,
++building, and installing Go packages and commands. The <code>go</code> command
++does away with makefiles, instead using Go source code to find dependencies and
++determine build conditions. Most existing Go programs will no longer require
++makefiles to be built.
++</p>
++
++<p>
++See <a href="/doc/code.html">How to Write Go Code</a> for a primer on the
++<code>go</code> command and the <a href="/cmd/go/">go command documentation</a>
++for the full details.
++</p>
++
++<p>
++<em>Updating</em>:
++Projects that depend on the Go project's old makefile-based build
++infrastructure (<code>Make.pkg</code>, <code>Make.cmd</code>, and so on) should
++switch to using the <code>go</code> command for building Go code and, if
++necessary, rewrite their makefiles to perform any auxiliary build tasks.
++</p>
++
++<h2 id="cmd_cgo">The cgo command</h2>
++
++<p>
++In Go 1, the <a href="/cmd/cgo">cgo command</a>
++uses a different <code>_cgo_export.h</code>
++file, which is generated for packages containing <code>//export</code> lines.
++The <code>_cgo_export.h</code> file now begins with the C preamble comment,
++so that exported function definitions can use types defined there.
++This has the effect of compiling the preamble multiple times, so a
++package using <code>//export</code> must not put function definitions
++or variable initializations in the C preamble.
++</p>
++
++<h2 id="releases">Packaged releases</h2>
++
++<p>
++One of the most significant changes associated with Go 1 is the availability
++of prepackaged, downloadable distributions.
++They are available for many combinations of architecture and operating system
++(including Windows) and the list will grow.
++Installation details are described on the
++<a href="/doc/install">Getting Started</a> page, while
++the distributions themselves are listed on the
++<a href="http://code.google.com/p/go/downloads/list">downloads page</a>.
++
++
++</div>
++
++<div id="footer">
++Build version go1.0.1.<br>
++A link <a href="http://code.google.com/policies.html#restrictions">noted</a>,
++and then, coming up on the very next line, we will
++find yet another link, link 3.0 if you will,
++after a few more words <a href="/LINK">link text</a>.<br>
++<a href="/doc/tos.html">Terms of Service</a> | 
++<a href="http://www.google.com/intl/en/privacy/privacy-policy.html">Privacy Policy</a>
++</div>
++
++<script type="text/javascript">
++(function() {
++  var ga = document.createElement("script"); ga.type = "text/javascript"; ga.async = true;
++  ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + ".google-analytics.com/ga.js";
++  var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ga, s);
++})();
++</script>
++</body>
++<script type="text/javascript">
++  (function() {
++    var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
++    po.src = 'https://apis.google.com/js/minusone.js';
++    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
++  })();
++</script>
++</html>
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9b4c2d8be0a2dfe7e7f2ab87bb116b5ab5adeced
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,28 @@@
++The *.dat files in this directory are copied from The WebKit Open Source
++Project, specifically $WEBKITROOT/LayoutTests/html5lib/resources.
++WebKit is licensed under a BSD style license.
++http://webkit.org/coding/bsd-license.html says:
++
++Copyright (C) 2009 Apple Inc. All rights reserved.
++
++Redistribution and use in source and binary forms, with or without
++modification, are permitted provided that the following conditions are met:
++
++1. Redistributions of source code must retain the above copyright notice,
++this list of conditions and the following disclaimer.
++
++2. Redistributions in binary form must reproduce the above copyright notice,
++this list of conditions and the following disclaimer in the documentation
++and/or other materials provided with the distribution.
++
++THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
++EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
++WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
++DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
++DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
++LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
++ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
++SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..38f98efded0ae8a4f096f4c1cebba64a914241ea
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,354 @@@
++#data
++<a><p></a></p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,10): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <p>
++|       <a>
++
++#data
++<a>1<p>2</a>3</p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,12): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|     <p>
++|       <a>
++|         "2"
++|       "3"
++
++#data
++<a>1<button>2</a>3</button>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,17): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|     <button>
++|       <a>
++|         "2"
++|       "3"
++
++#data
++<a>1<b>2</a>3</b>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,12): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|       <b>
++|         "2"
++|     <b>
++|       "3"
++
++#data
++<a>1<div>2<div>3</a>4</div>5</div>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,20): adoption-agency-1.3
++(1,20): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|     <div>
++|       <a>
++|         "2"
++|       <div>
++|         <a>
++|           "3"
++|         "4"
++|       "5"
++
++#data
++<table><a>1<p>2</a>3</p>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,10): unexpected-start-tag-implies-table-voodoo
++(1,11): unexpected-character-implies-table-voodoo
++(1,14): unexpected-start-tag-implies-table-voodoo
++(1,15): unexpected-character-implies-table-voodoo
++(1,19): unexpected-end-tag-implies-table-voodoo
++(1,19): adoption-agency-1.3
++(1,20): unexpected-character-implies-table-voodoo
++(1,24): unexpected-end-tag-implies-table-voodoo
++(1,24): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|     <p>
++|       <a>
++|         "2"
++|       "3"
++|     <table>
++
++#data
++<b><b><a><p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,16): adoption-agency-1.3
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <b>
++|         <a>
++|         <p>
++|           <a>
++
++#data
++<b><a><b><p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,16): adoption-agency-1.3
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <a>
++|         <b>
++|       <b>
++|         <p>
++|           <a>
++
++#data
++<a><b><b><p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,16): adoption-agency-1.3
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|         <b>
++|     <b>
++|       <b>
++|         <p>
++|           <a>
++
++#data
++<p>1<s id="A">2<b id="B">3</p>4</s>5</b>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,30): unexpected-end-tag
++(1,35): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "1"
++|       <s>
++|         id="A"
++|         "2"
++|         <b>
++|           id="B"
++|           "3"
++|     <s>
++|       id="A"
++|       <b>
++|         id="B"
++|         "4"
++|     <b>
++|       id="B"
++|       "5"
++
++#data
++<table><a>1<td>2</td>3</table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,10): unexpected-start-tag-implies-table-voodoo
++(1,11): unexpected-character-implies-table-voodoo
++(1,15): unexpected-cell-in-table-body
++(1,30): unexpected-implied-end-tag-in-table-view
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "1"
++|     <a>
++|       "3"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "2"
++
++#data
++<table>A<td>B</td>C</table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,8): unexpected-character-implies-table-voodoo
++(1,12): unexpected-cell-in-table-body
++(1,22): unexpected-character-implies-table-voodoo
++#document
++| <html>
++|   <head>
++|   <body>
++|     "AC"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "B"
++
++#data
++<a><svg><tr><input></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,23): unexpected-end-tag
++(1,23): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <svg svg>
++|         <svg tr>
++|           <svg input>
++
++#data
++<div><a><b><div><div><div><div><div><div><div><div><div><div></a>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): adoption-agency-1.3
++(1,65): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <a>
++|         <b>
++|       <b>
++|         <div>
++|           <a>
++|           <div>
++|             <a>
++|             <div>
++|               <a>
++|               <div>
++|                 <a>
++|                 <div>
++|                   <a>
++|                   <div>
++|                     <a>
++|                     <div>
++|                       <a>
++|                       <div>
++|                         <a>
++|                           <div>
++|                             <div>
++
++#data
++<div><a><b><u><i><code><div></a>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,32): adoption-agency-1.3
++(1,32): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <a>
++|         <b>
++|           <u>
++|             <i>
++|               <code>
++|       <u>
++|         <i>
++|           <code>
++|             <div>
++|               <a>
++
++#data
++<b><b><b><b>x</b></b></b></b>y
++#errors
++(1,3): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <b>
++|         <b>
++|           <b>
++|             "x"
++|     "y"
++
++#data
++<p><b><b><b><b><p>x
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,18): unexpected-end-tag
++(1,19): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|         <b>
++|           <b>
++|             <b>
++|     <p>
++|       <b>
++|         <b>
++|           <b>
++|             "x"
++
++#data
++<b><em><foo><foob><fooc><aside></b></em>
++#errors
++(1,35): adoption-agency-1.3
++(1,40): adoption-agency-1.3
++(1,40): expected-closing-tag-but-got-eof
++#document-fragment
++div
++#document
++| <b>
++|   <em>
++|     <foo>
++|       <foob>
++|         <fooc>
++| <aside>
++|   <b>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e54d8033bac7197de04c202a1c4d556f090f809d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,39 @@@
++#data
++<b>1<i>2<p>3</b>4
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,16): adoption-agency-1.3
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "1"
++|       <i>
++|         "2"
++|     <i>
++|       <p>
++|         <b>
++|           "3"
++|         "4"
++
++#data
++<a><div><style></style><address><a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,35): unexpected-start-tag-implies-end-tag
++(1,35): adoption-agency-1.3
++(1,35): adoption-agency-1.3
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <div>
++|       <a>
++|         <style>
++|       <address>
++|         <a>
++|         <a>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5d3871ea12547d069082866148db3984081d3c06
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,719 @@@
++#data
++<!doctype html><p>foo<address>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “address”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <address>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><address><p>foo</address>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <address>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<article>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “article”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <article>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><article><p>foo</article>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <article>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<aside>bar<p>baz
++#errors
++(1,37): expected-closing-tag-but-got-eof
++28: Unclosed element “aside”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <aside>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><aside><p>foo</aside>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <aside>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<blockquote>bar<p>baz
++#errors
++(1,42): expected-closing-tag-but-got-eof
++33: Unclosed element “blockquote”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <blockquote>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><blockquote><p>foo</blockquote>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <blockquote>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<center>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “center”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <center>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><center><p>foo</center>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <center>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<details>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “details”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <details>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><details><p>foo</details>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <details>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<dialog>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “dialog”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <dialog>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><dialog><p>foo</dialog>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dialog>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<dir>bar<p>baz
++#errors
++(1,35): expected-closing-tag-but-got-eof
++26: Unclosed element “dir”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <dir>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><dir><p>foo</dir>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dir>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<div>bar<p>baz
++#errors
++(1,35): expected-closing-tag-but-got-eof
++26: Unclosed element “div”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <div>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><div><p>foo</div>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<dl>bar<p>baz
++#errors
++(1,34): expected-closing-tag-but-got-eof
++25: Unclosed element “dl”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <dl>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><dl><p>foo</dl>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dl>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<fieldset>bar<p>baz
++#errors
++(1,40): expected-closing-tag-but-got-eof
++31: Unclosed element “fieldset”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <fieldset>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><fieldset><p>foo</fieldset>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <fieldset>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<figcaption>bar<p>baz
++#errors
++(1,42): expected-closing-tag-but-got-eof
++33: Unclosed element “figcaption”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <figcaption>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><figcaption><p>foo</figcaption>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <figcaption>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<figure>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “figure”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <figure>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><figure><p>foo</figure>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <figure>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<footer>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “footer”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <footer>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><footer><p>foo</footer>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <footer>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<header>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “header”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <header>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><header><p>foo</header>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <header>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<hgroup>bar<p>baz
++#errors
++(1,38): expected-closing-tag-but-got-eof
++29: Unclosed element “hgroup”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <hgroup>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><hgroup><p>foo</hgroup>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <hgroup>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<listing>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “listing”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <listing>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><listing><p>foo</listing>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <listing>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<menu>bar<p>baz
++#errors
++(1,36): expected-closing-tag-but-got-eof
++27: Unclosed element “menu”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <menu>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><menu><p>foo</menu>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menu>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<nav>bar<p>baz
++#errors
++(1,35): expected-closing-tag-but-got-eof
++26: Unclosed element “nav”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <nav>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><nav><p>foo</nav>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <nav>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<ol>bar<p>baz
++#errors
++(1,34): expected-closing-tag-but-got-eof
++25: Unclosed element “ol”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <ol>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><ol><p>foo</ol>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ol>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<pre>bar<p>baz
++#errors
++(1,35): expected-closing-tag-but-got-eof
++26: Unclosed element “pre”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <pre>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><pre><p>foo</pre>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<section>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “section”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <section>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><section><p>foo</section>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <section>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<summary>bar<p>baz
++#errors
++(1,39): expected-closing-tag-but-got-eof
++30: Unclosed element “summary”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <summary>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><summary><p>foo</summary>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <summary>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!doctype html><p>foo<ul>bar<p>baz
++#errors
++(1,34): expected-closing-tag-but-got-eof
++25: Unclosed element “ul”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <ul>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><ul><p>foo</ul>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <p>
++|         "foo"
++|     "bar"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fa79c2b16bc3d441c985eb2a53c8a3cacca14ec7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,224 @@@
++#data
++FOO<!-- BAR -->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR  -->
++|     "BAZ"
++
++#data
++FOO<!-- BAR --!>BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): unexpected-bang-after-double-dash-in-comment
++#new-errors
++(1:16) incorrectly-closed-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR  -->
++|     "BAZ"
++
++#data
++FOO<!-- BAR --! >BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++#new-errors
++(1:20) eof-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR --! >BAZ -->
++
++#data
++FOO<!-- BAR --!
++>BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++#new-errors
++(1:20) eof-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR --!
++>BAZ -->
++
++#data
++FOO<!-- BAR --   >BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): unexpected-char-in-comment
++(1,21): eof-in-comment
++#new-errors
++(1:22) eof-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR --   >BAZ -->
++
++#data
++FOO<!-- BAR -- <QUX> -- MUX -->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): unexpected-char-in-comment
++(1,24): unexpected-char-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR -- <QUX> -- MUX  -->
++|     "BAZ"
++
++#data
++FOO<!-- BAR -- <QUX> -- MUX --!>BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): unexpected-char-in-comment
++(1,24): unexpected-char-in-comment
++(1,31): unexpected-bang-after-double-dash-in-comment
++#new-errors
++(1:32) incorrectly-closed-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR -- <QUX> -- MUX  -->
++|     "BAZ"
++
++#data
++FOO<!-- BAR -- <QUX> -- MUX -- >BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): unexpected-char-in-comment
++(1,24): unexpected-char-in-comment
++(1,31): unexpected-char-in-comment
++(1,35): eof-in-comment
++#new-errors
++(1:36) eof-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  BAR -- <QUX> -- MUX -- >BAZ -->
++
++#data
++FOO<!---->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  -->
++|     "BAZ"
++
++#data
++FOO<!--->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,9): incorrect-comment
++#new-errors
++(1:9) abrupt-closing-of-empty-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  -->
++|     "BAZ"
++
++#data
++FOO<!-->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,8): incorrect-comment
++#new-errors
++(1:8) abrupt-closing-of-empty-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!--  -->
++|     "BAZ"
++
++#data
++<?xml version="1.0">Hi
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,22): expected-doctype-but-got-chars
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?xml version="1.0" -->
++| <html>
++|   <head>
++|   <body>
++|     "Hi"
++
++#data
++<?xml version="1.0">
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,20): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?xml version="1.0" -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<?xml version
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,13): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?xml version -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++FOO<!----->BAZ
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,10): unexpected-dash-after-double-dash-in-comment
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <!-- - -->
++|     "BAZ"
++
++#data
++<html><!-- comment --><title>Comment before head</title>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <!--  comment  -->
++|   <head>
++|     <title>
++|       "Comment before head"
++|   <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c845becfc54fc48236c89104befc3e04681d313c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,470 @@@
++#data
++<!DOCTYPE html>Hello
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!dOctYpE HtMl>Hello
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPEhtml>Hello
++#errors
++(1,9): need-space-after-doctype
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE>Hello
++#errors
++(1,9): need-space-after-doctype
++(1,10): expected-doctype-name-but-got-right-bracket
++(1,10): unknown-doctype
++#new-errors
++(1:10) missing-doctype-name
++#document
++| <!DOCTYPE >
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE >Hello
++#errors
++(1,11): expected-doctype-name-but-got-right-bracket
++(1,11): unknown-doctype
++#new-errors
++(1:11) missing-doctype-name
++#document
++| <!DOCTYPE >
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato>Hello
++#errors
++(1,17): unknown-doctype
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato >Hello
++#errors
++(1,18): unknown-doctype
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato taco>Hello
++#errors
++(1,17): expected-space-or-right-bracket-in-doctype
++(1,22): unknown-doctype
++#new-errors
++(1:18) invalid-character-sequence-after-doctype-name
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato taco "ddd>Hello
++#errors
++(1,17): expected-space-or-right-bracket-in-doctype
++(1,27): unknown-doctype
++#new-errors
++(1:18) invalid-character-sequence-after-doctype-name
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato sYstEM>Hello
++#errors
++(1,24): unexpected-char-in-doctype
++(1,24): unknown-doctype
++#new-errors
++(1:24) missing-doctype-system-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato sYstEM    >Hello
++#errors
++(1,28): unexpected-char-in-doctype
++(1,28): unknown-doctype
++#new-errors
++(1:28) missing-doctype-system-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE   potato       sYstEM  ggg>Hello
++#errors
++(1,34): unexpected-char-in-doctype
++(1,37): unknown-doctype
++#new-errors
++(1:34) missing-quote-before-doctype-system-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato SYSTEM taco  >Hello
++#errors
++(1,25): unexpected-char-in-doctype
++(1,31): unknown-doctype
++#new-errors
++(1:25) missing-quote-before-doctype-system-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato SYSTEM 'taco"'>Hello
++#errors
++(1,32): unknown-doctype
++#document
++| <!DOCTYPE potato "" "taco"">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato SYSTEM "taco">Hello
++#errors
++(1,31): unknown-doctype
++#document
++| <!DOCTYPE potato "" "taco">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato SYSTEM "tai'co">Hello
++#errors
++(1,33): unknown-doctype
++#document
++| <!DOCTYPE potato "" "tai'co">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato SYSTEMtaco "ddd">Hello
++#errors
++(1,24): unexpected-char-in-doctype
++(1,34): unknown-doctype
++#new-errors
++(1:24) missing-quote-before-doctype-system-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato grass SYSTEM taco>Hello
++#errors
++(1,17): expected-space-or-right-bracket-in-doctype
++(1,35): unknown-doctype
++#new-errors
++(1:18) invalid-character-sequence-after-doctype-name
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato pUbLIc>Hello
++#errors
++(1,24): unexpected-end-of-doctype
++(1,24): unknown-doctype
++#new-errors
++(1:24) missing-doctype-public-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato pUbLIc >Hello
++#errors
++(1,25): unexpected-end-of-doctype
++(1,25): unknown-doctype
++#new-errors
++(1:25) missing-doctype-public-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato pUbLIcgoof>Hello
++#errors
++(1,24): unexpected-char-in-doctype
++(1,28): unknown-doctype
++#new-errors
++(1:24) missing-quote-before-doctype-public-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato PUBLIC goof>Hello
++#errors
++(1,25): unexpected-char-in-doctype
++(1,29): unknown-doctype
++#new-errors
++(1:25) missing-quote-before-doctype-public-identifier
++#document
++| <!DOCTYPE potato>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato PUBLIC "go'of">Hello
++#errors
++(1,32): unknown-doctype
++#document
++| <!DOCTYPE potato "go'of" "">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato PUBLIC 'go'of'>Hello
++#errors
++(1,29): unexpected-char-in-doctype
++(1,32): unknown-doctype
++#new-errors
++(1:29) missing-quote-before-doctype-system-identifier
++#document
++| <!DOCTYPE potato "go" "">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato PUBLIC 'go:hh   of' >Hello
++#errors
++(1,38): unknown-doctype
++#document
++| <!DOCTYPE potato "go:hh   of" "">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE potato PUBLIC "W3C-//dfdf" SYSTEM ggg>Hello
++#errors
++(1,38): unexpected-char-in-doctype
++(1,48): unknown-doctype
++#new-errors
++(1:38) missing-quote-before-doctype-system-identifier
++#document
++| <!DOCTYPE potato "W3C-//dfdf" "">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
++   "http://www.w3.org/TR/html4/strict.dtd">Hello
++#errors
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE ...>Hello
++#errors
++(1,14): unknown-doctype
++#document
++| <!DOCTYPE ...>
++| <html>
++|   <head>
++|   <body>
++|     "Hello"
++
++#data
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
++"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
++#errors
++(2,58): unknown-doctype
++#document
++| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
++"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
++#errors
++(2,54): unknown-doctype
++#document
++| <!DOCTYPE html "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] "uri" [ 
++<!-- internal declarations -->
++]>
++#errors
++(1,23): expected-space-or-right-bracket-in-doctype
++(2,30): unknown-doctype
++#new-errors
++(1:24) invalid-character-sequence-after-doctype-name
++#document
++| <!DOCTYPE root-element>
++| <html>
++|   <head>
++|   <body>
++|     "]>"
++
++#data
++<!DOCTYPE html PUBLIC
++  "-//WAPFORUM//DTD XHTML Mobile 1.0//EN"
++    "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
++#errors
++(3,53): unknown-doctype
++#document
++| <!DOCTYPE html "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE HTML SYSTEM "http://www.w3.org/DTD/HTML4-strict.dtd"><body><b>Mine!</b></body>
++#errors
++(1,63): unknown-doctype
++#document
++| <!DOCTYPE html "" "http://www.w3.org/DTD/HTML4-strict.dtd">
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "Mine!"
++
++#data
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN""http://www.w3.org/TR/html4/strict.dtd">
++#errors
++(1,50): unexpected-char-in-doctype
++#new-errors
++(1:50) missing-whitespace-between-doctype-public-and-system-identifiers
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
++#errors
++(1,50): unexpected-char-in-doctype
++#new-errors
++(1:50) missing-whitespace-between-doctype-public-and-system-identifiers
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01//EN"'http://www.w3.org/TR/html4/strict.dtd'>
++#errors
++(1,21): unexpected-char-in-doctype
++(1,49): unexpected-char-in-doctype
++#new-errors
++(1:22) missing-whitespace-after-doctype-public-keyword
++(1:49) missing-whitespace-between-doctype-public-and-system-identifiers
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'>
++#errors
++(1,21): unexpected-char-in-doctype
++(1,49): unexpected-char-in-doctype
++#new-errors
++(1:22) missing-whitespace-after-doctype-public-keyword
++(1:49) missing-whitespace-between-doctype-public-and-system-identifiers
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
++| <html>
++|   <head>
++|   <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0a1b10f96d9d62a67d631c640cf0bd68637da63d
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9bacebea050d93acf8ddea2bac5d9e4dbd3efbdf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,943 @@@
++#data
++FOO&gt;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO>BAR"
++
++#data
++FOO&gtBAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,6): named-entity-without-semicolon
++#new-errors
++(1:7) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO>BAR"
++
++#data
++FOO&gt BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,6): named-entity-without-semicolon
++#new-errors
++(1:7) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO> BAR"
++
++#data
++FOO&gt;;;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO>;;BAR"
++
++#data
++I'm &notit; I tell you
++#errors
++(1,4): expected-doctype-but-got-chars
++(1,9): named-entity-without-semicolon
++#new-errors
++(1:9) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "I'm ¬it; I tell you"
++
++#data
++I'm &notin; I tell you
++#errors
++(1,4): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "I'm ∉ I tell you"
++
++#data
++&ammmp;
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,7): unknown-named-character-reference
++#new-errors
++(1:7) unknown-named-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&ammmp;"
++
++#data
++&ammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmp;
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,950): unknown-named-character-reference
++#new-errors
++(1:950) unknown-named-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&ammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmp;"
++
++#data
++FOO& BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO& BAR"
++
++#data
++FOO&<BAR>
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,9): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&"
++|     <bar>
++
++#data
++FOO&&&&gt;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&&&>BAR"
++
++#data
++FOO&#41;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO)BAR"
++
++#data
++FOO&#x41;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOABAR"
++
++#data
++FOO&#X41;BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOABAR"
++
++#data
++FOO&#BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,5): expected-numeric-entity
++#new-errors
++(1:6) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&#BAR"
++
++#data
++FOO&#ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,5): expected-numeric-entity
++#new-errors
++(1:6) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&#ZOO"
++
++#data
++FOO&#xBAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,7): expected-numeric-entity
++#new-errors
++(1:9) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOºR"
++
++#data
++FOO&#xZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,6): expected-numeric-entity
++#new-errors
++(1:7) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&#xZOO"
++
++#data
++FOO&#XZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,6): expected-numeric-entity
++#new-errors
++(1:7) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO&#XZOO"
++
++#data
++FOO&#41BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,7): numeric-entity-without-semicolon
++#new-errors
++(1:8) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO)BAR"
++
++#data
++FOO&#x41BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,10): numeric-entity-without-semicolon
++#new-errors
++(1:11) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO䆺R"
++
++#data
++FOO&#x41ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,8): numeric-entity-without-semicolon
++#new-errors
++(1:9) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOAZOO"
++
++#data
++FOO&#x0000;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) null-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#x0078;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOxZOO"
++
++#data
++FOO&#x0079;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOyZOO"
++
++#data
++FOO&#x0080;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO€ZOO"
++
++#data
++FOO&#x0081;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO\81ZOO"
++
++#data
++FOO&#x0082;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO‚ZOO"
++
++#data
++FOO&#x0083;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOƒZOO"
++
++#data
++FOO&#x0084;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO„ZOO"
++
++#data
++FOO&#x0085;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO…ZOO"
++
++#data
++FOO&#x0086;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO†ZOO"
++
++#data
++FOO&#x0087;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO‡ZOO"
++
++#data
++FOO&#x0088;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOˆZOO"
++
++#data
++FOO&#x0089;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO‰ZOO"
++
++#data
++FOO&#x008A;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOŠZOO"
++
++#data
++FOO&#x008B;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO‹ZOO"
++
++#data
++FOO&#x008C;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOŒZOO"
++
++#data
++FOO&#x008D;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO\8dZOO"
++
++#data
++FOO&#x008E;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOŽZOO"
++
++#data
++FOO&#x008F;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO\8fZOO"
++
++#data
++FOO&#x0090;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO\90ZOO"
++
++#data
++FOO&#x0091;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO‘ZOO"
++
++#data
++FOO&#x0092;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO’ZOO"
++
++#data
++FOO&#x0093;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO“ZOO"
++
++#data
++FOO&#x0094;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO”ZOO"
++
++#data
++FOO&#x0095;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO•ZOO"
++
++#data
++FOO&#x0096;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO–ZOO"
++
++#data
++FOO&#x0097;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO—ZOO"
++
++#data
++FOO&#x0098;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO˜ZOO"
++
++#data
++FOO&#x0099;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO™ZOO"
++
++#data
++FOO&#x009A;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOšZOO"
++
++#data
++FOO&#x009B;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO›ZOO"
++
++#data
++FOO&#x009C;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOœZOO"
++
++#data
++FOO&#x009D;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO\9dZOO"
++
++#data
++FOO&#x009E;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOžZOO"
++
++#data
++FOO&#x009F;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) control-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOŸZOO"
++
++#data
++FOO&#x00A0;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO ZOO"
++
++#data
++FOO&#xD7FF;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO퟿ZOO"
++
++#data
++FOO&#xD800;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) surrogate-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#xD801;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) surrogate-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#xDFFE;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) surrogate-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#xDFFF;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,11): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:12) surrogate-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#xE000;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOOZOO"
++
++#data
++FOO&#x10FFFE;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:14) noncharacter-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO􏿾ZOO"
++
++#data
++FOO&#x1087D4;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO􈟔ZOO"
++
++#data
++FOO&#x10FFFF;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:14) noncharacter-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO􏿿ZOO"
++
++#data
++FOO&#x110000;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:14) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#xFFFFFF;ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:14) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#11111111111
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++(1,13): eof-in-numeric-entity
++#new-errors
++(1:17) missing-semicolon-after-character-reference
++(1:17) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�"
++
++#data
++FOO&#1111111111
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++(1,13): eof-in-numeric-entity
++#new-errors
++(1:16) missing-semicolon-after-character-reference
++(1:16) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�"
++
++#data
++FOO&#111111111111
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,13): illegal-codepoint-for-numeric-entity
++(1,13): eof-in-numeric-entity
++#new-errors
++(1:18) missing-semicolon-after-character-reference
++(1:18) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�"
++
++#data
++FOO&#11111111111ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,16): numeric-entity-without-semicolon
++(1,16): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:17) missing-semicolon-after-character-reference
++(1:17) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#1111111111ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,15): numeric-entity-without-semicolon
++(1,15): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:16) missing-semicolon-after-character-reference
++(1:16) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
++
++#data
++FOO&#111111111111ZOO
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,17): numeric-entity-without-semicolon
++(1,17): illegal-codepoint-for-numeric-entity
++#new-errors
++(1:18) missing-semicolon-after-character-reference
++(1:18) character-reference-outside-unicode-range
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO�ZOO"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0c6e898cdf316b11716c1637a43fb560aa29f635
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,309 @@@
++#data
++<div bar="ZZ&gt;YY"></div>
++#errors
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ>YY"
++
++#data
++<div bar="ZZ&"></div>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&"
++
++#data
++<div bar='ZZ&'></div>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&"
++
++#data
++<div bar=ZZ&></div>
++#errors
++(1,13): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&"
++
++#data
++<div bar="ZZ&gt=YY"></div>
++#errors
++(1,15): named-entity-without-semicolon
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&gt=YY"
++
++#data
++<div bar="ZZ&gt0YY"></div>
++#errors
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&gt0YY"
++
++#data
++<div bar="ZZ&gt9YY"></div>
++#errors
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&gt9YY"
++
++#data
++<div bar="ZZ&gtaYY"></div>
++#errors
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&gtaYY"
++
++#data
++<div bar="ZZ&gtZYY"></div>
++#errors
++(1,20): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&gtZYY"
++
++#data
++<div bar="ZZ&gt YY"></div>
++#errors
++(1,15): named-entity-without-semicolon
++(1,20): expected-doctype-but-got-start-tag
++#new-errors
++(1:16) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ> YY"
++
++#data
++<div bar="ZZ&gt"></div>
++#errors
++(1,15): named-entity-without-semicolon
++(1,17): expected-doctype-but-got-start-tag
++#new-errors
++(1:16) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ>"
++
++#data
++<div bar='ZZ&gt'></div>
++#errors
++(1,15): named-entity-without-semicolon
++(1,17): expected-doctype-but-got-start-tag
++#new-errors
++(1:16) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ>"
++
++#data
++<div bar=ZZ&gt></div>
++#errors
++(1,14): named-entity-without-semicolon
++(1,15): expected-doctype-but-got-start-tag
++#new-errors
++(1:15) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ>"
++
++#data
++<div bar="ZZ&pound_id=23"></div>
++#errors
++(1,18): named-entity-without-semicolon
++(1,26): expected-doctype-but-got-start-tag
++#new-errors
++(1:19) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ£_id=23"
++
++#data
++<div bar="ZZ&prod_id=23"></div>
++#errors
++(1,25): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&prod_id=23"
++
++#data
++<div bar="ZZ&pound;_id=23"></div>
++#errors
++(1,27): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ£_id=23"
++
++#data
++<div bar="ZZ&prod;_id=23"></div>
++#errors
++(1,26): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ∏_id=23"
++
++#data
++<div bar="ZZ&pound=23"></div>
++#errors
++(1,18): named-entity-without-semicolon
++(1,23): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&pound=23"
++
++#data
++<div bar="ZZ&prod=23"></div>
++#errors
++(1,22): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       bar="ZZ&prod=23"
++
++#data
++<div>ZZ&pound_id=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,13): named-entity-without-semicolon
++#new-errors
++(1:14) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ£_id=23"
++
++#data
++<div>ZZ&prod_id=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ&prod_id=23"
++
++#data
++<div>ZZ&pound;_id=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ£_id=23"
++
++#data
++<div>ZZ&prod;_id=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ∏_id=23"
++
++#data
++<div>ZZ&pound=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,13): named-entity-without-semicolon
++#new-errors
++(1:14) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ£=23"
++
++#data
++<div>ZZ&prod=23</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZ&prod=23"
++
++#data
++<div>ZZ&AElig=</div>
++#errors
++#new-errors
++(1:14) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "ZZÆ="
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c81ae8171255f3a82a0b99f4227f046c099088b1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,559 @@@
++#data
++<nobr>X
++#errors
++6: HTML start tag “nobr” in a foreign namespace context.
++7: End of file seen and there were open elements.
++6: Unclosed element “nobr”.
++#document-fragment
++svg path
++#document
++| <svg nobr>
++|   "X"
++
++#data
++<font color></font>X
++#errors
++12: HTML start tag “font” in a foreign namespace context.
++#document-fragment
++svg path
++#document
++| <svg font>
++|   color=""
++| "X"
++
++#data
++<font></font>X
++#errors
++#document-fragment
++svg path
++#document
++| <svg font>
++| "X"
++
++#data
++<g></path>X
++#errors
++10: End tag “path” did not match the name of the current open element (“g”).
++11: End of file seen and there were open elements.
++3: Unclosed element “g”.
++#document-fragment
++svg path
++#document
++| <svg g>
++|   "X"
++
++#data
++</path>X
++#errors
++5: Stray end tag “path”.
++#document-fragment
++svg path
++#document
++| "X"
++
++#data
++</foreignObject>X
++#errors
++5: Stray end tag “foreignobject”.
++#document-fragment
++svg foreignObject
++#document
++| "X"
++
++#data
++</desc>X
++#errors
++5: Stray end tag “desc”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++</title>X
++#errors
++5: Stray end tag “title”.
++#document-fragment
++svg title
++#document
++| "X"
++
++#data
++</svg>X
++#errors
++5: Stray end tag “svg”.
++#document-fragment
++svg svg
++#document
++| "X"
++
++#data
++</mfenced>X
++#errors
++5: Stray end tag “mfenced”.
++#document-fragment
++math mfenced
++#document
++| "X"
++
++#data
++</malignmark>X
++#errors
++5: Stray end tag “malignmark”.
++#document-fragment
++math malignmark
++#document
++| "X"
++
++#data
++</math>X
++#errors
++5: Stray end tag “math”.
++#document-fragment
++math math
++#document
++| "X"
++
++#data
++</annotation-xml>X
++#errors
++5: Stray end tag “annotation-xml”.
++#document-fragment
++math annotation-xml
++#document
++| "X"
++
++#data
++</mtext>X
++#errors
++5: Stray end tag “mtext”.
++#document-fragment
++math mtext
++#document
++| "X"
++
++#data
++</mi>X
++#errors
++5: Stray end tag “mi”.
++#document-fragment
++math mi
++#document
++| "X"
++
++#data
++</mo>X
++#errors
++5: Stray end tag “mo”.
++#document-fragment
++math mo
++#document
++| "X"
++
++#data
++</mn>X
++#errors
++5: Stray end tag “mn”.
++#document-fragment
++math mn
++#document
++| "X"
++
++#data
++</ms>X
++#errors
++5: Stray end tag “ms”.
++#document-fragment
++math ms
++#document
++| "X"
++
++#data
++<b></b><mglyph/><i></i><malignmark/><u></u><ms/>X
++#errors
++51: Self-closing syntax (“/>”) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
++52: End of file seen and there were open elements.
++51: Unclosed element “ms”.
++#new-errors
++(1:44-1:49) non-void-html-element-start-tag-with-trailing-solidus
++#document-fragment
++math ms
++#document
++| <b>
++| <math mglyph>
++| <i>
++| <math malignmark>
++| <u>
++| <ms>
++|   "X"
++
++#data
++<malignmark></malignmark>
++#errors
++#document-fragment
++math ms
++#document
++| <math malignmark>
++
++#data
++<div></div>
++#errors
++#document-fragment
++math ms
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math ms
++#document
++| <figure>
++
++#data
++<b></b><mglyph/><i></i><malignmark/><u></u><mn/>X
++#errors
++51: Self-closing syntax (“/>”) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
++52: End of file seen and there were open elements.
++51: Unclosed element “mn”.
++#new-errors
++(1:44-1:49) non-void-html-element-start-tag-with-trailing-solidus
++#document-fragment
++math mn
++#document
++| <b>
++| <math mglyph>
++| <i>
++| <math malignmark>
++| <u>
++| <mn>
++|   "X"
++
++#data
++<malignmark></malignmark>
++#errors
++#document-fragment
++math mn
++#document
++| <math malignmark>
++
++#data
++<div></div>
++#errors
++#document-fragment
++math mn
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math mn
++#document
++| <figure>
++
++#data
++<b></b><mglyph/><i></i><malignmark/><u></u><mo/>X
++#errors
++51: Self-closing syntax (“/>”) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
++52: End of file seen and there were open elements.
++51: Unclosed element “mo”.
++#new-errors
++(1:44-1:49) non-void-html-element-start-tag-with-trailing-solidus
++#document-fragment
++math mo
++#document
++| <b>
++| <math mglyph>
++| <i>
++| <math malignmark>
++| <u>
++| <mo>
++|   "X"
++
++#data
++<malignmark></malignmark>
++#errors
++#document-fragment
++math mo
++#document
++| <math malignmark>
++
++#data
++<div></div>
++#errors
++#document-fragment
++math mo
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math mo
++#document
++| <figure>
++
++#data
++<b></b><mglyph/><i></i><malignmark/><u></u><mi/>X
++#errors
++51: Self-closing syntax (“/>”) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
++52: End of file seen and there were open elements.
++51: Unclosed element “mi”.
++#new-errors
++(1:44-1:49) non-void-html-element-start-tag-with-trailing-solidus
++#document-fragment
++math mi
++#document
++| <b>
++| <math mglyph>
++| <i>
++| <math malignmark>
++| <u>
++| <mi>
++|   "X"
++
++#data
++<malignmark></malignmark>
++#errors
++#document-fragment
++math mi
++#document
++| <math malignmark>
++
++#data
++<div></div>
++#errors
++#document-fragment
++math mi
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math mi
++#document
++| <figure>
++
++#data
++<b></b><mglyph/><i></i><malignmark/><u></u><mtext/>X
++#errors
++51: Self-closing syntax (“/>”) used on a non-void HTML element. Ignoring the slash and treating as a start tag.
++52: End of file seen and there were open elements.
++51: Unclosed element “mtext”.
++#new-errors
++(1:44-1:52) non-void-html-element-start-tag-with-trailing-solidus
++#document-fragment
++math mtext
++#document
++| <b>
++| <math mglyph>
++| <i>
++| <math malignmark>
++| <u>
++| <mtext>
++|   "X"
++
++#data
++<malignmark></malignmark>
++#errors
++#document-fragment
++math mtext
++#document
++| <math malignmark>
++
++#data
++<div></div>
++#errors
++#document-fragment
++math mtext
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math mtext
++#document
++| <figure>
++
++#data
++<div></div>
++#errors
++5: HTML start tag “div” in a foreign namespace context.
++#document-fragment
++math annotation-xml
++#document
++| <math div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math annotation-xml
++#document
++| <math figure>
++
++#data
++<div></div>
++#errors
++5: HTML start tag “div” in a foreign namespace context.
++#document-fragment
++math math
++#document
++| <math div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++math math
++#document
++| <math figure>
++
++#data
++<div></div>
++#errors
++#document-fragment
++svg foreignObject
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++svg foreignObject
++#document
++| <figure>
++
++#data
++<div></div>
++#errors
++#document-fragment
++svg title
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++svg title
++#document
++| <figure>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++svg desc
++#document
++| <figure>
++
++#data
++<div><h1>X</h1></div>
++#errors
++5: HTML start tag “div” in a foreign namespace context.
++9: HTML start tag “h1” in a foreign namespace context.
++#document-fragment
++svg svg
++#document
++| <svg div>
++|   <svg h1>
++|     "X"
++
++#data
++<div></div>
++#errors
++5: HTML start tag “div” in a foreign namespace context.
++#document-fragment
++svg svg
++#document
++| <svg div>
++
++#data
++<div></div>
++#errors
++#document-fragment
++svg desc
++#document
++| <div>
++
++#data
++<figure></figure>
++#errors
++#document-fragment
++svg desc
++#document
++| <figure>
++
++#data
++<plaintext><foo>
++#errors
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++svg desc
++#document
++| <plaintext>
++|   "<foo>"
++
++#data
++<frameset>X
++#errors
++6: Stray start tag “frameset”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++<head>X
++#errors
++6: Stray start tag “head”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++<body>X
++#errors
++6: Stray start tag “body”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++<html>X
++#errors
++6: Stray start tag “html”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++<html class="foo">X
++#errors
++6: Stray start tag “html”.
++#document-fragment
++svg desc
++#document
++| "X"
++
++#data
++<body class="foo">X
++#errors
++6: Stray start tag “body”.
++#document-fragment
++svg desc
++#document
++| "X"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f7380101eeae13b5dc3037d4b26da487aa9b4808
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,302 @@@
++#data
++<div<div>
++#errors
++(1,9): expected-doctype-but-got-start-tag
++(1,9): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div<div>
++
++#data
++<div foo<bar=''>
++#errors
++(1,9): invalid-character-in-attribute-name
++(1,16): expected-doctype-but-got-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#new-errors
++(1:9) unexpected-character-in-attribute-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       foo<bar=""
++
++#data
++<div foo=`bar`>
++#errors
++(1,10): equals-in-unquoted-attribute-value
++(1,14): unexpected-character-in-unquoted-attribute-value
++(1,15): expected-doctype-but-got-start-tag
++(1,15): expected-closing-tag-but-got-eof
++#new-errors
++(1:10) unexpected-character-in-unquoted-attribute-value
++(1:14) unexpected-character-in-unquoted-attribute-value
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       foo="`bar`"
++
++#data
++<div \"foo=''>
++#errors
++(1,7): invalid-character-in-attribute-name
++(1,14): expected-doctype-but-got-start-tag
++(1,14): expected-closing-tag-but-got-eof
++#new-errors
++(1:7) unexpected-character-in-attribute-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       \"foo=""
++
++#data
++<a href='\nbar'></a>
++#errors
++(1,16): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="\nbar"
++
++#data
++<!DOCTYPE html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++&lang;&rang;
++#errors
++(1,6): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "⟨⟩"
++
++#data
++&apos;
++#errors
++(1,6): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "'"
++
++#data
++&ImaginaryI;
++#errors
++(1,12): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "ⅈ"
++
++#data
++&Kopf;
++#errors
++(1,6): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "𝕂"
++
++#data
++&notinva;
++#errors
++(1,9): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "∉"
++
++#data
++<?import namespace="foo" implementation="#bar">
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,47): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?import namespace="foo" implementation="#bar" -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!--foo--bar-->
++#errors
++(1,10): unexpected-char-in-comment
++(1,15): expected-doctype-but-got-eof
++#document
++| <!-- foo--bar -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<![CDATA[x]]>
++#errors
++(1,2): expected-dashes-or-doctype
++(1,13): expected-doctype-but-got-eof
++#new-errors
++(1:9) cdata-in-html-content
++#document
++| <!-- [CDATA[x]] -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<textarea><!--</textarea>--></textarea>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,39): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<!--"
++|     "-->"
++
++#data
++<textarea><!--</textarea>-->
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<!--"
++|     "-->"
++
++#data
++<style><!--</style>--></style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,30): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--"
++|   <body>
++|     "-->"
++
++#data
++<style><!--</style>-->
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--"
++|   <body>
++|     "-->"
++
++#data
++<ul><li>A </li> <li>B</li></ul>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <li>
++|         "A "
++|       " "
++|       <li>
++|         "B"
++
++#data
++<table><form><input type=hidden><input></form><div></div></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,13): unexpected-form-in-table
++(1,32): unexpected-hidden-input-in-table
++(1,39): unexpected-start-tag-implies-table-voodoo
++(1,46): unexpected-end-tag-implies-table-voodoo
++(1,46): unexpected-end-tag
++(1,51): unexpected-start-tag-implies-table-voodoo
++(1,57): unexpected-end-tag-implies-table-voodoo
++#document
++| <html>
++|   <head>
++|   <body>
++|     <input>
++|     <div>
++|     <table>
++|       <form>
++|       <input>
++|         type="hidden"
++
++#data
++<i>A<b>B<p></i>C</b>D
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,15): adoption-agency-1.3
++(1,20): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "A"
++|       <b>
++|         "B"
++|     <b>
++|     <p>
++|       <b>
++|         <i>
++|         "C"
++|       "D"
++
++#data
++<div></div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++
++#data
++<svg></svg>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<math></math>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..10f6520f6fe0c64ac57ebee89bdbbbeac1a3849c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,54 @@@
++#data
++<button>1</foo>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,15): unexpected-end-tag
++(1,15): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <button>
++|       "1"
++
++#data
++<foo>1<p>2</foo>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,16): unexpected-end-tag
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       "1"
++|       <p>
++|         "2"
++
++#data
++<dd>1</foo>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <dd>
++|       "1"
++
++#data
++<foo>1<dd>2</foo>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): unexpected-end-tag
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       "1"
++|       <dd>
++|         "2"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..733f82ea8eef7314b41711d938e056f75a440ca1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++#data
++<isindex>
++#errors
++(1,9): expected-doctype-but-got-start-tag
++(1,9): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <isindex>
++
++#data
++<isindex name="A" action="B" prompt="C" foo="D">
++#errors
++(1,48): expected-doctype-but-got-start-tag
++(1,48): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <isindex>
++|       action="B"
++|       foo="D"
++|       name="A"
++|       prompt="C"
++
++#data
++<form><isindex>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,15): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <form>
++|       <isindex>
++
++#data
++<!doctype html><isindex>x</isindex>x
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <isindex>
++|       "x"
++|     "x"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4b103bb0fa34ce745afe2a995c8020a90018bfa0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,46 @@@
++#data
++<!doctype html><p>foo<main>bar<p>baz
++#errors
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|     <main>
++|       "bar"
++|       <p>
++|         "baz"
++
++#data
++<!doctype html><main><p>foo</main>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <main>
++|       <p>
++|         "foo"
++|     "bar"
++
++#data
++<!DOCTYPE html>xxx<svg><x><g><a><main><b>
++#errors
++ * (1,42) unexpected HTML-like start tag token in foreign content
++ * (1,42) unexpected end of file
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "xxx"
++|     <svg svg>
++|       <svg x>
++|         <svg g>
++|           <svg a>
++|             <svg main>
++|     <b>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ae9cd7c612e47ec2ea8a7c5eca703a17e6857f02
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,81 @@@
++#data
++<math><tr><td><mo><tr>
++#errors
++#document-fragment
++td
++#document
++| <math math>
++|   <math tr>
++|     <math td>
++|       <math mo>
++
++#data
++<math><tr><td><mo><tr>
++#errors
++#document-fragment
++tr
++#document
++| <math math>
++|   <math tr>
++|     <math td>
++|       <math mo>
++
++#data
++<math><thead><mo><tbody>
++#errors
++#document-fragment
++thead
++#document
++| <math math>
++|   <math thead>
++|     <math mo>
++
++#data
++<math><tfoot><mo><tbody>
++#errors
++#document-fragment
++tfoot
++#document
++| <math math>
++|   <math tfoot>
++|     <math mo>
++
++#data
++<math><tbody><mo><tfoot>
++#errors
++#document-fragment
++tbody
++#document
++| <math math>
++|   <math tbody>
++|     <math mo>
++
++#data
++<math><tbody><mo></table>
++#errors
++#document-fragment
++tbody
++#document
++| <math math>
++|   <math tbody>
++|     <math mo>
++
++#data
++<math><thead><mo></table>
++#errors
++#document-fragment
++tbody
++#document
++| <math math>
++|   <math thead>
++|     <math mo>
++
++#data
++<math><tfoot><mo></table>
++#errors
++#document-fragment
++tbody
++#document
++| <math math>
++|   <math tfoot>
++|     <math mo>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..43aa0c67b890318096ff86eae1be9f7924a02249
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,257 @@@
++#data
++<menuitem>
++#errors
++10: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
++10: End of file seen and there were open elements.
++10: Unclosed element “menuitem”.
++#document
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++
++#data
++</menuitem>
++#errors
++11: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
++11: Stray end tag “menuitem”.
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><body><menuitem>A
++#errors
++32: End of file seen and there were open elements.
++31: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       "A"
++
++#data
++<!DOCTYPE html><body><menuitem>A<menuitem>B
++#errors
++43: End of file seen and there were open elements.
++42: Unclosed element “menuitem”.
++31: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       "A"
++|       <menuitem>
++|         "B"
++
++#data
++<!DOCTYPE html><body><menuitem>A<menu>B</menu>
++#errors
++46: End of file seen and there were open elements.
++31: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       "A"
++|       <menu>
++|         "B"
++
++#data
++<!DOCTYPE html><body><menuitem>A<hr>B
++#errors
++37: End of file seen and there were open elements.
++31: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       "A"
++|       <hr>
++|       "B"
++
++#data
++<!DOCTYPE html><li><menuitem><li>
++#errors
++33: End tag “li” implied, but there were open elements.
++29: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <li>
++|       <menuitem>
++|     <li>
++
++#data
++<!DOCTYPE html><menuitem><p></menuitem>x
++#errors
++39: Stray end tag “menuitem”.
++40: End of file seen and there were open elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       <p>
++|         "x"
++
++#data
++<!DOCTYPE html><p><b></p><menuitem>
++#errors
++25: End tag “p” seen, but there were open elements.
++21: Unclosed element “b”.
++35: End of file seen and there were open elements.
++35: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|     <b>
++|       <menuitem>
++
++#data
++<!DOCTYPE html><menuitem><asdf></menuitem>x
++#errors
++42: End tag “menuitem” seen, but there were open elements.
++31: Unclosed element “asdf”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       <asdf>
++|     "x"
++
++#data
++<!DOCTYPE html></menuitem>
++#errors
++26: Stray end tag “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><html></menuitem>
++#errors
++26: Stray end tag “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><head></menuitem>
++#errors
++26: Stray end tag “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><select><menuitem></select>
++#errors
++33: Stray start tag “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!DOCTYPE html><option><menuitem>
++#errors
++33: End of file seen and there were open elements.
++33: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <option>
++|       <menuitem>
++
++#data
++<!DOCTYPE html><menuitem><option>
++#errors
++33: End of file seen and there were open elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       <option>
++
++#data
++<!DOCTYPE html><menuitem></body>
++#errors
++32: End tag for  “body” seen, but there were unclosed elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++
++#data
++<!DOCTYPE html><menuitem></html>
++#errors
++32: End tag for  “html” seen, but there were unclosed elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++
++#data
++<!DOCTYPE html><menuitem><p>
++#errors
++28: End of file seen and there were open elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       <p>
++
++#data
++<!DOCTYPE html><menuitem><li>
++#errors
++29: End of file seen and there were open elements.
++25: Unclosed element “menuitem”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <menuitem>
++|       <li>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ca35c0e7cbeaf9959f60ef4d1da4045446ad505b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++#data
++<body><table><tr><td><svg><td><foreignObject><span></td>Foo
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     "Foo"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg td>
++|                 <svg foreignObject>
++|                   <span>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ec3496ce92fee5878f3455025978c09624cf693a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,237 @@@
++#data
++<head><noscript><!doctype html><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 31 Unexpected DOCTYPE. Ignored.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><html class="foo"><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 34 html needs to be the first start tag.
++#script-off
++#document
++| <html>
++|   class="foo"
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript></noscript>
++#errors
++(1,6): expected-doctype-but-got-tag
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++
++#data
++<head><noscript>   </noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       "   "
++|   <body>
++
++#data
++<head><noscript><!--foo--></noscript>
++#errors
++(1,6): expected-doctype-but-got-tag
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><basefont><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <basefont>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><bgsound><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <bgsound>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><link><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <link>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><meta><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <meta>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><noframes>XXX</noscript></noframes></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <noframes>
++|         "XXX</noscript>"
++|   <body>
++
++#data
++<head><noscript><style>XXX</style></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <style>
++|         "XXX"
++|   <body>
++
++#data
++<head><noscript></br><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 21 Element br not allowed in a inhead-noscript context
++Line: 1 Col: 21 Unexpected end tag (br). Treated as br element.
++Line: 1 Col: 42 Unexpected end tag (noscript). Ignored.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <br>
++|     <!-- foo -->
++
++#data
++<head><noscript><head class="foo"><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 34 Unexpected start tag (head).
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><noscript class="foo"><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 34 Unexpected start tag (noscript).
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript></p><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 20 Unexpected end tag (p). Ignored.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- foo -->
++|   <body>
++
++#data
++<head><noscript><p><!--foo--></noscript>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 19 Element p not allowed in a inhead-noscript context
++Line: 1 Col: 40 Unexpected end tag (noscript). Ignored.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <p>
++|       <!-- foo -->
++
++#data
++<head><noscript>XXX<!--foo--></noscript></head>
++#errors
++Line: 1 Col: 6 Unexpected start tag (head). Expected DOCTYPE.
++Line: 1 Col: 19 Unexpected non-space character. Expected inhead-noscript content
++Line: 1 Col: 30 Unexpected end tag (noscript). Ignored.
++Line: 1 Col: 37 Unexpected end tag (head). Ignored.
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     "XXX"
++|     <!-- foo -->
++
++#data
++<head><noscript>
++#errors
++(1,6): expected-doctype-but-got-tag
++(1,6): eof-in-head-noscript
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2c546d40b8b1d8a918878a64d19d36dc7fe29204
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1647d7f23a96e03d085c03e6a7c87ddd439c0d2d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,46 @@@
++#data
++<input type="hidden"><frameset>
++#errors
++(1,21): expected-doctype-but-got-start-tag
++(1,31): unexpected-start-tag
++(1,31): eof-in-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><table><caption><svg>foo</table>bar
++#errors
++(1,47): unexpected-end-tag
++(1,47): end-table-tag-in-caption
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <svg svg>
++|           "foo"
++|     "bar"
++
++#data
++<table><tr><td><svg><desc><td></desc><circle>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,30): unexpected-cell-end-tag
++(1,37): unexpected-end-tag
++(1,45): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg desc>
++|           <td>
++|             <circle>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dfb5cb6329222da4ca6f465bf761f324943ae4c6
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..696782f04a75007836ea7bb9971e170cb74cfc05
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,301 @@@
++#data
++<html><ruby>a<rb>b<rb></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|       <rb>
++
++#data
++<html><ruby>a<rb>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rb>b<rtc></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|       <rtc>
++
++#data
++<html><ruby>a<rb>b<rp></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|       <rp>
++
++#data
++<html><ruby>a<rb>b<span></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,31): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|         <span>
++
++#data
++<html><ruby>a<rt>b<rb></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|       <rb>
++
++#data
++<html><ruby>a<rt>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rt>b<rtc></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|       <rtc>
++
++#data
++<html><ruby>a<rt>b<rp></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|       <rp>
++
++#data
++<html><ruby>a<rt>b<span></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,31): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|         <span>
++
++#data
++<html><ruby>a<rtc>b<rb></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|       <rb>
++
++#data
++<html><ruby>a<rtc>b<rt>c<rt>d</ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|         <rt>
++|           "c"
++|         <rt>
++|           "d"
++
++#data
++<html><ruby>a<rtc>b<rtc></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|       <rtc>
++
++#data
++<html><ruby>a<rtc>b<rp></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|         <rp>
++
++#data
++<html><ruby>a<rtc>b<span></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|         <span>
++
++#data
++<html><ruby>a<rp>b<rb></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|       <rb>
++
++#data
++<html><ruby>a<rp>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rp>b<rtc></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|       <rtc>
++
++#data
++<html><ruby>a<rp>b<rp></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|       <rp>
++
++#data
++<html><ruby>a<rp>b<span></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,31): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|         <span>
++
++#data
++<html><ruby><rtc><ruby>a<rb>b<rt></ruby></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <rtc>
++|         <ruby>
++|           "a"
++|           <rb>
++|             "b"
++|           <rt>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e57085899f8f02e851934e9a3b0014ae24831dcf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,385 @@@
++#data
++FOO<script>'Hello'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'Hello'"
++|     "BAR"
++
++#data
++FOO<script></script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|     "BAR"
++
++#data
++FOO<script></script >BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|     "BAR"
++
++#data
++FOO<script></script/>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,21): self-closing-flag-on-end-tag
++#new-errors
++(1:21) end-tag-with-trailing-solidus
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|     "BAR"
++
++#data
++FOO<script></script/ >BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,20): unexpected-character-after-solidus-in-tag
++#new-errors
++(1:21) unexpected-solidus-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|     "BAR"
++
++#data
++FOO<script type="text/plain"></scriptx>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,42): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "</scriptx>BAR"
++
++#data
++FOO<script></script foo=">" dd>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,31): attributes-in-end-tag
++#new-errors
++(1:31) end-tag-with-attributes
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|     "BAR"
++
++#data
++FOO<script>'<'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<'"
++|     "BAR"
++
++#data
++FOO<script>'<!'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!'"
++|     "BAR"
++
++#data
++FOO<script>'<!-'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-'"
++|     "BAR"
++
++#data
++FOO<script>'<!--'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!--'"
++|     "BAR"
++
++#data
++FOO<script>'<!---'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!---'"
++|     "BAR"
++
++#data
++FOO<script>'<!-->'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-->'"
++|     "BAR"
++
++#data
++FOO<script>'<!-->'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-->'"
++|     "BAR"
++
++#data
++FOO<script>'<!-- potato'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-- potato'"
++|     "BAR"
++
++#data
++FOO<script>'<!-- <sCrIpt'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-- <sCrIpt'"
++|     "BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt>'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,56): expected-script-data-but-got-eof
++(1,56): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:57) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt>'</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt> -'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,58): expected-script-data-but-got-eof
++(1,58): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:59) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt> -'</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt> --'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,59): expected-script-data-but-got-eof
++(1,59): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:60) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt> --'</script>BAR"
++
++#data
++FOO<script>'<!-- <sCrIpt> -->'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "'<!-- <sCrIpt> -->'"
++|     "BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt> --!>'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,61): expected-script-data-but-got-eof
++(1,61): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:62) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt> --!>'</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt> -- >'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,61): expected-script-data-but-got-eof
++(1,61): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:62) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt> -- >'</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt '</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,56): expected-script-data-but-got-eof
++(1,56): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:57) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt '</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++(1,56): expected-script-data-but-got-eof
++(1,56): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:57) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt/'</script>BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt\'</script>BAR
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt\'"
++|     "BAR"
++
++#data
++FOO<script type="text/plain">'<!-- <sCrIpt/'</script>BAR</script>QUX
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       type="text/plain"
++|       "'<!-- <sCrIpt/'</script>BAR"
++|     "QUX"
++
++#data
++FOO<script><!--<script>-></script>--></script>QUX
++#errors
++(1,3): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "FOO"
++|     <script>
++|       "<!--<script>-></script>-->"
++|     "QUX"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5cc0f07496a658ef7a91dbcdb652f88e212e93d1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++#data
++<p><b id="A"><script>document.getElementById("A").id = "B"</script></p>TEXT</b>
++#errors
++#script-on
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|         id="B"
++|         <script>
++|           "document.getElementById("A").id = "B""
++|     <b>
++|       id="A"
++|       "TEXT"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..feebeadba1d8a08a136be74ccfe9352587026989
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,27 @@@
++#data
++<p><font size=4><font size=4><font size=4><script>document.getElementsByTagName("font")[2].setAttribute("size", "5");</script><font size=4><p>X
++#errors
++#script-on
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="5"
++|             <script>
++|               "document.getElementsByTagName("font")[2].setAttribute("size", "5");"
++|             <font>
++|               size="4"
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="4"
++|             "X"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3e71c1baccc9bc26200de9d17698f10f01224a6e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,30 @@@
++#data
++1<script>document.write("2")</script>3
++#errors
++#script-on
++#document
++| <html>
++|   <head>
++|   <body>
++|     "1"
++|     <script>
++|       "document.write("2")"
++|     "23"
++
++#data
++1<script>document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")</script>4
++#errors
++#script-on
++#document
++| <html>
++|   <head>
++|   <body>
++|     "1"
++|     <script>
++|       "document.write("<script>document.write('2')</scr"+ "ipt><script>document.write('3')</scr" + "ipt>")"
++|     <script>
++|       "document.write('2')"
++|     "2"
++|     <script>
++|       "document.write('3')"
++|     "34"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8e9a2bbb0d3c5d65d3c1d6c2240a6a1d0d0fe5d7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,81 @@@
++#data
++<svg><tr><td><title><tr>
++#errors
++#document-fragment
++td
++#document
++| <svg svg>
++|   <svg tr>
++|     <svg td>
++|       <svg title>
++
++#data
++<svg><tr><td><title><tr>
++#errors
++#document-fragment
++tr
++#document
++| <svg svg>
++|   <svg tr>
++|     <svg td>
++|       <svg title>
++
++#data
++<svg><thead><title><tbody>
++#errors
++#document-fragment
++thead
++#document
++| <svg svg>
++|   <svg thead>
++|     <svg title>
++
++#data
++<svg><tfoot><title><tbody>
++#errors
++#document-fragment
++tfoot
++#document
++| <svg svg>
++|   <svg tfoot>
++|     <svg title>
++
++#data
++<svg><tbody><title><tfoot>
++#errors
++#document-fragment
++tbody
++#document
++| <svg svg>
++|   <svg tbody>
++|     <svg title>
++
++#data
++<svg><tbody><title></table>
++#errors
++#document-fragment
++tbody
++#document
++| <svg svg>
++|   <svg tbody>
++|     <svg title>
++
++#data
++<svg><thead><title></table>
++#errors
++#document-fragment
++tbody
++#document
++| <svg svg>
++|   <svg thead>
++|     <svg title>
++
++#data
++<svg><tfoot><title></table>
++#errors
++#document-fragment
++tbody
++#document
++| <svg svg>
++|   <svg tfoot>
++|     <svg title>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f0caaa3c5fcbb719393caa55958d0c2a16b9c1ee
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,286 @@@
++#data
++<table><th>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,11): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <th>
++
++#data
++<table><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,11): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><col foo='bar'>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,22): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|         <col>
++|           foo="bar"
++
++#data
++<table><colgroup></html>foo
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,24): unexpected-end-tag
++(1,27): foster-parenting-character-in-table
++(1,27): foster-parenting-character-in-table
++(1,27): foster-parenting-character-in-table
++(1,27): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     "foo"
++|     <table>
++|       <colgroup>
++
++#data
++<table></table><p>foo
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|     <p>
++|       "foo"
++
++#data
++<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,14): unexpected-end-tag
++(1,24): unexpected-end-tag
++(1,30): unexpected-end-tag
++(1,41): unexpected-end-tag
++(1,48): unexpected-end-tag
++(1,56): unexpected-end-tag
++(1,61): unexpected-end-tag
++(1,69): unexpected-end-tag
++(1,74): unexpected-end-tag
++(1,82): unexpected-end-tag
++(1,87): unexpected-end-tag
++(1,91): unexpected-cell-in-table-body
++(1,91): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><select><option>3</select></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-implies-table-voodoo
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|         "3"
++|     <table>
++
++#data
++<table><select><table></table></select></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-implies-table-voodoo
++(1,22): unexpected-table-element-start-tag-in-select-in-table
++(1,22): unexpected-start-tag-implies-end-tag
++(1,39): unexpected-end-tag
++(1,47): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <table>
++|     <table>
++
++#data
++<table><select></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-implies-table-voodoo
++(1,23): unexpected-table-element-end-tag-in-select-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <table>
++
++#data
++<table><select><option>A<tr><td>B</td></tr></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-implies-table-voodoo
++(1,28): unexpected-table-element-start-tag-in-select-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|         "A"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "B"
++
++#data
++<table><td></body></caption></col></colgroup></html>foo
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,18): unexpected-end-tag
++(1,28): unexpected-end-tag
++(1,34): unexpected-end-tag
++(1,45): unexpected-end-tag
++(1,52): unexpected-end-tag
++(1,55): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "foo"
++
++#data
++<table><td>A</table>B
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "A"
++|     "B"
++
++#data
++<table><tr><caption>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|       <caption>
++
++#data
++<table><tr></body></caption></col></colgroup></html></td></th><td>foo
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,18): unexpected-end-tag-in-table-row
++(1,28): unexpected-end-tag-in-table-row
++(1,34): unexpected-end-tag-in-table-row
++(1,45): unexpected-end-tag-in-table-row
++(1,52): unexpected-end-tag-in-table-row
++(1,57): unexpected-end-tag-in-table-row
++(1,62): unexpected-end-tag-in-table-row
++(1,69): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "foo"
++
++#data
++<table><td><tr>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,15): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|         <tr>
++
++#data
++<table><td><button><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,23): unexpected-cell-end-tag
++(1,23): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <button>
++|           <td>
++
++#data
++<table><tr><td><svg><desc><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,30): unexpected-cell-end-tag
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg desc>
++|           <td>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b38d4f58084f69af395e2f88dc7e82118cc96b14
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1604 @@@
++#data
++<body><template>Hello</template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         "Hello"
++
++#data
++<template>Hello</template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         "Hello"
++|   <body>
++
++#data
++<template></template><div></div>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|   <body>
++|     <div>
++
++#data
++<html><template>Hello</template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         "Hello"
++|   <body>
++
++#data
++<head><template><div></div></template></head>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <div>
++|   <body>
++
++#data
++<div><template><div><span></template><b>
++#errors
++ * (1,6) missing DOCTYPE
++ * (1,38) mismatched template end tag
++ * (1,41) unexpected end of file
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <template>
++|         content
++|           <div>
++|             <span>
++|       <b>
++
++#data
++<div><template></div>Hello
++#errors
++ * (1,6) missing DOCTYPE
++ * (1,22) unexpected token in template
++ * (1,27) unexpected end of file in template
++ * (1,27) unexpected end of file
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <template>
++|         content
++|           "Hello"
++
++#data
++<div></template></div>
++#errors
++ * (1,6) missing DOCTYPE
++ * (1,17) unexpected template end tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++
++#data
++<table><template></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++
++#data
++<table><template></template></div>
++#errors
++ * (1,8) missing DOCTYPE
++ * (1,35) unexpected token in table - foster parenting
++ * (1,35) unexpected end tag
++ * (1,35) unexpected end of file
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++
++#data
++<table><div><template></template></div>
++#errors
++ * (1,8) missing DOCTYPE
++ * (1,13) unexpected token in table - foster parenting
++ * (1,40) unexpected token in table - foster parenting
++ * (1,40) unexpected end of file
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <template>
++|         content
++|     <table>
++
++#data
++<table><template></template><div></div>
++#errors
++no doctype
++bad div in table
++bad /div in table
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|     <table>
++|       <template>
++|         content
++
++#data
++<table>   <template></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       "   "
++|       <template>
++|         content
++
++#data
++<table><tbody><template></template></tbody>
++#errors
++no doctype
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <template>
++|           content
++
++#data
++<table><tbody><template></tbody></template>
++#errors
++no doctype
++bad /tbody
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <template>
++|           content
++
++#data
++<table><tbody><template></template></tbody></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <template>
++|           content
++
++#data
++<table><thead><template></template></thead>
++#errors
++no doctype
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <thead>
++|         <template>
++|           content
++
++#data
++<table><tfoot><template></template></tfoot>
++#errors
++no doctype
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tfoot>
++|         <template>
++|           content
++
++#data
++<select><template></template></select>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <template>
++|         content
++
++#data
++<select><template><option></option></template></select>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <template>
++|         content
++|           <option>
++
++#data
++<template><option></option></select><option></option></template>
++#errors
++no doctype
++bad /select
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <option>
++|         <option>
++|   <body>
++
++#data
++<select><template></template><option></select>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <template>
++|         content
++|       <option>
++
++#data
++<select><option><template></template></select>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|         <template>
++|           content
++
++#data
++<select><template>
++#errors
++no doctype
++eof in template
++eof in select
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <template>
++|         content
++
++#data
++<select><option></option><template>
++#errors
++no doctype
++eof in template
++eof in select
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|       <template>
++|         content
++
++#data
++<select><option></option><template><option>
++#errors
++no doctype
++eof in template
++eof in select
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|       <template>
++|         content
++|           <option>
++
++#data
++<table><thead><template><td></template></table>
++#errors
++ * (1,8) missing DOCTYPE
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <thead>
++|         <template>
++|           content
++|             <td>
++
++#data
++<table><template><thead></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <thead>
++
++#data
++<body><table><template><td></tr><div></template></table>
++#errors
++no doctype
++bad </tr>
++missing </div>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <td>
++|             <div>
++
++#data
++<table><template><thead></template></thead></table>
++#errors
++no doctype
++bad /thead after /template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <thead>
++
++#data
++<table><thead><template><tr></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <thead>
++|         <template>
++|           content
++|             <tr>
++
++#data
++<table><template><tr></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <tr>
++
++#data
++<table><tr><template><td>
++#errors
++no doctype
++eof in template
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <template>
++|             content
++|               <td>
++
++#data
++<table><template><tr><template><td></template></tr></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <tr>
++|             <template>
++|               content
++|                 <td>
++
++#data
++<table><template><tr><template><td></td></template></tr></template></table>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <tr>
++|             <template>
++|               content
++|                 <td>
++
++#data
++<table><template><td></template>
++#errors
++no doctype
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <template>
++|         content
++|           <td>
++
++#data
++<body><template><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++
++#data
++<body><template><template><tr></tr></template><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <tr>
++|         <td>
++
++#data
++<table><colgroup><template><col>
++#errors
++no doctype
++eof in template
++eof in table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|         <template>
++|           content
++|             <col>
++
++#data
++<frameset><template><frame></frame></template></frameset>
++#errors
++ * (1,11) missing DOCTYPE
++ * (1,21) unexpected start tag token
++ * (1,36) unexpected end tag token
++ * (1,47) unexpected end tag token
++#document
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<template><frame></frame></frameset><frame></frame></template>
++#errors
++ * (1,11) missing DOCTYPE
++ * (1,18) unexpected start tag
++ * (1,26) unexpected end tag
++ * (1,37) unexpected end tag
++ * (1,44) unexpected start tag
++ * (1,52) unexpected end tag
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|   <body>
++
++#data
++<template><div><frameset><span></span></div><span></span></template>
++#errors
++no doctype
++bad frameset
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <div>
++|           <span>
++|         <span>
++|   <body>
++
++#data
++<body><template><div><frameset><span></span></div><span></span></template></body>
++#errors
++no doctype
++bad frameset
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <div>
++|           <span>
++|         <span>
++
++#data
++<body><template><script>var i = 1;</script><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <script>
++|           "var i = 1;"
++|         <td>
++
++#data
++<body><template><tr><div></div></tr></template>
++#errors
++no doctype
++foster-parented div
++foster-parented /div
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <div>
++
++#data
++<body><template><tr></tr><td></td></template>
++#errors
++no doctype
++unexpected <td>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <tr>
++|           <td>
++
++#data
++<body><template><td></td></tr><td></td></template>
++#errors
++no doctype
++bad </tr>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++|         <td>
++
++#data
++<body><template><td></td><tbody><td></td></template>
++#errors
++no doctype
++bad <tbody>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++|         <td>
++
++#data
++<body><template><td></td><caption></caption><td></td></template>
++#errors
++ * (1,7) missing DOCTYPE
++ * (1,35) unexpected start tag in table row
++ * (1,45) unexpected end tag in table row
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++|         <td>
++
++#data
++<body><template><td></td><colgroup></caption><td></td></template>
++#errors
++ * (1,7) missing DOCTYPE
++ * (1,36) unexpected start tag in table row
++ * (1,46) unexpected end tag in table row
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++|         <td>
++
++#data
++<body><template><td></td></table><td></td></template>
++#errors
++no doctype
++bad </table>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <td>
++|         <td>
++
++#data
++<body><template><tr></tr><tbody><tr></tr></template>
++#errors
++no doctype
++bad <tbody>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <tr>
++
++#data
++<body><template><tr></tr><caption><tr></tr></template>
++#errors
++no doctype
++bad <caption>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <tr>
++
++#data
++<body><template><tr></tr></table><tr></tr></template>
++#errors
++no doctype
++bad </table>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <tr>
++
++#data
++<body><template><thead></thead><caption></caption><tbody></tbody></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <thead>
++|         <caption>
++|         <tbody>
++
++#data
++<body><template><thead></thead></table><tbody></tbody></template></body>
++#errors
++no doctype
++bad </table>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <thead>
++|         <tbody>
++
++#data
++<body><template><div><tr></tr></div></template>
++#errors
++no doctype
++bad tr
++bad /tr
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <div>
++
++#data
++<body><template><em>Hello</em></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <em>
++|           "Hello"
++
++#data
++<body><template><!--comment--></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <!-- comment -->
++
++#data
++<body><template><style></style><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <style>
++|         <td>
++
++#data
++<body><template><meta><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <meta>
++|         <td>
++
++#data
++<body><template><link><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <link>
++|         <td>
++
++#data
++<body><template><template><tr></tr></template><td></td></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <tr>
++|         <td>
++
++#data
++<body><table><colgroup><template><col></col></template></colgroup></table></body>
++#errors
++no doctype
++bad /col
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|         <template>
++|           content
++|             <col>
++
++#data
++<body a=b><template><div></div><body c=d><div></div></body></template></body>
++#errors
++no doctype
++bad <body>
++bad </body>
++#document
++| <html>
++|   <head>
++|   <body>
++|     a="b"
++|     <template>
++|       content
++|         <div>
++|         <div>
++
++#data
++<html a=b><template><div><html b=c><span></template>
++#errors
++no doctype
++bad <html>
++missing end tags in template
++#document
++| <html>
++|   a="b"
++|   <head>
++|     <template>
++|       content
++|         <div>
++|           <span>
++|   <body>
++
++#data
++<html a=b><template><col></col><html b=c><col></col></template>
++#errors
++no doctype
++bad /col
++bad html
++bad /col
++#document
++| <html>
++|   a="b"
++|   <head>
++|     <template>
++|       content
++|         <col>
++|         <col>
++|   <body>
++
++#data
++<html a=b><template><frame></frame><html b=c><frame></frame></template>
++#errors
++no doctype
++bad frame
++bad /frame
++bad html
++bad frame
++bad /frame
++#document
++| <html>
++|   a="b"
++|   <head>
++|     <template>
++|       content
++|   <body>
++
++#data
++<body><template><tr></tr><template></template><td></td></template>
++#errors
++no doctype
++unexpected <td>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <tr>
++|         <template>
++|           content
++|         <tr>
++|           <td>
++
++#data
++<body><template><thead></thead><template><tr></tr></template><tr></tr><tfoot></tfoot></template>
++#errors
++no doctype
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <thead>
++|         <template>
++|           content
++|             <tr>
++|         <tbody>
++|           <tr>
++|         <tfoot>
++
++#data
++<body><template><template><b><template></template></template>text</template>
++#errors
++no doctype
++missing </b>
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <b>
++|               <template>
++|                 content
++|         "text"
++
++#data
++<body><template><col><colgroup>
++#errors
++no doctype
++bad colgroup
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><col></colgroup>
++#errors
++no doctype
++bogus /colgroup
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><col><colgroup></template></body>
++#errors
++no doctype
++bad colgroup
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><col><div>
++#errors
++ * (1,7) missing DOCTYPE
++ * (1,27) unexpected token
++ * (1,27) unexpected end of file in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><col></div>
++#errors
++no doctype
++bad /div
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><col>Hello
++#errors
++no doctype
++unexpected text
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <col>
++
++#data
++<body><template><i><menu>Foo</i>
++#errors
++no doctype
++mising /menu
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <i>
++|         <menu>
++|           <i>
++|             "Foo"
++
++#data
++<body><template></div><div>Foo</div><template></template><tr></tr>
++#errors
++no doctype
++bogus /div
++bogus tr
++bogus /tr
++eof in template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++|         <div>
++|           "Foo"
++|         <template>
++|           content
++
++#data
++<body><div><template></div><tr><td>Foo</td></tr></template>
++#errors
++ * (1,7) missing DOCTYPE
++ * (1,28) unexpected token in template
++ * (1,60) unexpected end of file
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <template>
++|         content
++|           <tr>
++|             <td>
++|               "Foo"
++
++#data
++<template></figcaption><sub><table></table>
++#errors
++no doctype
++bad /figcaption
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <sub>
++|           <table>
++|   <body>
++
++#data
++<template><template>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|   <body>
++
++#data
++<template><div>
++#errors
++no doctype
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <div>
++|   <body>
++
++#data
++<template><template><div>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <div>
++|   <body>
++
++#data
++<template><template><table>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <table>
++|   <body>
++
++#data
++<template><template><tbody>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <tbody>
++|   <body>
++
++#data
++<template><template><tr>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <tr>
++|   <body>
++
++#data
++<template><template><td>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <td>
++|   <body>
++
++#data
++<template><template><caption>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <caption>
++|   <body>
++
++#data
++<template><template><colgroup>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <colgroup>
++|   <body>
++
++#data
++<template><template><col>
++#errors
++no doctype
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <col>
++|   <body>
++
++#data
++<template><template><tbody><select>
++#errors
++ * (1,11) missing DOCTYPE
++ * (1,36) unexpected token in table - foster parenting
++ * (1,36) unexpected end of file in template
++ * (1,36) unexpected end of file in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <tbody>
++|             <select>
++|   <body>
++
++#data
++<template><template><table>Foo
++#errors
++no doctype
++foster-parenting text F
++foster-parenting text o
++foster-parenting text o
++eof
++eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             "Foo"
++|             <table>
++|   <body>
++
++#data
++<template><template><frame>
++#errors
++no doctype
++bad tag
++eof
++eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|   <body>
++
++#data
++<template><template><script>var i
++#errors
++no doctype
++eof in script
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <script>
++|               "var i"
++|   <body>
++
++#data
++<template><template><style>var i
++#errors
++no doctype
++eof in style
++eof in template
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <template>
++|           content
++|             <style>
++|               "var i"
++|   <body>
++
++#data
++<template><table></template><body><span>Foo
++#errors
++no doctype
++missing /table
++bad eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <table>
++|   <body>
++|     <span>
++|       "Foo"
++
++#data
++<template><td></template><body><span>Foo
++#errors
++no doctype
++bad eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <td>
++|   <body>
++|     <span>
++|       "Foo"
++
++#data
++<template><object></template><body><span>Foo
++#errors
++no doctype
++missing /object
++bad eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <object>
++|   <body>
++|     <span>
++|       "Foo"
++
++#data
++<template><svg><template>
++#errors
++no doctype
++eof in template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <svg svg>
++|           <svg template>
++|   <body>
++
++#data
++<template><svg><foo><template><foreignObject><div></template><div>
++#errors
++no doctype
++ugly template closure
++bad eof
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <svg svg>
++|           <svg foo>
++|             <svg template>
++|               <svg foreignObject>
++|                 <div>
++|   <body>
++|     <div>
++
++#data
++<dummy><template><span></dummy>
++#errors
++no doctype
++bad end tag </dummy>
++eof in template
++eof in dummy
++#document
++| <html>
++|   <head>
++|   <body>
++|     <dummy>
++|       <template>
++|         content
++|           <span>
++
++#data
++<body><table><tr><td><select><template>Foo</template><caption>A</table>
++#errors
++no doctype
++(1,62): unexpected-caption-in-select-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <select>
++|               <template>
++|                 content
++|                   "Foo"
++|       <caption>
++|         "A"
++
++#data
++<body></body><template>
++#errors
++no doctype
++(1,23): template-after-body
++(1,24): eof-in-template
++#document
++| <html>
++|   <head>
++|   <body>
++|     <template>
++|       content
++
++#data
++<head></head><template>
++#errors
++no doctype
++(1,23): template-after-head
++(1,24): eof-in-template
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|   <body>
++
++#data
++<head></head><template>Foo</template>
++#errors
++no doctype
++(1,23): template-after-head
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         "Foo"
++|   <body>
++
++#data
++<!DOCTYPE HTML><dummy><table><template><table><template><table><script>
++#errors
++eof script
++eof template
++eof template
++eof table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dummy>
++|       <table>
++|         <template>
++|           content
++|             <table>
++|               <template>
++|                 content
++|                   <table>
++|                     <script>
++
++#data
++<template><a><table><a>
++#errors
++#document
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <a>
++|           <a>
++|           <table>
++|   <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1c36c1b87dd2ee7965dd17866df6dfb3dbac63dc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1988 @@@
++#data
++Test
++#errors
++(1,0): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "Test"
++
++#data
++<p>One<p>Two
++#errors
++(1,3): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "One"
++|     <p>
++|       "Two"
++
++#data
++Line1<br>Line2<br>Line3<br>Line4
++#errors
++(1,0): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "Line1"
++|     <br>
++|     "Line2"
++|     <br>
++|     "Line3"
++|     <br>
++|     "Line4"
++
++#data
++<html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<head>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head></head>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head></head><body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head></head><body></body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head><body></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><head><body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<html><body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<head></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++</head>
++#errors
++(1,7): expected-doctype-but-got-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++</body>
++#errors
++(1,7): expected-doctype-but-got-end-tag element.
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++</html>
++#errors
++(1,7): expected-doctype-but-got-end-tag element.
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<b><table><td><i></table>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,25): unexpected-cell-end-tag
++(1,25): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <i>
++
++#data
++<b><table><td></b><i></table>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,18): unexpected-end-tag
++(1,29): unexpected-cell-end-tag
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <i>
++|       "X"
++
++#data
++<h1>Hello<h2>World
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,13): unexpected-start-tag
++(1,18): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <h1>
++|       "Hello"
++|     <h2>
++|       "World"
++
++#data
++<a><p>X<a>Y</a>Z</p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,10): unexpected-start-tag-implies-end-tag
++(1,10): adoption-agency-1.3
++(1,24): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <p>
++|       <a>
++|         "X"
++|       <a>
++|         "Y"
++|       "Z"
++
++#data
++<b><button>foo</b>bar
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,18): adoption-agency-1.3
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|     <button>
++|       <b>
++|         "foo"
++|       "bar"
++
++#data
++<!DOCTYPE html><span><button>foo</span>bar
++#errors
++(1,39): unexpected-end-tag
++(1,42): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <span>
++|       <button>
++|         "foobar"
++
++#data
++<p><b><div><marquee></p></b></div>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++(1,24): unexpected-end-tag
++(1,28): unexpected-end-tag
++(1,34): end-tag-too-early
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|     <div>
++|       <b>
++|         <marquee>
++|           <p>
++|           "X"
++
++#data
++<script><div></script></div><title><p></title><p><p>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,28): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<div>"
++|     <title>
++|       "<p>"
++|   <body>
++|     <p>
++|     <p>
++
++#data
++<!--><div>--<!-->
++#errors
++(1,5): incorrect-comment
++(1,10): expected-doctype-but-got-start-tag
++(1,17): incorrect-comment
++(1,17): expected-closing-tag-but-got-eof
++#new-errors
++(1:5) abrupt-closing-of-empty-comment
++(1:17) abrupt-closing-of-empty-comment
++#document
++| <!--  -->
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "--"
++|       <!--  -->
++
++#data
++<p><hr></p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <hr>
++|     <p>
++
++#data
++<select><b><option><select><option></b></select>X
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): unexpected-start-tag-in-select
++(1,27): unexpected-select-in-select
++(1,39): unexpected-end-tag
++(1,48): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|     <option>
++|       "X"
++
++#data
++<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,35): unexpected-start-tag-implies-end-tag
++(1,40): unexpected-cell-end-tag
++(1,43): unexpected-start-tag-implies-table-voodoo
++(1,43): unexpected-start-tag-implies-end-tag
++(1,43): unexpected-end-tag
++(1,63): unexpected-start-tag-implies-end-tag
++(1,64): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <a>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <a>
++|                 <table>
++|               <a>
++|     <a>
++|       <b>
++|         "X"
++|       "C"
++|     <a>
++|       "Y"
++
++#data
++<a X>0<b>1<a Y>2
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-implies-end-tag
++(1,15): adoption-agency-1.3
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       x=""
++|       "0"
++|       <b>
++|         "1"
++|     <b>
++|       <a>
++|         y=""
++|         "2"
++
++#data
++<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X-->
++#errors
++(1,7): unexpected-dash-after-double-dash-in-comment
++(1,14): expected-doctype-but-got-start-tag
++(1,41): unexpected-start-tag-implies-table-voodoo
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): foster-parenting-character-in-table
++(1,48): unexpected-cell-in-table-body
++(1,63): unexpected-cell-end-tag
++(1,71): eof-in-table
++#document
++| <!-- - -->
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|       <div>
++|         "helloexcite!"
++|         <b>
++|           "me!"
++|         <table>
++|           <tbody>
++|             <tr>
++|               <th>
++|                 <i>
++|                   "please!"
++|             <!-- X -->
++
++#data
++<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do-->
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <li>
++|       "hello"
++|     <li>
++|       "world"
++|       <ul>
++|         "how"
++|         <li>
++|           "do"
++|       "you"
++|   <!-- do -->
++
++#data
++<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E
++#errors
++(1,54): unexpected-end-tag-in-select
++(1,55): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++|     <option>
++|       "B"
++|     <optgroup>
++|       "C"
++|       <select>
++|         "DE"
++
++#data
++<
++#errors
++(1,1): expected-tag-name
++(1,1): expected-doctype-but-got-chars
++#new-errors
++(1:2) eof-before-tag-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     "<"
++
++#data
++<#
++#errors
++(1,1): expected-tag-name
++(1,1): expected-doctype-but-got-chars
++#new-errors
++(1:2) invalid-first-character-of-tag-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     "<#"
++
++#data
++</
++#errors
++(1,2): expected-closing-tag-but-got-eof
++(1,2): expected-doctype-but-got-chars
++#new-errors
++(1:3) eof-before-tag-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     "</"
++
++#data
++</#
++#errors
++(1,2): expected-closing-tag-but-got-char
++(1,3): expected-doctype-but-got-eof
++#new-errors
++(1:3) invalid-first-character-of-tag-name
++#document
++| <!-- # -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<?
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,2): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ? -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<?#
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,3): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?# -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!
++#errors
++(1,2): expected-dashes-or-doctype
++(1,2): expected-doctype-but-got-eof
++#new-errors
++(1:3) incorrectly-opened-comment
++#document
++| <!--  -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!#
++#errors
++(1,2): expected-dashes-or-doctype
++(1,3): expected-doctype-but-got-eof
++#new-errors
++(1:3) incorrectly-opened-comment
++#document
++| <!-- # -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<?COMMENT?>
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,11): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?COMMENT? -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!COMMENT>
++#errors
++(1,2): expected-dashes-or-doctype
++(1,10): expected-doctype-but-got-eof
++#new-errors
++(1:3) incorrectly-opened-comment
++#document
++| <!-- COMMENT -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++</ COMMENT >
++#errors
++(1,2): expected-closing-tag-but-got-char
++(1,12): expected-doctype-but-got-eof
++#new-errors
++(1:3) invalid-first-character-of-tag-name
++#document
++| <!--  COMMENT  -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<?COM--MENT?>
++#errors
++(1,1): expected-tag-name-but-got-question-mark
++(1,13): expected-doctype-but-got-eof
++#new-errors
++(1:2) unexpected-question-mark-instead-of-tag-name
++#document
++| <!-- ?COM--MENT? -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!COM--MENT>
++#errors
++(1,2): expected-dashes-or-doctype
++(1,12): expected-doctype-but-got-eof
++#new-errors
++(1:3) incorrectly-opened-comment
++#document
++| <!-- COM--MENT -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++</ COM--MENT >
++#errors
++(1,2): expected-closing-tag-but-got-char
++(1,14): expected-doctype-but-got-eof
++#new-errors
++(1:3) invalid-first-character-of-tag-name
++#document
++| <!--  COM--MENT  -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><style> EOF
++#errors
++(1,26): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       " EOF"
++|   <body>
++
++#data
++<!DOCTYPE html><script> <!-- </script> --> </script> EOF
++#errors
++(1,52): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       " <!-- "
++|     " "
++|   <body>
++|     "-->  EOF"
++
++#data
++<b><p></b>TEST
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,10): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|     <p>
++|       <b>
++|       "TEST"
++
++#data
++<p id=a><b><p id=b></b>TEST
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,19): unexpected-end-tag
++(1,23): adoption-agency-1.2
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       id="a"
++|       <b>
++|     <p>
++|       id="b"
++|       "TEST"
++
++#data
++<b id=a><p><b id=b></p></b>TEST
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,23): unexpected-end-tag
++(1,27): adoption-agency-1.2
++(1,31): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       id="a"
++|       <p>
++|         <b>
++|           id="b"
++|       "TEST"
++
++#data
++<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body>
++#errors
++(1,61): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "U-test"
++|   <body>
++|     <div>
++|       <p>
++|         "Test"
++|         <u>
++
++#data
++<!DOCTYPE html><font><table></font></table></font>
++#errors
++(1,35): unexpected-end-tag-implies-table-voodoo
++(1,35): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|       <table>
++
++#data
++<font><p>hello<b>cruel</font>world
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,29): adoption-agency-1.3
++(1,29): adoption-agency-1.3
++(1,34): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|     <p>
++|       <font>
++|         "hello"
++|         <b>
++|           "cruel"
++|       <b>
++|         "world"
++
++#data
++<b>Test</i>Test
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++(1,15): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "TestTest"
++
++#data
++<b>A<cite>B<div>C
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "A"
++|       <cite>
++|         "B"
++|         <div>
++|           "C"
++
++#data
++<b>A<cite>B<div>C</cite>D
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,24): unexpected-end-tag
++(1,25): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "A"
++|       <cite>
++|         "B"
++|         <div>
++|           "CD"
++
++#data
++<b>A<cite>B<div>C</b>D
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,21): adoption-agency-1.3
++(1,22): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "A"
++|       <cite>
++|         "B"
++|     <div>
++|       <b>
++|         "C"
++|       "D"
++
++#data
++
++#errors
++(1,0): expected-doctype-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<DIV>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,5): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++
++#data
++<DIV> abc
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,9): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc"
++
++#data
++<DIV> abc <B>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,13): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++
++#data
++<DIV> abc <B> def
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def"
++
++#data
++<DIV> abc <B> def <I>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++
++#data
++<DIV> abc <B> def <I> ghi
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,25): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi"
++
++#data
++<DIV> abc <B> def <I> ghi <P>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|           <p>
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|           <p>
++|             " jkl"
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|         <p>
++|           <b>
++|             " jkl "
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B> mno
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,42): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|         <p>
++|           <b>
++|             " jkl "
++|           " mno"
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,47): adoption-agency-1.3
++(1,47): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|       <p>
++|         <i>
++|           <b>
++|             " jkl "
++|           " mno "
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,47): adoption-agency-1.3
++(1,51): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|       <p>
++|         <i>
++|           <b>
++|             " jkl "
++|           " mno "
++|         " pqr"
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,47): adoption-agency-1.3
++(1,56): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|       <p>
++|         <i>
++|           <b>
++|             " jkl "
++|           " mno "
++|         " pqr "
++
++#data
++<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,38): adoption-agency-1.3
++(1,47): adoption-agency-1.3
++(1,60): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       " abc "
++|       <b>
++|         " def "
++|         <i>
++|           " ghi "
++|       <i>
++|       <p>
++|         <i>
++|           <b>
++|             " jkl "
++|           " mno "
++|         " pqr "
++|       " stu"
++
++#data
++<test attribute---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->
++#errors
++(1,1040): expected-doctype-but-got-start-tag
++(1,1040): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <test>
++|       attribute----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------=""
++
++#data
++<a href="blah">aba<table><a href="foo">br<tr><td></td></tr>x</table>aoe
++#errors
++(1,15): expected-doctype-but-got-start-tag
++(1,39): unexpected-start-tag-implies-table-voodoo
++(1,39): unexpected-start-tag-implies-end-tag
++(1,39): unexpected-end-tag
++(1,45): foster-parenting-character-in-table
++(1,45): foster-parenting-character-in-table
++(1,68): foster-parenting-character-in-table
++(1,71): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="blah"
++|       "aba"
++|       <a>
++|         href="foo"
++|         "br"
++|       <a>
++|         href="foo"
++|         "x"
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|     <a>
++|       href="foo"
++|       "aoe"
++
++#data
++<a href="blah">aba<table><tr><td><a href="foo">br</td></tr>x</table>aoe
++#errors
++(1,15): expected-doctype-but-got-start-tag
++(1,54): unexpected-cell-end-tag
++(1,68): unexpected text in table
++(1,71): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="blah"
++|       "abax"
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <a>
++|                 href="foo"
++|                 "br"
++|       "aoe"
++
++#data
++<table><a href="blah">aba<tr><td><a href="foo">br</td></tr>x</table>aoe
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,22): unexpected-start-tag-implies-table-voodoo
++(1,29): foster-parenting-character-in-table
++(1,29): foster-parenting-character-in-table
++(1,29): foster-parenting-character-in-table
++(1,54): unexpected-cell-end-tag
++(1,68): foster-parenting-character-in-table
++(1,71): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="blah"
++|       "aba"
++|     <a>
++|       href="blah"
++|       "x"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <a>
++|               href="foo"
++|               "br"
++|     <a>
++|       href="blah"
++|       "aoe"
++
++#data
++<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,45): end-tag-too-early
++(1,47): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="a"
++|       "aa"
++|       <marquee>
++|         "aa"
++|         <a>
++|           href="b"
++|           "bb"
++|       "aa"
++
++#data
++<wbr><strike><code></strike><code><strike></code>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,28): adoption-agency-1.3
++(1,49): adoption-agency-1.3
++(1,49): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <wbr>
++|     <strike>
++|       <code>
++|     <code>
++|       <code>
++|         <strike>
++
++#data
++<!DOCTYPE html><spacer>foo
++#errors
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <spacer>
++|       "foo"
++
++#data
++<title><meta></title><link><title><meta></title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "<meta>"
++|     <link>
++|     <title>
++|       "<meta>"
++|   <body>
++
++#data
++<style><!--</style><meta><script>--><link></script>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--"
++|     <meta>
++|     <script>
++|       "--><link>"
++|   <body>
++
++#data
++<head><meta></head><link>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,25): unexpected-start-tag-out-of-my-head
++#document
++| <html>
++|   <head>
++|     <meta>
++|     <link>
++|   <body>
++
++#data
++<table><tr><tr><td><td><span><th><span>X</table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,33): unexpected-cell-end-tag
++(1,48): unexpected-cell-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|         <tr>
++|           <td>
++|           <td>
++|             <span>
++|           <th>
++|             <span>
++|               "X"
++
++#data
++<body><body><base><link><meta><title><p></title><body><p></body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,12): unexpected-start-tag
++(1,54): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <base>
++|     <link>
++|     <meta>
++|     <title>
++|       "<p>"
++|     <p>
++
++#data
++<textarea><p></textarea>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<p>"
++
++#data
++<p><image></p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,10): unexpected-start-tag-treated-as
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <img>
++
++#data
++<a><table><a></table><p><a><div><a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,13): unexpected-start-tag-implies-table-voodoo
++(1,13): unexpected-start-tag-implies-end-tag
++(1,13): adoption-agency-1.3
++(1,27): unexpected-start-tag-implies-end-tag
++(1,27): adoption-agency-1.2
++(1,32): unexpected-end-tag
++(1,35): unexpected-start-tag-implies-end-tag
++(1,35): adoption-agency-1.2
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <a>
++|       <table>
++|     <p>
++|       <a>
++|     <div>
++|       <a>
++
++#data
++<head></p><meta><p>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,10): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <meta>
++|   <body>
++|     <p>
++
++#data
++<head></html><meta><p>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,19): expected-eof-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <meta>
++|     <p>
++
++#data
++<b><table><td><i></table>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,25): unexpected-cell-end-tag
++(1,25): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <i>
++
++#data
++<b><table><td></b><i></table>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,18): unexpected-end-tag
++(1,29): unexpected-cell-end-tag
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <i>
++
++#data
++<h1><h2>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,8): unexpected-start-tag
++(1,8): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <h1>
++|     <h2>
++
++#data
++<a><p><a></a></p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,9): unexpected-start-tag-implies-end-tag
++(1,9): adoption-agency-1.3
++(1,21): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <p>
++|       <a>
++|       <a>
++
++#data
++<b><button></b></button></b>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,15): adoption-agency-1.3
++(1,28): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|     <button>
++|       <b>
++
++#data
++<p><b><div><marquee></p></b></div>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++(1,24): unexpected-end-tag
++(1,28): unexpected-end-tag
++(1,34): end-tag-too-early
++(1,34): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|     <div>
++|       <b>
++|         <marquee>
++|           <p>
++
++#data
++<script></script></div><title></title><p><p>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,23): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|     <title>
++|   <body>
++|     <p>
++|     <p>
++
++#data
++<p><hr></p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <hr>
++|     <p>
++
++#data
++<select><b><option><select><option></b></select>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): unexpected-start-tag-in-select
++(1,27): unexpected-select-in-select
++(1,39): unexpected-end-tag
++(1,48): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|     <option>
++
++#data
++<html><head><title></title><body></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|   <body>
++
++#data
++<a><table><td><a><table></table><a></tr><a></table><a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-cell-in-table-body
++(1,35): unexpected-start-tag-implies-end-tag
++(1,40): unexpected-cell-end-tag
++(1,43): unexpected-start-tag-implies-table-voodoo
++(1,43): unexpected-start-tag-implies-end-tag
++(1,43): unexpected-end-tag
++(1,54): unexpected-start-tag-implies-end-tag
++(1,54): adoption-agency-1.2
++(1,54): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <a>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <a>
++|                 <table>
++|               <a>
++|     <a>
++
++#data
++<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,45): end-tag-too-early
++(1,58): end-tag-too-early
++(1,69): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <li>
++|       <div>
++|         <li>
++|       <li>
++|       <li>
++|         <div>
++|       <li>
++|         <address>
++|       <li>
++|         <b>
++|           <em>
++|       <li>
++
++#data
++<ul><li><ul></li><li>a</li></ul></li></ul>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,17): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <li>
++|         <ul>
++|           <li>
++|             "a"
++
++#data
++<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++|     <frameset>
++|       <frame>
++|     <noframes>
++
++#data
++<h1><table><td><h3></table><h3></h1>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,15): unexpected-cell-in-table-body
++(1,27): unexpected-cell-end-tag
++(1,31): unexpected-start-tag
++(1,36): end-tag-too-early
++#document
++| <html>
++|   <head>
++|   <body>
++|     <h1>
++|       <table>
++|         <tbody>
++|           <tr>
++|             <td>
++|               <h3>
++|     <h3>
++
++#data
++<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|         <col>
++|       <colgroup>
++|         <col>
++|         <col>
++|         <col>
++|       <colgroup>
++|         <col>
++|         <col>
++|       <thead>
++|         <tr>
++|           <td>
++
++#data
++<table><col><tbody><col><tr><col><td><col></table><col>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,37): unexpected-cell-in-table-body
++(1,55): unexpected-start-tag-ignored
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|         <col>
++|       <tbody>
++|       <colgroup>
++|         <col>
++|       <tbody>
++|         <tr>
++|       <colgroup>
++|         <col>
++|       <tbody>
++|         <tr>
++|           <td>
++|       <colgroup>
++|         <col>
++
++#data
++<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,52): unexpected-cell-in-table-body
++(1,80): unexpected-start-tag-ignored
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++|       <tbody>
++|       <colgroup>
++|       <tbody>
++|         <tr>
++|       <colgroup>
++|       <tbody>
++|         <tr>
++|           <td>
++|       <colgroup>
++
++#data
++</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
++#errors
++(1,9): expected-doctype-but-got-end-tag
++(1,9): unexpected-end-tag-before-html
++(1,13): unexpected-end-tag-before-html
++(1,18): unexpected-end-tag-before-html
++(1,22): unexpected-end-tag-before-html
++(1,26): unexpected-end-tag-before-html
++(1,35): unexpected-end-tag-before-html
++(1,39): unexpected-end-tag-before-html
++(1,47): unexpected-end-tag-before-html
++(1,52): unexpected-end-tag-before-html
++(1,58): unexpected-end-tag-before-html
++(1,64): unexpected-end-tag-before-html
++(1,72): unexpected-end-tag-before-html
++(1,79): unexpected-end-tag-before-html
++(1,88): unexpected-end-tag-before-html
++(1,93): unexpected-end-tag-before-html
++(1,98): unexpected-end-tag-before-html
++(1,103): unexpected-end-tag-before-html
++(1,108): unexpected-end-tag-before-html
++(1,113): unexpected-end-tag-before-html
++(1,118): unexpected-end-tag-before-html
++(1,130): unexpected-end-tag-after-body
++(1,130): unexpected-end-tag-treated-as
++(1,134): unexpected-end-tag
++(1,140): unexpected-end-tag
++(1,148): unexpected-end-tag
++(1,155): unexpected-end-tag
++(1,163): unexpected-end-tag
++(1,172): unexpected-end-tag
++(1,180): unexpected-end-tag
++(1,185): unexpected-end-tag
++(1,190): unexpected-end-tag
++(1,195): unexpected-end-tag
++(1,203): unexpected-end-tag
++(1,210): unexpected-end-tag
++(1,217): unexpected-end-tag
++(1,225): unexpected-end-tag
++(1,230): unexpected-end-tag
++(1,238): unexpected-end-tag
++(1,244): unexpected-end-tag
++(1,251): unexpected-end-tag
++(1,258): unexpected-end-tag
++(1,269): unexpected-end-tag
++(1,279): unexpected-end-tag
++(1,287): unexpected-end-tag
++(1,296): unexpected-end-tag
++(1,300): unexpected-end-tag
++(1,305): unexpected-end-tag
++(1,310): unexpected-end-tag
++(1,320): unexpected-end-tag
++(1,331): unexpected-end-tag
++(1,339): unexpected-end-tag
++(1,347): unexpected-end-tag
++(1,355): unexpected-end-tag
++(1,365): end-tag-too-early
++(1,378): end-tag-too-early
++(1,387): end-tag-too-early
++(1,393): end-tag-too-early
++(1,399): end-tag-too-early
++(1,404): end-tag-too-early
++(1,415): end-tag-too-early
++(1,425): end-tag-too-early
++(1,432): end-tag-too-early
++(1,437): end-tag-too-early
++(1,442): end-tag-too-early
++(1,447): unexpected-end-tag
++(1,454): unexpected-end-tag
++(1,460): unexpected-end-tag
++(1,467): unexpected-end-tag
++(1,476): end-tag-too-early
++(1,486): end-tag-too-early
++(1,495): end-tag-too-early
++(1,513): expected-eof-but-got-end-tag
++(1,513): unexpected-end-tag
++(1,520): unexpected-end-tag
++(1,529): unexpected-end-tag
++(1,537): unexpected-end-tag
++(1,547): unexpected-end-tag
++(1,557): unexpected-end-tag
++(1,568): unexpected-end-tag
++(1,579): unexpected-end-tag
++(1,590): unexpected-end-tag
++(1,599): unexpected-end-tag
++(1,611): unexpected-end-tag
++(1,622): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <br>
++|     <p>
++
++#data
++<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,20): unexpected-end-tag-implies-table-voodoo
++(1,20): unexpected-end-tag
++(1,24): unexpected-end-tag-implies-table-voodoo
++(1,24): unexpected-end-tag
++(1,29): unexpected-end-tag-implies-table-voodoo
++(1,29): unexpected-end-tag
++(1,33): unexpected-end-tag-implies-table-voodoo
++(1,33): unexpected-end-tag
++(1,37): unexpected-end-tag-implies-table-voodoo
++(1,37): unexpected-end-tag
++(1,46): unexpected-end-tag-implies-table-voodoo
++(1,46): unexpected-end-tag
++(1,50): unexpected-end-tag-implies-table-voodoo
++(1,50): unexpected-end-tag
++(1,58): unexpected-end-tag-implies-table-voodoo
++(1,58): unexpected-end-tag
++(1,63): unexpected-end-tag-implies-table-voodoo
++(1,63): unexpected-end-tag
++(1,69): unexpected-end-tag-implies-table-voodoo
++(1,69): end-tag-too-early
++(1,75): unexpected-end-tag-implies-table-voodoo
++(1,75): unexpected-end-tag
++(1,83): unexpected-end-tag-implies-table-voodoo
++(1,83): unexpected-end-tag
++(1,90): unexpected-end-tag-implies-table-voodoo
++(1,90): unexpected-end-tag
++(1,99): unexpected-end-tag-implies-table-voodoo
++(1,99): unexpected-end-tag
++(1,104): unexpected-end-tag-implies-table-voodoo
++(1,104): end-tag-too-early
++(1,109): unexpected-end-tag-implies-table-voodoo
++(1,109): end-tag-too-early
++(1,114): unexpected-end-tag-implies-table-voodoo
++(1,114): end-tag-too-early
++(1,119): unexpected-end-tag-implies-table-voodoo
++(1,119): end-tag-too-early
++(1,124): unexpected-end-tag-implies-table-voodoo
++(1,124): end-tag-too-early
++(1,129): unexpected-end-tag-implies-table-voodoo
++(1,129): end-tag-too-early
++(1,136): unexpected-end-tag-in-table-row
++(1,141): unexpected-end-tag-implies-table-voodoo
++(1,141): unexpected-end-tag-treated-as
++(1,145): unexpected-end-tag-implies-table-voodoo
++(1,145): unexpected-end-tag
++(1,151): unexpected-end-tag-implies-table-voodoo
++(1,151): unexpected-end-tag
++(1,159): unexpected-end-tag-implies-table-voodoo
++(1,159): unexpected-end-tag
++(1,166): unexpected-end-tag-implies-table-voodoo
++(1,166): unexpected-end-tag
++(1,174): unexpected-end-tag-implies-table-voodoo
++(1,174): unexpected-end-tag
++(1,183): unexpected-end-tag-implies-table-voodoo
++(1,183): unexpected-end-tag
++(1,196): unexpected-end-tag
++(1,201): unexpected-end-tag
++(1,206): unexpected-end-tag
++(1,214): unexpected-end-tag
++(1,221): unexpected-end-tag
++(1,228): unexpected-end-tag
++(1,236): unexpected-end-tag
++(1,241): unexpected-end-tag
++(1,249): unexpected-end-tag
++(1,255): unexpected-end-tag
++(1,262): unexpected-end-tag
++(1,269): unexpected-end-tag
++(1,280): unexpected-end-tag
++(1,290): unexpected-end-tag
++(1,298): unexpected-end-tag
++(1,307): unexpected-end-tag
++(1,311): unexpected-end-tag
++(1,316): unexpected-end-tag
++(1,321): unexpected-end-tag
++(1,331): unexpected-end-tag
++(1,342): unexpected-end-tag
++(1,350): unexpected-end-tag
++(1,358): unexpected-end-tag
++(1,366): unexpected-end-tag
++(1,376): end-tag-too-early
++(1,389): end-tag-too-early
++(1,398): end-tag-too-early
++(1,404): end-tag-too-early
++(1,410): end-tag-too-early
++(1,415): end-tag-too-early
++(1,426): end-tag-too-early
++(1,436): end-tag-too-early
++(1,443): end-tag-too-early
++(1,448): end-tag-too-early
++(1,453): end-tag-too-early
++(1,458): unexpected-end-tag
++(1,465): unexpected-end-tag
++(1,471): unexpected-end-tag
++(1,478): unexpected-end-tag
++(1,487): end-tag-too-early
++(1,497): end-tag-too-early
++(1,506): end-tag-too-early
++(1,524): expected-eof-but-got-end-tag
++(1,524): unexpected-end-tag
++(1,531): unexpected-end-tag
++(1,540): unexpected-end-tag
++(1,548): unexpected-end-tag
++(1,558): unexpected-end-tag
++(1,568): unexpected-end-tag
++(1,579): unexpected-end-tag
++(1,590): unexpected-end-tag
++(1,601): unexpected-end-tag
++(1,610): unexpected-end-tag
++(1,622): unexpected-end-tag
++(1,633): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <br>
++|     <table>
++|       <tbody>
++|         <tr>
++|     <p>
++
++#data
++<frameset>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,10): eof-in-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f84e2d546fab64d7c5633bad46c1e7377601f985
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,849 @@@
++#data
++<!DOCTYPE html><svg></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<!DOCTYPE html><svg></svg><![CDATA[a]]>
++#errors
++(1,28) expected-dashes-or-doctype
++#new-errors
++(1:35) cdata-in-html-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|     <!-- [CDATA[a]] -->
++
++#data
++<!DOCTYPE html><body><svg></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<!DOCTYPE html><body><select><svg></svg></select>
++#errors
++(1,34) unexpected-start-tag-in-select
++(1,40) unexpected-end-tag-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!DOCTYPE html><body><select><option><svg></svg></option></select>
++#errors
++(1,42) unexpected-start-tag-in-select
++(1,48) unexpected-end-tag-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++
++#data
++<!DOCTYPE html><body><table><svg></svg></table>
++#errors
++(1,33) foster-parenting-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><svg><g>foo</g></svg></table>
++#errors
++(1,33) foster-parenting-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table>
++#errors
++(1,33) foster-parenting-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table>
++#errors
++(1,40) foster-parenting-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <table>
++|       <tbody>
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table>
++#errors
++(1,44) foster-parenting-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg g>
++|                 "foo"
++|               <svg g>
++|                 "bar"
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg g>
++|                 "foo"
++|               <svg g>
++|                 "bar"
++|             <p>
++|               "baz"
++
++#data
++<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <svg svg>
++|           <svg g>
++|             "foo"
++|           <svg g>
++|             "bar"
++|         <p>
++|           "baz"
++
++#data
++<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
++#errors
++(1,65) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <svg svg>
++|           <svg g>
++|             "foo"
++|           <svg g>
++|             "bar"
++|         <p>
++|           "baz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux
++#errors
++(1,73) unexpected-end-tag
++(1,73) expected-one-end-tag-but-got-another
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <svg svg>
++|           <svg g>
++|             "foo"
++|           <svg g>
++|             "bar"
++|           "baz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
++#errors
++(1,43) foster-parenting-start-tag svg
++(1,66) unexpected HTML-like start tag token in foreign content
++(1,66) foster-parenting-start-tag
++(1,67) foster-parenting-character
++(1,68) foster-parenting-character
++(1,69) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <p>
++|       "baz"
++|     <table>
++|       <colgroup>
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
++#errors
++(1,49) unexpected-start-tag-in-select
++(1,52) unexpected-start-tag-in-select
++(1,59) unexpected-end-tag-in-select
++(1,62) unexpected-start-tag-in-select
++(1,69) unexpected-end-tag-in-select
++(1,72) unexpected-start-tag-in-select
++(1,83) unexpected-table-element-end-tag-in-select-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <select>
++|               "foobarbaz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux
++#errors
++(1,36) unexpected-start-tag-implies-table-voodoo
++(1,41) unexpected-start-tag-in-select
++(1,44) unexpected-start-tag-in-select
++(1,51) unexpected-end-tag-in-select
++(1,54) unexpected-start-tag-in-select
++(1,61) unexpected-end-tag-in-select
++(1,64) unexpected-start-tag-in-select
++(1,75) unexpected-table-element-end-tag-in-select-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "foobarbaz"
++|     <table>
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz
++#errors
++(1,40) expected-eof-but-got-start-tag
++(1,63) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <p>
++|       "baz"
++
++#data
++<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz
++#errors
++(1,33) unexpected-start-tag-after-body
++(1,56) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg g>
++|         "foo"
++|       <svg g>
++|         "bar"
++|     <p>
++|       "baz"
++
++#data
++<!DOCTYPE html><frameset><svg><g></g><g></g><p><span>
++#errors
++(1,30) unexpected-start-tag-in-frameset
++(1,33) unexpected-start-tag-in-frameset
++(1,37) unexpected-end-tag-in-frameset
++(1,40) unexpected-start-tag-in-frameset
++(1,44) unexpected-end-tag-in-frameset
++(1,47) unexpected-start-tag-in-frameset
++(1,53) unexpected-start-tag-in-frameset
++(1,53) eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span>
++#errors
++(1,41) unexpected-start-tag-after-frameset
++(1,44) unexpected-start-tag-after-frameset
++(1,48) unexpected-end-tag-after-frameset
++(1,51) unexpected-start-tag-after-frameset
++(1,55) unexpected-end-tag-after-frameset
++(1,58) unexpected-start-tag-after-frameset
++(1,64) unexpected-start-tag-after-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     <svg svg>
++|       xlink href="foo"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <svg svg>
++|       <svg g>
++|         xlink href="foo"
++|         xml lang="en"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <svg svg>
++|       <svg g>
++|         xlink href="foo"
++|         xml lang="en"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <svg svg>
++|       <svg g>
++|         xlink href="foo"
++|         xml lang="en"
++|       "bar"
++
++#data
++<svg></path>
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,12) unexpected-end-tag
++(1,12) unexpected-end-tag
++(1,12) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<div><svg></div>a
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,16) unexpected-end-tag
++(1,16) end-tag-too-early
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|     "a"
++
++#data
++<div><svg><path></div>a
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,22) unexpected-end-tag
++(1,22) end-tag-too-early
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|         <svg path>
++|     "a"
++
++#data
++<div><svg><path></svg><path>
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,22) unexpected-end-tag
++(1,28) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|         <svg path>
++|       <path>
++
++#data
++<div><svg><path><foreignObject><math></div>a
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,43) unexpected-end-tag
++(1,43) end-tag-too-early
++(1,44) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|         <svg path>
++|           <svg foreignObject>
++|             <math math>
++|               "a"
++
++#data
++<div><svg><path><foreignObject><p></div>a
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,40) end-tag-too-early
++(1,41) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|         <svg path>
++|           <svg foreignObject>
++|             <p>
++|               "a"
++
++#data
++<!DOCTYPE html><svg><desc><div><svg><ul>a
++#errors
++(1,40) unexpected-html-element-in-foreign-content
++(1,41) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg desc>
++|         <div>
++|           <svg svg>
++|           <ul>
++|             "a"
++
++#data
++<!DOCTYPE html><svg><desc><svg><ul>a
++#errors
++(1,35) unexpected-html-element-in-foreign-content
++(1,36) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg desc>
++|         <svg svg>
++|         <ul>
++|           "a"
++
++#data
++<!DOCTYPE html><p><svg><desc><p>
++#errors
++(1,32) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <svg svg>
++|         <svg desc>
++|           <p>
++
++#data
++<!DOCTYPE html><p><svg><title><p>
++#errors
++(1,33) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <svg svg>
++|         <svg title>
++|           <p>
++
++#data
++<div><svg><path><foreignObject><p></foreignObject><p>
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,50) unexpected-end-tag
++(1,53) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <svg svg>
++|         <svg path>
++|           <svg foreignObject>
++|             <p>
++|             <p>
++
++#data
++<math><mi><div><object><div><span></span></div></object></div></mi><mi>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,71) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         <div>
++|           <object>
++|             <div>
++|               <span>
++|       <math mi>
++
++#data
++<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,83) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         <svg svg>
++|           <svg foreignObject>
++|             <div>
++|               <div>
++|       <math mi>
++
++#data
++<svg><script></script><path>
++#errors
++(1,5) expected-doctype-but-got-start-tag
++(1,28) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg script>
++|       <svg path>
++
++#data
++<table><svg></svg><tr>
++#errors
++(1,7) expected-doctype-but-got-start-tag
++(1,12) unexpected-start-tag-implies-table-voodoo
++(1,22) eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<math><mi><mglyph>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,18) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         <math mglyph>
++
++#data
++<math><mi><malignmark>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,22) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         <math malignmark>
++
++#data
++<math><mo><mglyph>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,18) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mo>
++|         <math mglyph>
++
++#data
++<math><mo><malignmark>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,22) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mo>
++|         <math malignmark>
++
++#data
++<math><mn><mglyph>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,18) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mn>
++|         <math mglyph>
++
++#data
++<math><mn><malignmark>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,22) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mn>
++|         <math malignmark>
++
++#data
++<math><ms><mglyph>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,18) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math ms>
++|         <math mglyph>
++
++#data
++<math><ms><malignmark>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,22) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math ms>
++|         <math malignmark>
++
++#data
++<math><mtext><mglyph>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,21) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mtext>
++|         <math mglyph>
++
++#data
++<math><mtext><malignmark>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,25) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mtext>
++|         <math malignmark>
++
++#data
++<math><annotation-xml><svg></svg></annotation-xml><mi>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,54) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <svg svg>
++|       <math mi>
++
++#data
++<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,144) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <svg svg>
++|           <svg foreignObject>
++|             <div>
++|               <math math>
++|                 <math mi>
++|               <span>
++|           <svg path>
++|       <math mi>
++
++#data
++<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi>
++#errors
++(1,6) expected-doctype-but-got-start-tag
++(1,153) expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <svg svg>
++|           <svg foreignObject>
++|             <math math>
++|               <math mi>
++|                 <svg svg>
++|               <math mo>
++|             <span>
++|           <svg path>
++|       <math mi>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b9901e79ec4054762a2bdf134b991dea8829b009
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,523 @@@
++#data
++<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' diffuseConstant='' edgeMode='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       attributeName=""
++|       attributeType=""
++|       baseFrequency=""
++|       baseProfile=""
++|       calcMode=""
++|       clipPathUnits=""
++|       diffuseConstant=""
++|       edgeMode=""
++|       filterUnits=""
++|       glyphRef=""
++|       gradientTransform=""
++|       gradientUnits=""
++|       kernelMatrix=""
++|       kernelUnitLength=""
++|       keyPoints=""
++|       keySplines=""
++|       keyTimes=""
++|       lengthAdjust=""
++|       limitingConeAngle=""
++|       markerHeight=""
++|       markerUnits=""
++|       markerWidth=""
++|       maskContentUnits=""
++|       maskUnits=""
++|       numOctaves=""
++|       pathLength=""
++|       patternContentUnits=""
++|       patternTransform=""
++|       patternUnits=""
++|       pointsAtX=""
++|       pointsAtY=""
++|       pointsAtZ=""
++|       preserveAlpha=""
++|       preserveAspectRatio=""
++|       primitiveUnits=""
++|       refX=""
++|       refY=""
++|       repeatCount=""
++|       repeatDur=""
++|       requiredExtensions=""
++|       requiredFeatures=""
++|       specularConstant=""
++|       specularExponent=""
++|       spreadMethod=""
++|       startOffset=""
++|       stdDeviation=""
++|       stitchTiles=""
++|       surfaceScale=""
++|       systemLanguage=""
++|       tableValues=""
++|       targetX=""
++|       targetY=""
++|       textLength=""
++|       viewBox=""
++|       viewTarget=""
++|       xChannelSelector=""
++|       yChannelSelector=""
++|       zoomAndPan=""
++
++#data
++<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' DIFFUSECONSTANT='' EDGEMODE='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       attributeName=""
++|       attributeType=""
++|       baseFrequency=""
++|       baseProfile=""
++|       calcMode=""
++|       clipPathUnits=""
++|       diffuseConstant=""
++|       edgeMode=""
++|       filterUnits=""
++|       glyphRef=""
++|       gradientTransform=""
++|       gradientUnits=""
++|       kernelMatrix=""
++|       kernelUnitLength=""
++|       keyPoints=""
++|       keySplines=""
++|       keyTimes=""
++|       lengthAdjust=""
++|       limitingConeAngle=""
++|       markerHeight=""
++|       markerUnits=""
++|       markerWidth=""
++|       maskContentUnits=""
++|       maskUnits=""
++|       numOctaves=""
++|       pathLength=""
++|       patternContentUnits=""
++|       patternTransform=""
++|       patternUnits=""
++|       pointsAtX=""
++|       pointsAtY=""
++|       pointsAtZ=""
++|       preserveAlpha=""
++|       preserveAspectRatio=""
++|       primitiveUnits=""
++|       refX=""
++|       refY=""
++|       repeatCount=""
++|       repeatDur=""
++|       requiredExtensions=""
++|       requiredFeatures=""
++|       specularConstant=""
++|       specularExponent=""
++|       spreadMethod=""
++|       startOffset=""
++|       stdDeviation=""
++|       stitchTiles=""
++|       surfaceScale=""
++|       systemLanguage=""
++|       tableValues=""
++|       targetX=""
++|       targetY=""
++|       textLength=""
++|       viewBox=""
++|       viewTarget=""
++|       xChannelSelector=""
++|       yChannelSelector=""
++|       zoomAndPan=""
++
++#data
++<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' diffuseconstant='' edgemode='' filterunits='' filterres='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       attributeName=""
++|       attributeType=""
++|       baseFrequency=""
++|       baseProfile=""
++|       calcMode=""
++|       clipPathUnits=""
++|       diffuseConstant=""
++|       edgeMode=""
++|       filterUnits=""
++|       filterres=""
++|       glyphRef=""
++|       gradientTransform=""
++|       gradientUnits=""
++|       kernelMatrix=""
++|       kernelUnitLength=""
++|       keyPoints=""
++|       keySplines=""
++|       keyTimes=""
++|       lengthAdjust=""
++|       limitingConeAngle=""
++|       markerHeight=""
++|       markerUnits=""
++|       markerWidth=""
++|       maskContentUnits=""
++|       maskUnits=""
++|       numOctaves=""
++|       pathLength=""
++|       patternContentUnits=""
++|       patternTransform=""
++|       patternUnits=""
++|       pointsAtX=""
++|       pointsAtY=""
++|       pointsAtZ=""
++|       preserveAlpha=""
++|       preserveAspectRatio=""
++|       primitiveUnits=""
++|       refX=""
++|       refY=""
++|       repeatCount=""
++|       repeatDur=""
++|       requiredExtensions=""
++|       requiredFeatures=""
++|       specularConstant=""
++|       specularExponent=""
++|       spreadMethod=""
++|       startOffset=""
++|       stdDeviation=""
++|       stitchTiles=""
++|       surfaceScale=""
++|       systemLanguage=""
++|       tableValues=""
++|       targetX=""
++|       targetY=""
++|       textLength=""
++|       viewBox=""
++|       viewTarget=""
++|       xChannelSelector=""
++|       yChannelSelector=""
++|       zoomAndPan=""
++
++#data
++<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' diffuseConstant='' edgeMode='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       attributename=""
++|       attributetype=""
++|       basefrequency=""
++|       baseprofile=""
++|       calcmode=""
++|       clippathunits=""
++|       diffuseconstant=""
++|       edgemode=""
++|       filterunits=""
++|       glyphref=""
++|       gradienttransform=""
++|       gradientunits=""
++|       kernelmatrix=""
++|       kernelunitlength=""
++|       keypoints=""
++|       keysplines=""
++|       keytimes=""
++|       lengthadjust=""
++|       limitingconeangle=""
++|       markerheight=""
++|       markerunits=""
++|       markerwidth=""
++|       maskcontentunits=""
++|       maskunits=""
++|       numoctaves=""
++|       pathlength=""
++|       patterncontentunits=""
++|       patterntransform=""
++|       patternunits=""
++|       pointsatx=""
++|       pointsaty=""
++|       pointsatz=""
++|       preservealpha=""
++|       preserveaspectratio=""
++|       primitiveunits=""
++|       refx=""
++|       refy=""
++|       repeatcount=""
++|       repeatdur=""
++|       requiredextensions=""
++|       requiredfeatures=""
++|       specularconstant=""
++|       specularexponent=""
++|       spreadmethod=""
++|       startoffset=""
++|       stddeviation=""
++|       stitchtiles=""
++|       surfacescale=""
++|       systemlanguage=""
++|       tablevalues=""
++|       targetx=""
++|       targety=""
++|       textlength=""
++|       viewbox=""
++|       viewtarget=""
++|       xchannelselector=""
++|       ychannelselector=""
++|       zoomandpan=""
++
++#data
++<!DOCTYPE html><body><svg contentScriptType='' contentStyleType='' externalResourcesRequired='' filterRes=''></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       contentscripttype=""
++|       contentstyletype=""
++|       externalresourcesrequired=""
++|       filterres=""
++
++#data
++<!DOCTYPE html><body><svg CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' EXTERNALRESOURCESREQUIRED='' FILTERRES=''></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       contentscripttype=""
++|       contentstyletype=""
++|       externalresourcesrequired=""
++|       filterres=""
++
++#data
++<!DOCTYPE html><body><svg contentscripttype='' contentstyletype='' externalresourcesrequired='' filterres=''></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       contentscripttype=""
++|       contentstyletype=""
++|       externalresourcesrequired=""
++|       filterres=""
++
++#data
++<!DOCTYPE html><body><math contentScriptType='' contentStyleType='' externalResourcesRequired='' filterRes=''></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       contentscripttype=""
++|       contentstyletype=""
++|       externalresourcesrequired=""
++|       filterres=""
++
++#data
++<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg altGlyph>
++|       <svg altGlyphDef>
++|       <svg altGlyphItem>
++|       <svg animateColor>
++|       <svg animateMotion>
++|       <svg animateTransform>
++|       <svg clipPath>
++|       <svg feBlend>
++|       <svg feColorMatrix>
++|       <svg feComponentTransfer>
++|       <svg feComposite>
++|       <svg feConvolveMatrix>
++|       <svg feDiffuseLighting>
++|       <svg feDisplacementMap>
++|       <svg feDistantLight>
++|       <svg feFlood>
++|       <svg feFuncA>
++|       <svg feFuncB>
++|       <svg feFuncG>
++|       <svg feFuncR>
++|       <svg feGaussianBlur>
++|       <svg feImage>
++|       <svg feMerge>
++|       <svg feMergeNode>
++|       <svg feMorphology>
++|       <svg feOffset>
++|       <svg fePointLight>
++|       <svg feSpecularLighting>
++|       <svg feSpotLight>
++|       <svg feTile>
++|       <svg feTurbulence>
++|       <svg foreignObject>
++|       <svg glyphRef>
++|       <svg linearGradient>
++|       <svg radialGradient>
++|       <svg textPath>
++
++#data
++<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg altGlyph>
++|       <svg altGlyphDef>
++|       <svg altGlyphItem>
++|       <svg animateColor>
++|       <svg animateMotion>
++|       <svg animateTransform>
++|       <svg clipPath>
++|       <svg feBlend>
++|       <svg feColorMatrix>
++|       <svg feComponentTransfer>
++|       <svg feComposite>
++|       <svg feConvolveMatrix>
++|       <svg feDiffuseLighting>
++|       <svg feDisplacementMap>
++|       <svg feDistantLight>
++|       <svg feFlood>
++|       <svg feFuncA>
++|       <svg feFuncB>
++|       <svg feFuncG>
++|       <svg feFuncR>
++|       <svg feGaussianBlur>
++|       <svg feImage>
++|       <svg feMerge>
++|       <svg feMergeNode>
++|       <svg feMorphology>
++|       <svg feOffset>
++|       <svg fePointLight>
++|       <svg feSpecularLighting>
++|       <svg feSpotLight>
++|       <svg feTile>
++|       <svg feTurbulence>
++|       <svg foreignObject>
++|       <svg glyphRef>
++|       <svg linearGradient>
++|       <svg radialGradient>
++|       <svg textPath>
++
++#data
++<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg altGlyph>
++|       <svg altGlyphDef>
++|       <svg altGlyphItem>
++|       <svg animateColor>
++|       <svg animateMotion>
++|       <svg animateTransform>
++|       <svg clipPath>
++|       <svg feBlend>
++|       <svg feColorMatrix>
++|       <svg feComponentTransfer>
++|       <svg feComposite>
++|       <svg feConvolveMatrix>
++|       <svg feDiffuseLighting>
++|       <svg feDisplacementMap>
++|       <svg feDistantLight>
++|       <svg feFlood>
++|       <svg feFuncA>
++|       <svg feFuncB>
++|       <svg feFuncG>
++|       <svg feFuncR>
++|       <svg feGaussianBlur>
++|       <svg feImage>
++|       <svg feMerge>
++|       <svg feMergeNode>
++|       <svg feMorphology>
++|       <svg feOffset>
++|       <svg fePointLight>
++|       <svg feSpecularLighting>
++|       <svg feSpotLight>
++|       <svg feTile>
++|       <svg feTurbulence>
++|       <svg foreignObject>
++|       <svg glyphRef>
++|       <svg linearGradient>
++|       <svg radialGradient>
++|       <svg textPath>
++
++#data
++<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math altglyph>
++|       <math altglyphdef>
++|       <math altglyphitem>
++|       <math animatecolor>
++|       <math animatemotion>
++|       <math animatetransform>
++|       <math clippath>
++|       <math feblend>
++|       <math fecolormatrix>
++|       <math fecomponenttransfer>
++|       <math fecomposite>
++|       <math feconvolvematrix>
++|       <math fediffuselighting>
++|       <math fedisplacementmap>
++|       <math fedistantlight>
++|       <math feflood>
++|       <math fefunca>
++|       <math fefuncb>
++|       <math fefuncg>
++|       <math fefuncr>
++|       <math fegaussianblur>
++|       <math feimage>
++|       <math femerge>
++|       <math femergenode>
++|       <math femorphology>
++|       <math feoffset>
++|       <math fepointlight>
++|       <math fespecularlighting>
++|       <math fespotlight>
++|       <math fetile>
++|       <math feturbulence>
++|       <math foreignobject>
++|       <math glyphref>
++|       <math lineargradient>
++|       <math radialgradient>
++|       <math textpath>
++
++#data
++<!DOCTYPE html><body><svg><solidColor /></svg>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg solidcolor>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..63107d277b6a7f1597155ad2527868bbc2c323de
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,62 @@@
++#data
++<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++|       <math math>
++|         <math mtext>
++|           <i>
++|             "baz"
++|         <math annotation-xml>
++|           <svg svg>
++|             <svg desc>
++|               <b>
++|                 "eggs"
++|             <svg g>
++|               <svg foreignObject>
++|                 <p>
++|                   "spam"
++|                 <table>
++|                   <tbody>
++|                     <tr>
++|                       <td>
++|                         <img>
++|             <svg g>
++|               "quux"
++|       "bar"
++
++#data
++<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "foo"
++|     <math math>
++|       <math mtext>
++|         <i>
++|           "baz"
++|       <math annotation-xml>
++|         <svg svg>
++|           <svg desc>
++|             <b>
++|               "eggs"
++|           <svg g>
++|             <svg foreignObject>
++|               <p>
++|                 "spam"
++|               <table>
++|                 <tbody>
++|                   <tr>
++|                     <td>
++|                       <img>
++|           <svg g>
++|             "quux"
++|     "bar"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a08b7649ebab76276be3c38d19e75bb9598e5731
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,75 @@@
++#data
++<!DOCTYPE html><html><body><xyz:abc></xyz:abc>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <xyz:abc>
++
++#data
++<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <xyz:abc>
++|     <span>
++
++#data
++<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc>
++#errors
++(1,38): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   abc:def="gh"
++|   <head>
++|   <body>
++|     <xyz:abc>
++
++#data
++<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo>
++#errors
++(1,53): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   xml:lang="bar"
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><html 123=456>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   123="456"
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><html 123=456><html 789=012>
++#errors
++(1,43): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   123="456"
++|   789="012"
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><html><body 789=012>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     789="012"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..93d06a871708a2929e900c331adec80d3697709e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,216 @@@
++#data
++<!DOCTYPE html><p><b><i><u></p> <p>X
++#errors
++(1,31): unexpected-end-tag
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|         <i>
++|           <u>
++|     <b>
++|       <i>
++|         <u>
++|           " "
++|           <p>
++|             "X"
++
++#data
++<p><b><i><u></p>
++<p>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,16): unexpected-end-tag
++(2,4): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|         <i>
++|           <u>
++|     <b>
++|       <i>
++|         <u>
++|           "
++"
++|           <p>
++|             "X"
++
++#data
++<!doctype html></html> <head>
++#errors
++(1,29): expected-eof-but-got-start-tag
++(1,29): unexpected-start-tag-ignored
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " "
++
++#data
++<!doctype html></body><meta>
++#errors
++(1,28): unexpected-start-tag-after-body
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <meta>
++
++#data
++<html></html><!-- foo -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++| <!--  foo  -->
++
++#data
++<!doctype html></body><title>X</title>
++#errors
++(1,29): unexpected-start-tag-after-body
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <title>
++|       "X"
++
++#data
++<!doctype html><table> X<meta></table>
++#errors
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++(1,30): foster-parenting-start-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " X"
++|     <meta>
++|     <table>
++
++#data
++<!doctype html><table> x</table>
++#errors
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " x"
++|     <table>
++
++#data
++<!doctype html><table> x </table>
++#errors
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++(1,25): foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " x "
++|     <table>
++
++#data
++<!doctype html><table><tr> x</table>
++#errors
++(1,27): foster-parenting-character
++(1,28): foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " x"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><table>X<style> <tr>x </style> </table>
++#errors
++(1,23): foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++|     <table>
++|       <style>
++|         " <tr>x "
++|       " "
++
++#data
++<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div>
++#errors
++(1,30): foster-parenting-start-tag
++(1,31): foster-parenting-character
++(1,32): foster-parenting-character
++(1,33): foster-parenting-character
++(1,37): foster-parenting-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <a>
++|         "foo"
++|       <table>
++|         " "
++|         <tbody>
++|           <tr>
++|             <td>
++|               "bar"
++|             " "
++
++#data
++<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,7): unexpected-start-tag-ignored
++(1,15): unexpected-end-tag
++(1,23): unexpected-end-tag
++(1,33): unexpected-start-tag
++(1,99): expected-named-closing-tag-but-got-eof
++(1,99): eof-in-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++|     <frameset>
++|       <frame>
++|     <noframes>
++|       "</frameset><noframes>"
++
++#data
++<!DOCTYPE html><object></html>
++#errors
++(1,30): expected-body-in-scope
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <object>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cea7340a0cfa5ed2a6a94f885751e04623c4d2b8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2604 @@@
++#data
++<!doctype html><script>
++#errors
++(1,23): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<!doctype html><script>a
++#errors
++(1,24): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "a"
++|   <body>
++
++#data
++<!doctype html><script><
++#errors
++(1,24): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<"
++|   <body>
++
++#data
++<!doctype html><script></
++#errors
++(1,25): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</"
++|   <body>
++
++#data
++<!doctype html><script></S
++#errors
++(1,26): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</S"
++|   <body>
++
++#data
++<!doctype html><script></SC
++#errors
++(1,27): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</SC"
++|   <body>
++
++#data
++<!doctype html><script></SCR
++#errors
++(1,28): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</SCR"
++|   <body>
++
++#data
++<!doctype html><script></SCRI
++#errors
++(1,29): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</SCRI"
++|   <body>
++
++#data
++<!doctype html><script></SCRIP
++#errors
++(1,30): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</SCRIP"
++|   <body>
++
++#data
++<!doctype html><script></SCRIPT
++#errors
++(1,31): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</SCRIPT"
++|   <body>
++
++#data
++<!doctype html><script></SCRIPT 
++#errors
++(1,32): expected-attribute-name-but-got-eof
++(1,32): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:33) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<!doctype html><script></s
++#errors
++(1,26): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</s"
++|   <body>
++
++#data
++<!doctype html><script></sc
++#errors
++(1,27): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</sc"
++|   <body>
++
++#data
++<!doctype html><script></scr
++#errors
++(1,28): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</scr"
++|   <body>
++
++#data
++<!doctype html><script></scri
++#errors
++(1,29): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</scri"
++|   <body>
++
++#data
++<!doctype html><script></scrip
++#errors
++(1,30): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</scrip"
++|   <body>
++
++#data
++<!doctype html><script></script
++#errors
++(1,31): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "</script"
++|   <body>
++
++#data
++<!doctype html><script></script 
++#errors
++(1,32): expected-attribute-name-but-got-eof
++(1,32): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:33) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<!doctype html><script><!
++#errors
++(1,25): expected-script-data-but-got-eof
++(1,25): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!"
++|   <body>
++
++#data
++<!doctype html><script><!a
++#errors
++(1,26): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!a"
++|   <body>
++
++#data
++<!doctype html><script><!-
++#errors
++(1,26): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!-"
++|   <body>
++
++#data
++<!doctype html><script><!-a
++#errors
++(1,27): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!-a"
++|   <body>
++
++#data
++<!doctype html><script><!--
++#errors
++(1,27): expected-named-closing-tag-but-got-eof
++(1,27): unexpected-eof-in-text-mode
++#new-errors
++(1:28) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--"
++|   <body>
++
++#data
++<!doctype html><script><!--a
++#errors
++(1,28): expected-named-closing-tag-but-got-eof
++(1,28): unexpected-eof-in-text-mode
++#new-errors
++(1:29) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--a"
++|   <body>
++
++#data
++<!doctype html><script><!--<
++#errors
++(1,28): expected-named-closing-tag-but-got-eof
++(1,28): unexpected-eof-in-text-mode
++#new-errors
++(1:29) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<"
++|   <body>
++
++#data
++<!doctype html><script><!--<a
++#errors
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<a"
++|   <body>
++
++#data
++<!doctype html><script><!--</
++#errors
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--</"
++|   <body>
++
++#data
++<!doctype html><script><!--</script
++#errors
++(1,35): expected-named-closing-tag-but-got-eof
++(1,35): unexpected-eof-in-text-mode
++#new-errors
++(1:36) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--</script"
++|   <body>
++
++#data
++<!doctype html><script><!--</script 
++#errors
++(1,36): expected-attribute-name-but-got-eof
++(1,36): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:37) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--"
++|   <body>
++
++#data
++<!doctype html><script><!--<s
++#errors
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<s"
++|   <body>
++
++#data
++<!doctype html><script><!--<script
++#errors
++(1,34): expected-named-closing-tag-but-got-eof
++(1,34): unexpected-eof-in-text-mode
++#new-errors
++(1:35) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script"
++|   <body>
++
++#data
++<!doctype html><script><!--<script 
++#errors
++(1,35): eof-in-script-in-script
++(1,35): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:36) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script "
++|   <body>
++
++#data
++<!doctype html><script><!--<script <
++#errors
++(1,36): eof-in-script-in-script
++(1,36): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:37) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script <"
++|   <body>
++
++#data
++<!doctype html><script><!--<script <a
++#errors
++(1,37): eof-in-script-in-script
++(1,37): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script <a"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </
++#errors
++(1,37): eof-in-script-in-script
++(1,37): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </s
++#errors
++(1,38): eof-in-script-in-script
++(1,38): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:39) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </s"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script
++#errors
++(1,43): eof-in-script-in-script
++(1,43): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:44) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </scripta
++#errors
++(1,44): eof-in-script-in-script
++(1,44): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:45) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </scripta"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script 
++#errors
++(1,44): expected-named-closing-tag-but-got-eof
++(1,44): unexpected-eof-in-text-mode
++#new-errors
++(1:45) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script>
++#errors
++(1,44): expected-named-closing-tag-but-got-eof
++(1,44): unexpected-eof-in-text-mode
++#new-errors
++(1:45) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script>"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script/
++#errors
++(1,44): expected-named-closing-tag-but-got-eof
++(1,44): unexpected-eof-in-text-mode
++#new-errors
++(1:45) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script/"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script <
++#errors
++(1,45): expected-named-closing-tag-but-got-eof
++(1,45): unexpected-eof-in-text-mode
++#new-errors
++(1:46) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script <"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script <a
++#errors
++(1,46): expected-named-closing-tag-but-got-eof
++(1,46): unexpected-eof-in-text-mode
++#new-errors
++(1:47) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script <a"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script </
++#errors
++(1,46): expected-named-closing-tag-but-got-eof
++(1,46): unexpected-eof-in-text-mode
++#new-errors
++(1:47) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script </"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script </script
++#errors
++(1,52): expected-named-closing-tag-but-got-eof
++(1,52): unexpected-eof-in-text-mode
++#new-errors
++(1:53) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script </script"
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script </script 
++#errors
++(1,53): expected-attribute-name-but-got-eof
++(1,53): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:54) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script </script/
++#errors
++(1,53): unexpected-EOF-after-solidus-in-tag
++(1,53): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:54) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<!doctype html><script><!--<script </script </script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<!doctype html><script><!--<script -
++#errors
++(1,36): eof-in-script-in-script
++(1,36): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:37) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -"
++|   <body>
++
++#data
++<!doctype html><script><!--<script -a
++#errors
++(1,37): eof-in-script-in-script
++(1,37): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -a"
++|   <body>
++
++#data
++<!doctype html><script><!--<script -<
++#errors
++(1,37): eof-in-script-in-script
++(1,37): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -<"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --
++#errors
++(1,37): eof-in-script-in-script
++(1,37): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --a
++#errors
++(1,38): eof-in-script-in-script
++(1,38): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:39) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --a"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --<
++#errors
++(1,38): eof-in-script-in-script
++(1,38): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:39) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --<"
++|   <body>
++
++#data
++<!doctype html><script><!--<script -->
++#errors
++(1,38): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --><
++#errors
++(1,39): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --><"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --></
++#errors
++(1,40): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --></"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --></script
++#errors
++(1,46): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --></script"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --></script 
++#errors
++(1,47): expected-attribute-name-but-got-eof
++(1,47): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:48) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --></script/
++#errors
++(1,47): unexpected-EOF-after-solidus-in-tag
++(1,47): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:48) eof-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script --></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script><\/script>--></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script><\/script>-->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></scr'+'ipt>--></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></scr'+'ipt>-->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script>--><!--</script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>--><!--"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script>-- ></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>-- >"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script>- -></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>- ->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script>- - ></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>- - >"
++|   <body>
++
++#data
++<!doctype html><script><!--<script></script><script></script>-></script>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>->"
++|   <body>
++
++#data
++<!doctype html><script><!--<script>--!></script>X
++#errors
++(1,49): expected-named-closing-tag-but-got-eof
++(1,49): unexpected-EOF-in-text-mode
++#new-errors
++(1:50) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script>--!></script>X"
++|   <body>
++
++#data
++<!doctype html><script><!--<scr'+'ipt></script>--></script>
++#errors
++(1,59): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<scr'+'ipt>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><script><!--<script></scr'+'ipt></script>X
++#errors
++(1,57): expected-named-closing-tag-but-got-eof
++(1,57): unexpected-eof-in-text-mode
++#new-errors
++(1:58) eof-in-script-html-comment-like-text
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></scr'+'ipt></script>X"
++|   <body>
++
++#data
++<!doctype html><style><!--<style></style>--></style>
++#errors
++(1,52): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--<style>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><style><!--</style>X
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--"
++|   <body>
++|     "X"
++
++#data
++<!doctype html><style><!--...</style>...--></style>
++#errors
++(1,51): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--..."
++|   <body>
++|     "...-->"
++
++#data
++<!doctype html><style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
++|   <body>
++|     "X"
++
++#data
++<!doctype html><style><!--...<style><!--...--!></style>--></style>
++#errors
++(1,66): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--...<style><!--...--!>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><style><!--...</style><!-- --><style>@import ...</style>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "<!--..."
++|     <!--   -->
++|     <style>
++|       "@import ..."
++|   <body>
++
++#data
++<!doctype html><style>...<style><!--...</style><!-- --></style>
++#errors
++(1,63): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "...<style><!--..."
++|     <!--   -->
++|   <body>
++
++#data
++<!doctype html><style>...<!--[if IE]><style>...</style>X
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <style>
++|       "...<!--[if IE]><style>..."
++|   <body>
++|     "X"
++
++#data
++<!doctype html><title><!--<title></title>--></title>
++#errors
++(1,52): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "<!--<title>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><title>&lt;/title></title>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "</title>"
++|   <body>
++
++#data
++<!doctype html><title>foo/title><link></head><body>X
++#errors
++(1,52): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "foo/title><link></head><body>X"
++|   <body>
++
++#data
++<!doctype html><noscript><!--<noscript></noscript>--></noscript>
++#errors
++(1,64): unexpected-end-tag
++#script-on
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|       "<!--<noscript>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><noscript><!--<noscript></noscript>--></noscript>
++#errors
++#script-off
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- <noscript></noscript> -->
++|   <body>
++
++#data
++<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
++#errors
++#script-on
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|       "<!--"
++|   <body>
++|     "X"
++|     <noscript>
++|       "-->"
++
++#data
++<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>
++#errors
++#script-off
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- </noscript>X<noscript> -->
++|   <body>
++
++#data
++<!doctype html><noscript><iframe></noscript>X
++#errors
++#script-on
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|       "<iframe>"
++|   <body>
++|     "X"
++
++#data
++<!doctype html><noscript><iframe></noscript>X
++#errors
++ * (1,34) unexpected token in head noscript
++ * (1,46) unexpected EOF
++#script-off
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <iframe>
++|       "</noscript>X"
++
++#data
++<!doctype html><noframes><!--<noframes></noframes>--></noframes>
++#errors
++(1,64): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noframes>
++|       "<!--<noframes>"
++|   <body>
++|     "-->"
++
++#data
++<!doctype html><noframes><body><script><!--...</script></body></noframes></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noframes>
++|       "<body><script><!--...</script></body>"
++|   <body>
++
++#data
++<!doctype html><textarea><!--<textarea></textarea>--></textarea>
++#errors
++(1,64): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<!--<textarea>"
++|     "-->"
++
++#data
++<!doctype html><textarea>&lt;/textarea></textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "</textarea>"
++
++#data
++<!doctype html><textarea>&lt;</textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<"
++
++#data
++<!doctype html><textarea>a&lt;b</textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "a<b"
++
++#data
++<!doctype html><iframe><!--<iframe></iframe>--></iframe>
++#errors
++(1,56): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       "<!--<iframe>"
++|     "-->"
++
++#data
++<!doctype html><iframe>...<!--X->...<!--/X->...</iframe>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       "...<!--X->...<!--/X->..."
++
++#data
++<!doctype html><xmp><!--<xmp></xmp>--></xmp>
++#errors
++(1,44): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <xmp>
++|       "<!--<xmp>"
++|     "-->"
++
++#data
++<!doctype html><noembed><!--<noembed></noembed>--></noembed>
++#errors
++(1,60): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <noembed>
++|       "<!--<noembed>"
++|     "-->"
++
++#data
++<script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,8): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<script>a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,9): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "a"
++|   <body>
++
++#data
++<script><
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,9): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<"
++|   <body>
++
++#data
++<script></
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,10): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</"
++|   <body>
++
++#data
++<script></S
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</S"
++|   <body>
++
++#data
++<script></SC
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,12): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</SC"
++|   <body>
++
++#data
++<script></SCR
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,13): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</SCR"
++|   <body>
++
++#data
++<script></SCRI
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,14): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</SCRI"
++|   <body>
++
++#data
++<script></SCRIP
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,15): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</SCRIP"
++|   <body>
++
++#data
++<script></SCRIPT
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,16): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</SCRIPT"
++|   <body>
++
++#data
++<script></SCRIPT 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,17): expected-attribute-name-but-got-eof
++(1,17): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:18) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<script></s
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</s"
++|   <body>
++
++#data
++<script></sc
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,12): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</sc"
++|   <body>
++
++#data
++<script></scr
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,13): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</scr"
++|   <body>
++
++#data
++<script></scri
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,14): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</scri"
++|   <body>
++
++#data
++<script></scrip
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,15): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</scrip"
++|   <body>
++
++#data
++<script></script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,16): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</script"
++|   <body>
++
++#data
++<script></script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,17): expected-attribute-name-but-got-eof
++(1,17): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:18) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<script><!
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,10): expected-script-data-but-got-eof
++(1,10): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!"
++|   <body>
++
++#data
++<script><!a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!a"
++|   <body>
++
++#data
++<script><!-
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!-"
++|   <body>
++
++#data
++<script><!-a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,12): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!-a"
++|   <body>
++
++#data
++<script><!--
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,12): expected-named-closing-tag-but-got-eof
++(1,12): unexpected-eof-in-text-mode
++#new-errors
++(1:13) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--"
++|   <body>
++
++#data
++<script><!--a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,13): expected-named-closing-tag-but-got-eof
++(1,13): unexpected-eof-in-text-mode
++#new-errors
++(1:14) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--a"
++|   <body>
++
++#data
++<script><!--<
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,13): expected-named-closing-tag-but-got-eof
++(1,13): unexpected-eof-in-text-mode
++#new-errors
++(1:14) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<"
++|   <body>
++
++#data
++<script><!--<a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,14): expected-named-closing-tag-but-got-eof
++(1,14): unexpected-eof-in-text-mode
++#new-errors
++(1:15) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<a"
++|   <body>
++
++#data
++<script><!--</
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,14): expected-named-closing-tag-but-got-eof
++(1,14): unexpected-eof-in-text-mode
++#new-errors
++(1:15) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--</"
++|   <body>
++
++#data
++<script><!--</script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,20): expected-named-closing-tag-but-got-eof
++(1,20): unexpected-eof-in-text-mode
++#new-errors
++(1:21) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--</script"
++|   <body>
++
++#data
++<script><!--</script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,21): expected-attribute-name-but-got-eof
++(1,21): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:22) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--"
++|   <body>
++
++#data
++<script><!--<s
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,14): expected-named-closing-tag-but-got-eof
++(1,14): unexpected-eof-in-text-mode
++#new-errors
++(1:15) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<s"
++|   <body>
++
++#data
++<script><!--<script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,19): expected-named-closing-tag-but-got-eof
++(1,19): unexpected-eof-in-text-mode
++#new-errors
++(1:20) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script"
++|   <body>
++
++#data
++<script><!--<script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,20): eof-in-script-in-script
++(1,20): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:21) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script "
++|   <body>
++
++#data
++<script><!--<script <
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,21): eof-in-script-in-script
++(1,21): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:22) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script <"
++|   <body>
++
++#data
++<script><!--<script <a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,22): eof-in-script-in-script
++(1,22): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:23) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script <a"
++|   <body>
++
++#data
++<script><!--<script </
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,22): eof-in-script-in-script
++(1,22): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:23) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </"
++|   <body>
++
++#data
++<script><!--<script </s
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,23): eof-in-script-in-script
++(1,23): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:24) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </s"
++|   <body>
++
++#data
++<script><!--<script </script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,28): eof-in-script-in-script
++(1,28): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:29) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script"
++|   <body>
++
++#data
++<script><!--<script </scripta
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,29): eof-in-script-in-script
++(1,29): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </scripta"
++|   <body>
++
++#data
++<script><!--<script </script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<script><!--<script </script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script>"
++|   <body>
++
++#data
++<script><!--<script </script/
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,29): expected-named-closing-tag-but-got-eof
++(1,29): unexpected-eof-in-text-mode
++#new-errors
++(1:30) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script/"
++|   <body>
++
++#data
++<script><!--<script </script <
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,30): expected-named-closing-tag-but-got-eof
++(1,30): unexpected-eof-in-text-mode
++#new-errors
++(1:31) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script <"
++|   <body>
++
++#data
++<script><!--<script </script <a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,31): expected-named-closing-tag-but-got-eof
++(1,31): unexpected-eof-in-text-mode
++#new-errors
++(1:32) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script <a"
++|   <body>
++
++#data
++<script><!--<script </script </
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,31): expected-named-closing-tag-but-got-eof
++(1,31): unexpected-eof-in-text-mode
++#new-errors
++(1:32) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script </"
++|   <body>
++
++#data
++<script><!--<script </script </script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,37): expected-named-closing-tag-but-got-eof
++(1,37): unexpected-eof-in-text-mode
++#new-errors
++(1:38) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script </script"
++|   <body>
++
++#data
++<script><!--<script </script </script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,38): expected-attribute-name-but-got-eof
++(1,38): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:39) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<script><!--<script </script </script/
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,38): unexpected-EOF-after-solidus-in-tag
++(1,38): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:39) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<script><!--<script </script </script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script </script "
++|   <body>
++
++#data
++<script><!--<script -
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,21): eof-in-script-in-script
++(1,21): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:22) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -"
++|   <body>
++
++#data
++<script><!--<script -a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,22): eof-in-script-in-script
++(1,22): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:23) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -a"
++|   <body>
++
++#data
++<script><!--<script --
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,22): eof-in-script-in-script
++(1,22): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:23) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --"
++|   <body>
++
++#data
++<script><!--<script --a
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,23): eof-in-script-in-script
++(1,23): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:24) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --a"
++|   <body>
++
++#data
++<script><!--<script -->
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,23): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<script><!--<script --><
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,24): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --><"
++|   <body>
++
++#data
++<script><!--<script --></
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,25): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --></"
++|   <body>
++
++#data
++<script><!--<script --></script
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,31): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script --></script"
++|   <body>
++
++#data
++<script><!--<script --></script 
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,32): expected-attribute-name-but-got-eof
++(1,32): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:33) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<script><!--<script --></script/
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,32): unexpected-EOF-after-solidus-in-tag
++(1,32): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:33) eof-in-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<script><!--<script --></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script -->"
++|   <body>
++
++#data
++<script><!--<script><\/script>--></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script><\/script>-->"
++|   <body>
++
++#data
++<script><!--<script></scr'+'ipt>--></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></scr'+'ipt>-->"
++|   <body>
++
++#data
++<script><!--<script></script><script></script></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>"
++|   <body>
++
++#data
++<script><!--<script></script><script></script>--><!--</script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>--><!--"
++|   <body>
++
++#data
++<script><!--<script></script><script></script>-- ></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>-- >"
++|   <body>
++
++#data
++<script><!--<script></script><script></script>- -></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>- ->"
++|   <body>
++
++#data
++<script><!--<script></script><script></script>- - ></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>- - >"
++|   <body>
++
++#data
++<script><!--<script></script><script></script>-></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></script><script></script>->"
++|   <body>
++
++#data
++<script><!--<script>--!></script>X
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,34): expected-named-closing-tag-but-got-eof
++(1,34): unexpected-eof-in-text-mode
++#new-errors
++(1:35) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script>--!></script>X"
++|   <body>
++
++#data
++<script><!--<scr'+'ipt></script>--></script>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,44): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<scr'+'ipt>"
++|   <body>
++|     "-->"
++
++#data
++<script><!--<script></scr'+'ipt></script>X
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,42): expected-named-closing-tag-but-got-eof
++(1,42): unexpected-eof-in-text-mode
++#new-errors
++(1:43) eof-in-script-html-comment-like-text
++#document
++| <html>
++|   <head>
++|     <script>
++|       "<!--<script></scr'+'ipt></script>X"
++|   <body>
++
++#data
++<style><!--<style></style>--></style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,37): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--<style>"
++|   <body>
++|     "-->"
++
++#data
++<style><!--</style>X
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--"
++|   <body>
++|     "X"
++
++#data
++<style><!--...</style>...--></style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,36): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--..."
++|   <body>
++|     "...-->"
++
++#data
++<style><!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style></style>X
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--<br><html xmlns:v="urn:schemas-microsoft-com:vml"><!--[if !mso]><style>"
++|   <body>
++|     "X"
++
++#data
++<style><!--...<style><!--...--!></style>--></style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,51): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--...<style><!--...--!>"
++|   <body>
++|     "-->"
++
++#data
++<style><!--...</style><!-- --><style>@import ...</style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "<!--..."
++|     <!--   -->
++|     <style>
++|       "@import ..."
++|   <body>
++
++#data
++<style>...<style><!--...</style><!-- --></style>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,48): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "...<style><!--..."
++|     <!--   -->
++|   <body>
++
++#data
++<style>...<!--[if IE]><style>...</style>X
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       "...<!--[if IE]><style>..."
++|   <body>
++|     "X"
++
++#data
++<title><!--<title></title>--></title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,37): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "<!--<title>"
++|   <body>
++|     "-->"
++
++#data
++<title>&lt;/title></title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "</title>"
++|   <body>
++
++#data
++<title>foo/title><link></head><body>X
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,37): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <title>
++|       "foo/title><link></head><body>X"
++|   <body>
++
++#data
++<noscript><!--<noscript></noscript>--></noscript>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,49): unexpected-end-tag
++#script-on
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       "<!--<noscript>"
++|   <body>
++|     "-->"
++
++#data
++<noscript><!--<noscript></noscript>--></noscript>
++#errors
++ * (1,11) missing DOCTYPE
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- <noscript></noscript> -->
++|   <body>
++
++#data
++<noscript><!--</noscript>X<noscript>--></noscript>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#script-on
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       "<!--"
++|   <body>
++|     "X"
++|     <noscript>
++|       "-->"
++
++#data
++<noscript><!--</noscript>X<noscript>--></noscript>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- </noscript>X<noscript> -->
++|   <body>
++
++#data
++<noscript><iframe></noscript>X
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#script-on
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       "<iframe>"
++|   <body>
++|     "X"
++
++#data
++<noscript><iframe></noscript>X
++#errors
++ * (1,11) missing DOCTYPE
++ * (1,19) unexpected token in head noscript
++ * (1,31) unexpected EOF
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <iframe>
++|       "</noscript>X"
++
++#data
++<noframes><!--<noframes></noframes>--></noframes>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,49): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <noframes>
++|       "<!--<noframes>"
++|   <body>
++|     "-->"
++
++#data
++<noframes><body><script><!--...</script></body></noframes></html>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <noframes>
++|       "<body><script><!--...</script></body>"
++|   <body>
++
++#data
++<textarea><!--<textarea></textarea>--></textarea>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,49): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "<!--<textarea>"
++|     "-->"
++
++#data
++<textarea>&lt;/textarea></textarea>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "</textarea>"
++
++#data
++<iframe><!--<iframe></iframe>--></iframe>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,41): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       "<!--<iframe>"
++|     "-->"
++
++#data
++<iframe>...<!--X->...<!--/X->...</iframe>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       "...<!--X->...<!--/X->..."
++
++#data
++<xmp><!--<xmp></xmp>--></xmp>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,29): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <xmp>
++|       "<!--<xmp>"
++|     "-->"
++
++#data
++<noembed><!--<noembed></noembed>--></noembed>
++#errors
++(1,9): expected-doctype-but-got-start-tag
++(1,45): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <noembed>
++|       "<!--<noembed>"
++|     "-->"
++
++#data
++<!doctype html><table>
++
++#errors
++(2,0): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       "
++"
++
++#data
++<!doctype html><table><td><span><font></span><span>
++#errors
++(1,26): unexpected-cell-in-table-body
++(1,45): unexpected-end-tag
++(1,51): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <span>
++|               <font>
++|             <font>
++|               <span>
++
++#data
++<!doctype html><form><table></form><form></table></form>
++#errors
++(1,35): unexpected-end-tag-implies-table-voodoo
++(1,35): unexpected-end-tag
++(1,41): unexpected-form-in-table
++(1,56): unexpected-end-tag
++(1,56): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <form>
++|       <table>
++|         <form>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e49bcf03142dc30cacae4a770b1aa9d3febb0713
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,179 @@@
++#data
++<!doctype html><table><tbody><select><tr>
++#errors
++(1,37): unexpected-start-tag-implies-table-voodoo
++(1,41): unexpected-table-element-start-tag-in-select-in-table
++(1,41): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><table><tr><select><td>
++#errors
++(1,34): unexpected-start-tag-implies-table-voodoo
++(1,38): unexpected-table-element-start-tag-in-select-in-table
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<!doctype html><table><tr><td><select><td>
++#errors
++(1,42): unexpected-table-element-start-tag-in-select-in-table
++(1,42): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <select>
++|           <td>
++
++#data
++<!doctype html><table><tr><th><select><td>
++#errors
++(1,42): unexpected-table-element-start-tag-in-select-in-table
++(1,42): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <th>
++|             <select>
++|           <td>
++
++#data
++<!doctype html><table><caption><select><tr>
++#errors
++(1,43): unexpected-table-element-start-tag-in-select-in-table
++(1,43): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <select>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><select><tr>
++#errors
++(1,27): unexpected-start-tag-in-select
++(1,27): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><td>
++#errors
++(1,27): unexpected-start-tag-in-select
++(1,27): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><th>
++#errors
++(1,27): unexpected-start-tag-in-select
++(1,27): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><tbody>
++#errors
++(1,30): unexpected-start-tag-in-select
++(1,30): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><thead>
++#errors
++(1,30): unexpected-start-tag-in-select
++(1,30): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><tfoot>
++#errors
++(1,30): unexpected-start-tag-in-select
++(1,30): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><select><caption>
++#errors
++(1,32): unexpected-start-tag-in-select
++(1,32): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><table><tr></table>a
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|     "a"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..05363b392d9915deab0fb195c6031ba601069e46
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,534 @@@
++#data
++<plaintext></plaintext>
++#errors
++11: Start tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
++23: End of file seen and there were open elements.
++11: Unclosed element “plaintext”.
++#document
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><plaintext></plaintext>
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><html><plaintext></plaintext>
++#errors
++44: End of file seen and there were open elements.
++32: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><head><plaintext></plaintext>
++#errors
++44: End of file seen and there were open elements.
++32: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><html><noscript><plaintext></plaintext>
++#errors
++42: Bad start tag in “plaintext” in “head”.
++54: End of file seen and there were open elements.
++42: Unclosed element “plaintext”.
++#script-off
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <noscript>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html></head><plaintext></plaintext>
++#errors
++45: End of file seen and there were open elements.
++33: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><body><plaintext></plaintext>
++#errors
++44: End of file seen and there were open elements.
++32: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><table><plaintext></plaintext>
++#errors
++(1,33): foster-parenting-start-tag
++(1,45): foster-parenting-character
++(1,45): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++|     <table>
++
++#data
++<!doctype html><table><tbody><plaintext></plaintext>
++#errors
++(1,40): foster-parenting-start-tag
++(1,41): foster-parenting-character
++(1,52): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++|     <table>
++|       <tbody>
++
++#data
++<!doctype html><table><tbody><tr><plaintext></plaintext>
++#errors
++(1,44): foster-parenting-start-tag
++(1,56): foster-parenting-character
++(1,56): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><table><td><plaintext></plaintext>
++#errors
++(1,26): unexpected-cell-in-table-body
++(1,49): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <plaintext>
++|               "</plaintext>"
++
++#data
++<!doctype html><table><caption><plaintext></plaintext>
++#errors
++(1,54): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <plaintext>
++|           "</plaintext>"
++
++#data
++<!doctype html><table><colgroup><plaintext></plaintext>
++#errors
++43: Start tag “plaintext” seen in “table”.
++55: Misplaced non-space characters inside a table.
++55: End of file seen and there were open elements.
++43: Unclosed element “plaintext”.
++22: Unclosed element “table”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++|     <table>
++|       <colgroup>
++
++#data
++<!doctype html><select><plaintext></plaintext>X
++#errors
++34: Stray start tag “plaintext”.
++46: Stray end tag “plaintext”.
++47: End of file seen and there were open elements.
++23: Unclosed element “select”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "X"
++
++#data
++<!doctype html><table><select><plaintext>a<caption>b
++#errors
++30: Start tag “select” seen in “table”.
++41: Stray start tag “plaintext”.
++51: “caption” start tag with “select” open.
++52: End of file seen and there were open elements.
++51: Unclosed element “caption”.
++22: Unclosed element “table”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "a"
++|     <table>
++|       <caption>
++|         "b"
++
++#data
++<!doctype html><template><plaintext>a</template>b
++#errors
++49: End of file seen and there were open elements.
++36: Unclosed element “plaintext”.
++25: Unclosed element “template”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <template>
++|       content
++|         <plaintext>
++|           "a</template>b"
++|   <body>
++
++#data
++<!doctype html><body></body><plaintext></plaintext>
++#errors
++39: Stray start tag “plaintext”.
++51: End of file seen and there were open elements.
++39: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><frameset><plaintext></plaintext>
++#errors
++36: Stray start tag “plaintext”.
++48: Stray end tag “plaintext”.
++48: End of file seen and there were open elements.
++25: Unclosed element “frameset”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><frameset></frameset><plaintext></plaintext>
++#errors
++47: Stray start tag “plaintext”.
++59: Stray end tag “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><body></body></html><plaintext></plaintext>
++#errors
++46: Stray start tag “plaintext”.
++58: End of file seen and there were open elements.
++46: Unclosed element “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!doctype html><frameset></frameset></html><plaintext></plaintext>
++#errors
++54: Stray start tag “plaintext”.
++66: Stray end tag “plaintext”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><svg><plaintext>a</plaintext>b
++#errors
++45: End of file seen and there were open elements.
++20: Unclosed element “svg”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg plaintext>
++|         "a"
++|       "b"
++
++#data
++<!doctype html><svg><title><plaintext>a</plaintext>b
++#errors
++52: End of file seen and there were open elements.
++38: Unclosed element “plaintext”.
++27: Unclosed element “title”.
++20: Unclosed element “svg”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg title>
++|         <plaintext>
++|           "a</plaintext>b"
++
++#data
++<!doctype html><table><tr><style></script></style>abc
++#errors
++(1,51): foster-parenting-character
++(1,52): foster-parenting-character
++(1,53): foster-parenting-character
++(1,53): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "abc"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <style>
++|             "</script>"
++
++#data
++<!doctype html><table><tr><script></style></script>abc
++#errors
++(1,52): foster-parenting-character
++(1,53): foster-parenting-character
++(1,54): foster-parenting-character
++(1,54): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "abc"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <script>
++|             "</style>"
++
++#data
++<!doctype html><table><caption><style></script></style>abc
++#errors
++(1,58): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <style>
++|           "</script>"
++|         "abc"
++
++#data
++<!doctype html><table><td><style></script></style>abc
++#errors
++(1,26): unexpected-cell-in-table-body
++(1,53): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <style>
++|               "</script>"
++|             "abc"
++
++#data
++<!doctype html><select><script></style></script>abc
++#errors
++(1,51): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <script>
++|         "</style>"
++|       "abc"
++
++#data
++<!doctype html><table><select><script></style></script>abc
++#errors
++(1,30): unexpected-start-tag-implies-table-voodoo
++(1,58): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <script>
++|         "</style>"
++|       "abc"
++|     <table>
++
++#data
++<!doctype html><table><tr><select><script></style></script>abc
++#errors
++(1,34): unexpected-start-tag-implies-table-voodoo
++(1,62): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <script>
++|         "</style>"
++|       "abc"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><frameset></frameset><noframes>abc
++#errors
++(1,49): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   <noframes>
++|     "abc"
++
++#data
++<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   <noframes>
++|     "abc"
++|   <!-- abc -->
++
++#data
++<!doctype html><frameset></frameset></html><noframes>abc
++#errors
++(1,56): expected-named-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   <noframes>
++|     "abc"
++
++#data
++<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc-->
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   <noframes>
++|     "abc"
++| <!-- abc -->
++
++#data
++<!doctype html><table><tr></tbody><tfoot>
++#errors
++(1,41): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|       <tfoot>
++
++#data
++<!doctype html><table><td><svg></svg>abc<td>
++#errors
++(1,26): unexpected-cell-in-table-body
++(1,44): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|             "abc"
++|           <td>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a1897774df3bbc048f09ff6962e052d62b12966f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1454 @@@
++#data
++<!doctype html><math><mn DefinitionUrl="foo">
++#errors
++(1,45): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mn>
++|         definitionURL="foo"
++
++#data
++<!doctype html><html></p><!--foo-->
++#errors
++(1,25): end-tag-after-implied-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   <!-- foo -->
++|   <head>
++|   <body>
++
++#data
++<!doctype html><head></head></p><!--foo-->
++#errors
++(1,32): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <!-- foo -->
++|   <body>
++
++#data
++<!doctype html><body><p><pre>
++#errors
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <pre>
++
++#data
++<!doctype html><body><p><listing>
++#errors
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <listing>
++
++#data
++<!doctype html><p><plaintext>
++#errors
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <plaintext>
++
++#data
++<!doctype html><p><h1>
++#errors
++(1,22): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <h1>
++
++#data
++<!doctype html><isindex type="hidden">
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <isindex>
++|       type="hidden"
++
++#data
++<!doctype html><ruby><p><rp>
++#errors
++(1,28): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <p>
++|       <rp>
++
++#data
++<!doctype html><ruby><div><span><rp>
++#errors
++(1,36): XXX-undefined-error
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <span>
++|           <rp>
++
++#data
++<!doctype html><ruby><div><p><rp>
++#errors
++(1,33): XXX-undefined-error
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <p>
++|         <rp>
++
++#data
++<!doctype html><ruby><p><rt>
++#errors
++(1,28): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <p>
++|       <rt>
++
++#data
++<!doctype html><ruby><div><span><rt>
++#errors
++(1,36): XXX-undefined-error
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <span>
++|           <rt>
++
++#data
++<!doctype html><ruby><div><p><rt>
++#errors
++(1,33): XXX-undefined-error
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <p>
++|         <rt>
++
++#data
++<html><ruby>a<rb>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rb>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rp>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rp>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rt>b<rt></ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rt>
++|         "b"
++|       <rt>
++
++#data
++<html><ruby>a<rtc>b<rt>c<rb>d</ruby></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       "a"
++|       <rtc>
++|         "b"
++|         <rt>
++|           "c"
++|       <rb>
++|         "d"
++
++#data
++<!doctype html><math/><foo>
++#errors
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|     <foo>
++
++#data
++<!doctype html><svg/><foo>
++#errors
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|     <foo>
++
++#data
++<!doctype html><div></body><!--foo-->
++#errors
++(1,27): expected-one-end-tag-but-got-another
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|   <!-- foo -->
++
++#data
++<!doctype html><h1><div><h3><span></h1>foo
++#errors
++(1,39): end-tag-too-early
++(1,42): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <h1>
++|       <div>
++|         <h3>
++|           <span>
++|         "foo"
++
++#data
++<!doctype html><p></h3>foo
++#errors
++(1,23): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "foo"
++
++#data
++<!doctype html><h3><li>abc</h2>foo
++#errors
++(1,31): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <h3>
++|       <li>
++|         "abc"
++|     "foo"
++
++#data
++<!doctype html><table>abc<!--foo-->
++#errors
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++(1,25): foster-parenting-character
++(1,35): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "abc"
++|     <table>
++|       <!-- foo -->
++
++#data
++<!doctype html><table>  <!--foo-->
++#errors
++(1,34): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       "  "
++|       <!-- foo -->
++
++#data
++<!doctype html><table> b <!--foo-->
++#errors
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++(1,25): foster-parenting-character
++(1,35): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     " b "
++|     <table>
++|       <!-- foo -->
++
++#data
++<!doctype html><select><option><option>
++#errors
++(1,39): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|       <option>
++
++#data
++<!doctype html><select><option></optgroup>
++#errors
++(1,42): unexpected-end-tag-in-select
++(1,42): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++
++#data
++<!doctype html><select><option></optgroup>
++#errors
++(1,42): unexpected-end-tag-in-select
++(1,42): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++
++#data
++<!doctype html><dd><optgroup><dd>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dd>
++|       <optgroup>
++|     <dd>
++
++#data
++<!doctype html><p><math><mi><p><h1>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math mi>
++|           <p>
++|           <h1>
++
++#data
++<!doctype html><p><math><mo><p><h1>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math mo>
++|           <p>
++|           <h1>
++
++#data
++<!doctype html><p><math><mn><p><h1>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math mn>
++|           <p>
++|           <h1>
++
++#data
++<!doctype html><p><math><ms><p><h1>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math ms>
++|           <p>
++|           <h1>
++
++#data
++<!doctype html><p><math><mtext><p><h1>
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math mtext>
++|           <p>
++|           <h1>
++
++#data
++<!doctype html><frameset></noframes>
++#errors
++(1,36): unexpected-end-tag-in-frameset
++(1,36): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><html c=d><body></html><html a=b>
++#errors
++(1,48): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   a="b"
++|   c="d"
++|   <head>
++|   <body>
++
++#data
++<!doctype html><html c=d><frameset></frameset></html><html a=b>
++#errors
++(1,63): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   a="b"
++|   c="d"
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><html><frameset></frameset></html><!--foo-->
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++| <!-- foo -->
++
++#data
++<!doctype html><html><frameset></frameset></html>  
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   "  "
++
++#data
++<!doctype html><html><frameset></frameset></html>abc
++#errors
++(1,50): expected-eof-but-got-char
++(1,51): expected-eof-but-got-char
++(1,52): expected-eof-but-got-char
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><html><frameset></frameset></html><p>
++#errors
++(1,52): expected-eof-but-got-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><html><frameset></frameset></html></p>
++#errors
++(1,53): expected-eof-but-got-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<html><frameset></frameset></html><!doctype html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,49): unexpected-doctype
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><body><frameset>
++#errors
++(1,31): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!doctype html><p><frameset><frame>
++#errors
++(1,28): unexpected-start-tag
++(1,35): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<!doctype html><p>a<frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "a"
++
++#data
++<!doctype html><p> <frameset><frame>
++#errors
++(1,29): unexpected-start-tag
++(1,36): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<!doctype html><pre><frameset>
++#errors
++(1,30): unexpected-start-tag
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++
++#data
++<!doctype html><listing><frameset>
++#errors
++(1,34): unexpected-start-tag
++(1,34): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <listing>
++
++#data
++<!doctype html><li><frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <li>
++
++#data
++<!doctype html><dd><frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dd>
++
++#data
++<!doctype html><dt><frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dt>
++
++#data
++<!doctype html><button><frameset>
++#errors
++(1,33): unexpected-start-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <button>
++
++#data
++<!doctype html><applet><frameset>
++#errors
++(1,33): unexpected-start-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <applet>
++
++#data
++<!doctype html><marquee><frameset>
++#errors
++(1,34): unexpected-start-tag
++(1,34): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <marquee>
++
++#data
++<!doctype html><object><frameset>
++#errors
++(1,33): unexpected-start-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <object>
++
++#data
++<!doctype html><table><frameset>
++#errors
++(1,32): unexpected-start-tag-implies-table-voodoo
++(1,32): unexpected-start-tag
++(1,32): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++
++#data
++<!doctype html><area><frameset>
++#errors
++(1,31): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <area>
++
++#data
++<!doctype html><basefont><frameset>
++#errors
++(1,35): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <basefont>
++|   <frameset>
++
++#data
++<!doctype html><bgsound><frameset>
++#errors
++(1,34): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <bgsound>
++|   <frameset>
++
++#data
++<!doctype html><br><frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <br>
++
++#data
++<!doctype html><embed><frameset>
++#errors
++(1,32): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <embed>
++
++#data
++<!doctype html><img><frameset>
++#errors
++(1,30): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <img>
++
++#data
++<!doctype html><input><frameset>
++#errors
++(1,32): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <input>
++
++#data
++<!doctype html><keygen><frameset>
++#errors
++(1,33): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <keygen>
++
++#data
++<!doctype html><wbr><frameset>
++#errors
++(1,30): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <wbr>
++
++#data
++<!doctype html><hr><frameset>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <hr>
++
++#data
++<!doctype html><textarea></textarea><frameset>
++#errors
++(1,46): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++
++#data
++<!doctype html><xmp></xmp><frameset>
++#errors
++(1,36): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <xmp>
++
++#data
++<!doctype html><iframe></iframe><frameset>
++#errors
++(1,42): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++
++#data
++<!doctype html><select></select><frameset>
++#errors
++(1,42): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!doctype html><svg></svg><frameset><frame>
++#errors
++(1,36): unexpected-start-tag
++(1,43): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<!doctype html><math></math><frameset><frame>
++#errors
++(1,38): unexpected-start-tag
++(1,45): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<!doctype html><svg><foreignObject><div> <frameset><frame>
++#errors
++(1,51): unexpected-start-tag
++(1,58): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<!doctype html><svg>a</svg><frameset><frame>
++#errors
++(1,37): unexpected-start-tag
++(1,44): unexpected-start-tag-ignored
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "a"
++
++#data
++<!doctype html><svg> </svg><frameset><frame>
++#errors
++(1,37): unexpected-start-tag
++(1,44): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     <frame>
++
++#data
++<html>aaa<frameset></frameset>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,19): unexpected-start-tag
++(1,30): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     "aaa"
++
++#data
++<html> a <frameset></frameset>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,19): unexpected-start-tag
++(1,30): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     "a "
++
++#data
++<!doctype html><div><frameset>
++#errors
++(1,30): unexpected-start-tag
++(1,30): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><div><body><frameset>
++#errors
++(1,26): unexpected-start-tag
++(1,36): unexpected-start-tag
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++
++#data
++<!doctype html><p><math></p>a
++#errors
++(1,28): unexpected-end-tag
++(1,28): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|     "a"
++
++#data
++<!doctype html><p><math><mn><span></p>a
++#errors
++(1,38): unexpected-end-tag
++(1,39): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <math math>
++|         <math mn>
++|           <span>
++|             <p>
++|             "a"
++
++#data
++<!doctype html><math></html>
++#errors
++(1,28): unexpected-end-tag
++(1,28): expected-one-end-tag-but-got-another
++(1,28): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++
++#data
++<!doctype html><meta charset="ascii">
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <meta>
++|       charset="ascii"
++|   <body>
++
++#data
++<!doctype html><meta http-equiv="content-type" content="text/html;charset=ascii">
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <meta>
++|       content="text/html;charset=ascii"
++|       http-equiv="content-type"
++|   <body>
++
++#data
++<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset="utf8">
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <!-- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -->
++|     <meta>
++|       charset="utf8"
++|   <body>
++
++#data
++<!doctype html><html a=b><head></head><html c=d>
++#errors
++(1,48): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   a="b"
++|   c="d"
++|   <head>
++|   <body>
++
++#data
++<!doctype html><image/>
++#errors
++(1,23): image-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <img>
++
++#data
++<!doctype html>a<i>b<table>c<b>d</i>e</b>f
++#errors
++(1,28): foster-parenting-character
++(1,31): foster-parenting-start-tag
++(1,32): foster-parenting-character
++(1,36): foster-parenting-end-tag
++(1,36): adoption-agency-1.3
++(1,37): foster-parenting-character
++(1,41): foster-parenting-end-tag
++(1,42): foster-parenting-character
++(1,42): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "a"
++|     <i>
++|       "bc"
++|       <b>
++|         "de"
++|       "f"
++|       <table>
++
++#data
++<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
++#errors
++(1,25): foster-parenting-start-tag
++(1,26): foster-parenting-character
++(1,29): foster-parenting-start-tag
++(1,30): foster-parenting-character
++(1,35): foster-parenting-start-tag
++(1,36): foster-parenting-character
++(1,39): foster-parenting-start-tag
++(1,40): foster-parenting-character
++(1,44): foster-parenting-end-tag
++(1,44): adoption-agency-1.3
++(1,44): adoption-agency-1.3
++(1,45): foster-parenting-character
++(1,49): foster-parenting-end-tag
++(1,49): adoption-agency-1.3
++(1,49): adoption-agency-1.3
++(1,50): foster-parenting-character
++(1,50): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "a"
++|       <b>
++|         "b"
++|     <b>
++|     <div>
++|       <b>
++|         <i>
++|           "c"
++|           <a>
++|             "d"
++|         <a>
++|           "e"
++|       <a>
++|         "f"
++|     <table>
++
++#data
++<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f
++#errors
++(1,37): adoption-agency-1.3
++(1,37): adoption-agency-1.3
++(1,42): adoption-agency-1.3
++(1,42): adoption-agency-1.3
++(1,43): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "a"
++|       <b>
++|         "b"
++|     <b>
++|     <div>
++|       <b>
++|         <i>
++|           "c"
++|           <a>
++|             "d"
++|         <a>
++|           "e"
++|       <a>
++|         "f"
++
++#data
++<!doctype html><table><i>a<b>b<div>c</i>
++#errors
++(1,25): foster-parenting-start-tag
++(1,26): foster-parenting-character
++(1,29): foster-parenting-start-tag
++(1,30): foster-parenting-character
++(1,35): foster-parenting-start-tag
++(1,36): foster-parenting-character
++(1,40): foster-parenting-end-tag
++(1,40): adoption-agency-1.3
++(1,40): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "a"
++|       <b>
++|         "b"
++|     <b>
++|       <div>
++|         <i>
++|           "c"
++|     <table>
++
++#data
++<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f
++#errors
++(1,25): foster-parenting-start-tag
++(1,26): foster-parenting-character
++(1,29): foster-parenting-start-tag
++(1,30): foster-parenting-character
++(1,35): foster-parenting-start-tag
++(1,36): foster-parenting-character
++(1,39): foster-parenting-start-tag
++(1,40): foster-parenting-character
++(1,44): foster-parenting-end-tag
++(1,44): adoption-agency-1.3
++(1,44): adoption-agency-1.3
++(1,45): foster-parenting-character
++(1,49): foster-parenting-end-tag
++(1,44): adoption-agency-1.3
++(1,44): adoption-agency-1.3
++(1,50): foster-parenting-character
++(1,50): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "a"
++|       <b>
++|         "b"
++|     <b>
++|     <div>
++|       <b>
++|         <i>
++|           "c"
++|           <a>
++|             "d"
++|         <a>
++|           "e"
++|       <a>
++|         "f"
++|     <table>
++
++#data
++<!doctype html><table><i>a<div>b<tr>c<b>d</i>e
++#errors
++(1,25): foster-parenting-start-tag
++(1,26): foster-parenting-character
++(1,31): foster-parenting-start-tag
++(1,32): foster-parenting-character
++(1,37): foster-parenting-character
++(1,40): foster-parenting-start-tag
++(1,41): foster-parenting-character
++(1,45): foster-parenting-end-tag
++(1,45): adoption-agency-1.3
++(1,46): foster-parenting-character
++(1,46): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <i>
++|       "a"
++|       <div>
++|         "b"
++|     <i>
++|       "c"
++|       <b>
++|         "d"
++|     <b>
++|       "e"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><table><td><table><i>a<div>b<b>c</i>d
++#errors
++(1,26): unexpected-cell-in-table-body
++(1,36): foster-parenting-start-tag
++(1,37): foster-parenting-character
++(1,42): foster-parenting-start-tag
++(1,43): foster-parenting-character
++(1,46): foster-parenting-start-tag
++(1,47): foster-parenting-character
++(1,51): foster-parenting-end-tag
++(1,51): adoption-agency-1.3
++(1,51): adoption-agency-1.3
++(1,52): foster-parenting-character
++(1,52): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <i>
++|               "a"
++|             <div>
++|               <i>
++|                 "b"
++|                 <b>
++|                   "c"
++|               <b>
++|                 "d"
++|             <table>
++
++#data
++<!doctype html><body><bgsound>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <bgsound>
++
++#data
++<!doctype html><body><basefont>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <basefont>
++
++#data
++<!doctype html><a><b></a><basefont>
++#errors
++(1,25): adoption-agency-1.3
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|     <basefont>
++
++#data
++<!doctype html><a><b></a><bgsound>
++#errors
++(1,25): adoption-agency-1.3
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|     <bgsound>
++
++#data
++<!doctype html><figcaption><article></figcaption>a
++#errors
++(1,49): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <figcaption>
++|       <article>
++|     "a"
++
++#data
++<!doctype html><summary><article></summary>a
++#errors
++(1,43): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <summary>
++|       <article>
++|     "a"
++
++#data
++<!doctype html><p><a><plaintext>b
++#errors
++(1,32): unexpected-end-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <a>
++|     <plaintext>
++|       <a>
++|         "b"
++
++#data
++<!DOCTYPE html><div>a<a></div>b<p>c</p>d
++#errors
++(1,30): end-tag-too-early
++(1,40): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "a"
++|       <a>
++|     <a>
++|       "b"
++|       <p>
++|         "c"
++|       "d"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b44fec4d768895a4871fa587281f51092ca5ab04
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,821 @@@
++#data
++<!DOCTYPE html>Test
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "Test"
++
++#data
++<textarea>test</div>test
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,24): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "test</div>test"
++
++#data
++<table><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,11): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><td>test</tbody></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "test"
++
++#data
++<frame>test
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,7): unexpected-start-tag-ignored
++#document
++| <html>
++|   <head>
++|   <body>
++|     "test"
++
++#data
++<!DOCTYPE html><frameset>test
++#errors
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><frameset> te st
++#errors
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): unexpected-char-in-frameset
++(1,29): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|     "  "
++
++#data
++<!DOCTYPE html><frameset></frameset> te st
++#errors
++(1,29): unexpected-char-after-frameset
++(1,29): unexpected-char-after-frameset
++(1,29): unexpected-char-after-frameset
++(1,29): unexpected-char-after-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++|   "  "
++
++#data
++<!DOCTYPE html><frameset><!DOCTYPE html>
++#errors
++(1,40): unexpected-doctype
++(1,40): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><font><p><b>test</font>
++#errors
++(1,38): adoption-agency-1.3
++(1,38): adoption-agency-1.3
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|     <p>
++|       <font>
++|         <b>
++|           "test"
++
++#data
++<!DOCTYPE html><dt><div><dd>
++#errors
++(1,28): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <dt>
++|       <div>
++|     <dd>
++
++#data
++<script></x
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,11): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <script>
++|       "</x"
++|   <body>
++
++#data
++<table><plaintext><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,18): unexpected-start-tag-implies-table-voodoo
++(1,22): foster-parenting-character-in-table
++(1,22): foster-parenting-character-in-table
++(1,22): foster-parenting-character-in-table
++(1,22): foster-parenting-character-in-table
++(1,22): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "<td>"
++|     <table>
++
++#data
++<plaintext></plaintext>
++#errors
++(1,11): expected-doctype-but-got-start-tag
++(1,23): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "</plaintext>"
++
++#data
++<!DOCTYPE html><table><tr>TEST
++#errors
++(1,30): foster-parenting-character-in-table
++(1,30): foster-parenting-character-in-table
++(1,30): foster-parenting-character-in-table
++(1,30): foster-parenting-character-in-table
++(1,30): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "TEST"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4>
++#errors
++(1,37): unexpected-start-tag
++(1,53): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     t1="1"
++|     t2="2"
++|     t3="3"
++|     t4="4"
++
++#data
++</b test
++#errors
++(1,8): eof-in-attribute-name
++(1,8): expected-doctype-but-got-eof
++#new-errors
++(1:9) eof-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html></b test<b &=&amp>X
++#errors
++(1,24): invalid-character-in-attribute-name
++(1,32): named-entity-without-semicolon
++(1,33): attributes-in-end-tag
++(1,33): unexpected-end-tag-before-html
++#new-errors
++(1:24) unexpected-character-in-attribute-name
++(1:33) missing-semicolon-after-character-reference
++(1:33) end-tag-with-attributes
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++
++#data
++<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt
++#errors
++(1,9): need-space-after-doctype
++(1,54): expected-named-closing-tag-but-got-eof
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       type="text/x-foobar;baz"
++|       "X</SCRipt"
++|   <body>
++
++#data
++&
++#errors
++(1,1): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&"
++
++#data
++&#
++#errors
++(1,2): expected-numeric-entity
++(1,2): expected-doctype-but-got-chars
++#new-errors
++(1:3) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&#"
++
++#data
++&#X
++#errors
++(1,3): expected-numeric-entity
++(1,3): expected-doctype-but-got-chars
++#new-errors
++(1:4) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&#X"
++
++#data
++&#x
++#errors
++(1,3): expected-numeric-entity
++(1,3): expected-doctype-but-got-chars
++#new-errors
++(1:4) absence-of-digits-in-numeric-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&#x"
++
++#data
++&#45
++#errors
++(1,4): numeric-entity-without-semicolon
++(1,4): expected-doctype-but-got-chars
++#new-errors
++(1:5) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "-"
++
++#data
++&x-test
++#errors
++(1,2): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&x-test"
++
++#data
++<!doctypehtml><p><li>
++#errors
++(1,9): need-space-after-doctype
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <li>
++
++#data
++<!doctypehtml><p><dt>
++#errors
++(1,9): need-space-after-doctype
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <dt>
++
++#data
++<!doctypehtml><p><dd>
++#errors
++(1,9): need-space-after-doctype
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <dd>
++
++#data
++<!doctypehtml><p><form>
++#errors
++(1,9): need-space-after-doctype
++(1,23): expected-closing-tag-but-got-eof
++#new-errors
++(1:10) missing-whitespace-before-doctype-name
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <form>
++
++#data
++<!DOCTYPE html><p></P>X
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     "X"
++
++#data
++&AMP
++#errors
++(1,4): named-entity-without-semicolon
++(1,4): expected-doctype-but-got-chars
++#new-errors
++(1:5) missing-semicolon-after-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&"
++
++#data
++&AMp;
++#errors
++(1,3): expected-named-entity
++(1,3): expected-doctype-but-got-chars
++#new-errors
++(1:5) unknown-named-character-reference
++#document
++| <html>
++|   <head>
++|   <body>
++|     "&AMp;"
++
++#data
++<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY>
++#errors
++(1,110): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <thisisasillytestelementnametomakesurecrazytagnamesareparsedcorrectly>
++
++#data
++<!DOCTYPE html>X</body>X
++#errors
++(1,24): unexpected-char-after-body
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "XX"
++
++#data
++<!DOCTYPE html><!-- X
++#errors
++(1,21): eof-in-comment
++#new-errors
++(1:22) eof-in-comment
++#document
++| <!DOCTYPE html>
++| <!--  X -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><table><caption>test TEST</caption><td>test
++#errors
++(1,54): unexpected-cell-in-table-body
++(1,58): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         "test TEST"
++|       <tbody>
++|         <tr>
++|           <td>
++|             "test"
++
++#data
++<!DOCTYPE html><select><option><optgroup>
++#errors
++(1,41): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|       <optgroup>
++
++#data
++<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>
++#errors
++(1,68): unexpected-select-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <optgroup>
++|         <option>
++|       <option>
++|     <option>
++
++#data
++<!DOCTYPE html><select><optgroup><option><optgroup>
++#errors
++(1,51): eof-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <optgroup>
++|         <option>
++|       <optgroup>
++
++#data
++<!DOCTYPE html><datalist><option>foo</datalist>bar
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <datalist>
++|       <option>
++|         "foo"
++|     "bar"
++
++#data
++<!DOCTYPE html><font><input><input></font>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|       <input>
++|       <input>
++
++#data
++<!DOCTYPE html><!-- XXX - XXX -->
++#errors
++#document
++| <!DOCTYPE html>
++| <!--  XXX - XXX  -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><!-- XXX - XXX
++#errors
++(1,29): eof-in-comment
++#new-errors
++(1:30) eof-in-comment
++#document
++| <!DOCTYPE html>
++| <!--  XXX - XXX -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><!-- XXX - XXX - XXX -->
++#errors
++#document
++| <!DOCTYPE html>
++| <!--  XXX - XXX - XXX  -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++test
++test
++#errors
++(2,4): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "test
++test"
++
++#data
++<!DOCTYPE html><body><title>test</body></title>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <title>
++|       "test</body>"
++
++#data
++<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style>
++x { content:"</style" } </style>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <title>
++|       "X"
++|     <meta>
++|       name="z"
++|     <link>
++|       rel="foo"
++|     <style>
++|       "
++x { content:"</style" } "
++
++#data
++<!DOCTYPE html><select><optgroup></optgroup></select>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <optgroup>
++
++#data
++ 
++ 
++#errors
++(2,1): expected-doctype-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html>  <html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><script>
++</script>  <title>x</title>  </head>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <script>
++|       "
++"
++|     "  "
++|     <title>
++|       "x"
++|     "  "
++|   <body>
++
++#data
++<!DOCTYPE html><html><body><html id=x>
++#errors
++(1,38): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   id="x"
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html>X</body><html id="x">
++#errors
++(1,36): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   id="x"
++|   <head>
++|   <body>
++|     "X"
++
++#data
++<!DOCTYPE html><head><html id=x>
++#errors
++(1,32): non-html-root
++#document
++| <!DOCTYPE html>
++| <html>
++|   id="x"
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html>X</html>X
++#errors
++(1,24): expected-eof-but-got-char
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "XX"
++
++#data
++<!DOCTYPE html>X</html> 
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X "
++
++#data
++<!DOCTYPE html>X</html><p>X
++#errors
++(1,26): expected-eof-but-got-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++|     <p>
++|       "X"
++
++#data
++<!DOCTYPE html>X<p/x/y/z>
++#errors
++(1,19): unexpected-character-after-solidus-in-tag
++(1,21): unexpected-character-after-solidus-in-tag
++(1,23): unexpected-character-after-solidus-in-tag
++#new-errors
++(1:20) unexpected-solidus-in-tag
++(1:22) unexpected-solidus-in-tag
++(1:24) unexpected-solidus-in-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++|     <p>
++|       x=""
++|       y=""
++|       z=""
++
++#data
++<!DOCTYPE html><!--x--
++#errors
++(1,22): eof-in-comment-double-dash
++#new-errors
++(1:23) eof-in-comment
++#document
++| <!DOCTYPE html>
++| <!-- x -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE html><table><tr><td></p></table>
++#errors
++(1,34): unexpected-end-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <p>
++
++#data
++<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->-->
++#errors
++(1,20): expected-space-or-right-bracket-in-doctype
++(1,25): unknown-doctype
++(1,35): unexpected-char-in-comment
++#new-errors
++(1:21) invalid-character-sequence-after-doctype-name
++(1:35) nested-comment
++#document
++| <!DOCTYPE <!doctype>
++| <html>
++|   <head>
++|   <body>
++|     ">"
++|     <!-- <!--x -->
++|     "-->"
++
++#data
++<!doctype html><div><form></form><div></div></div>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <form>
++|       <div>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..afdae7431dfd1fefc7e7742b9c32a2192a615ffa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,582 @@@
++#data
++<!doctype html><p><button><button>
++#errors
++(1,34): unexpected-start-tag-implies-end-tag
++(1,34): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|       <button>
++
++#data
++<!doctype html><p><button><address>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <address>
++
++#data
++<!doctype html><p><button><blockquote>
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <blockquote>
++
++#data
++<!doctype html><p><button><menu>
++#errors
++(1,32): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <menu>
++
++#data
++<!doctype html><p><button><p>
++#errors
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <p>
++
++#data
++<!doctype html><p><button><ul>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <ul>
++
++#data
++<!doctype html><p><button><h1>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <h1>
++
++#data
++<!doctype html><p><button><h6>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <h6>
++
++#data
++<!doctype html><p><button><listing>
++#errors
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <listing>
++
++#data
++<!doctype html><p><button><pre>
++#errors
++(1,31): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <pre>
++
++#data
++<!doctype html><p><button><form>
++#errors
++(1,32): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <form>
++
++#data
++<!doctype html><p><button><li>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <li>
++
++#data
++<!doctype html><p><button><dd>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <dd>
++
++#data
++<!doctype html><p><button><dt>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <dt>
++
++#data
++<!doctype html><p><button><plaintext>
++#errors
++(1,37): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <plaintext>
++
++#data
++<!doctype html><p><button><table>
++#errors
++(1,33): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <table>
++
++#data
++<!doctype html><p><button><hr>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <hr>
++
++#data
++<!doctype html><p><button><xmp>
++#errors
++(1,31): expected-named-closing-tag-but-got-eof
++(1,31): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <xmp>
++
++#data
++<!doctype html><p><button></p>
++#errors
++(1,30): unexpected-end-tag
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <button>
++|         <p>
++
++#data
++<!doctype html><address><button></address>a
++#errors
++(1,42): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <address>
++|       <button>
++|     "a"
++
++#data
++<!doctype html><address><button></address>a
++#errors
++(1,42): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <address>
++|       <button>
++|     "a"
++
++#data
++<p><table></p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,14): unexpected-end-tag-implies-table-voodoo
++(1,14): unexpected-end-tag
++(1,14): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <p>
++|       <table>
++
++#data
++<!doctype html><svg>
++#errors
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<!doctype html><p><figcaption>
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <figcaption>
++
++#data
++<!doctype html><p><summary>
++#errors
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <summary>
++
++#data
++<!doctype html><form><table><form>
++#errors
++(1,34): unexpected-form-in-table
++(1,34): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <form>
++|       <table>
++
++#data
++<!doctype html><table><form><form>
++#errors
++(1,28): unexpected-form-in-table
++(1,34): unexpected-form-in-table
++(1,34): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <form>
++
++#data
++<!doctype html><table><form></table><form>
++#errors
++(1,28): unexpected-form-in-table
++(1,42): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <form>
++
++#data
++<!doctype html><svg><foreignObject><p>
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg foreignObject>
++|         <p>
++
++#data
++<!doctype html><svg><title>abc
++#errors
++(1,30): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg title>
++|         "abc"
++
++#data
++<option><span><option>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,22): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <option>
++|       <span>
++|         <option>
++
++#data
++<option><option>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <option>
++|     <option>
++
++#data
++<math><annotation-xml><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): unexpected-html-element-in-foreign-content
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|     <div>
++
++#data
++<math><annotation-xml encoding="application/svg+xml"><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,58): unexpected-html-element-in-foreign-content
++(1,58): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding="application/svg+xml"
++|     <div>
++
++#data
++<math><annotation-xml encoding="application/xhtml+xml"><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,60): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding="application/xhtml+xml"
++|         <div>
++
++#data
++<math><annotation-xml encoding="aPPlication/xhtmL+xMl"><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,60): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding="aPPlication/xhtmL+xMl"
++|         <div>
++
++#data
++<math><annotation-xml encoding="text/html"><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,48): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding="text/html"
++|         <div>
++
++#data
++<math><annotation-xml encoding="Text/htmL"><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,48): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding="Text/htmL"
++|         <div>
++
++#data
++<math><annotation-xml encoding=" text/html "><div>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,50): unexpected-html-element-in-foreign-content
++(1,50): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         encoding=" text/html "
++|     <div>
++
++#data
++<math><annotation-xml> </annotation-xml>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,40): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         " "
++
++#data
++<math><annotation-xml>c</annotation-xml>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,40): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         "c"
++
++#data
++<math><annotation-xml><!--foo-->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,32): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <!-- foo -->
++
++#data
++<math><annotation-xml></svg>x
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,28): unexpected-end-tag
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         "x"
++
++#data
++<math><annotation-xml><svg>x
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,28): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <svg svg>
++|           "x"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1e2af7c1909d511ab4e173c79f1450e55009608a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,325 @@@
++#data
++<svg><![CDATA[foo]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo"
++
++#data
++<math><![CDATA[foo]]>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       "foo"
++
++#data
++<div><![CDATA[foo]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,7): expected-dashes-or-doctype
++(1,20): expected-closing-tag-but-got-eof
++#new-errors
++(1:14) cdata-in-html-content
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <!-- [CDATA[foo]] -->
++
++#data
++<svg><![CDATA[foo
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#new-errors
++(1:18) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo"
++
++#data
++<svg><![CDATA[foo
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#new-errors
++(1:18) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo"
++
++#data
++<svg><![CDATA[
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,14): expected-closing-tag-but-got-eof
++#new-errors
++(1:15) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<svg><![CDATA[]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++
++#data
++<svg><![CDATA[]] >]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "]] >"
++
++#data
++<svg><![CDATA[]] >]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "]] >"
++
++#data
++<svg><![CDATA[]]
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#new-errors
++(1:17) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "]]"
++
++#data
++<svg><![CDATA[]
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,15): expected-closing-tag-but-got-eof
++#new-errors
++(1:16) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "]"
++
++#data
++<svg><![CDATA[]>a
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#new-errors
++(1:18) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "]>a"
++
++#data
++<!DOCTYPE html><svg><![CDATA[foo]]]>
++#errors
++(1,36): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo]"
++
++#data
++<!DOCTYPE html><svg><![CDATA[foo]]]]>
++#errors
++(1,37): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo]]"
++
++#data
++<!DOCTYPE html><svg><![CDATA[foo]]]]]>
++#errors
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "foo]]]"
++
++#data
++<svg><foreignObject><div><![CDATA[foo]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,27): expected-dashes-or-doctype
++(1,40): expected-closing-tag-but-got-eof
++#new-errors
++(1:34) cdata-in-html-content
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg foreignObject>
++|         <div>
++|           <!-- [CDATA[foo]] -->
++
++#data
++<svg><![CDATA[<svg>]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,22): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>"
++
++#data
++<svg><![CDATA[</svg>a]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,24): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "</svg>a"
++
++#data
++<svg><![CDATA[<svg>a
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,20): expected-closing-tag-but-got-eof
++#new-errors
++(1:21) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>a"
++
++#data
++<svg><![CDATA[</svg>a
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#new-errors
++(1:22) eof-in-cdata
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "</svg>a"
++
++#data
++<svg><![CDATA[<svg>]]><path>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,28): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>"
++|       <svg path>
++
++#data
++<svg><![CDATA[<svg>]]></path>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,29): unexpected-end-tag
++(1,29): unexpected-end-tag
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>"
++
++#data
++<svg><![CDATA[<svg>]]><!--path-->
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>"
++|       <!-- path -->
++
++#data
++<svg><![CDATA[<svg>]]>path
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<svg>path"
++
++#data
++<svg><![CDATA[<!--svg-->]]>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       "<!--svg-->"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..31e6d9e331042da8dc42c1d46776691ff30f1fb3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,190 @@@
++#data
++<a><b><big><em><strong><div>X</a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,33): adoption-agency-1.3
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|         <big>
++|           <em>
++|             <strong>
++|     <big>
++|       <em>
++|         <strong>
++|           <div>
++|             <a>
++|               "X"
++
++#data
++<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): adoption-agency-1.3
++(1,91): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|     <b>
++|       <div>
++|         id="1"
++|         <a>
++|         <div>
++|           id="2"
++|           <a>
++|           <div>
++|             id="3"
++|             <a>
++|             <div>
++|               id="4"
++|               <a>
++|               <div>
++|                 id="5"
++|                 <a>
++|                 <div>
++|                   id="6"
++|                   <a>
++|                   <div>
++|                     id="7"
++|                     <a>
++|                     <div>
++|                       id="8"
++|                       <a>
++|                         "A"
++
++#data
++<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): adoption-agency-1.3
++(1,101): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|     <b>
++|       <div>
++|         id="1"
++|         <a>
++|         <div>
++|           id="2"
++|           <a>
++|           <div>
++|             id="3"
++|             <a>
++|             <div>
++|               id="4"
++|               <a>
++|               <div>
++|                 id="5"
++|                 <a>
++|                 <div>
++|                   id="6"
++|                   <a>
++|                   <div>
++|                     id="7"
++|                     <a>
++|                     <div>
++|                       id="8"
++|                       <a>
++|                         <div>
++|                           id="9"
++|                           "A"
++
++#data
++<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): adoption-agency-1.3
++(1,112): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       <b>
++|     <b>
++|       <div>
++|         id="1"
++|         <a>
++|         <div>
++|           id="2"
++|           <a>
++|           <div>
++|             id="3"
++|             <a>
++|             <div>
++|               id="4"
++|               <a>
++|               <div>
++|                 id="5"
++|                 <a>
++|                 <div>
++|                   id="6"
++|                   <a>
++|                   <div>
++|                     id="7"
++|                     <a>
++|                     <div>
++|                       id="8"
++|                       <a>
++|                         <div>
++|                           id="9"
++|                           <div>
++|                             id="10"
++|                             "A"
++
++#data
++<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,46): adoption-agency-1.3
++(1,50): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <cite>
++|       <b>
++|         <cite>
++|           <i>
++|             <cite>
++|               <i>
++|                 <cite>
++|                   <i>
++|       <i>
++|         <i>
++|           <div>
++|             <b>
++|               "X"
++|             "TEST"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..49e4a4ace58be40162fbeb8c900a4c0053fa8b58
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,168 @@@
++#data
++<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,116): unexpected-end-tag
++(1,117): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           color="red"
++|           <font>
++|             size="4"
++|             <font>
++|               size="4"
++|               <font>
++|                 size="4"
++|                 <font>
++|                   size="4"
++|                   <font>
++|                     size="4"
++|                     <font>
++|                       color="red"
++|     <p>
++|       <font>
++|         color="red"
++|         <font>
++|           size="4"
++|           <font>
++|             size="4"
++|             <font>
++|               size="4"
++|               <font>
++|                 color="red"
++|                 "X"
++
++#data
++<p><font size=4><font size=4><font size=4><font size=4><p>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,58): unexpected-end-tag
++(1,59): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="4"
++|             <font>
++|               size="4"
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="4"
++|             "X"
++
++#data
++<p><font size=4><font size=4><font size=4><font size="5"><font size=4><p>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,73): unexpected-end-tag
++(1,74): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="4"
++|             <font>
++|               size="5"
++|               <font>
++|                 size="4"
++|     <p>
++|       <font>
++|         size="4"
++|         <font>
++|           size="4"
++|           <font>
++|             size="5"
++|             <font>
++|               size="4"
++|               "X"
++
++#data
++<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,68): unexpected-end-tag
++(1,69): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <font>
++|         id="a"
++|         size="4"
++|         <font>
++|           id="b"
++|           size="4"
++|           <font>
++|             size="4"
++|             <font>
++|               size="4"
++|     <p>
++|       <font>
++|         id="a"
++|         size="4"
++|         <font>
++|           id="b"
++|           size="4"
++|           <font>
++|             size="4"
++|             <font>
++|               size="4"
++|               "X"
++
++#data
++<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,64): end-tag-too-early
++(1,67): unexpected-end-tag
++(1,68): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <b>
++|         id="a"
++|         <b>
++|           id="a"
++|           <b>
++|             id="a"
++|             <b>
++|               <object>
++|                 <b>
++|                   id="a"
++|                   <b>
++|                     id="a"
++|                     "X"
++|     <p>
++|       <b>
++|         id="a"
++|         <b>
++|           id="a"
++|           <b>
++|             id="a"
++|             <b>
++|               "Y"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f6dc7eb48a53d7417418f8827c9a24031b5edcd7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,79 @@@
++#data
++<!DOCTYPE html>&NotEqualTilde;
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "≂̸"
++
++#data
++<!DOCTYPE html>&NotEqualTilde;A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "≂̸A"
++
++#data
++<!DOCTYPE html>&ThickSpace;
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "  "
++
++#data
++<!DOCTYPE html>&ThickSpace;A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "  A"
++
++#data
++<!DOCTYPE html>&NotSubset;
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "⊂⃒"
++
++#data
++<!DOCTYPE html>&NotSubset;A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "⊂⃒A"
++
++#data
++<!DOCTYPE html>&Gopf;
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "𝔾"
++
++#data
++<!DOCTYPE html>&Gopf;A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "𝔾A"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5bb369b262660dd58d1ae606717cab6359b3c421
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,288 @@@
++#data
++<!DOCTYPE html><body><foo>A
++#errors
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       "A"
++
++#data
++<!DOCTYPE html><body><area>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <area>
++|     "A"
++
++#data
++<!DOCTYPE html><body><base>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <base>
++|     "A"
++
++#data
++<!DOCTYPE html><body><basefont>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <basefont>
++|     "A"
++
++#data
++<!DOCTYPE html><body><bgsound>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <bgsound>
++|     "A"
++
++#data
++<!DOCTYPE html><body><br>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <br>
++|     "A"
++
++#data
++<!DOCTYPE html><body><col>A
++#errors
++(1,26): unexpected-start-tag-ignored
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><body><command>A
++#errors
++eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <command>
++|       "A"
++
++#data
++<!DOCTYPE html><body><embed>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <embed>
++|     "A"
++
++#data
++<!DOCTYPE html><body><frame>A
++#errors
++(1,28): unexpected-start-tag-ignored
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><body><hr>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <hr>
++|     "A"
++
++#data
++<!DOCTYPE html><body><img>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <img>
++|     "A"
++
++#data
++<!DOCTYPE html><body><input>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <input>
++|     "A"
++
++#data
++<!DOCTYPE html><body><keygen>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <keygen>
++|     "A"
++
++#data
++<!DOCTYPE html><keygen>A</keygen>B
++#errors
++33: Stray end tag “keygen”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <keygen>
++|     "AB"
++
++#data
++</keygen>A
++#errors
++9: End tag seen without seeing a doctype first. Expected “<!DOCTYPE html>”.
++9: Stray end tag “keygen”.
++#document
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html></keygen>A
++#errors
++24: Stray end tag “keygen”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><head></keygen>A
++#errors
++30: Stray end tag “keygen”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><head></head></keygen>A
++#errors
++30: Stray end tag “keygen”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><body></keygen>A
++#errors
++30: Stray end tag “keygen”.
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "A"
++
++#data
++<!DOCTYPE html><body><link>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <link>
++|     "A"
++
++#data
++<!DOCTYPE html><body><meta>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <meta>
++|     "A"
++
++#data
++<!DOCTYPE html><body><param>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <param>
++|     "A"
++
++#data
++<!DOCTYPE html><body><source>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <source>
++|     "A"
++
++#data
++<!DOCTYPE html><body><track>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <track>
++|     "A"
++
++#data
++<!DOCTYPE html><body><wbr>A
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <wbr>
++|     "A"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..de453b9cb7a5646342b26eff030af2048dddafbd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,393 @@@
++#data
++<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a>
++#errors
++(1,47): unexpected-start-tag-implies-end-tag
++(1,51): adoption-agency-1.3
++(1,74): unexpected-start-tag-implies-end-tag
++(1,74): adoption-agency-1.3
++(1,81): unexpected-start-tag-implies-end-tag
++(1,85): adoption-agency-1.3
++(1,108): unexpected-start-tag-implies-end-tag
++(1,108): adoption-agency-1.3
++(1,115): unexpected-start-tag-implies-end-tag
++(1,119): adoption-agency-1.3
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       href="#1"
++|       <nobr>
++|         "1"
++|       <nobr>
++|     <nobr>
++|       <br>
++|       <a>
++|         href="#2"
++|     <a>
++|       href="#2"
++|       <nobr>
++|         "2"
++|       <nobr>
++|     <nobr>
++|       <br>
++|       <a>
++|         href="#3"
++|     <a>
++|       href="#3"
++|       <nobr>
++|         "3"
++|       <nobr>
++
++#data
++<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3
++#errors
++(1,37): unexpected-start-tag-implies-end-tag
++(1,41): adoption-agency-1.3
++(1,50): unexpected-start-tag-implies-end-tag
++(1,50): adoption-agency-1.3
++(1,57): unexpected-start-tag-implies-end-tag
++(1,61): adoption-agency-1.3
++(1,62): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|       <nobr>
++|     <nobr>
++|       <i>
++|     <i>
++|       <nobr>
++|         "2"
++|       <nobr>
++|     <nobr>
++|       "3"
++
++#data
++<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3
++#errors
++(1,44): foster-parenting-start-tag
++(1,48): foster-parenting-end-tag
++(1,48): adoption-agency-1.3
++(1,51): foster-parenting-start-tag
++(1,57): foster-parenting-start-tag
++(1,57): nobr-already-in-scope
++(1,57): adoption-agency-1.2
++(1,58): foster-parenting-character
++(1,64): foster-parenting-start-tag
++(1,64): nobr-already-in-scope
++(1,68): foster-parenting-end-tag
++(1,68): adoption-agency-1.2
++(1,69): foster-parenting-character
++(1,69): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|         <nobr>
++|           <i>
++|         <i>
++|           <nobr>
++|             "2"
++|           <nobr>
++|         <nobr>
++|           "3"
++|         <table>
++
++#data
++<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3
++#errors
++(1,56): unexpected-end-tag
++(1,65): unexpected-start-tag-implies-end-tag
++(1,65): adoption-agency-1.3
++(1,72): unexpected-start-tag-implies-end-tag
++(1,76): adoption-agency-1.3
++(1,77): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|         <table>
++|           <tbody>
++|             <tr>
++|               <td>
++|                 <nobr>
++|                   <i>
++|                 <i>
++|                   <nobr>
++|                     "2"
++|                   <nobr>
++|                 <nobr>
++|                   "3"
++
++#data
++<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3
++#errors
++(1,42): unexpected-start-tag-implies-end-tag
++(1,42): adoption-agency-1.3
++(1,46): adoption-agency-1.3
++(1,46): adoption-agency-1.3
++(1,55): unexpected-start-tag-implies-end-tag
++(1,55): adoption-agency-1.3
++(1,62): unexpected-start-tag-implies-end-tag
++(1,66): adoption-agency-1.3
++(1,67): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|     <div>
++|       <b>
++|         <nobr>
++|         <nobr>
++|       <nobr>
++|         <i>
++|       <i>
++|         <nobr>
++|           "2"
++|         <nobr>
++|       <nobr>
++|         "3"
++
++#data
++<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3
++#errors
++(1,37): unexpected-start-tag-implies-end-tag
++(1,41): adoption-agency-1.3
++(1,55): unexpected-start-tag-implies-end-tag
++(1,55): adoption-agency-1.3
++(1,62): unexpected-start-tag-implies-end-tag
++(1,66): adoption-agency-1.3
++(1,67): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|       <nobr>
++|     <div>
++|       <nobr>
++|         <i>
++|       <i>
++|         <nobr>
++|           "2"
++|         <nobr>
++|       <nobr>
++|         "3"
++
++#data
++<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr>
++#errors
++(1,37): unexpected-start-tag-implies-end-tag
++(1,46): adoption-agency-1.3
++(1,55): unexpected-start-tag-implies-end-tag
++(1,55): adoption-agency-1.3
++(1,55): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|       <nobr>
++|         <ins>
++|     <nobr>
++|       <i>
++|     <i>
++|       <nobr>
++
++#data
++<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2
++#errors
++(1,42): unexpected-start-tag-implies-end-tag
++(1,42): adoption-agency-1.3
++(1,46): adoption-agency-1.3
++(1,50): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <nobr>
++|         "1"
++|         <ins>
++|       <nobr>
++|     <nobr>
++|       <i>
++|         "2"
++
++#data
++<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i>
++#errors
++(1,35): adoption-agency-1.3
++(1,44): unexpected-start-tag-implies-end-tag
++(1,44): adoption-agency-1.3
++(1,49): adoption-agency-1.3
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "1"
++|       <nobr>
++|     <nobr>
++|       <i>
++|     <i>
++|       <nobr>
++|         "2"
++
++#data
++<p><code x</code></p>
++
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,11): invalid-character-in-attribute-name
++(1,12): unexpected-character-after-solidus-in-tag
++(1,21): unexpected-end-tag
++(2,0): expected-closing-tag-but-got-eof
++#new-errors
++(1:11) unexpected-character-in-attribute-name
++(1:13) unexpected-solidus-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <code>
++|         code=""
++|         x<=""
++|     <code>
++|       code=""
++|       x<=""
++|       "
++"
++
++#data
++<!DOCTYPE html><svg><foreignObject><p><i></p>a
++#errors
++(1,45): unexpected-end-tag
++(1,46): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg foreignObject>
++|         <p>
++|           <i>
++|         <i>
++|           "a"
++
++#data
++<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a
++#errors
++(1,60): unexpected-end-tag
++(1,61): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg foreignObject>
++|                 <p>
++|                   <i>
++|                 <i>
++|                   "a"
++
++#data
++<!DOCTYPE html><math><mtext><p><i></p>a
++#errors
++(1,38): unexpected-end-tag
++(1,39): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mtext>
++|         <p>
++|           <i>
++|         <i>
++|           "a"
++
++#data
++<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a
++#errors
++(1,53): unexpected-end-tag
++(1,54): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <math math>
++|               <math mtext>
++|                 <p>
++|                   <i>
++|                 <i>
++|                   "a"
++
++#data
++<!DOCTYPE html><body><div><!/div>a
++#errors
++(1,28): expected-dashes-or-doctype
++(1,34): expected-closing-tag-but-got-eof
++#new-errors
++(1:29) incorrectly-opened-comment
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <!-- /div -->
++|       "a"
++
++#data
++<button><p><button>
++#errors
++Line 1 Col 8 Unexpected start tag (button). Expected DOCTYPE.
++Line 1 Col 19 Unexpected start tag (button) implies end tag (button).
++Line 1 Col 19 Expected closing tag. Unexpected end of file.
++#document
++| <html>
++|   <head>
++|   <body>
++|     <button>
++|       <p>
++|     <button>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c7583d99e8b698287e1a45042126485c42d3c174
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,305 @@@
++#data
++<head></head><style></style>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,20): unexpected-start-tag-out-of-my-head
++#document
++| <html>
++|   <head>
++|     <style>
++|   <body>
++
++#data
++<head></head><script></script>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,21): unexpected-start-tag-out-of-my-head
++#document
++| <html>
++|   <head>
++|     <script>
++|   <body>
++
++#data
++<head></head><!-- --><style></style><!-- --><script></script>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,28): unexpected-start-tag-out-of-my-head
++(1,52): unexpected-start-tag-out-of-my-head
++#document
++| <html>
++|   <head>
++|     <style>
++|     <script>
++|   <!--   -->
++|   <!--   -->
++|   <body>
++
++#data
++<head></head><!-- -->x<style></style><!-- --><script></script>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <!--   -->
++|   <body>
++|     "x"
++|     <style>
++|     <!--   -->
++|     <script>
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>
++</pre></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>
++foo</pre></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "foo"
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>
++
++foo</pre></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "
++foo"
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>
++foo
++</pre></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "foo
++"
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>x</pre><span>
++</span></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "x"
++|     <span>
++|       "
++"
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>x
++y</pre></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "x
++y"
++
++#data
++<!DOCTYPE html><html><head></head><body><pre>x<div>
++y</pre></body></html>
++#errors
++(2,7): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "x"
++|       <div>
++|         "
++y"
++
++#data
++<!DOCTYPE html><pre>&#x0a;&#x0a;A</pre>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <pre>
++|       "
++A"
++
++#data
++<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML>
++#errors
++(1,33): two-heads-are-not-better-than-one
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <meta>
++|   <body>
++
++#data
++<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML>
++#errors
++(1,33): two-heads-are-not-better-than-one
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<textarea>foo<span>bar</span><i>baz
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,35): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "foo<span>bar</span><i>baz"
++
++#data
++<title>foo<span>bar</em><i>baz
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,30): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|     <title>
++|       "foo<span>bar</em><i>baz"
++|   <body>
++
++#data
++<!DOCTYPE html><textarea>
++</textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++
++#data
++<!DOCTYPE html><textarea>
++foo</textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "foo"
++
++#data
++<!DOCTYPE html><textarea>
++
++foo</textarea>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       "
++foo"
++
++#data
++<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html>
++#errors
++(1,60): end-tag-too-early
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <li>
++|         <div>
++|           <p>
++|       <li>
++
++#data
++<!doctype html><nobr><nobr><nobr>
++#errors
++(1,27): unexpected-start-tag-implies-end-tag
++(1,33): unexpected-start-tag-implies-end-tag
++(1,33): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <nobr>
++|     <nobr>
++|     <nobr>
++
++#data
++<!doctype html><nobr><nobr></nobr><nobr>
++#errors
++(1,27): unexpected-start-tag-implies-end-tag
++(1,40): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <nobr>
++|     <nobr>
++|     <nobr>
++
++#data
++<!doctype html><html><body><p><table></table></body></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <table>
++
++#data
++<p><table></table>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <table>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0a6174c36c0e6ddc6cae2e911a0c030895c4f4ad
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,58 @@@
++#data
++direct div content
++#errors
++#document-fragment
++div
++#document
++| "direct div content"
++
++#data
++direct textarea content
++#errors
++#document-fragment
++textarea
++#document
++| "direct textarea content"
++
++#data
++textarea content with <em>pseudo</em> <foo>markup
++#errors
++#document-fragment
++textarea
++#document
++| "textarea content with <em>pseudo</em> <foo>markup"
++
++#data
++this is &#x0043;DATA inside a <style> element
++#errors
++#document-fragment
++style
++#document
++| "this is &#x0043;DATA inside a <style> element"
++
++#data
++</plaintext>
++#errors
++#document-fragment
++plaintext
++#document
++| "</plaintext>"
++
++#data
++setting html's innerHTML
++#errors
++#document-fragment
++html
++#document
++| <head>
++| <body>
++|   "setting html's innerHTML"
++
++#data
++<title>setting head's innerHTML</title>
++#errors
++#document-fragment
++head
++#document
++| <title>
++|   "setting head's innerHTML"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1ef8cae421386e5d1faaae4a2be85c267aa8f9b8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,210 @@@
++#data
++<style> <!-- </style>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       " <!-- "
++|   <body>
++|     "x"
++
++#data
++<style> <!-- </style> --> </style>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,34): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       " <!-- "
++|     " "
++|   <body>
++|     "--> x"
++
++#data
++<style> <!--> </style>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       " <!--> "
++|   <body>
++|     "x"
++
++#data
++<style> <!---> </style>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       " <!---> "
++|   <body>
++|     "x"
++
++#data
++<iframe> <!---> </iframe>x
++#errors
++(1,8): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       " <!---> "
++|     "x"
++
++#data
++<iframe> <!--- </iframe>->x</iframe> --> </iframe>x
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,36): unexpected-end-tag
++(1,50): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <iframe>
++|       " <!--- "
++|     "->x --> x"
++
++#data
++<script> <!-- </script> --> </script>x
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,37): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <script>
++|       " <!-- "
++|     " "
++|   <body>
++|     "--> x"
++
++#data
++<title> <!-- </title> --> </title>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,34): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       " <!-- "
++|     " "
++|   <body>
++|     "--> x"
++
++#data
++<textarea> <!--- </textarea>->x</textarea> --> </textarea>x
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,42): unexpected-end-tag
++(1,58): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <textarea>
++|       " <!--- "
++|     "->x --> x"
++
++#data
++<style> <!</-- </style>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <style>
++|       " <!</-- "
++|   <body>
++|     "x"
++
++#data
++<p><xmp></xmp>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|     <xmp>
++
++#data
++<xmp> <!-- > --> </xmp>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <xmp>
++|       " <!-- > --> "
++
++#data
++<title>&amp;</title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "&"
++|   <body>
++
++#data
++<title><!--&amp;--></title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "<!--&-->"
++|   <body>
++
++#data
++<title><!--</title>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|     <title>
++|       "<!--"
++|   <body>
++
++#data
++<noscript><!--</noscript>--></noscript>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,39): unexpected-end-tag
++#script-on
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       "<!--"
++|   <body>
++|     "-->"
++
++#data
++<noscript><!--</noscript>--></noscript>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#script-off
++#document
++| <html>
++|   <head>
++|     <noscript>
++|       <!-- </noscript> -->
++|   <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f3991232da0a47894367325ad1591ba17ace2306
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,663 @@@
++#data
++<!doctype html></head> <head>
++#errors
++(1,29): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   " "
++|   <body>
++
++#data
++<!doctype html><form><div></form><div>
++#errors
++(1,33): end-tag-too-early-ignored
++(1,38): expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <form>
++|       <div>
++|         <div>
++
++#data
++<!doctype html><title>&amp;</title>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "&"
++|   <body>
++
++#data
++<!doctype html><title><!--&amp;--></title>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "<!--&-->"
++|   <body>
++
++#data
++<!doctype>
++#errors
++(1,9): need-space-after-doctype
++(1,10): expected-doctype-name-but-got-right-bracket
++(1,10): unknown-doctype
++#new-errors
++(1:10) missing-doctype-name
++#document
++| <!DOCTYPE >
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!---x
++#errors
++(1,6): eof-in-comment
++(1,6): expected-doctype-but-got-eof
++#new-errors
++(1:7) eof-in-comment
++#document
++| <!-- -x -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<body>
++<div>
++#errors
++(1,6): unexpected-start-tag
++(2,5): expected-closing-tag-but-got-eof
++#document-fragment
++div
++#document
++| "
++"
++| <div>
++
++#data
++<frameset></frameset>
++foo
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(2,1): unexpected-char-after-frameset
++(2,2): unexpected-char-after-frameset
++(2,3): unexpected-char-after-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   "
++"
++
++#data
++<frameset></frameset>
++<noframes>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(2,10): expected-named-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   "
++"
++|   <noframes>
++
++#data
++<frameset></frameset>
++<div>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(2,5): unexpected-start-tag-after-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   "
++"
++
++#data
++<frameset></frameset>
++</html>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   "
++"
++
++#data
++<frameset></frameset>
++</div>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(2,6): unexpected-end-tag-after-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   "
++"
++
++#data
++<form><form>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,12): unexpected-start-tag
++(1,12): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <form>
++
++#data
++<button><button>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,16): unexpected-start-tag-implies-end-tag
++(1,16): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <button>
++|     <button>
++
++#data
++<table><tr><td></th>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,20): unexpected-end-tag
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><caption><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,20): unexpected-cell-in-table-body
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><caption><div>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <div>
++
++#data
++</caption><div>
++#errors
++(1,10): XXX-undefined-error
++(1,15): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <div>
++
++#data
++<table><caption><div></caption>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,31): expected-one-end-tag-but-got-another
++(1,31): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <div>
++
++#data
++<table><caption></table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++
++#data
++</table><div>
++#errors
++(1,8): unexpected-end-tag
++(1,13): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <div>
++
++#data
++<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,23): unexpected-end-tag
++(1,29): unexpected-end-tag
++(1,40): unexpected-end-tag
++(1,47): unexpected-end-tag
++(1,55): unexpected-end-tag
++(1,60): unexpected-end-tag
++(1,68): unexpected-end-tag
++(1,73): unexpected-end-tag
++(1,81): unexpected-end-tag
++(1,86): unexpected-end-tag
++(1,86): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++
++#data
++<table><caption><div></div>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <div>
++
++#data
++<table><tr><td></body></caption></col></colgroup></html>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,22): unexpected-end-tag
++(1,32): unexpected-end-tag
++(1,38): unexpected-end-tag
++(1,49): unexpected-end-tag
++(1,56): unexpected-end-tag
++(1,56): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++</table></tbody></tfoot></thead></tr><div>
++#errors
++(1,8): unexpected-end-tag
++(1,16): unexpected-end-tag
++(1,24): unexpected-end-tag
++(1,32): unexpected-end-tag
++(1,37): unexpected-end-tag
++(1,42): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <div>
++
++#data
++<table><colgroup>foo
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,18): foster-parenting-character-in-table
++(1,19): foster-parenting-character-in-table
++(1,20): foster-parenting-character-in-table
++(1,20): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     "foo"
++|     <table>
++|       <colgroup>
++
++#data
++foo<col>
++#errors
++(1,1): unexpected-character-in-colgroup
++(1,2): unexpected-character-in-colgroup
++(1,3): unexpected-character-in-colgroup
++#document-fragment
++colgroup
++#document
++| <col>
++
++#data
++<table><colgroup></col>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,23): no-end-tag
++(1,23): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <colgroup>
++
++#data
++<frameset><div>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,15): unexpected-start-tag-in-frameset
++(1,15): eof-in-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++</frameset><frame>
++#errors
++(1,11): unexpected-frameset-in-frameset-innerhtml
++#document-fragment
++frameset
++#document
++| <frame>
++
++#data
++<frameset></div>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++(1,16): unexpected-end-tag-in-frameset
++(1,16): eof-in-frameset
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++</body><div>
++#errors
++(1,7): unexpected-close-tag
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++body
++#document
++| <div>
++
++#data
++<table><tr><div>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,16): unexpected-start-tag-implies-table-voodoo
++(1,16): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++</tr><td>
++#errors
++(1,5): unexpected-end-tag
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++</tbody></tfoot></thead><td>
++#errors
++(1,8): unexpected-end-tag
++(1,16): unexpected-end-tag
++(1,24): unexpected-end-tag
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<table><tr><div><td>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,16): foster-parenting-start-tag
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<caption><col><colgroup><tbody><tfoot><thead><tr>
++#errors
++(1,9): unexpected-start-tag
++(1,14): unexpected-start-tag
++(1,24): unexpected-start-tag
++(1,31): unexpected-start-tag
++(1,38): unexpected-start-tag
++(1,45): unexpected-start-tag
++#document-fragment
++tbody
++#document
++| <tr>
++
++#data
++<table><tbody></thead>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,22): unexpected-end-tag-in-table-body
++(1,22): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++
++#data
++</table><tr>
++#errors
++(1,8): unexpected-end-tag
++#document-fragment
++tbody
++#document
++| <tr>
++
++#data
++<table><tbody></body></caption></col></colgroup></html></td></th></tr>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,21): unexpected-end-tag-in-table-body
++(1,31): unexpected-end-tag-in-table-body
++(1,37): unexpected-end-tag-in-table-body
++(1,48): unexpected-end-tag-in-table-body
++(1,55): unexpected-end-tag-in-table-body
++(1,60): unexpected-end-tag-in-table-body
++(1,65): unexpected-end-tag-in-table-body
++(1,70): unexpected-end-tag-in-table-body
++(1,70): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++
++#data
++<table><tbody></div>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,20): unexpected-end-tag-implies-table-voodoo
++(1,20): end-tag-too-early
++(1,20): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++
++#data
++<table><table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,14): unexpected-start-tag-implies-end-tag
++(1,14): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|     <table>
++
++#data
++<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,14): unexpected-end-tag
++(1,24): unexpected-end-tag
++(1,30): unexpected-end-tag
++(1,41): unexpected-end-tag
++(1,48): unexpected-end-tag
++(1,56): unexpected-end-tag
++(1,61): unexpected-end-tag
++(1,69): unexpected-end-tag
++(1,74): unexpected-end-tag
++(1,82): unexpected-end-tag
++(1,87): unexpected-end-tag
++(1,87): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++
++#data
++</table><tr>
++#errors
++(1,8): unexpected-end-tag
++#document-fragment
++table
++#document
++| <tbody>
++|   <tr>
++
++#data
++<body></body></html>
++#errors
++(1,20): unexpected-end-tag-after-body-innerhtml
++#document-fragment
++html
++#document
++| <head>
++| <body>
++
++#data
++<html><frameset></frameset></html> 
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++|   " "
++
++#data
++<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"><html></html>
++#errors
++#document
++| <!DOCTYPE html "-//W3C//DTD HTML 4.01//EN" "">
++| <html>
++|   <head>
++|   <body>
++
++#data
++<param><frameset></frameset>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,17): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<source><frameset></frameset>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,18): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<track><frameset></frameset>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,17): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++</html><frameset></frameset>
++#errors
++(1,7): expected-doctype-but-got-end-tag
++(1,17): expected-eof-but-got-start-tag
++(1,17): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++</body><frameset></frameset>
++#errors
++(1,7): expected-doctype-but-got-end-tag
++(1,17): unexpected-start-tag-after-body
++(1,17): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..395dc72bdbd1355c9a80a13f22ef35cf4b074064
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,418 @@@
++#data
++<!doctype html><body><title>X</title>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <title>
++|       "X"
++
++#data
++<!doctype html><table><title>X</title></table>
++#errors
++(1,29): unexpected-start-tag-implies-table-voodoo
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <title>
++|       "X"
++|     <table>
++
++#data
++<!doctype html><head></head><title>X</title>
++#errors
++(1,35): unexpected-start-tag-out-of-my-head
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "X"
++|   <body>
++
++#data
++<!doctype html></head><title>X</title>
++#errors
++(1,29): unexpected-start-tag-out-of-my-head
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|     <title>
++|       "X"
++|   <body>
++
++#data
++<!doctype html><table><meta></table>
++#errors
++(1,28): unexpected-start-tag-implies-table-voodoo
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <meta>
++|     <table>
++
++#data
++<!doctype html><table>X<tr><td><table> <meta></table></table>
++#errors
++unexpected text in table
++(1,45): unexpected-start-tag-implies-table-voodoo
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <meta>
++|             <table>
++|               " "
++
++#data
++<!doctype html><html> <head>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!doctype html> <head>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!doctype html><table><style> <tr>x </style> </table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <style>
++|         " <tr>x "
++|       " "
++
++#data
++<!doctype html><table><TBODY><script> <tr>x </script> </table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <script>
++|           " <tr>x "
++|         " "
++
++#data
++<!doctype html><p><applet><p>X</p></applet>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <applet>
++|         <p>
++|           "X"
++
++#data
++<!doctype html><p><object type="application/x-non-existant-plugin"><p>X</p></object>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <object>
++|         type="application/x-non-existant-plugin"
++|         <p>
++|           "X"
++
++#data
++<!doctype html><listing>
++X</listing>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <listing>
++|       "X"
++
++#data
++<!doctype html><select><input>X
++#errors
++(1,30): unexpected-input-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <input>
++|     "X"
++
++#data
++<!doctype html><select><select>X
++#errors
++(1,31): unexpected-select-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     "X"
++
++#data
++<!doctype html><table><input type=hidDEN></table>
++#errors
++(1,41): unexpected-hidden-input-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <input>
++|         type="hidDEN"
++
++#data
++<!doctype html><table>X<input type=hidDEN></table>
++#errors
++(1,23): foster-parenting-character
++(1,42): unexpected-hidden-input-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     "X"
++|     <table>
++|       <input>
++|         type="hidDEN"
++
++#data
++<!doctype html><table>  <input type=hidDEN></table>
++#errors
++(1,43): unexpected-hidden-input-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       "  "
++|       <input>
++|         type="hidDEN"
++
++#data
++<!doctype html><table>  <input type='hidDEN'></table>
++#errors
++(1,45): unexpected-hidden-input-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       "  "
++|       <input>
++|         type="hidDEN"
++
++#data
++<!doctype html><table><input type=" hidden"><input type=hidDEN></table>
++#errors
++(1,44): unexpected-start-tag-implies-table-voodoo
++(1,63): unexpected-hidden-input-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <input>
++|       type=" hidden"
++|     <table>
++|       <input>
++|         type="hidDEN"
++
++#data
++<!doctype html><table><select>X<tr>
++#errors
++(1,30): unexpected-start-tag-implies-table-voodoo
++(1,35): unexpected-table-element-start-tag-in-select-in-table
++(1,35): eof-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "X"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!doctype html><select>X</select>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "X"
++
++#data
++<!DOCTYPE hTmL><html></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<!DOCTYPE HTML><html></html>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++
++#data
++<body>X</body></body>
++#errors
++(1,21): unexpected-end-tag-after-body
++#document-fragment
++html
++#document
++| <head>
++| <body>
++|   "X"
++
++#data
++<div><p>a</x> b
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,13): unexpected-end-tag
++(1,15): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <p>
++|         "a b"
++
++#data
++<table><tr><td><code></code> </table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <code>
++|             " "
++
++#data
++<table><b><tr><td>aaa</td></tr>bbb</table>ccc
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,10): foster-parenting-start-tag
++(1,32): foster-parenting-character
++(1,33): foster-parenting-character
++(1,34): foster-parenting-character
++(1,45): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|     <b>
++|       "bbb"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "aaa"
++|     <b>
++|       "ccc"
++
++#data
++A<table><tr> B</tr> B</table>
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,13): foster-parenting-character
++(1,14): foster-parenting-character
++(1,20): foster-parenting-character
++(1,21): foster-parenting-character
++#document
++| <html>
++|   <head>
++|   <body>
++|     "A B B"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++A<table><tr> B</tr> </em>C</table>
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,13): foster-parenting-character
++(1,14): foster-parenting-character
++(1,20): foster-parenting-character
++(1,25): unexpected-end-tag
++(1,25): unexpected-end-tag-in-special-element
++(1,26): foster-parenting-character
++#document
++| <html>
++|   <head>
++|   <body>
++|     "A BC"
++|     <table>
++|       <tbody>
++|         <tr>
++|         " "
++
++#data
++<select><keygen>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,16): unexpected-input-in-select
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|     <keygen>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ba2e63dd81978c0f48ff8276f6df64c5ce07d542
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,162 @@@
++#data
++<div>
++<div></div>
++</span>x
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(3,7): unexpected-end-tag
++(3,8): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "
++"
++|       <div>
++|       "
++x"
++
++#data
++<div>x<div></div>
++</span>x
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(2,7): unexpected-end-tag
++(2,8): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "x"
++|       <div>
++|       "
++x"
++
++#data
++<div>x<div></div>x</span>x
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,25): unexpected-end-tag
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "x"
++|       <div>
++|       "xx"
++
++#data
++<div>x<div></div>y</span>z
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,25): unexpected-end-tag
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "x"
++|       <div>
++|       "yz"
++
++#data
++<table><div>x<div></div>x</span>x
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,12): foster-parenting-start-tag
++(1,13): foster-parenting-character
++(1,18): foster-parenting-start-tag
++(1,24): foster-parenting-end-tag
++(1,25): foster-parenting-start-tag
++(1,32): foster-parenting-end-tag
++(1,32): unexpected-end-tag
++(1,33): foster-parenting-character
++(1,33): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "x"
++|       <div>
++|       "xx"
++|     <table>
++
++#data
++<table><li><li></table>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <li>
++|     <li>
++|     <table>
++
++#data
++x<table>x
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,9): foster-parenting-character
++(1,9): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     "xx"
++|     <table>
++
++#data
++x<table><table>x
++#errors
++(1,1): expected-doctype-but-got-chars
++(1,15): unexpected-start-tag-implies-end-tag
++(1,16): foster-parenting-character
++(1,16): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     "x"
++|     <table>
++|     "x"
++|     <table>
++
++#data
++<b>a<div></div><div></b>y
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,24): adoption-agency-1.3
++(1,25): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       "a"
++|       <div>
++|     <div>
++|       <b>
++|       "y"
++
++#data
++<a><div><p></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,15): adoption-agency-1.3
++(1,15): adoption-agency-1.3
++(1,15): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <div>
++|       <a>
++|       <p>
++|         <a>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f8d04b23bc0bef55c822503a71b15de97450e88c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,472 @@@
++#data
++<!DOCTYPE html><math></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++
++#data
++<!DOCTYPE html><body><math></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++
++#data
++<!DOCTYPE html><math><mi>
++#errors
++(1,25) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++
++#data
++<!DOCTYPE html><math><annotation-xml><svg><u>
++#errors
++(1,45) unexpected-html-element-in-foreign-content
++(1,45) expected-closing-tag-but-got-eof
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math annotation-xml>
++|         <svg svg>
++|     <u>
++
++#data
++<!DOCTYPE html><body><select><math></math></select>
++#errors
++(1,35) unexpected-start-tag-in-select
++(1,42) unexpected-end-tag-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++
++#data
++<!DOCTYPE html><body><select><option><math></math></option></select>
++#errors
++(1,43) unexpected-start-tag-in-select
++(1,50) unexpected-end-tag-in-select
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++
++#data
++<!DOCTYPE html><body><table><math></math></table>
++#errors
++(1,34) unexpected-start-tag-implies-table-voodoo
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><math><mi>foo</mi></math></table>
++#errors
++(1,34) foster-parenting-start-token
++(1,39) foster-parenting-character
++(1,40) foster-parenting-character
++(1,41) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table>
++#errors
++(1,34) foster-parenting-start-tag
++(1,39) foster-parenting-character
++(1,40) foster-parenting-character
++(1,41) foster-parenting-character
++(1,51) foster-parenting-character
++(1,52) foster-parenting-character
++(1,53) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <table>
++
++#data
++<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table>
++#errors
++(1,41) foster-parenting-start-tag
++(1,46) foster-parenting-character
++(1,47) foster-parenting-character
++(1,48) foster-parenting-character
++(1,58) foster-parenting-character
++(1,59) foster-parenting-character
++(1,60) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <table>
++|       <tbody>
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table>
++#errors
++(1,45) foster-parenting-start-tag
++(1,50) foster-parenting-character
++(1,51) foster-parenting-character
++(1,52) foster-parenting-character
++(1,62) foster-parenting-character
++(1,63) foster-parenting-character
++(1,64) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <math math>
++|               <math mi>
++|                 "foo"
++|               <math mi>
++|                 "bar"
++
++#data
++<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <math math>
++|               <math mi>
++|                 "foo"
++|               <math mi>
++|                 "bar"
++|             <p>
++|               "baz"
++
++#data
++<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <math math>
++|           <math mi>
++|             "foo"
++|           <math mi>
++|             "bar"
++|         <p>
++|           "baz"
++
++#data
++<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
++#errors
++(1,70) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <math math>
++|           <math mi>
++|             "foo"
++|           <math mi>
++|             "bar"
++|         <p>
++|           "baz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux
++#errors
++(1,78) unexpected-end-tag
++(1,78) expected-one-end-tag-but-got-another
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <caption>
++|         <math math>
++|           <math mi>
++|             "foo"
++|           <math mi>
++|             "bar"
++|           "baz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
++#errors
++(1,44) foster-parenting-start-tag
++(1,49) foster-parenting-character
++(1,50) foster-parenting-character
++(1,51) foster-parenting-character
++(1,61) foster-parenting-character
++(1,62) foster-parenting-character
++(1,63) foster-parenting-character
++(1,71) unexpected-html-element-in-foreign-content
++(1,71) foster-parenting-start-tag
++(1,63) foster-parenting-character
++(1,63) foster-parenting-character
++(1,63) foster-parenting-character
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <p>
++|       "baz"
++|     <table>
++|       <colgroup>
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
++#errors
++(1,50) unexpected-start-tag-in-select
++(1,54) unexpected-start-tag-in-select
++(1,62) unexpected-end-tag-in-select
++(1,66) unexpected-start-tag-in-select
++(1,74) unexpected-end-tag-in-select
++(1,77) unexpected-start-tag-in-select
++(1,88) unexpected-table-element-end-tag-in-select-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <select>
++|               "foobarbaz"
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux
++#errors
++(1,36) unexpected-start-tag-implies-table-voodoo
++(1,42) unexpected-start-tag-in-select
++(1,46) unexpected-start-tag-in-select
++(1,54) unexpected-end-tag-in-select
++(1,58) unexpected-start-tag-in-select
++(1,66) unexpected-end-tag-in-select
++(1,69) unexpected-start-tag-in-select
++(1,80) unexpected-table-element-end-tag-in-select-in-table
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       "foobarbaz"
++|     <table>
++|     <p>
++|       "quux"
++
++#data
++<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz
++#errors
++(1,41) expected-eof-but-got-start-tag
++(1,68) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <p>
++|       "baz"
++
++#data
++<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz
++#errors
++(1,34) unexpected-start-tag-after-body
++(1,61) unexpected-html-element-in-foreign-content
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mi>
++|         "foo"
++|       <math mi>
++|         "bar"
++|     <p>
++|       "baz"
++
++#data
++<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span>
++#errors
++(1,31) unexpected-start-tag-in-frameset
++(1,35) unexpected-start-tag-in-frameset
++(1,40) unexpected-end-tag-in-frameset
++(1,44) unexpected-start-tag-in-frameset
++(1,49) unexpected-end-tag-in-frameset
++(1,52) unexpected-start-tag-in-frameset
++(1,58) unexpected-start-tag-in-frameset
++(1,58) eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span>
++#errors
++(1,42) unexpected-start-tag-after-frameset
++(1,46) unexpected-start-tag-after-frameset
++(1,51) unexpected-end-tag-after-frameset
++(1,55) unexpected-start-tag-after-frameset
++(1,60) unexpected-end-tag-after-frameset
++(1,63) unexpected-start-tag-after-frameset
++(1,69) unexpected-start-tag-after-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     <math math>
++|       xlink href="foo"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <math math>
++|       <math mi>
++|         xlink href="foo"
++|         xml lang="en"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <math math>
++|       <math mi>
++|         xlink href="foo"
++|         xml lang="en"
++
++#data
++<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math>
++#errors
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     xlink:href="foo"
++|     xml:lang="en"
++|     <math math>
++|       <math mi>
++|         xlink href="foo"
++|         xml lang="en"
++|       "bar"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..54f436848c9fa2d62d2384898c9cdd11316e0ba5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,887 @@@
++#data
++<body><span>
++#errors
++(1,6): unexpected-start-tag
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++body
++#document
++| <span>
++
++#data
++<span><body>
++#errors
++(1,12): unexpected-start-tag
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++body
++#document
++| <span>
++
++#data
++<span><body>
++#errors
++(1,12): unexpected-start-tag
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++div
++#document
++| <span>
++
++#data
++<body><span>
++#errors
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++html
++#document
++| <head>
++| <body>
++|   <span>
++
++#data
++<frameset><span>
++#errors
++(1,10): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++body
++#document
++| <span>
++
++#data
++<span><frameset>
++#errors
++(1,16): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++body
++#document
++| <span>
++
++#data
++<span><frameset>
++#errors
++(1,16): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++div
++#document
++| <span>
++
++#data
++<frameset><span>
++#errors
++(1,16): unexpected-start-tag-in-frameset
++(1,16): eof-in-frameset
++#document-fragment
++html
++#document
++| <head>
++| <frameset>
++
++#data
++<table><tr>
++#errors
++(1,7): unexpected-start-tag
++#document-fragment
++table
++#document
++| <tbody>
++|   <tr>
++
++#data
++</table><tr>
++#errors
++(1,8): unexpected-end-tag
++#document-fragment
++table
++#document
++| <tbody>
++|   <tr>
++
++#data
++<a>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,3): eof-in-table
++#document-fragment
++table
++#document
++| <a>
++
++#data
++<a>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,3): eof-in-table
++#document-fragment
++table
++#document
++| <a>
++
++#data
++<a><caption>a
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,13): expected-closing-tag-but-got-eof
++#document-fragment
++table
++#document
++| <a>
++| <caption>
++|   "a"
++
++#data
++<a><colgroup><col>
++#errors
++(1,3): foster-parenting-start-token
++(1,18): expected-closing-tag-but-got-eof
++#document-fragment
++table
++#document
++| <a>
++| <colgroup>
++|   <col>
++
++#data
++<a><tbody><tr>
++#errors
++(1,3): foster-parenting-start-tag
++#document-fragment
++table
++#document
++| <a>
++| <tbody>
++|   <tr>
++
++#data
++<a><tfoot><tr>
++#errors
++(1,3): foster-parenting-start-tag
++#document-fragment
++table
++#document
++| <a>
++| <tfoot>
++|   <tr>
++
++#data
++<a><thead><tr>
++#errors
++(1,3): foster-parenting-start-tag
++#document-fragment
++table
++#document
++| <a>
++| <thead>
++|   <tr>
++
++#data
++<a><tr>
++#errors
++(1,3): foster-parenting-start-tag
++#document-fragment
++table
++#document
++| <a>
++| <tbody>
++|   <tr>
++
++#data
++<a><th>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,7): unexpected-cell-in-table-body
++#document-fragment
++table
++#document
++| <a>
++| <tbody>
++|   <tr>
++|     <th>
++
++#data
++<a><td>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,7): unexpected-cell-in-table-body
++#document-fragment
++table
++#document
++| <a>
++| <tbody>
++|   <tr>
++|     <td>
++
++#data
++<table></table><tbody>
++#errors
++(1,22): unexpected-start-tag
++#document-fragment
++caption
++#document
++| <table>
++
++#data
++</table><span>
++#errors
++(1,8): unexpected-end-tag
++(1,14): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++
++#data
++<span></table>
++#errors
++(1,14): unexpected-end-tag
++(1,14): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++
++#data
++</caption><span>
++#errors
++(1,10): XXX-undefined-error
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++
++#data
++<span></caption><span>
++#errors
++(1,16): XXX-undefined-error
++(1,22): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><caption><span>
++#errors
++(1,15): unexpected-start-tag
++(1,21): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><col><span>
++#errors
++(1,11): unexpected-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><colgroup><span>
++#errors
++(1,16): unexpected-start-tag
++(1,22): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><html><span>
++#errors
++(1,12): non-html-root
++(1,18): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><tbody><span>
++#errors
++(1,13): unexpected-start-tag
++(1,19): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><td><span>
++#errors
++(1,10): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><tfoot><span>
++#errors
++(1,13): unexpected-start-tag
++(1,19): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><thead><span>
++#errors
++(1,13): unexpected-start-tag
++(1,19): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><th><span>
++#errors
++(1,10): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span><tr><span>
++#errors
++(1,10): unexpected-start-tag
++(1,16): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++<span></table><span>
++#errors
++(1,14): unexpected-end-tag
++(1,20): expected-closing-tag-but-got-eof
++#document-fragment
++caption
++#document
++| <span>
++|   <span>
++
++#data
++</colgroup><col>
++#errors
++(1,11): XXX-undefined-error
++#document-fragment
++colgroup
++#document
++| <col>
++
++#data
++<a><col>
++#errors
++(1,3): XXX-undefined-error
++#document-fragment
++colgroup
++#document
++| <col>
++
++#data
++<caption><a>
++#errors
++(1,9): XXX-undefined-error
++(1,12): unexpected-start-tag-implies-table-voodoo
++(1,12): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<col><a>
++#errors
++(1,5): XXX-undefined-error
++(1,8): unexpected-start-tag-implies-table-voodoo
++(1,8): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<colgroup><a>
++#errors
++(1,10): XXX-undefined-error
++(1,13): unexpected-start-tag-implies-table-voodoo
++(1,13): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<tbody><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): unexpected-start-tag-implies-table-voodoo
++(1,10): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<tfoot><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): unexpected-start-tag-implies-table-voodoo
++(1,10): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<thead><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): unexpected-start-tag-implies-table-voodoo
++(1,10): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++</table><a>
++#errors
++(1,8): XXX-undefined-error
++(1,11): unexpected-start-tag-implies-table-voodoo
++(1,11): eof-in-table
++#document-fragment
++tbody
++#document
++| <a>
++
++#data
++<a><tr>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++#document-fragment
++tbody
++#document
++| <a>
++| <tr>
++
++#data
++<a><td>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,7): unexpected-cell-in-table-body
++#document-fragment
++tbody
++#document
++| <a>
++| <tr>
++|   <td>
++
++#data
++<a><td>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,7): unexpected-cell-in-table-body
++#document-fragment
++tbody
++#document
++| <a>
++| <tr>
++|   <td>
++
++#data
++<a><td>
++#errors
++(1,3): unexpected-start-tag-implies-table-voodoo
++(1,7): unexpected-cell-in-table-body
++#document-fragment
++tbody
++#document
++| <a>
++| <tr>
++|   <td>
++
++#data
++<td><table><tbody><a><tr>
++#errors
++(1,4): unexpected-cell-in-table-body
++(1,21): unexpected-start-tag-implies-table-voodoo
++(1,25): eof-in-table
++#document-fragment
++tbody
++#document
++| <tr>
++|   <td>
++|     <a>
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++</tr><td>
++#errors
++(1,5): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<td><table><a><tr></tr><tr>
++#errors
++(1,14): unexpected-start-tag-implies-table-voodoo
++(1,27): eof-in-table
++#document-fragment
++tr
++#document
++| <td>
++|   <a>
++|   <table>
++|     <tbody>
++|       <tr>
++|       <tr>
++
++#data
++<caption><td>
++#errors
++(1,9): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<col><td>
++#errors
++(1,5): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<colgroup><td>
++#errors
++(1,10): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<tbody><td>
++#errors
++(1,7): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<tfoot><td>
++#errors
++(1,7): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<thead><td>
++#errors
++(1,7): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<tr><td>
++#errors
++(1,4): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++</table><td>
++#errors
++(1,8): XXX-undefined-error
++#document-fragment
++tr
++#document
++| <td>
++
++#data
++<td><table></table><td>
++#errors
++#document-fragment
++tr
++#document
++| <td>
++|   <table>
++| <td>
++
++#data
++<td><table></table><td>
++#errors
++#document-fragment
++tr
++#document
++| <td>
++|   <table>
++| <td>
++
++#data
++<caption><a>
++#errors
++(1,9): XXX-undefined-error
++(1,12): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<col><a>
++#errors
++(1,5): XXX-undefined-error
++(1,8): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<colgroup><a>
++#errors
++(1,10): XXX-undefined-error
++(1,13): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<tbody><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<tfoot><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<th><a>
++#errors
++(1,4): XXX-undefined-error
++(1,7): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<thead><a>
++#errors
++(1,7): XXX-undefined-error
++(1,10): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<tr><a>
++#errors
++(1,4): XXX-undefined-error
++(1,7): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</table><a>
++#errors
++(1,8): XXX-undefined-error
++(1,11): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</tbody><a>
++#errors
++(1,8): XXX-undefined-error
++(1,11): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</td><a>
++#errors
++(1,5): unexpected-end-tag
++(1,8): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</tfoot><a>
++#errors
++(1,8): XXX-undefined-error
++(1,11): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</thead><a>
++#errors
++(1,8): XXX-undefined-error
++(1,11): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</th><a>
++#errors
++(1,5): unexpected-end-tag
++(1,8): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++</tr><a>
++#errors
++(1,5): XXX-undefined-error
++(1,8): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <a>
++
++#data
++<table><td><td>
++#errors
++(1,11): unexpected-cell-in-table-body
++(1,15): expected-closing-tag-but-got-eof
++#document-fragment
++td
++#document
++| <table>
++|   <tbody>
++|     <tr>
++|       <td>
++|       <td>
++
++#data
++</select><option>
++#errors
++(1,9): XXX-undefined-error
++#document-fragment
++select
++#document
++| <option>
++
++#data
++<input><option>
++#errors
++(1,7): unexpected-input-in-select
++#document-fragment
++select
++#document
++| <option>
++
++#data
++<keygen><option>
++#errors
++(1,8): unexpected-input-in-select
++#document-fragment
++select
++#document
++| <option>
++
++#data
++<textarea><option>
++#errors
++(1,10): unexpected-input-in-select
++#document-fragment
++select
++#document
++| <option>
++
++#data
++</html><!--abc-->
++#errors
++(1,7): unexpected-end-tag-after-body-innerhtml
++#document-fragment
++html
++#document
++| <head>
++| <body>
++| <!-- abc -->
++
++#data
++</frameset><frame>
++#errors
++(1,11): unexpected-frameset-in-frameset-innerhtml
++#document-fragment
++frameset
++#document
++| <frame>
++
++#data
++#errors
++#document-fragment
++html
++#document
++| <head>
++| <body>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..753502a2619e0ba75fcb93957c6d2e544183f561
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,336 @@@
++#data
++<b><p>Bold </b> Not bold</p>
++Also not bold.
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,15): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|     <p>
++|       <b>
++|         "Bold "
++|       " Not bold"
++|     "
++Also not bold."
++
++#data
++<html>
++<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain
++<p>I should not be red. <font color=red>Red. <i>Italic and red.</p>
++<p>Italic and red. </i> Red.</font> I should not be red.</p>
++<b>Bold <i>Bold and italic</b> Only Italic </i> Plain
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(2,58): adoption-agency-1.3
++(3,67): unexpected-end-tag
++(4,23): adoption-agency-1.3
++(4,35): adoption-agency-1.3
++(5,30): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|       color="red"
++|       <i>
++|         "Italic and Red"
++|     <i>
++|       <p>
++|         <font>
++|           color="red"
++|           "Italic and Red "
++|         " Just italic."
++|       " Italic only."
++|     " Plain
++"
++|     <p>
++|       "I should not be red. "
++|       <font>
++|         color="red"
++|         "Red. "
++|         <i>
++|           "Italic and red."
++|     <font>
++|       color="red"
++|       <i>
++|         "
++"
++|     <p>
++|       <font>
++|         color="red"
++|         <i>
++|           "Italic and red. "
++|         " Red."
++|       " I should not be red."
++|     "
++"
++|     <b>
++|       "Bold "
++|       <i>
++|         "Bold and italic"
++|     <i>
++|       " Only Italic "
++|     " Plain"
++
++#data
++<html><body>
++<p><font size="7">First paragraph.</p>
++<p>Second paragraph.</p></font>
++<b><p><i>Bold and Italic</b> Italic</p>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(2,38): unexpected-end-tag
++(4,28): adoption-agency-1.3
++(4,28): adoption-agency-1.3
++(4,39): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     "
++"
++|     <p>
++|       <font>
++|         size="7"
++|         "First paragraph."
++|     <font>
++|       size="7"
++|       "
++"
++|       <p>
++|         "Second paragraph."
++|     "
++"
++|     <b>
++|     <p>
++|       <b>
++|         <i>
++|           "Bold and Italic"
++|       <i>
++|         " Italic"
++
++#data
++<html>
++<dl>
++<dt><b>Boo
++<dd>Goo?
++</dl>
++</html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(4,4): end-tag-too-early
++(5,5): end-tag-too-early
++(6,7): expected-one-end-tag-but-got-another
++#document
++| <html>
++|   <head>
++|   <body>
++|     <dl>
++|       "
++"
++|       <dt>
++|         <b>
++|           "Boo
++"
++|       <dd>
++|         <b>
++|           "Goo?
++"
++|     <b>
++|       "
++"
++
++#data
++<html><body>
++<label><a><div>Hello<div>World</div></a></label>  
++</body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(2,40): adoption-agency-1.3
++(2,48): unexpected-end-tag
++(3,7): expected-one-end-tag-but-got-another
++#document
++| <html>
++|   <head>
++|   <body>
++|     "
++"
++|     <label>
++|       <a>
++|       <div>
++|         <a>
++|           "Hello"
++|           <div>
++|             "World"
++|         "  
++"
++
++#data
++<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table>
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,15): foster-parenting-start-tag
++(1,16): foster-parenting-character
++(1,22): foster-parenting-start-tag
++(1,23): foster-parenting-character
++(1,32): foster-parenting-end-tag
++(1,32): end-tag-too-early
++(1,33): foster-parenting-character
++(1,38): foster-parenting-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <center>
++|       " "
++|       <font>
++|         "a"
++|     <font>
++|       <img>
++|       " "
++|     <table>
++|       " "
++|       <tbody>
++|         <tr>
++|           <td>
++|             " "
++|           " "
++|         " "
++
++#data
++<table><tr><p><a><p>You should see this text.
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,14): unexpected-start-tag-implies-table-voodoo
++(1,17): unexpected-start-tag-implies-table-voodoo
++(1,20): unexpected-start-tag-implies-table-voodoo
++(1,20): closing-non-current-p-element
++(1,21): foster-parenting-character
++(1,22): foster-parenting-character
++(1,23): foster-parenting-character
++(1,24): foster-parenting-character
++(1,25): foster-parenting-character
++(1,26): foster-parenting-character
++(1,27): foster-parenting-character
++(1,28): foster-parenting-character
++(1,29): foster-parenting-character
++(1,30): foster-parenting-character
++(1,31): foster-parenting-character
++(1,32): foster-parenting-character
++(1,33): foster-parenting-character
++(1,34): foster-parenting-character
++(1,35): foster-parenting-character
++(1,36): foster-parenting-character
++(1,37): foster-parenting-character
++(1,38): foster-parenting-character
++(1,39): foster-parenting-character
++(1,40): foster-parenting-character
++(1,41): foster-parenting-character
++(1,42): foster-parenting-character
++(1,43): foster-parenting-character
++(1,44): foster-parenting-character
++(1,45): foster-parenting-character
++(1,45): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       <a>
++|     <p>
++|       <a>
++|         "You should see this text."
++|     <table>
++|       <tbody>
++|         <tr>
++
++#data
++<TABLE>
++<TR>
++<CENTER><CENTER><TD></TD></TR><TR>
++<FONT>
++<TABLE><tr></tr></TABLE>
++</P>
++<a></font><font></a>
++This page contains an insanely badly-nested tag sequence.
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(3,8): unexpected-start-tag-implies-table-voodoo
++(3,16): unexpected-start-tag-implies-table-voodoo
++(4,6): unexpected-start-tag-implies-table-voodoo
++(4,6): unexpected character token in table (the newline)
++(5,7): unexpected-start-tag-implies-end-tag
++(6,4): unexpected p end tag
++(7,10): adoption-agency-1.3
++(7,20): adoption-agency-1.3
++(8,57): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <center>
++|       <center>
++|     <font>
++|       "
++"
++|     <table>
++|       "
++"
++|       <tbody>
++|         <tr>
++|           "
++"
++|           <td>
++|         <tr>
++|           "
++"
++|     <table>
++|       <tbody>
++|         <tr>
++|     <font>
++|       "
++"
++|       <p>
++|       "
++"
++|       <a>
++|     <a>
++|       <font>
++|     <font>
++|       "
++This page contains an insanely badly-nested tag sequence."
++
++#data
++<html>
++<body>
++<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the
++nobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre>
++</body>
++</html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(3,56): adoption-agency-1.3
++(4,58): adoption-agency-1.3
++(5,7): expected-one-end-tag-but-got-another
++#document
++| <html>
++|   <head>
++|   <body>
++|     "
++"
++|     <b>
++|       <nobr>
++|     <div>
++|       <b>
++|         <nobr>
++|           "This text is in a div inside a nobr"
++|         "More text that should not be in the nobr, i.e., the
++nobr should have closed the div inside it implicitly. "
++|       <pre>
++|         "A pre tag outside everything else."
++|       "
++
++"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2127cfe1cae35e3c1ff822a7b7df4d671c1d6699
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,755 @@@
++#data
++Test
++#errors
++(1,4): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "Test"
++
++#data
++<div></div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++
++#data
++<div>Test</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "Test"
++
++#data
++<di
++#errors
++(1,3): eof-in-tag-name
++(1,3): expected-doctype-but-got-eof
++#new-errors
++(1:4) eof-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<div>Hello</div>
++<script>
++console.log("PASS");
++</script>
++<div>Bye</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "Hello"
++|     "
++"
++|     <script>
++|       "
++console.log("PASS");
++"
++|     "
++"
++|     <div>
++|       "Bye"
++
++#data
++<div foo="bar">Hello</div>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       foo="bar"
++|       "Hello"
++
++#data
++<div>Hello</div>
++<script>
++console.log("FOO<span>BAR</span>BAZ");
++</script>
++<div>Bye</div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       "Hello"
++|     "
++"
++|     <script>
++|       "
++console.log("FOO<span>BAR</span>BAZ");
++"
++|     "
++"
++|     <div>
++|       "Bye"
++
++#data
++<foo bar="baz"></foo><potato quack="duck"></potato>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       bar="baz"
++|     <potato>
++|       quack="duck"
++
++#data
++<foo bar="baz"><potato quack="duck"></potato></foo>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       bar="baz"
++|       <potato>
++|         quack="duck"
++
++#data
++<foo></foo bar="baz"><potato></potato quack="duck">
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,21): attributes-in-end-tag
++(1,51): attributes-in-end-tag
++#new-errors
++(1:21) end-tag-with-attributes
++(1:51) end-tag-with-attributes
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|     <potato>
++
++#data
++</ tttt>
++#errors
++(1,2): expected-closing-tag-but-got-char
++(1,8): expected-doctype-but-got-eof
++#new-errors
++(1:3) invalid-first-character-of-tag-name
++#document
++| <!--  tttt -->
++| <html>
++|   <head>
++|   <body>
++
++#data
++<div FOO ><img><img></div>
++#errors
++(1,10): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       foo=""
++|       <img>
++|       <img>
++
++#data
++<p>Test</p<p>Test2</p>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,13): unexpected-end-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       "TestTest2"
++
++#data
++<rdar://problem/6869687>
++#errors
++(1,7): unexpected-character-after-solidus-in-tag
++(1,8): unexpected-character-after-solidus-in-tag
++(1,16): unexpected-character-after-solidus-in-tag
++(1,24): expected-doctype-but-got-start-tag
++(1,24): expected-closing-tag-but-got-eof
++#new-errors
++(1:8) unexpected-solidus-in-tag
++(1:9) unexpected-solidus-in-tag
++(1:17) unexpected-solidus-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <rdar:>
++|       6869687=""
++|       problem=""
++
++#data
++<A>test< /A>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,8): expected-tag-name
++(1,12): expected-closing-tag-but-got-eof
++#new-errors
++(1:9) invalid-first-character-of-tag-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|       "test< /A>"
++
++#data
++&lt;
++#errors
++(1,4): expected-doctype-but-got-chars
++#document
++| <html>
++|   <head>
++|   <body>
++|     "<"
++
++#data
++<body foo='bar'><body foo='baz' yo='mama'>
++#errors
++(1,16): expected-doctype-but-got-start-tag
++(1,42): unexpected-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     foo="bar"
++|     yo="mama"
++
++#data
++<body></br foo="bar"></body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,21): attributes-in-end-tag
++(1,21): unexpected-end-tag-treated-as
++#new-errors
++(1:21) end-tag-with-attributes
++#document
++| <html>
++|   <head>
++|   <body>
++|     <br>
++
++#data
++<bdy><br foo="bar"></body>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,26): expected-one-end-tag-but-got-another
++#document
++| <html>
++|   <head>
++|   <body>
++|     <bdy>
++|       <br>
++|         foo="bar"
++
++#data
++<body></body></br foo="bar">
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,28): attributes-in-end-tag
++(1,28): unexpected-end-tag-after-body
++(1,28): unexpected-end-tag-treated-as
++#new-errors
++(1:28) end-tag-with-attributes
++#document
++| <html>
++|   <head>
++|   <body>
++|     <br>
++
++#data
++<bdy></body><br foo="bar">
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,12): expected-one-end-tag-but-got-another
++(1,26): unexpected-start-tag-after-body
++(1,26): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <bdy>
++|       <br>
++|         foo="bar"
++
++#data
++<html><body></body></html><!-- Hi there -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++| <!--  Hi there  -->
++
++#data
++<html><body></body></html><!-- Comment A --><!-- Comment B --><!-- Comment C --><!-- Comment D --><!-- Comment E -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++| <!--  Comment A  -->
++| <!--  Comment B  -->
++| <!--  Comment C  -->
++| <!--  Comment D  -->
++| <!--  Comment E  -->
++
++#data
++<html><body></body></html>x<!-- Hi there -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): expected-eof-but-got-char
++#document
++| <html>
++|   <head>
++|   <body>
++|     "x"
++|     <!--  Hi there  -->
++
++#data
++<html><body></body></html>x<!-- Hi there --></html><!-- Again -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): expected-eof-but-got-char
++#document
++| <html>
++|   <head>
++|   <body>
++|     "x"
++|     <!--  Hi there  -->
++| <!--  Again  -->
++
++#data
++<html><body></body></html>x<!-- Hi there --></body></html><!-- Again -->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): expected-eof-but-got-char
++#document
++| <html>
++|   <head>
++|   <body>
++|     "x"
++|     <!--  Hi there  -->
++| <!--  Again  -->
++
++#data
++<html><body><ruby><div><rp>xx</rp></div></ruby></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): XXX-undefined-error
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <rp>
++|           "xx"
++
++#data
++<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,27): XXX-undefined-error
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ruby>
++|       <div>
++|         <rt>
++|           "xx"
++
++#data
++<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <frameset>
++|     <!-- 1 -->
++|     <noframes>
++|       "A"
++|     <!-- 2 -->
++|   <!-- 3 -->
++|   <noframes>
++|     "B"
++|   <!-- 4 -->
++|   <noframes>
++|     "C"
++| <!-- 5 -->
++| <!-- 6 -->
++
++#data
++<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select>
++#errors
++(1,8): expected-doctype-but-got-start-tag
++(1,25): unexpected-select-in-select
++(1,59): unexpected-select-in-select
++(1,93): unexpected-select-in-select
++(1,127): unexpected-select-in-select
++#document
++| <html>
++|   <head>
++|   <body>
++|     <select>
++|       <option>
++|         "A"
++|     <option>
++|       "B"
++|       <select>
++|         <option>
++|           "C"
++|     <option>
++|       "D"
++|       <select>
++|         <option>
++|           "E"
++|     <option>
++|       "F"
++|       <select>
++|         <option>
++|           "G"
++
++#data
++<dd><dd><dt><dt><dd><li><li>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <dd>
++|     <dd>
++|     <dt>
++|     <dt>
++|     <dd>
++|       <li>
++|       <li>
++
++#data
++<div><b></div><div><nobr>a<nobr>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,14): end-tag-too-early
++(1,32): unexpected-start-tag-implies-end-tag
++(1,32): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <b>
++|     <div>
++|       <b>
++|         <nobr>
++|           "a"
++|         <nobr>
++
++#data
++<head></head>
++<body></body>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   "
++"
++|   <body>
++
++#data
++<head></head> <style></style>ddd
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,21): unexpected-start-tag-out-of-my-head
++#document
++| <html>
++|   <head>
++|     <style>
++|   " "
++|   <body>
++|     "ddd"
++
++#data
++<kbd><table></kbd><col><select><tr>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,18): unexpected-end-tag-implies-table-voodoo
++(1,18): unexpected-end-tag
++(1,31): unexpected-start-tag-implies-table-voodoo
++(1,35): unexpected-table-element-start-tag-in-select-in-table
++(1,35): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     <kbd>
++|       <select>
++|       <table>
++|         <colgroup>
++|           <col>
++|         <tbody>
++|           <tr>
++
++#data
++<kbd><table></kbd><col><select><tr></table><div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,18): unexpected-end-tag-implies-table-voodoo
++(1,18): unexpected-end-tag
++(1,31): unexpected-start-tag-implies-table-voodoo
++(1,35): unexpected-table-element-start-tag-in-select-in-table
++(1,48): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <kbd>
++|       <select>
++|       <table>
++|         <colgroup>
++|           <col>
++|         <tbody>
++|           <tr>
++|       <div>
++
++#data
++<a><li><style></style><title></title></a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,41): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <li>
++|       <a>
++|         <style>
++|         <title>
++
++#data
++<font></p><p><meta><title></title></font>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,10): unexpected-end-tag
++(1,41): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <font>
++|       <p>
++|     <p>
++|       <font>
++|         <meta>
++|         <title>
++
++#data
++<a><center><title></title><a>
++#errors
++(1,3): expected-doctype-but-got-start-tag
++(1,29): unexpected-start-tag-implies-end-tag
++(1,29): adoption-agency-1.3
++(1,29): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <a>
++|     <center>
++|       <a>
++|         <title>
++|       <a>
++
++#data
++<svg><title><div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg title>
++|         <div>
++
++#data
++<svg><title><rect><div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,23): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg title>
++|         <rect>
++|           <div>
++
++#data
++<svg><title><svg><div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,22): unexpected-html-element-in-foreign-content
++(1,22): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg title>
++|         <svg svg>
++|         <div>
++
++#data
++<img <="" FAIL>
++#errors
++(1,6): invalid-character-in-attribute-name
++(1,15): expected-doctype-but-got-start-tag
++#new-errors
++(1:6) unexpected-character-in-attribute-name
++#document
++| <html>
++|   <head>
++|   <body>
++|     <img>
++|       <=""
++|       fail=""
++
++#data
++<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul>
++#errors
++(1,4): expected-doctype-but-got-start-tag
++(1,23): non-void-element-with-trailing-solidus
++(1,29): end-tag-too-early
++#new-errors
++(1:9-1:24) non-void-html-element-start-tag-with-trailing-solidus
++#document
++| <html>
++|   <head>
++|   <body>
++|     <ul>
++|       <li>
++|         <div>
++|           id="foo"
++|           "A"
++|       <li>
++|         "B"
++|         <div>
++|           "C"
++
++#data
++<svg><em><desc></em>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,9): unexpected-html-element-in-foreign-content
++(1,20): adoption-agency-1.3
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|     <em>
++|       <desc>
++
++#data
++<table><tr><td><svg><desc><td></desc><circle>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             <svg svg>
++|               <svg desc>
++|           <td>
++|             <circle>
++
++#data
++<svg><tfoot></mi><td>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++(1,17): unexpected-end-tag
++(1,17): unexpected-end-tag
++(1,21): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg tfoot>
++|         <svg td>
++
++#data
++<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <math math>
++|       <math mrow>
++|         <math mrow>
++|           <math mn>
++|             "1"
++|         <math mi>
++|           "a"
++
++#data
++<!doctype html><input type="hidden"><frameset>
++#errors
++(1,46): unexpected-start-tag
++(1,46): eof-in-frameset
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <frameset>
++
++#data
++<!doctype html><input type="button"><frameset>
++#errors
++(1,46): unexpected-start-tag
++#document
++| <!DOCTYPE html>
++| <html>
++|   <head>
++|   <body>
++|     <input>
++|       type="button"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..791991d2029021a0ea08acf4a088308ad62e07a1
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,303 @@@
++#data
++<foo bar=qux/>
++#errors
++(1,14): expected-doctype-but-got-start-tag
++(1,14): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <foo>
++|       bar="qux/"
++
++#data
++<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#script-on
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       id="status"
++|       <noscript>
++|         "<strong>A</strong>"
++|       <span>
++|         "B"
++
++#data
++<p id="status"><noscript><strong>A</strong></noscript><span>B</span></p>
++#errors
++(1,15): expected-doctype-but-got-start-tag
++#script-off
++#document
++| <html>
++|   <head>
++|   <body>
++|     <p>
++|       id="status"
++|       <noscript>
++|         <strong>
++|           "A"
++|       <span>
++|         "B"
++
++#data
++<div><sarcasm><div></div></sarcasm></div>
++#errors
++(1,5): expected-doctype-but-got-start-tag
++#document
++| <html>
++|   <head>
++|   <body>
++|     <div>
++|       <sarcasm>
++|         <div>
++
++#data
++<html><body><img src="" border="0" alt="><div>A</div></body></html>
++#errors
++(1,6): expected-doctype-but-got-start-tag
++(1,67): eof-in-attribute-value-double-quote
++#new-errors
++(1:68) eof-in-tag
++#document
++| <html>
++|   <head>
++|   <body>
++
++#data
++<table><td></tbody>A
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,20): foster-parenting-character
++(1,20): eof-in-table
++#document
++| <html>
++|   <head>
++|   <body>
++|     "A"
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++
++#data
++<table><td></thead>A
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,19): XXX-undefined-error
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "A"
++
++#data
++<table><td></tfoot>A
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,11): unexpected-cell-in-table-body
++(1,19): XXX-undefined-error
++(1,20): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <tbody>
++|         <tr>
++|           <td>
++|             "A"
++
++#data
++<table><thead><td></tbody>A
++#errors
++(1,7): expected-doctype-but-got-start-tag
++(1,18): unexpected-cell-in-table-body
++(1,26): XXX-undefined-error
++(1,27): expected-closing-tag-but-got-eof
++#document
++| <html>
++|   <head>
++|   <body>
++|     <table>
++|       <thead>
++|         <tr>
++|           <td>
++|             "A"
++
++#data
++<legend>test</legend>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <legend>
++|       "test"
++
++#data
++<table><input>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <input>
++|     <table>
++
++#data
++<b><em><foo><foo><aside></b>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <em>
++|         <foo>
++|           <foo>
++|     <em>
++|       <aside>
++|         <b>
++
++#data
++<b><em><foo><foo><aside></b></em>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <em>
++|         <foo>
++|           <foo>
++|     <em>
++|     <aside>
++|       <em>
++|         <b>
++
++#data
++<b><em><foo><foo><foo><aside></b>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <em>
++|         <foo>
++|           <foo>
++|             <foo>
++|     <aside>
++|       <b>
++
++#data
++<b><em><foo><foo><foo><aside></b></em>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <b>
++|       <em>
++|         <foo>
++|           <foo>
++|             <foo>
++|     <aside>
++|       <b>
++
++#data
++<b><em><foo><foo><foo><foo><foo><foo><foo><foo><foo><foo><aside></b></em>
++#errors
++#document-fragment
++div
++#document
++| <b>
++|   <em>
++|     <foo>
++|       <foo>
++|         <foo>
++|           <foo>
++|             <foo>
++|               <foo>
++|                 <foo>
++|                   <foo>
++|                     <foo>
++|                       <foo>
++| <aside>
++|   <b>
++
++#data
++<b><em><foo><foob><foob><foob><foob><fooc><fooc><fooc><fooc><food><aside></b></em>
++#errors
++#document-fragment
++div
++#document
++| <b>
++|   <em>
++|     <foo>
++|       <foob>
++|         <foob>
++|           <foob>
++|             <foob>
++|               <fooc>
++|                 <fooc>
++|                   <fooc>
++|                     <fooc>
++|                       <food>
++| <aside>
++|   <b>
++
++#data
++<option><XH<optgroup></optgroup>
++#errors
++#document-fragment
++select
++#document
++| <option>
++
++#data
++<svg><foreignObject><div>foo</div><plaintext></foreignObject></svg><div>bar</div>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg foreignObject>
++|         <div>
++|           "foo"
++|         <plaintext>
++|           "</foreignObject></svg><div>bar</div>"
++
++#data
++<svg><foreignObject></foreignObject><title></svg>foo
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <svg svg>
++|       <svg foreignObject>
++|       <svg title>
++|     "foo"
++
++#data
++</foreignObject><plaintext><div>foo</div>
++#errors
++#document
++| <html>
++|   <head>
++|   <body>
++|     <plaintext>
++|       "<div>foo</div>"
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a4861bd002f7460cbbff63c9dbfa3bf470fdea5a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1272 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bytes"
++      "errors"
++      "io"
++      "strconv"
++      "strings"
++
++      "git.earlybird.gay/today-engine/internal/html/atom"
++)
++
++// A TokenType is the type of a Token.
++type TokenType uint32
++
++const (
++      // ErrorToken means that an error occurred during tokenization.
++      ErrorToken TokenType = iota
++      // TextToken means a text node.
++      TextToken
++      // A StartTagToken looks like <a>.
++      StartTagToken
++      // An EndTagToken looks like </a>.
++      EndTagToken
++      // A SelfClosingTagToken tag looks like <br/>.
++      SelfClosingTagToken
++      // A CommentToken looks like <!--x-->.
++      CommentToken
++      // A DoctypeToken looks like <!DOCTYPE x>
++      DoctypeToken
++)
++
++// ErrBufferExceeded means that the buffering limit was exceeded.
++var ErrBufferExceeded = errors.New("max buffer exceeded")
++
++// String returns a string representation of the TokenType.
++func (t TokenType) String() string {
++      switch t {
++      case ErrorToken:
++              return "Error"
++      case TextToken:
++              return "Text"
++      case StartTagToken:
++              return "StartTag"
++      case EndTagToken:
++              return "EndTag"
++      case SelfClosingTagToken:
++              return "SelfClosingTag"
++      case CommentToken:
++              return "Comment"
++      case DoctypeToken:
++              return "Doctype"
++      }
++      return "Invalid(" + strconv.Itoa(int(t)) + ")"
++}
++
++// An Attribute is an attribute namespace-key-value triple. Namespace is
++// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
++// does not contain escapable characters like '&', '<' or '>'), and Val is
++// unescaped (it looks like "a<b" rather than "a&lt;b").
++//
++// Namespace is only used by the parser, not the tokenizer.
++type Attribute struct {
++      Namespace, Key, Val string
++}
++
++// A Token consists of a TokenType and some Data (tag name for start and end
++// tags, content for text, comments and doctypes). A tag Token may also contain
++// a slice of Attributes. Data is unescaped for all Tokens (it looks like "a<b"
++// rather than "a&lt;b"). For tag Tokens, DataAtom is the atom for Data, or
++// zero if Data is not a known tag name.
++type Token struct {
++      Type     TokenType
++      DataAtom atom.Atom
++      Data     string
++      Attr     []Attribute
++}
++
++// tagString returns a string representation of a tag Token's Data and Attr.
++func (t Token) tagString() string {
++      if len(t.Attr) == 0 {
++              return t.Data
++      }
++      buf := bytes.NewBufferString(t.Data)
++      for _, a := range t.Attr {
++              buf.WriteByte(' ')
++              buf.WriteString(a.Key)
++              buf.WriteString(`="`)
++              escape(buf, a.Val)
++              buf.WriteByte('"')
++      }
++      return buf.String()
++}
++
++// String returns a string representation of the Token.
++func (t Token) String() string {
++      switch t.Type {
++      case ErrorToken:
++              return ""
++      case TextToken:
++              return EscapeString(t.Data)
++      case StartTagToken:
++              return "<" + t.tagString() + ">"
++      case EndTagToken:
++              return "</" + t.tagString() + ">"
++      case SelfClosingTagToken:
++              return "<" + t.tagString() + "/>"
++      case CommentToken:
++              return "<!--" + escapeCommentString(t.Data) + "-->"
++      case DoctypeToken:
++              return "<!DOCTYPE " + EscapeString(t.Data) + ">"
++      }
++      return "Invalid(" + strconv.Itoa(int(t.Type)) + ")"
++}
++
++// span is a range of bytes in a Tokenizer's buffer. The start is inclusive,
++// the end is exclusive.
++type span struct {
++      start, end int
++}
++
++// A Tokenizer returns a stream of HTML Tokens.
++type Tokenizer struct {
++      // r is the source of the HTML text.
++      r io.Reader
++      // tt is the TokenType of the current token.
++      tt TokenType
++      // err is the first error encountered during tokenization. It is possible
++      // for tt != Error && err != nil to hold: this means that Next returned a
++      // valid token but the subsequent Next call will return an error token.
++      // For example, if the HTML text input was just "plain", then the first
++      // Next call would set z.err to io.EOF but return a TextToken, and all
++      // subsequent Next calls would return an ErrorToken.
++      // err is never reset. Once it becomes non-nil, it stays non-nil.
++      err error
++      // readErr is the error returned by the io.Reader r. It is separate from
++      // err because it is valid for an io.Reader to return (n int, err1 error)
++      // such that n > 0 && err1 != nil, and callers should always process the
++      // n > 0 bytes before considering the error err1.
++      readErr error
++      // buf[raw.start:raw.end] holds the raw bytes of the current token.
++      // buf[raw.end:] is buffered input that will yield future tokens.
++      raw span
++      buf []byte
++      // maxBuf limits the data buffered in buf. A value of 0 means unlimited.
++      maxBuf int
++      // buf[data.start:data.end] holds the raw bytes of the current token's data:
++      // a text token's text, a tag token's tag name, etc.
++      data span
++      // pendingAttr is the attribute key and value currently being tokenized.
++      // When complete, pendingAttr is pushed onto attr. nAttrReturned is
++      // incremented on each call to TagAttr.
++      pendingAttr   [2]span
++      attr          [][2]span
++      nAttrReturned int
++      // rawTag is the "script" in "</script>" that closes the next token. If
++      // non-empty, the subsequent call to Next will return a raw or RCDATA text
++      // token: one that treats "<p>" as text instead of an element.
++      // rawTag's contents are lower-cased.
++      rawTag string
++      // textIsRaw is whether the current text token's data is not escaped.
++      textIsRaw bool
++      // convertNUL is whether NUL bytes in the current token's data should
++      // be converted into \ufffd replacement characters.
++      convertNUL bool
++      // allowCDATA is whether CDATA sections are allowed in the current context.
++      allowCDATA bool
++}
++
++// AllowCDATA sets whether or not the tokenizer recognizes <![CDATA[foo]]> as
++// the text "foo". The default value is false, which means to recognize it as
++// a bogus comment "<!-- [CDATA[foo]] -->" instead.
++//
++// Strictly speaking, an HTML5 compliant tokenizer should allow CDATA if and
++// only if tokenizing foreign content, such as MathML and SVG. However,
++// tracking foreign-contentness is difficult to do purely in the tokenizer,
++// as opposed to the parser, due to HTML integration points: an <svg> element
++// can contain a <foreignObject> that is foreign-to-SVG but not foreign-to-
++// HTML. For strict compliance with the HTML5 tokenization algorithm, it is the
++// responsibility of the user of a tokenizer to call AllowCDATA as appropriate.
++// In practice, if using the tokenizer without caring whether MathML or SVG
++// CDATA is text or comments, such as tokenizing HTML to find all the anchor
++// text, it is acceptable to ignore this responsibility.
++func (z *Tokenizer) AllowCDATA(allowCDATA bool) {
++      z.allowCDATA = allowCDATA
++}
++
++// NextIsNotRawText instructs the tokenizer that the next token should not be
++// considered as 'raw text'. Some elements, such as script and title elements,
++// normally require the next token after the opening tag to be 'raw text' that
++// has no child elements. For example, tokenizing "<title>a<b>c</b>d</title>"
++// yields a start tag token for "<title>", a text token for "a<b>c</b>d", and
++// an end tag token for "</title>". There are no distinct start tag or end tag
++// tokens for the "<b>" and "</b>".
++//
++// This tokenizer implementation will generally look for raw text at the right
++// times. Strictly speaking, an HTML5 compliant tokenizer should not look for
++// raw text if in foreign content: <title> generally needs raw text, but a
++// <title> inside an <svg> does not. Another example is that a <textarea>
++// generally needs raw text, but a <textarea> is not allowed as an immediate
++// child of a <select>; in normal parsing, a <textarea> implies </select>, but
++// one cannot close the implicit element when parsing a <select>'s InnerHTML.
++// Similarly to AllowCDATA, tracking the correct moment to override raw-text-
++// ness is difficult to do purely in the tokenizer, as opposed to the parser.
++// For strict compliance with the HTML5 tokenization algorithm, it is the
++// responsibility of the user of a tokenizer to call NextIsNotRawText as
++// appropriate. In practice, like AllowCDATA, it is acceptable to ignore this
++// responsibility for basic usage.
++//
++// Note that this 'raw text' concept is different from the one offered by the
++// Tokenizer.Raw method.
++func (z *Tokenizer) NextIsNotRawText() {
++      z.rawTag = ""
++}
++
++// Err returns the error associated with the most recent ErrorToken token.
++// This is typically io.EOF, meaning the end of tokenization.
++func (z *Tokenizer) Err() error {
++      if z.tt != ErrorToken {
++              return nil
++      }
++      return z.err
++}
++
++// readByte returns the next byte from the input stream, doing a buffered read
++// from z.r into z.buf if necessary. z.buf[z.raw.start:z.raw.end] remains a contiguous byte
++// slice that holds all the bytes read so far for the current token.
++// It sets z.err if the underlying reader returns an error.
++// Pre-condition: z.err == nil.
++func (z *Tokenizer) readByte() byte {
++      if z.raw.end >= len(z.buf) {
++              // Our buffer is exhausted and we have to read from z.r. Check if the
++              // previous read resulted in an error.
++              if z.readErr != nil {
++                      z.err = z.readErr
++                      return 0
++              }
++              // We copy z.buf[z.raw.start:z.raw.end] to the beginning of z.buf. If the length
++              // z.raw.end - z.raw.start is more than half the capacity of z.buf, then we
++              // allocate a new buffer before the copy.
++              c := cap(z.buf)
++              d := z.raw.end - z.raw.start
++              var buf1 []byte
++              if 2*d > c {
++                      buf1 = make([]byte, d, 2*c)
++              } else {
++                      buf1 = z.buf[:d]
++              }
++              copy(buf1, z.buf[z.raw.start:z.raw.end])
++              if x := z.raw.start; x != 0 {
++                      // Adjust the data/attr spans to refer to the same contents after the copy.
++                      z.data.start -= x
++                      z.data.end -= x
++                      z.pendingAttr[0].start -= x
++                      z.pendingAttr[0].end -= x
++                      z.pendingAttr[1].start -= x
++                      z.pendingAttr[1].end -= x
++                      for i := range z.attr {
++                              z.attr[i][0].start -= x
++                              z.attr[i][0].end -= x
++                              z.attr[i][1].start -= x
++                              z.attr[i][1].end -= x
++                      }
++              }
++              z.raw.start, z.raw.end, z.buf = 0, d, buf1[:d]
++              // Now that we have copied the live bytes to the start of the buffer,
++              // we read from z.r into the remainder.
++              var n int
++              n, z.readErr = readAtLeastOneByte(z.r, buf1[d:cap(buf1)])
++              if n == 0 {
++                      z.err = z.readErr
++                      return 0
++              }
++              z.buf = buf1[:d+n]
++      }
++      x := z.buf[z.raw.end]
++      z.raw.end++
++      if z.maxBuf > 0 && z.raw.end-z.raw.start >= z.maxBuf {
++              z.err = ErrBufferExceeded
++              return 0
++      }
++      return x
++}
++
++// Buffered returns a slice containing data buffered but not yet tokenized.
++func (z *Tokenizer) Buffered() []byte {
++      return z.buf[z.raw.end:]
++}
++
++// readAtLeastOneByte wraps an io.Reader so that reading cannot return (0, nil).
++// It returns io.ErrNoProgress if the underlying r.Read method returns (0, nil)
++// too many times in succession.
++func readAtLeastOneByte(r io.Reader, b []byte) (int, error) {
++      for i := 0; i < 100; i++ {
++              if n, err := r.Read(b); n != 0 || err != nil {
++                      return n, err
++              }
++      }
++      return 0, io.ErrNoProgress
++}
++
++// skipWhiteSpace skips past any white space.
++func (z *Tokenizer) skipWhiteSpace() {
++      if z.err != nil {
++              return
++      }
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      return
++              }
++              switch c {
++              case ' ', '\n', '\r', '\t', '\f':
++                      // No-op.
++              default:
++                      z.raw.end--
++                      return
++              }
++      }
++}
++
++// readRawOrRCDATA reads until the next "</foo>", where "foo" is z.rawTag and
++// is typically something like "script" or "textarea".
++func (z *Tokenizer) readRawOrRCDATA() {
++      if z.rawTag == "script" {
++              z.readScript()
++              z.textIsRaw = true
++              z.rawTag = ""
++              return
++      }
++loop:
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      break loop
++              }
++              if c != '<' {
++                      continue loop
++              }
++              c = z.readByte()
++              if z.err != nil {
++                      break loop
++              }
++              if c != '/' {
++                      z.raw.end--
++                      continue loop
++              }
++              if z.readRawEndTag() || z.err != nil {
++                      break loop
++              }
++      }
++      z.data.end = z.raw.end
++      // A textarea's or title's RCDATA can contain escaped entities.
++      z.textIsRaw = z.rawTag != "textarea" && z.rawTag != "title"
++      z.rawTag = ""
++}
++
++// readRawEndTag attempts to read a tag like "</foo>", where "foo" is z.rawTag.
++// If it succeeds, it backs up the input position to reconsume the tag and
++// returns true. Otherwise it returns false. The opening "</" has already been
++// consumed.
++func (z *Tokenizer) readRawEndTag() bool {
++      for i := 0; i < len(z.rawTag); i++ {
++              c := z.readByte()
++              if z.err != nil {
++                      return false
++              }
++              if c != z.rawTag[i] && c != z.rawTag[i]-('a'-'A') {
++                      z.raw.end--
++                      return false
++              }
++      }
++      c := z.readByte()
++      if z.err != nil {
++              return false
++      }
++      switch c {
++      case ' ', '\n', '\r', '\t', '\f', '/', '>':
++              // The 3 is 2 for the leading "</" plus 1 for the trailing character c.
++              z.raw.end -= 3 + len(z.rawTag)
++              return true
++      }
++      z.raw.end--
++      return false
++}
++
++// readScript reads until the next </script> tag, following the byzantine
++// rules for escaping/hiding the closing tag.
++func (z *Tokenizer) readScript() {
++      defer func() {
++              z.data.end = z.raw.end
++      }()
++      var c byte
++
++scriptData:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '<' {
++              goto scriptDataLessThanSign
++      }
++      goto scriptData
++
++scriptDataLessThanSign:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '/':
++              goto scriptDataEndTagOpen
++      case '!':
++              goto scriptDataEscapeStart
++      }
++      z.raw.end--
++      goto scriptData
++
++scriptDataEndTagOpen:
++      if z.readRawEndTag() || z.err != nil {
++              return
++      }
++      goto scriptData
++
++scriptDataEscapeStart:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '-' {
++              goto scriptDataEscapeStartDash
++      }
++      z.raw.end--
++      goto scriptData
++
++scriptDataEscapeStartDash:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '-' {
++              goto scriptDataEscapedDashDash
++      }
++      z.raw.end--
++      goto scriptData
++
++scriptDataEscaped:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataEscapedDash
++      case '<':
++              goto scriptDataEscapedLessThanSign
++      }
++      goto scriptDataEscaped
++
++scriptDataEscapedDash:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataEscapedDashDash
++      case '<':
++              goto scriptDataEscapedLessThanSign
++      }
++      goto scriptDataEscaped
++
++scriptDataEscapedDashDash:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataEscapedDashDash
++      case '<':
++              goto scriptDataEscapedLessThanSign
++      case '>':
++              goto scriptData
++      }
++      goto scriptDataEscaped
++
++scriptDataEscapedLessThanSign:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '/' {
++              goto scriptDataEscapedEndTagOpen
++      }
++      if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
++              goto scriptDataDoubleEscapeStart
++      }
++      z.raw.end--
++      goto scriptData
++
++scriptDataEscapedEndTagOpen:
++      if z.readRawEndTag() || z.err != nil {
++              return
++      }
++      goto scriptDataEscaped
++
++scriptDataDoubleEscapeStart:
++      z.raw.end--
++      for i := 0; i < len("script"); i++ {
++              c = z.readByte()
++              if z.err != nil {
++                      return
++              }
++              if c != "script"[i] && c != "SCRIPT"[i] {
++                      z.raw.end--
++                      goto scriptDataEscaped
++              }
++      }
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case ' ', '\n', '\r', '\t', '\f', '/', '>':
++              goto scriptDataDoubleEscaped
++      }
++      z.raw.end--
++      goto scriptDataEscaped
++
++scriptDataDoubleEscaped:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataDoubleEscapedDash
++      case '<':
++              goto scriptDataDoubleEscapedLessThanSign
++      }
++      goto scriptDataDoubleEscaped
++
++scriptDataDoubleEscapedDash:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataDoubleEscapedDashDash
++      case '<':
++              goto scriptDataDoubleEscapedLessThanSign
++      }
++      goto scriptDataDoubleEscaped
++
++scriptDataDoubleEscapedDashDash:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch c {
++      case '-':
++              goto scriptDataDoubleEscapedDashDash
++      case '<':
++              goto scriptDataDoubleEscapedLessThanSign
++      case '>':
++              goto scriptData
++      }
++      goto scriptDataDoubleEscaped
++
++scriptDataDoubleEscapedLessThanSign:
++      c = z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '/' {
++              goto scriptDataDoubleEscapeEnd
++      }
++      z.raw.end--
++      goto scriptDataDoubleEscaped
++
++scriptDataDoubleEscapeEnd:
++      if z.readRawEndTag() {
++              z.raw.end += len("</script>")
++              goto scriptDataEscaped
++      }
++      if z.err != nil {
++              return
++      }
++      goto scriptDataDoubleEscaped
++}
++
++// readComment reads the next comment token starting with "<!--". The opening
++// "<!--" has already been consumed.
++func (z *Tokenizer) readComment() {
++      // When modifying this function, consider manually increasing the
++      // maxSuffixLen constant in func TestComments, from 6 to e.g. 9 or more.
++      // That increase should only be temporary, not committed, as it
++      // exponentially affects the test running time.
++
++      z.data.start = z.raw.end
++      defer func() {
++              if z.data.end < z.data.start {
++                      // It's a comment with no data, like <!-->.
++                      z.data.end = z.data.start
++              }
++      }()
++
++      var dashCount int
++      beginning := true
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.calculateAbruptCommentDataEnd()
++                      return
++              }
++              switch c {
++              case '-':
++                      dashCount++
++                      continue
++              case '>':
++                      if dashCount >= 2 || beginning {
++                              z.data.end = z.raw.end - len("-->")
++                              return
++                      }
++              case '!':
++                      if dashCount >= 2 {
++                              c = z.readByte()
++                              if z.err != nil {
++                                      z.data.end = z.calculateAbruptCommentDataEnd()
++                                      return
++                              } else if c == '>' {
++                                      z.data.end = z.raw.end - len("--!>")
++                                      return
++                              } else if c == '-' {
++                                      dashCount = 1
++                                      beginning = false
++                                      continue
++                              }
++                      }
++              }
++              dashCount = 0
++              beginning = false
++      }
++}
++
++func (z *Tokenizer) calculateAbruptCommentDataEnd() int {
++      raw := z.Raw()
++      const prefixLen = len("<!--")
++      if len(raw) >= prefixLen {
++              raw = raw[prefixLen:]
++              if hasSuffix(raw, "--!") {
++                      return z.raw.end - 3
++              } else if hasSuffix(raw, "--") {
++                      return z.raw.end - 2
++              } else if hasSuffix(raw, "-") {
++                      return z.raw.end - 1
++              }
++      }
++      return z.raw.end
++}
++
++func hasSuffix(b []byte, suffix string) bool {
++      if len(b) < len(suffix) {
++              return false
++      }
++      b = b[len(b)-len(suffix):]
++      for i := range b {
++              if b[i] != suffix[i] {
++                      return false
++              }
++      }
++      return true
++}
++
++// readUntilCloseAngle reads until the next ">".
++func (z *Tokenizer) readUntilCloseAngle() {
++      z.data.start = z.raw.end
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return
++              }
++              if c == '>' {
++                      z.data.end = z.raw.end - len(">")
++                      return
++              }
++      }
++}
++
++// readMarkupDeclaration reads the next token starting with "<!". It might be
++// a "<!--comment-->", a "<!DOCTYPE foo>", a "<![CDATA[section]]>" or
++// "<!a bogus comment". The opening "<!" has already been consumed.
++func (z *Tokenizer) readMarkupDeclaration() TokenType {
++      z.data.start = z.raw.end
++      var c [2]byte
++      for i := 0; i < 2; i++ {
++              c[i] = z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return CommentToken
++              }
++      }
++      if c[0] == '-' && c[1] == '-' {
++              z.readComment()
++              return CommentToken
++      }
++      z.raw.end -= 2
++      if z.readDoctype() {
++              return DoctypeToken
++      }
++      if z.allowCDATA && z.readCDATA() {
++              z.convertNUL = true
++              return TextToken
++      }
++      // It's a bogus comment.
++      z.readUntilCloseAngle()
++      return CommentToken
++}
++
++// readDoctype attempts to read a doctype declaration and returns true if
++// successful. The opening "<!" has already been consumed.
++func (z *Tokenizer) readDoctype() bool {
++      const s = "DOCTYPE"
++      for i := 0; i < len(s); i++ {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return false
++              }
++              if c != s[i] && c != s[i]+('a'-'A') {
++                      // Back up to read the fragment of "DOCTYPE" again.
++                      z.raw.end = z.data.start
++                      return false
++              }
++      }
++      if z.skipWhiteSpace(); z.err != nil {
++              z.data.start = z.raw.end
++              z.data.end = z.raw.end
++              return true
++      }
++      z.readUntilCloseAngle()
++      return true
++}
++
++// readCDATA attempts to read a CDATA section and returns true if
++// successful. The opening "<!" has already been consumed.
++func (z *Tokenizer) readCDATA() bool {
++      const s = "[CDATA["
++      for i := 0; i < len(s); i++ {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return false
++              }
++              if c != s[i] {
++                      // Back up to read the fragment of "[CDATA[" again.
++                      z.raw.end = z.data.start
++                      return false
++              }
++      }
++      z.data.start = z.raw.end
++      brackets := 0
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return true
++              }
++              switch c {
++              case ']':
++                      brackets++
++              case '>':
++                      if brackets >= 2 {
++                              z.data.end = z.raw.end - len("]]>")
++                              return true
++                      }
++                      brackets = 0
++              default:
++                      brackets = 0
++              }
++      }
++}
++
++// startTagIn returns whether the start tag in z.buf[z.data.start:z.data.end]
++// case-insensitively matches any element of ss.
++func (z *Tokenizer) startTagIn(ss ...string) bool {
++loop:
++      for _, s := range ss {
++              if z.data.end-z.data.start != len(s) {
++                      continue loop
++              }
++              for i := 0; i < len(s); i++ {
++                      c := z.buf[z.data.start+i]
++                      if 'A' <= c && c <= 'Z' {
++                              c += 'a' - 'A'
++                      }
++                      if c != s[i] {
++                              continue loop
++                      }
++              }
++              return true
++      }
++      return false
++}
++
++// readStartTag reads the next start tag token. The opening "<a" has already
++// been consumed, where 'a' means anything in [A-Za-z].
++func (z *Tokenizer) readStartTag() TokenType {
++      z.readTag(true)
++      if z.err != nil {
++              return ErrorToken
++      }
++      // Several tags flag the tokenizer's next token as raw.
++      c, raw := z.buf[z.data.start], false
++      if 'A' <= c && c <= 'Z' {
++              c += 'a' - 'A'
++      }
++      switch c {
++      case 'i':
++              raw = z.startTagIn("iframe")
++      case 'n':
++              raw = z.startTagIn("noembed", "noframes", "noscript")
++      case 'p':
++              raw = z.startTagIn("plaintext")
++      case 's':
++              raw = z.startTagIn("script", "style")
++      case 't':
++              raw = z.startTagIn("textarea", "title")
++      case 'x':
++              raw = z.startTagIn("xmp")
++      }
++      if raw {
++              z.rawTag = strings.ToLower(string(z.buf[z.data.start:z.data.end]))
++      }
++      // Look for a self-closing token like "<br/>".
++      if z.err == nil && z.buf[z.raw.end-2] == '/' {
++              return SelfClosingTagToken
++      }
++      return StartTagToken
++}
++
++// readTag reads the next tag token and its attributes. If saveAttr, those
++// attributes are saved in z.attr, otherwise z.attr is set to an empty slice.
++// The opening "<a" or "</a" has already been consumed, where 'a' means anything
++// in [A-Za-z].
++func (z *Tokenizer) readTag(saveAttr bool) {
++      z.attr = z.attr[:0]
++      z.nAttrReturned = 0
++      // Read the tag name and attribute key/value pairs.
++      z.readTagName()
++      if z.skipWhiteSpace(); z.err != nil {
++              return
++      }
++      for {
++              c := z.readByte()
++              if z.err != nil || c == '>' {
++                      break
++              }
++              z.raw.end--
++              z.readTagAttrKey()
++              z.readTagAttrVal()
++              // Save pendingAttr if saveAttr and that attribute has a non-empty key.
++              if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
++                      z.attr = append(z.attr, z.pendingAttr)
++              }
++              if z.skipWhiteSpace(); z.err != nil {
++                      break
++              }
++      }
++}
++
++// readTagName sets z.data to the "div" in "<div k=v>". The reader (z.raw.end)
++// is positioned such that the first byte of the tag name (the "d" in "<div")
++// has already been consumed.
++func (z *Tokenizer) readTagName() {
++      z.data.start = z.raw.end - 1
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      z.data.end = z.raw.end
++                      return
++              }
++              switch c {
++              case ' ', '\n', '\r', '\t', '\f':
++                      z.data.end = z.raw.end - 1
++                      return
++              case '/', '>':
++                      z.raw.end--
++                      z.data.end = z.raw.end
++                      return
++              }
++      }
++}
++
++// readTagAttrKey sets z.pendingAttr[0] to the "k" in "<div k=v>".
++// Precondition: z.err == nil.
++func (z *Tokenizer) readTagAttrKey() {
++      z.pendingAttr[0].start = z.raw.end
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      z.pendingAttr[0].end = z.raw.end
++                      return
++              }
++              switch c {
++              case '=':
++                      if z.pendingAttr[0].start+1 == z.raw.end {
++                              // WHATWG 13.2.5.32, if we see an equals sign before the attribute name
++                              // begins, we treat it as a character in the attribute name and continue.
++                              continue
++                      }
++                      fallthrough
++              case ' ', '\n', '\r', '\t', '\f', '/', '>':
++                      // WHATWG 13.2.5.33 Attribute name state
++                      // We need to reconsume the char in the after attribute name state to support the / character
++                      z.raw.end--
++                      z.pendingAttr[0].end = z.raw.end
++                      return
++              }
++      }
++}
++
++// readTagAttrVal sets z.pendingAttr[1] to the "v" in "<div k=v>".
++func (z *Tokenizer) readTagAttrVal() {
++      z.pendingAttr[1].start = z.raw.end
++      z.pendingAttr[1].end = z.raw.end
++      if z.skipWhiteSpace(); z.err != nil {
++              return
++      }
++      c := z.readByte()
++      if z.err != nil {
++              return
++      }
++      if c == '/' {
++              // WHATWG 13.2.5.34 After attribute name state
++              // U+002F SOLIDUS (/) - Switch to the self-closing start tag state.
++              return
++      }
++      if c != '=' {
++              z.raw.end--
++              return
++      }
++      if z.skipWhiteSpace(); z.err != nil {
++              return
++      }
++      quote := z.readByte()
++      if z.err != nil {
++              return
++      }
++      switch quote {
++      case '>':
++              z.raw.end--
++              return
++
++      case '\'', '"':
++              z.pendingAttr[1].start = z.raw.end
++              for {
++                      c := z.readByte()
++                      if z.err != nil {
++                              z.pendingAttr[1].end = z.raw.end
++                              return
++                      }
++                      if c == quote {
++                              z.pendingAttr[1].end = z.raw.end - 1
++                              return
++                      }
++              }
++
++      default:
++              z.pendingAttr[1].start = z.raw.end - 1
++              for {
++                      c := z.readByte()
++                      if z.err != nil {
++                              z.pendingAttr[1].end = z.raw.end
++                              return
++                      }
++                      switch c {
++                      case ' ', '\n', '\r', '\t', '\f':
++                              z.pendingAttr[1].end = z.raw.end - 1
++                              return
++                      case '>':
++                              z.raw.end--
++                              z.pendingAttr[1].end = z.raw.end
++                              return
++                      }
++              }
++      }
++}
++
++// Next scans the next token and returns its type.
++func (z *Tokenizer) Next() TokenType {
++      z.raw.start = z.raw.end
++      z.data.start = z.raw.end
++      z.data.end = z.raw.end
++      if z.err != nil {
++              z.tt = ErrorToken
++              return z.tt
++      }
++      if z.rawTag != "" {
++              if z.rawTag == "plaintext" {
++                      // Read everything up to EOF.
++                      for z.err == nil {
++                              z.readByte()
++                      }
++                      z.data.end = z.raw.end
++                      z.textIsRaw = true
++              } else {
++                      z.readRawOrRCDATA()
++              }
++              if z.data.end > z.data.start {
++                      z.tt = TextToken
++                      z.convertNUL = true
++                      return z.tt
++              }
++      }
++      z.textIsRaw = false
++      z.convertNUL = false
++
++loop:
++      for {
++              c := z.readByte()
++              if z.err != nil {
++                      break loop
++              }
++              if c != '<' {
++                      continue loop
++              }
++
++              // Check if the '<' we have just read is part of a tag, comment
++              // or doctype. If not, it's part of the accumulated text token.
++              c = z.readByte()
++              if z.err != nil {
++                      break loop
++              }
++              var tokenType TokenType
++              switch {
++              case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z':
++                      tokenType = StartTagToken
++              case c == '/':
++                      tokenType = EndTagToken
++              case c == '!' || c == '?':
++                      // We use CommentToken to mean any of "<!--actual comments-->",
++                      // "<!DOCTYPE declarations>" and "<?xml processing instructions?>".
++                      tokenType = CommentToken
++              default:
++                      // Reconsume the current character.
++                      z.raw.end--
++                      continue
++              }
++
++              // We have a non-text token, but we might have accumulated some text
++              // before that. If so, we return the text first, and return the non-
++              // text token on the subsequent call to Next.
++              if x := z.raw.end - len("<a"); z.raw.start < x {
++                      z.raw.end = x
++                      z.data.end = x
++                      z.tt = TextToken
++                      return z.tt
++              }
++              switch tokenType {
++              case StartTagToken:
++                      z.tt = z.readStartTag()
++                      return z.tt
++              case EndTagToken:
++                      c = z.readByte()
++                      if z.err != nil {
++                              break loop
++                      }
++                      if c == '>' {
++                              // "</>" does not generate a token at all. Generate an empty comment
++                              // to allow passthrough clients to pick up the data using Raw.
++                              // Reset the tokenizer state and start again.
++                              z.tt = CommentToken
++                              return z.tt
++                      }
++                      if 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' {
++                              z.readTag(false)
++                              if z.err != nil {
++                                      z.tt = ErrorToken
++                              } else {
++                                      z.tt = EndTagToken
++                              }
++                              return z.tt
++                      }
++                      z.raw.end--
++                      z.readUntilCloseAngle()
++                      z.tt = CommentToken
++                      return z.tt
++              case CommentToken:
++                      if c == '!' {
++                              z.tt = z.readMarkupDeclaration()
++                              return z.tt
++                      }
++                      z.raw.end--
++                      z.readUntilCloseAngle()
++                      z.tt = CommentToken
++                      return z.tt
++              }
++      }
++      if z.raw.start < z.raw.end {
++              z.data.end = z.raw.end
++              z.tt = TextToken
++              return z.tt
++      }
++      z.tt = ErrorToken
++      return z.tt
++}
++
++// Raw returns the unmodified text of the current token. Calling Next, Token,
++// Text, TagName or TagAttr may change the contents of the returned slice.
++//
++// The token stream's raw bytes partition the byte stream (up until an
++// ErrorToken). There are no overlaps or gaps between two consecutive token's
++// raw bytes. One implication is that the byte offset of the current token is
++// the sum of the lengths of all previous tokens' raw bytes.
++func (z *Tokenizer) Raw() []byte {
++      return z.buf[z.raw.start:z.raw.end]
++}
++
++// convertNewlines converts "\r" and "\r\n" in s to "\n".
++// The conversion happens in place, but the resulting slice may be shorter.
++func convertNewlines(s []byte) []byte {
++      for i, c := range s {
++              if c != '\r' {
++                      continue
++              }
++
++              src := i + 1
++              if src >= len(s) || s[src] != '\n' {
++                      s[i] = '\n'
++                      continue
++              }
++
++              dst := i
++              for src < len(s) {
++                      if s[src] == '\r' {
++                              if src+1 < len(s) && s[src+1] == '\n' {
++                                      src++
++                              }
++                              s[dst] = '\n'
++                      } else {
++                              s[dst] = s[src]
++                      }
++                      src++
++                      dst++
++              }
++              return s[:dst]
++      }
++      return s
++}
++
++var (
++      nul         = []byte("\x00")
++      replacement = []byte("\ufffd")
++)
++
++// Text returns the unescaped text of a text, comment or doctype token. The
++// contents of the returned slice may change on the next call to Next.
++func (z *Tokenizer) Text() []byte {
++      switch z.tt {
++      case TextToken, CommentToken, DoctypeToken:
++              s := z.buf[z.data.start:z.data.end]
++              z.data.start = z.raw.end
++              z.data.end = z.raw.end
++              s = convertNewlines(s)
++              if (z.convertNUL || z.tt == CommentToken) && bytes.Contains(s, nul) {
++                      s = bytes.Replace(s, nul, replacement, -1)
++              }
++              if !z.textIsRaw {
++                      s = unescape(s, false)
++              }
++              return s
++      }
++      return nil
++}
++
++// TagName returns the lower-cased name of a tag token (the `img` out of
++// `<IMG SRC="foo">`) and whether the tag has attributes.
++// The contents of the returned slice may change on the next call to Next.
++func (z *Tokenizer) TagName() (name []byte, hasAttr bool) {
++      if z.data.start < z.data.end {
++              switch z.tt {
++              case StartTagToken, EndTagToken, SelfClosingTagToken:
++                      s := z.buf[z.data.start:z.data.end]
++                      z.data.start = z.raw.end
++                      z.data.end = z.raw.end
++                      return lower(s), z.nAttrReturned < len(z.attr)
++              }
++      }
++      return nil, false
++}
++
++// TagAttr returns the lower-cased key and unescaped value of the next unparsed
++// attribute for the current tag token and whether there are more attributes.
++// The contents of the returned slices may change on the next call to Next.
++func (z *Tokenizer) TagAttr() (key, val []byte, moreAttr bool) {
++      if z.nAttrReturned < len(z.attr) {
++              switch z.tt {
++              case StartTagToken, SelfClosingTagToken:
++                      x := z.attr[z.nAttrReturned]
++                      z.nAttrReturned++
++                      key = z.buf[x[0].start:x[0].end]
++                      val = z.buf[x[1].start:x[1].end]
++                      return key, unescape(convertNewlines(val), true), z.nAttrReturned < len(z.attr)
++              }
++      }
++      return nil, nil, false
++}
++
++// Token returns the current Token. The result's Data and Attr values remain
++// valid after subsequent Next calls.
++func (z *Tokenizer) Token() Token {
++      t := Token{Type: z.tt}
++      switch z.tt {
++      case TextToken, CommentToken, DoctypeToken:
++              t.Data = string(z.Text())
++      case StartTagToken, SelfClosingTagToken, EndTagToken:
++              name, moreAttr := z.TagName()
++              for moreAttr {
++                      var key, val []byte
++                      key, val, moreAttr = z.TagAttr()
++                      t.Attr = append(t.Attr, Attribute{"", atom.String(key), string(val)})
++              }
++              if a := atom.Lookup(name); a != 0 {
++                      t.DataAtom, t.Data = a, a.String()
++              } else {
++                      t.DataAtom, t.Data = 0, string(name)
++              }
++      }
++      return t
++}
++
++// SetMaxBuf sets a limit on the amount of data buffered during tokenization.
++// A value of 0 means unlimited.
++func (z *Tokenizer) SetMaxBuf(n int) {
++      z.maxBuf = n
++}
++
++// NewTokenizer returns a new HTML Tokenizer for the given Reader.
++// The input is assumed to be UTF-8 encoded.
++func NewTokenizer(r io.Reader) *Tokenizer {
++      return NewTokenizerFragment(r, "")
++}
++
++// NewTokenizerFragment returns a new HTML Tokenizer for the given Reader, for
++// tokenizing an existing element's InnerHTML fragment. contextTag is that
++// element's tag, such as "div" or "iframe".
++//
++// For example, how the InnerHTML "a<b" is tokenized depends on whether it is
++// for a <p> tag or a <script> tag.
++//
++// The input is assumed to be UTF-8 encoded.
++func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
++      z := &Tokenizer{
++              r:   r,
++              buf: make([]byte, 0, 4096),
++      }
++      if contextTag != "" {
++              switch s := strings.ToLower(contextTag); s {
++              case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "title", "textarea", "xmp":
++                      z.rawTag = s
++              }
++      }
++      return z
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a36d112d74ed258d3839d2b8d243a70fdb86f424
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,917 @@@
++// Copyright 2010 The Go Authors. All rights reserved.
++// Use of this source code is governed by a BSD-style
++// license that can be found in the LICENSE file.
++
++package html
++
++import (
++      "bytes"
++      "io"
++      "os"
++      "reflect"
++      "runtime"
++      "strings"
++      "testing"
++)
++
++// https://github.com/golang/go/issues/58246
++const issue58246 = `<!--[if gte mso 12]>
++  <xml>
++      <o:OfficeDocumentSettings>
++      <o:AllowPNG/>
++      <o:PixelsPerInch>96</o:PixelsPerInch>
++      </o:OfficeDocumentSettings>
++    </xml>
++<![endif]-->`
++
++type tokenTest struct {
++      // A short description of the test case.
++      desc string
++      // The HTML to parse.
++      html string
++      // The string representations of the expected tokens, joined by '$'.
++      golden string
++}
++
++var tokenTests = []tokenTest{
++      {
++              "empty",
++              "",
++              "",
++      },
++      // A single text node. The tokenizer should not break text nodes on whitespace,
++      // nor should it normalize whitespace within a text node.
++      {
++              "text",
++              "foo  bar",
++              "foo  bar",
++      },
++      // An entity.
++      {
++              "entity",
++              "one &lt; two",
++              "one &lt; two",
++      },
++      // A start, self-closing and end tag. The tokenizer does not care if the start
++      // and end tokens don't match; that is the job of the parser.
++      {
++              "tags",
++              "<a>b<c/>d</e>",
++              "<a>$b$<c/>$d$</e>",
++      },
++      // Angle brackets that aren't a tag.
++      {
++              "not a tag #0",
++              "<",
++              "&lt;",
++      },
++      {
++              "not a tag #1",
++              "</",
++              "&lt;/",
++      },
++      {
++              "not a tag #2",
++              "</>",
++              "<!---->",
++      },
++      {
++              "not a tag #3",
++              "a</>b",
++              "a$<!---->$b",
++      },
++      {
++              "not a tag #4",
++              "</ >",
++              "<!-- -->",
++      },
++      {
++              "not a tag #5",
++              "</.",
++              "<!--.-->",
++      },
++      {
++              "not a tag #6",
++              "</.>",
++              "<!--.-->",
++      },
++      {
++              "not a tag #7",
++              "a < b",
++              "a &lt; b",
++      },
++      {
++              "not a tag #8",
++              "<.>",
++              "&lt;.&gt;",
++      },
++      {
++              "not a tag #9",
++              "a<<<b>>>c",
++              "a&lt;&lt;$<b>$&gt;&gt;c",
++      },
++      {
++              "not a tag #10",
++              "if x<0 and y < 0 then x*y>0",
++              "if x&lt;0 and y &lt; 0 then x*y&gt;0",
++      },
++      {
++              "not a tag #11",
++              "<<p>",
++              "&lt;$<p>",
++      },
++      // EOF in a tag name.
++      {
++              "tag name eof #0",
++              "<a",
++              "",
++      },
++      {
++              "tag name eof #1",
++              "<a ",
++              "",
++      },
++      {
++              "tag name eof #2",
++              "a<b",
++              "a",
++      },
++      {
++              "tag name eof #3",
++              "<a><b",
++              "<a>",
++      },
++      {
++              "tag name eof #4",
++              `<a x`,
++              ``,
++      },
++      // Some malformed tags that are missing a '>'.
++      {
++              "malformed tag #0",
++              `<p</p>`,
++              `<p< p="">`,
++      },
++      {
++              "malformed tag #1",
++              `<p </p>`,
++              `<p <="" p="">`,
++      },
++      {
++              "malformed tag #2",
++              `<p id`,
++              ``,
++      },
++      {
++              "malformed tag #3",
++              `<p id=`,
++              ``,
++      },
++      {
++              "malformed tag #4",
++              `<p id=>`,
++              `<p id="">`,
++      },
++      {
++              "malformed tag #5",
++              `<p id=0`,
++              ``,
++      },
++      {
++              "malformed tag #6",
++              `<p id=0</p>`,
++              `<p id="0&lt;/p">`,
++      },
++      {
++              "malformed tag #7",
++              `<p id="0</p>`,
++              ``,
++      },
++      {
++              "malformed tag #8",
++              `<p id="0"</p>`,
++              `<p id="0" <="" p="">`,
++      },
++      {
++              "malformed tag #9",
++              `<p></p id`,
++              `<p>`,
++      },
++      // Raw text and RCDATA.
++      {
++              "basic raw text",
++              "<script><a></b></script>",
++              "<script>$&lt;a&gt;&lt;/b&gt;$</script>",
++      },
++      {
++              "unfinished script end tag",
++              "<SCRIPT>a</SCR",
++              "<script>$a&lt;/SCR",
++      },
++      {
++              "broken script end tag",
++              "<SCRIPT>a</SCR ipt>",
++              "<script>$a&lt;/SCR ipt&gt;",
++      },
++      {
++              "EOF in script end tag",
++              "<SCRIPT>a</SCRipt",
++              "<script>$a&lt;/SCRipt",
++      },
++      {
++              "scriptx end tag",
++              "<SCRIPT>a</SCRiptx",
++              "<script>$a&lt;/SCRiptx",
++      },
++      {
++              "' ' completes script end tag",
++              "<SCRIPT>a</SCRipt ",
++              "<script>$a",
++      },
++      {
++              "'>' completes script end tag",
++              "<SCRIPT>a</SCRipt>",
++              "<script>$a$</script>",
++      },
++      {
++              "self-closing script end tag",
++              "<SCRIPT>a</SCRipt/>",
++              "<script>$a$</script>",
++      },
++      {
++              "nested script tag",
++              "<SCRIPT>a</SCRipt<script>",
++              "<script>$a&lt;/SCRipt&lt;script&gt;",
++      },
++      {
++              "script end tag after unfinished",
++              "<SCRIPT>a</SCRipt</script>",
++              "<script>$a&lt;/SCRipt$</script>",
++      },
++      {
++              "script/style mismatched tags",
++              "<script>a</style>",
++              "<script>$a&lt;/style&gt;",
++      },
++      {
++              "style element with entity",
++              "<style>&apos;",
++              "<style>$&amp;apos;",
++      },
++      {
++              "textarea with tag",
++              "<textarea><div></textarea>",
++              "<textarea>$&lt;div&gt;$</textarea>",
++      },
++      {
++              "title with tag and entity",
++              "<title><b>K&amp;R C</b></title>",
++              "<title>$&lt;b&gt;K&amp;R C&lt;/b&gt;$</title>",
++      },
++      {
++              "title with trailing '&lt;' entity",
++              "<title>foobar<</title>",
++              "<title>$foobar&lt;$</title>",
++      },
++      // DOCTYPE tests.
++      {
++              "Proper DOCTYPE",
++              "<!DOCTYPE html>",
++              "<!DOCTYPE html>",
++      },
++      {
++              "DOCTYPE with no space",
++              "<!doctypehtml>",
++              "<!DOCTYPE html>",
++      },
++      {
++              "DOCTYPE with two spaces",
++              "<!doctype  html>",
++              "<!DOCTYPE html>",
++      },
++      {
++              "looks like DOCTYPE but isn't",
++              "<!DOCUMENT html>",
++              "<!--DOCUMENT html-->",
++      },
++      {
++              "DOCTYPE at EOF",
++              "<!DOCtype",
++              "<!DOCTYPE >",
++      },
++      // XML processing instructions.
++      {
++              "XML processing instruction",
++              "<?xml?>",
++              "<!--?xml?-->",
++      },
++      // Comments. See also func TestComments.
++      {
++              "comment0",
++              "abc<b><!-- skipme --></b>def",
++              "abc$<b>$<!-- skipme -->$</b>$def",
++      },
++      {
++              "comment1",
++              "a<!-->z",
++              "a$<!---->$z",
++      },
++      {
++              "comment2",
++              "a<!--->z",
++              "a$<!---->$z",
++      },
++      {
++              "comment3",
++              "a<!--x>-->z",
++              "a$<!--x>-->$z",
++      },
++      {
++              "comment4",
++              "a<!--x->-->z",
++              "a$<!--x-&gt;-->$z",
++      },
++      {
++              "comment5",
++              "a<!>z",
++              "a$<!---->$z",
++      },
++      {
++              "comment6",
++              "a<!->z",
++              "a$<!----->$z",
++      },
++      {
++              "comment7",
++              "a<!---<>z",
++              "a$<!---<>z-->",
++      },
++      {
++              "comment8",
++              "a<!--z",
++              "a$<!--z-->",
++      },
++      {
++              "comment9",
++              "a<!--z-",
++              "a$<!--z-->",
++      },
++      {
++              "comment10",
++              "a<!--z--",
++              "a$<!--z-->",
++      },
++      {
++              "comment11",
++              "a<!--z---",
++              "a$<!--z--->",
++      },
++      {
++              "comment12",
++              "a<!--z----",
++              "a$<!--z---->",
++      },
++      {
++              "comment13",
++              "a<!--x--!>z",
++              "a$<!--x-->$z",
++      },
++      {
++              "comment14",
++              "a<!--!-->z",
++              "a$<!--!-->$z",
++      },
++      {
++              "comment15",
++              "a<!-- !-->z",
++              "a$<!-- !-->$z",
++      },
++      {
++              "comment16",
++              "a<!--i\x00j-->z",
++              "a$<!--i\uFFFDj-->$z",
++      },
++      {
++              "comment17",
++              "a<!--\x00",
++              "a$<!--\uFFFD-->",
++      },
++      {
++              "comment18",
++              "a<!--<!-->z",
++              "a$<!--<!-->$z",
++      },
++      {
++              "comment19",
++              "a<!--<!--",
++              "a$<!--<!-->",
++      },
++      {
++              "comment20",
++              "a<!--ij--kl-->z",
++              "a$<!--ij--kl-->$z",
++      },
++      {
++              "comment21",
++              "a<!--ij--kl--!>z",
++              "a$<!--ij--kl-->$z",
++      },
++      {
++              "comment22",
++              "a<!--!--!<--!-->z",
++              "a$<!--!--!<--!-->$z",
++      },
++      {
++              "comment23",
++              "a<!--&gt;-->z",
++              "a$<!--&gt;-->$z",
++      },
++      {
++              "comment24",
++              "a<!--&gt;>x",
++              "a$<!--&gt;>x-->",
++      },
++      {
++              "comment25",
++              "a<!--&gt;&gt;",
++              "a$<!--&gt;>-->",
++      },
++      {
++              "comment26",
++              "a<!--&gt;&gt;-",
++              "a$<!--&gt;>-->",
++      },
++      {
++              "comment27",
++              "a<!--&gt;&gt;-->z",
++              "a$<!--&gt;>-->$z",
++      },
++      {
++              "comment28",
++              "a<!--&amp;&gt;-->z",
++              "a$<!--&amp;>-->$z",
++      },
++      {
++              "comment29",
++              "a<!--&amp;gt;-->z",
++              "a$<!--&amp;gt;-->$z",
++      },
++      {
++              "comment30",
++              "a<!--&nosuchentity;-->z",
++              "a$<!--&amp;nosuchentity;-->$z",
++      },
++      {
++              "comment31",
++              "a<!--i>>j-->z",
++              "a$<!--i>>j-->$z",
++      },
++      {
++              "comment32",
++              "a<!--i!>>j-->z",
++              "a$<!--i!&gt;>j-->$z",
++      },
++      // https://stackoverflow.design/email/base/mso/#targeting-specific-outlook-versions
++      // says "[For] Windows Outlook 2003 and above... conditional comments allow
++      // us to add bits of HTML that are only read by the Word-based versions of
++      // Outlook". These comments (with angle brackets) should pass through
++      // unchanged (by this Go package) when rendering.
++      //
++      // We should also still escape ">" as "&gt;" when necessary.
++      // https://github.com/golang/go/issues/48237
++      //
++      // The "your code" example below comes from that stackoverflow.design link
++      // above but note that it can contain angle-bracket-rich XML.
++      // https://github.com/golang/go/issues/58246
++      {
++              "issue48237CommentWithAmpgtsemi1",
++              "a<!--<p></p>&lt;!--[video]--&gt;-->z",
++              "a$<!--<p></p><!--[video]--&gt;-->$z",
++      },
++      {
++              "issue48237CommentWithAmpgtsemi2",
++              "a<!--<p></p>&lt;!--[video]--!&gt;-->z",
++              "a$<!--<p></p><!--[video]--!&gt;-->$z",
++      },
++      {
++              "issue58246MicrosoftOutlookComment1",
++              "a<!--[if mso]> your code <![endif]-->z",
++              "a$<!--[if mso]> your code <![endif]-->$z",
++      },
++      {
++              "issue58246MicrosoftOutlookComment2",
++              "a" + issue58246 + "z",
++              "a$" + issue58246 + "$z",
++      },
++      // An attribute with a backslash.
++      {
++              "backslash",
++              `<p id="a\"b">`,
++              `<p id="a\" b"="">`,
++      },
++      // Entities, tag name and attribute key lower-casing, and whitespace
++      // normalization within a tag.
++      {
++              "tricky",
++              "<p \t\n iD=\"a&quot;B\"  foo=\"bar\"><EM>te&lt;&amp;;xt</em></p>",
++              `<p id="a&#34;B" foo="bar">$<em>$te&lt;&amp;;xt$</em>$</p>`,
++      },
++      // A nonexistent entity. Tokenizing and converting back to a string should
++      // escape the "&" to become "&amp;".
++      {
++              "noSuchEntity",
++              `<a b="c&noSuchEntity;d">&lt;&alsoDoesntExist;&`,
++              `<a b="c&amp;noSuchEntity;d">$&lt;&amp;alsoDoesntExist;&amp;`,
++      },
++      {
++              "entity without semicolon",
++              `&notit;&notin;<a b="q=z&amp=5&notice=hello&not;=world">`,
++              `¬it;∉$<a b="q=z&amp;amp=5&amp;notice=hello¬=world">`,
++      },
++      {
++              "entity with digits",
++              "&frac12;",
++              "½",
++      },
++      // Attribute tests:
++      // http://dev.w3.org/html5/pf-summary/Overview.html#attributes
++      {
++              "Empty attribute",
++              `<input disabled FOO>`,
++              `<input disabled="" foo="">`,
++      },
++      {
++              "Empty attribute, whitespace",
++              `<input disabled FOO >`,
++              `<input disabled="" foo="">`,
++      },
++      {
++              "Unquoted attribute value",
++              `<input value=yes FOO=BAR>`,
++              `<input value="yes" foo="BAR">`,
++      },
++      {
++              "Unquoted attribute value, spaces",
++              `<input value = yes FOO = BAR>`,
++              `<input value="yes" foo="BAR">`,
++      },
++      {
++              "Unquoted attribute value, trailing space",
++              `<input value=yes FOO=BAR >`,
++              `<input value="yes" foo="BAR">`,
++      },
++      {
++              "Single-quoted attribute value",
++              `<input value='yes' FOO='BAR'>`,
++              `<input value="yes" foo="BAR">`,
++      },
++      {
++              "Single-quoted attribute value, trailing space",
++              `<input value='yes' FOO='BAR' >`,
++              `<input value="yes" foo="BAR">`,
++      },
++      {
++              "Double-quoted attribute value",
++              `<input value="I'm an attribute" FOO="BAR">`,
++              `<input value="I&#39;m an attribute" foo="BAR">`,
++      },
++      {
++              "Attribute name characters",
++              `<meta http-equiv="content-type">`,
++              `<meta http-equiv="content-type">`,
++      },
++      {
++              "Mixed attributes",
++              `a<P V="0 1" w='2' X=3 y>z`,
++              `a$<p v="0 1" w="2" x="3" y="">$z`,
++      },
++      {
++              "Attributes with a solitary single quote",
++              `<p id=can't><p id=won't>`,
++              `<p id="can&#39;t">$<p id="won&#39;t">`,
++      },
++      // WHATWG 13.2.5.32 equals sign before attribute name state
++      {
++              "equals sign before attribute name",
++              `<p  =>`,
++              `<p =="">`,
++      },
++      {
++              "equals sign before attribute name, extra cruft",
++              `<p  =asd>`,
++              `<p =asd="">`,
++      },
++      {
++              "forward slash before attribute name",
++              `<p/=">`,
++              `<p ="="">`,
++      },
++      {
++              "forward slash before attribute name with spaces around",
++              `<p / =">`,
++              `<p ="="">`,
++      },
++      {
++              "forward slash after attribute name followed by a character",
++              `<p a/ ="">`,
++              `<p a="" =""="">`,
++      },
++}
++
++func TestTokenizer(t *testing.T) {
++      for _, tt := range tokenTests {
++              t.Run(tt.desc, func(t *testing.T) {
++                      z := NewTokenizer(strings.NewReader(tt.html))
++                      if tt.golden != "" {
++                              for i, s := range strings.Split(tt.golden, "$") {
++                                      if z.Next() == ErrorToken {
++                                              t.Errorf("%s token %d: want %q got error %v", tt.desc, i, s, z.Err())
++                                              return
++                                      }
++                                      actual := z.Token().String()
++                                      if s != actual {
++                                              t.Errorf("%s token %d: want %q got %q", tt.desc, i, s, actual)
++                                              return
++                                      }
++                              }
++                      }
++                      z.Next()
++                      if z.Err() != io.EOF {
++                              t.Errorf("%s: want EOF got %q", tt.desc, z.Err())
++                      }
++              })
++      }
++}
++
++func TestMaxBuffer(t *testing.T) {
++      // Exceeding the maximum buffer size generates ErrBufferExceeded.
++      z := NewTokenizer(strings.NewReader("<" + strings.Repeat("t", 10)))
++      z.SetMaxBuf(5)
++      tt := z.Next()
++      if got, want := tt, ErrorToken; got != want {
++              t.Fatalf("token type: got: %v want: %v", got, want)
++      }
++      if got, want := z.Err(), ErrBufferExceeded; got != want {
++              t.Errorf("error type: got: %v want: %v", got, want)
++      }
++      if got, want := string(z.Raw()), "<tttt"; got != want {
++              t.Fatalf("buffered before overflow: got: %q want: %q", got, want)
++      }
++}
++
++func TestMaxBufferReconstruction(t *testing.T) {
++      // Exceeding the maximum buffer size at any point while tokenizing permits
++      // reconstructing the original input.
++tests:
++      for _, test := range tokenTests {
++              for maxBuf := 1; ; maxBuf++ {
++                      r := strings.NewReader(test.html)
++                      z := NewTokenizer(r)
++                      z.SetMaxBuf(maxBuf)
++                      var tokenized bytes.Buffer
++                      for {
++                              tt := z.Next()
++                              tokenized.Write(z.Raw())
++                              if tt == ErrorToken {
++                                      if err := z.Err(); err != io.EOF && err != ErrBufferExceeded {
++                                              t.Errorf("%s: unexpected error: %v", test.desc, err)
++                                      }
++                                      break
++                              }
++                      }
++                      // Anything tokenized along with untokenized input or data left in the reader.
++                      assembled, err := io.ReadAll(io.MultiReader(&tokenized, bytes.NewReader(z.Buffered()), r))
++                      if err != nil {
++                              t.Errorf("%s: ReadAll: %v", test.desc, err)
++                              continue tests
++                      }
++                      if got, want := string(assembled), test.html; got != want {
++                              t.Errorf("%s: reassembled html:\n got: %q\nwant: %q", test.desc, got, want)
++                              continue tests
++                      }
++                      // EOF indicates that we completed tokenization and hence found the max
++                      // maxBuf that generates ErrBufferExceeded, so continue to the next test.
++                      if z.Err() == io.EOF {
++                              break
++                      }
++              } // buffer sizes
++      } // tests
++}
++
++func TestPassthrough(t *testing.T) {
++      // Accumulating the raw output for each parse event should reconstruct the
++      // original input.
++      for _, test := range tokenTests {
++              z := NewTokenizer(strings.NewReader(test.html))
++              var parsed bytes.Buffer
++              for {
++                      tt := z.Next()
++                      parsed.Write(z.Raw())
++                      if tt == ErrorToken {
++                              break
++                      }
++              }
++              if got, want := parsed.String(), test.html; got != want {
++                      t.Errorf("%s: parsed output:\n got: %q\nwant: %q", test.desc, got, want)
++              }
++      }
++}
++
++func TestBufAPI(t *testing.T) {
++      s := "0<a>1</a>2<b>3<a>4<a>5</a>6</b>7</a>8<a/>9"
++      z := NewTokenizer(bytes.NewBufferString(s))
++      var result bytes.Buffer
++      depth := 0
++loop:
++      for {
++              tt := z.Next()
++              switch tt {
++              case ErrorToken:
++                      if z.Err() != io.EOF {
++                              t.Error(z.Err())
++                      }
++                      break loop
++              case TextToken:
++                      if depth > 0 {
++                              result.Write(z.Text())
++                      }
++              case StartTagToken, EndTagToken:
++                      tn, _ := z.TagName()
++                      if len(tn) == 1 && tn[0] == 'a' {
++                              if tt == StartTagToken {
++                                      depth++
++                              } else {
++                                      depth--
++                              }
++                      }
++              }
++      }
++      u := "14567"
++      v := string(result.Bytes())
++      if u != v {
++              t.Errorf("TestBufAPI: want %q got %q", u, v)
++      }
++}
++
++func TestConvertNewlines(t *testing.T) {
++      testCases := map[string]string{
++              "Mac\rDOS\r\nUnix\n":    "Mac\nDOS\nUnix\n",
++              "Unix\nMac\rDOS\r\n":    "Unix\nMac\nDOS\n",
++              "DOS\r\nDOS\r\nDOS\r\n": "DOS\nDOS\nDOS\n",
++              "":                      "",
++              "\n":                    "\n",
++              "\n\r":                  "\n\n",
++              "\r":                    "\n",
++              "\r\n":                  "\n",
++              "\r\n\n":                "\n\n",
++              "\r\n\r":                "\n\n",
++              "\r\n\r\n":              "\n\n",
++              "\r\r":                  "\n\n",
++              "\r\r\n":                "\n\n",
++              "\r\r\n\n":              "\n\n\n",
++              "\r\r\r\n":              "\n\n\n",
++              "\r \n":                 "\n \n",
++              "xyz":                   "xyz",
++      }
++      for in, want := range testCases {
++              if got := string(convertNewlines([]byte(in))); got != want {
++                      t.Errorf("input %q: got %q, want %q", in, got, want)
++              }
++      }
++}
++
++func TestReaderEdgeCases(t *testing.T) {
++      const s = "<p>An io.Reader can return (0, nil) or (n, io.EOF).</p>"
++      testCases := []io.Reader{
++              &zeroOneByteReader{s: s},
++              &eofStringsReader{s: s},
++              &stuckReader{},
++      }
++      for i, tc := range testCases {
++              got := []TokenType{}
++              z := NewTokenizer(tc)
++              for {
++                      tt := z.Next()
++                      if tt == ErrorToken {
++                              break
++                      }
++                      got = append(got, tt)
++              }
++              if err := z.Err(); err != nil && err != io.EOF {
++                      if err != io.ErrNoProgress {
++                              t.Errorf("i=%d: %v", i, err)
++                      }
++                      continue
++              }
++              want := []TokenType{
++                      StartTagToken,
++                      TextToken,
++                      EndTagToken,
++              }
++              if !reflect.DeepEqual(got, want) {
++                      t.Errorf("i=%d: got %v, want %v", i, got, want)
++                      continue
++              }
++      }
++}
++
++// zeroOneByteReader is like a strings.Reader that alternates between
++// returning 0 bytes and 1 byte at a time.
++type zeroOneByteReader struct {
++      s string
++      n int
++}
++
++func (r *zeroOneByteReader) Read(p []byte) (int, error) {
++      if len(p) == 0 {
++              return 0, nil
++      }
++      if len(r.s) == 0 {
++              return 0, io.EOF
++      }
++      r.n++
++      if r.n%2 != 0 {
++              return 0, nil
++      }
++      p[0], r.s = r.s[0], r.s[1:]
++      return 1, nil
++}
++
++// eofStringsReader is like a strings.Reader but can return an (n, err) where
++// n > 0 && err != nil.
++type eofStringsReader struct {
++      s string
++}
++
++func (r *eofStringsReader) Read(p []byte) (int, error) {
++      n := copy(p, r.s)
++      r.s = r.s[n:]
++      if r.s != "" {
++              return n, nil
++      }
++      return n, io.EOF
++}
++
++// stuckReader is an io.Reader that always returns no data and no error.
++type stuckReader struct{}
++
++func (*stuckReader) Read(p []byte) (int, error) {
++      return 0, nil
++}
++
++const (
++      rawLevel = iota
++      lowLevel
++      highLevel
++)
++
++func benchmarkTokenizer(b *testing.B, level int) {
++      buf, err := os.ReadFile("testdata/go1.html")
++      if err != nil {
++              b.Fatalf("could not read testdata/go1.html: %v", err)
++      }
++      b.SetBytes(int64(len(buf)))
++      runtime.GC()
++      b.ReportAllocs()
++      b.ResetTimer()
++      for i := 0; i < b.N; i++ {
++              z := NewTokenizer(bytes.NewBuffer(buf))
++              for {
++                      tt := z.Next()
++                      if tt == ErrorToken {
++                              if err := z.Err(); err != nil && err != io.EOF {
++                                      b.Fatalf("tokenizer error: %v", err)
++                              }
++                              break
++                      }
++                      switch level {
++                      case rawLevel:
++                              // Calling z.Raw just returns the raw bytes of the token. It does
++                              // not unescape &lt; to <, or lower-case tag names and attribute keys.
++                              z.Raw()
++                      case lowLevel:
++                              // Caling z.Text, z.TagName and z.TagAttr returns []byte values
++                              // whose contents may change on the next call to z.Next.
++                              switch tt {
++                              case TextToken, CommentToken, DoctypeToken:
++                                      z.Text()
++                              case StartTagToken, SelfClosingTagToken:
++                                      _, more := z.TagName()
++                                      for more {
++                                              _, _, more = z.TagAttr()
++                                      }
++                              case EndTagToken:
++                                      z.TagName()
++                              }
++                      case highLevel:
++                              // Calling z.Token converts []byte values to strings whose validity
++                              // extend beyond the next call to z.Next.
++                              z.Token()
++                      }
++              }
++      }
++}
++
++func BenchmarkRawLevelTokenizer(b *testing.B)  { benchmarkTokenizer(b, rawLevel) }
++func BenchmarkLowLevelTokenizer(b *testing.B)  { benchmarkTokenizer(b, lowLevel) }
++func BenchmarkHighLevelTokenizer(b *testing.B) { benchmarkTokenizer(b, highLevel) }
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..95879e7d7723437211ace35ba2005aad310f294f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,185 @@@
++// Copyright (C) 2024 early (LGPL)
++package page
++
++import (
++      "context"
++      "html/template"
++      "path/filepath"
++      "strings"
++
++      "git.earlybird.gay/today-engine/htmltree"
++      "git.earlybird.gay/today-engine/include"
++      "git.earlybird.gay/today-engine/internal/compile"
++      "git.earlybird.gay/today-engine/part"
++      "git.earlybird.gay/today-engine/render"
++)
++
++type Page struct {
++      name   string
++      source include.Opener
++      raw    string
++
++      includes []compile.Source
++      onLoad   render.OnLoadFunc
++      indent   string
++
++      template      *template.Template
++      templateFuncs template.FuncMap
++      templateLoad  render.Loader
++
++      err error
++}
++
++type Config func(*Page)
++
++func Name(name string) Config {
++      return func(p *Page) {
++              p.name = name
++      }
++}
++
++func Source(source string) Config {
++      return func(p *Page) {
++              p.source = include.File(source, "git.earlybird.gay/today-engine/part")
++      }
++}
++
++func Funcs(funcs template.FuncMap) Config {
++      return func(p *Page) {
++              for name, f := range funcs {
++                      p.templateFuncs[name] = f
++              }
++      }
++}
++
++func Includes(includes ...compile.Source) Config {
++      return func(p *Page) {
++              p.includes = includes
++      }
++}
++
++func OnLoad(f render.OnLoadFunc) Config {
++      return func(p *Page) {
++              p.onLoad = f
++      }
++}
++
++func Pretty(indent string) Config {
++      return func(p *Page) {
++              p.indent = indent
++      }
++}
++
++func New(name string, source string, optional ...func(*Page)) *Page {
++      p := new(Page)
++      // Assign basic parameters
++      p.name = name
++      p.source = include.File(source, "git.earlybird.gay/today-engine/page")
++      p.onLoad = func(ctx context.Context, d render.Data) error {
++              return nil
++      }
++      p.templateFuncs = make(template.FuncMap)
++      // Run optional arguments
++      for _, of := range optional {
++              of(p)
++      }
++      // parse
++      // compile from assembled sources
++      sourceTransform := htmltree.Minify()
++      if p.indent != "" {
++              sourceTransform = htmltree.Prettify(p.indent)
++      }
++      result, err := compile.Compile(p, sourceTransform)
++      if err != nil {
++              p.err = err
++              return p
++      }
++      p.raw = result.TemplateRaw
++      p.templateLoad = result.TemplateDataLoader
++
++      // templatize
++      p.template, err = template.New(p.name).
++              Funcs(result.TemplateFuncs).
++              Parse(result.TemplateRaw)
++      if err != nil {
++              p.err = err
++              return p
++      }
++      return p
++}
++
++// Static returns a new Page that is just the passed source file, with no
++// additional options/parts/etc.
++func Static(source string) *Page {
++      filename := filepath.Base(source)
++      name := strings.TrimSuffix(filename, filepath.Ext(filename))
++      return New(name, source)
++}
++
++// With returns a shallow copy of p with all of optional applied to it.
++func (p *Page) With(optional ...func(*Page)) *Page {
++      q := &Page{
++              name:   p.name,
++              source: p.source,
++
++              includes:      p.includes,
++              onLoad:        p.onLoad,
++              templateFuncs: p.templateFuncs,
++      }
++
++      for _, of := range optional {
++              of(q)
++      }
++      return q
++}
++
++// Getters
++// These are mostly to implement interfaces that make pages usable around the
++// project.
++
++func (p *Page) Name() string {
++      return p.name
++}
++
++func (p *Page) Source() include.Opener {
++      return p.source
++}
++
++// FileDependencies returns a list of absolute paths to files that are used in
++// this page and its dependencies.
++func (p *Page) FileDependencies() []string {
++      out := make([]string, 0)
++      if fopener, ok := p.Source().(include.FileOpener); ok {
++              out = append(out, fopener.FileName())
++      }
++      for _, dep := range p.includes {
++              partDep, _ := dep.(*part.Part)
++              out = append(out, partDep.FileDependencies()...)
++      }
++      return out
++}
++
++// Pages are never included as a child, so this is always false.
++func (p *Page) IncludeTagName() bool {
++      return false
++}
++
++func (p *Page) TemplateFuncs() template.FuncMap {
++      return p.templateFuncs
++}
++
++func (p *Page) OnLoad() render.OnLoadFunc {
++      return p.onLoad
++}
++
++func (p *Page) Includes() []compile.Source {
++      return p.includes
++}
++
++func (p *Page) Raw() string {
++      return p.raw
++}
++
++func (p *Page) Error() error {
++      return p.err
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ad05884f38bc10a3eea58048d58903adf48d67de
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,30 @@@
++// Copyright (C) 2024 early (LGPL)
++package page
++
++import (
++      "net/http"
++
++      "git.earlybird.gay/today-engine/render"
++)
++
++type RootData struct {
++      SetDot func(value any) error
++
++      Data render.Data
++}
++
++func (p *Page) ServeHTTP(w http.ResponseWriter, r *http.Request) {
++      data, setDot, err := p.templateLoad.Compute(r)
++      if err != nil {
++              panic(err)
++      }
++      root := RootData{
++              SetDot: setDot,
++
++              Data: data,
++      }
++      err = p.template.Execute(w, root)
++      if err != nil {
++              panic(err)
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ed808cfaab1ce2b5c4139b6f7521e19dde5591d6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,136 @@@
++// Copyright (C) 2024 early (LGPL)
++package part
++
++import (
++      "context"
++      "text/template"
++
++      "git.earlybird.gay/today-engine/include"
++      "git.earlybird.gay/today-engine/internal/compile"
++      "git.earlybird.gay/today-engine/render"
++)
++
++type Part struct {
++      name   string
++      source include.Opener
++
++      noTag         bool
++      includes      []compile.Source
++      onLoad        render.OnLoadFunc
++      templateFuncs template.FuncMap
++}
++
++type Config func(*Part)
++
++func Name(name string) Config {
++      return func(p *Part) {
++              p.name = name
++      }
++}
++
++func Source(source string) Config {
++      return func(p *Part) {
++              p.source = include.File(source, "git.earlybird.gay/today-engine/part")
++      }
++}
++
++func Funcs(funcs template.FuncMap) Config {
++      return func(p *Part) {
++              for name, f := range funcs {
++                      p.templateFuncs[name] = f
++              }
++      }
++}
++
++func Includes(includes ...compile.Source) Config {
++      return func(p *Part) {
++              p.includes = includes
++      }
++}
++
++func OnLoad(f render.OnLoadFunc) Config {
++      return func(p *Part) {
++              p.onLoad = f
++      }
++}
++
++// Tag(false) will disable the inclusion of the "custom tag" for this part.
++// When using Web Components, the user-defined name is included in the HTML
++// document. This is also the default behavior for template parts, but you may
++// disable it with this config when it causes problems.
++func Tag(useTag bool) Config {
++      return func(p *Part) {
++              p.noTag = !useTag
++      }
++}
++
++func New(name string, source string, optional ...func(*Part)) *Part {
++      p := new(Part)
++      // Assign basic parameters
++      p.name = name
++      p.source = include.File(source, "git.earlybird.gay/today-engine/part")
++      p.onLoad = func(ctx context.Context, data render.Data) error {
++              return nil
++      }
++      p.templateFuncs = make(template.FuncMap)
++      // Run optional arguments
++      for _, of := range optional {
++              of(p)
++      }
++      return p
++}
++
++// With returns a shallow copy of p with all of optional applied to it.
++func (p *Part) With(optional ...func(*Part)) *Part {
++      q := &Part{
++              name:   p.name,
++              source: p.source,
++
++              includes:      p.includes,
++              onLoad:        p.onLoad,
++              templateFuncs: p.templateFuncs,
++      }
++
++      for _, of := range optional {
++              of(q)
++      }
++      return q
++}
++
++func (p *Part) Name() string {
++      return p.name
++}
++
++func (p *Part) Source() include.Opener {
++      return p.source
++}
++
++// FileDependencies returns a list of absolute paths to files that are used in
++// this part and its dependencies.
++func (p *Part) FileDependencies() []string {
++      out := make([]string, 0)
++      if fopener, ok := p.Source().(include.FileOpener); ok {
++              out = append(out, fopener.FileName())
++      }
++      for _, dep := range p.includes {
++              partDep, _ := dep.(*Part)
++              out = append(out, partDep.FileDependencies()...)
++      }
++      return out
++}
++
++func (p *Part) IncludeTagName() bool {
++      return !p.noTag
++}
++
++func (p *Part) TemplateFuncs() template.FuncMap {
++      return p.templateFuncs
++}
++
++func (p *Part) OnLoad() render.OnLoadFunc {
++      return p.onLoad
++}
++
++func (p *Part) Includes() []compile.Source {
++      return p.includes
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3f9fe9feb2269d3962413bcb7e7c04e678b01a81
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,53 @@@
++// Copyright (C) 2024 early (LGPL)
++package render
++
++import (
++      "context"
++      "net/http"
++      "regexp"
++)
++
++var keyRegexp = regexp.MustCompile(`^[a-zA-Z]\w+$`)
++
++type Data map[string]any
++
++func NewData(r *http.Request) Data {
++      d := make(Data)
++      d.Set("request", r)
++      return d
++}
++
++func (d Data) Get(key string) any {
++      return d[key]
++}
++
++func (d Data) IsSet(key string) bool {
++      _, ok := d[key]
++      return ok
++}
++
++func (d Data) Request() *http.Request {
++      return d.Get("request").(*http.Request)
++}
++
++// ID gets the *static* HTML id attribute of the component that owns this data.
++// If the ID cannot be determined at compile time, this returns an empty string.
++func (d Data) ID() string {
++      if id, ok := d.Get("id").(string); ok {
++              return id
++      }
++      return ""
++}
++
++// Set sets key to value.
++func (d Data) Set(key string, value any) {
++      if !keyRegexp.MatchString(key) {
++              panic("key " + key + " is not valid")
++      }
++      d[key] = value
++}
++
++type OnLoadFunc func(ctx context.Context, data Data) error
++type Loader interface {
++      Compute(r *http.Request) (Data, func(any) error, error)
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f5d6aa900a27b899ab2b8efdfa1898e224157317
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++// Copyright (C) 2024 early (LGPL)
++package render
++
++import "math/rand/v2"
++
++const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
++
++func ID() string {
++      id := make([]byte, 8)
++      id[0] = charset[rand.Int()%52]
++      for i := range 7 {
++              id[i+1] = charset[rand.Int()%62]
++      }
++      return string(id)
++}
diff --cc engine/run.go
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..94332b59f266eb9e8a575779e1bac615a6c21dc3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,61 @@@
++// Copyright (C) 2024 early (LGPL)
++package engine
++
++import (
++      "context"
++      "errors"
++      "fmt"
++      "net/http"
++      "os"
++      "os/signal"
++      "sync"
++      "syscall"
++)
++
++func Run(handler http.Handler) error {
++      fmt.Println("starting app")
++
++      wg := new(sync.WaitGroup)
++      errc := make(chan error, 1)
++
++      // Start main HTTP server
++      serv := new(http.Server)
++      serv.Addr = "0.0.0.0:3000"
++      serv.Handler = handler
++      wg.Add(1)
++      go func() {
++              err := serv.ListenAndServe()
++              if !errors.Is(err, http.ErrServerClosed) {
++                      errc <- err
++              }
++              wg.Done()
++      }()
++      fmt.Println("app available")
++
++      // Listening channel for interrupts
++      sigc := make(chan os.Signal, 1)
++      signal.Notify(sigc, syscall.SIGINT, syscall.SIGTERM)
++
++      // Await a reason to terminate application
++      wg.Add(1)
++      go func() {
++      await:
++              for {
++                      select {
++                      case sig := <-sigc:
++                              fmt.Println("received OS signal, shutting down", "signal", sig.String())
++                              break await
++                      case err := <-errc:
++                              fmt.Println("application encountered a fatal error", "detail", err.Error())
++                              break await
++                      }
++              }
++              // This may have happened already, but we need to be sure.
++              serv.Shutdown(context.Background())
++              wg.Done()
++      }()
++
++      wg.Wait()
++      fmt.Println("application shut down")
++      return nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f8aae3674447ca2029def131c4cf1ccb166e9b96
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,109 @@@
++package stdpart
++
++import (
++      "context"
++      "errors"
++      "fmt"
++      "net/http"
++      "net/url"
++
++      "git.earlybird.gay/today-engine/part"
++      "git.earlybird.gay/today-engine/render"
++)
++
++var (
++      ErrFormValidation = errors.New("form input is invalid")
++)
++
++func Err(base error, reason string) error {
++      return errors.Join(base, errors.New(reason))
++}
++
++type ContactFormResponse struct {
++      ID       string
++      Name     string
++      Contact  string
++      Category string
++      Content  string
++}
++
++func parseContactFormResponse(r *http.Request) (ContactFormResponse, error) {
++      resp := ContactFormResponse{}
++      err := r.ParseForm()
++      if err != nil {
++              return resp, err
++      }
++      f := r.Form
++
++      resp.ID = f.Get("id")
++      resp.Name = f.Get("name")
++      resp.Contact = f.Get("contact")
++      resp.Category = f.Get("category")
++      resp.Content = f.Get("content")
++
++      return resp, nil
++}
++
++func ContactForm(categories []string) *part.Part {
++      return part.New("stdp-contact-form", "contact_form.html",
++              part.OnLoad(func(ctx context.Context, data render.Data) error {
++                      data.Set("categories", categories)
++
++                      // Set message if one is given for this part
++                      r := data.Request()
++                      q := r.URL.Query()
++                      id := data.ID()
++
++                      if q.Get("resp_to") == id {
++                              message, err := url.QueryUnescape(q.Get("message"))
++                              if err != nil {
++                                      message = "invalid response message from server"
++                              }
++                              data.Set("message", map[string]any{
++                                      "success": q.Get("success") == "true",
++                                      "message": message,
++                              })
++                      }
++                      return nil
++              }),
++      )
++}
++
++func HandleContactForm(validate, handle func(ContactFormResponse) error) http.Handler {
++      return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
++              resp, err := parseContactFormResponse(r)
++              callback := r.FormValue("callback")
++              respond := func(ok bool, msg string) {
++                      msg = url.QueryEscape(msg)
++                      redirect := fmt.Sprintf("%s?success=%t&message=%s", callback, ok, msg)
++                      if resp.ID != "" {
++                              redirect += fmt.Sprintf("&resp_to=%s", resp.ID)
++                      }
++                      w.Header().Set("Location", redirect)
++                      w.WriteHeader(http.StatusSeeOther)
++              }
++              if err != nil {
++                      respond(false, "unexpected error, please try again later")
++                      return
++              }
++
++              if validate != nil {
++                      err = validate(resp)
++                      if err != nil {
++                              respond(false, err.Error())
++                      }
++              }
++
++              err = handle(resp)
++              if err != nil {
++                      respond(false, "unexpected error, please try again later")
++              }
++
++              respond(true, "message sent")
++      })
++}
++
++func PrintContact(resp ContactFormResponse) error {
++      fmt.Printf("%+v\n", resp)
++      return nil
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9cbc6aeabd921d51051ee318e1a303c65d0dc729
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,28 @@@
++<template>
++  {{- $id := "contact-form" -}}
++  {{- if .id }}{{ $id = .id }}{{ end -}}
++  <form action="{{.action}}"
++    {{ with .method }}method="{{.}}"{{ end }}>
++    <input type="hidden" id="{{$id}}-callback" name="callback" value="{{.request.URL.Path}}">
++    <input type="hidden" id="{{$id}}-id" name="id" value="{{.id}}">
++    <label for="{{$id}}-name">Name:</label>
++    <input type="text" name="name" id="{{$id}}-name">
++    <label for="{{$id}}-contact">Contact Info:</label>
++    <input type="text" name="contact" id="{{$id}}-contact">
++    {{- with .categories }}
++    <label for="{{$id}}-category">Category:</label>
++    <select name="category" id="{{$id}}-category">
++      <option value="">--Select a category--</option>
++      {{- range . }}
++      <option value="{{.}}">{{.}}</option>
++      {{ end -}}
++    </select>
++    {{ end -}}
++    <label for="{{$id}}-content">Message:</label>
++    <textarea name="content" id="{{$id}}-content"></textarea>
++    <input type="submit">
++  </form>
++  {{- with .message }}
++  <p class="{{ if .success }}success{{ else }}error{{ end }}">{{ .message }}</p>
++  {{ end -}}
++</template>