|
@@ -21,66 +21,92 @@ import (
|
|
|
"golang.org/x/net/html/atom"
|
|
"golang.org/x/net/html/atom"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+type testAttrs struct {
|
|
|
|
|
+ text, want, context string
|
|
|
|
|
+ scripting bool
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
// readParseTest reads a single test case from r.
|
|
// readParseTest reads a single test case from r.
|
|
|
-func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
|
|
|
|
|
|
|
+func readParseTest(r *bufio.Reader) (*testAttrs, error) {
|
|
|
|
|
+ ta := &testAttrs{scripting: true}
|
|
|
line, err := r.ReadSlice('\n')
|
|
line, err := r.ReadSlice('\n')
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
var b []byte
|
|
var b []byte
|
|
|
|
|
|
|
|
// Read the HTML.
|
|
// Read the HTML.
|
|
|
if string(line) != "#data\n" {
|
|
if string(line) != "#data\n" {
|
|
|
- return "", "", "", fmt.Errorf(`got %q want "#data\n"`, line)
|
|
|
|
|
|
|
+ return nil, fmt.Errorf(`got %q want "#data\n"`, line)
|
|
|
}
|
|
}
|
|
|
for {
|
|
for {
|
|
|
line, err = r.ReadSlice('\n')
|
|
line, err = r.ReadSlice('\n')
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
if line[0] == '#' {
|
|
if line[0] == '#' {
|
|
|
break
|
|
break
|
|
|
}
|
|
}
|
|
|
b = append(b, line...)
|
|
b = append(b, line...)
|
|
|
}
|
|
}
|
|
|
- text = strings.TrimSuffix(string(b), "\n")
|
|
|
|
|
|
|
+ ta.text = strings.TrimSuffix(string(b), "\n")
|
|
|
b = b[:0]
|
|
b = b[:0]
|
|
|
|
|
|
|
|
// Skip the error list.
|
|
// Skip the error list.
|
|
|
if string(line) != "#errors\n" {
|
|
if string(line) != "#errors\n" {
|
|
|
- return "", "", "", fmt.Errorf(`got %q want "#errors\n"`, line)
|
|
|
|
|
|
|
+ return nil, fmt.Errorf(`got %q want "#errors\n"`, line)
|
|
|
}
|
|
}
|
|
|
for {
|
|
for {
|
|
|
line, err = r.ReadSlice('\n')
|
|
line, err = r.ReadSlice('\n')
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
if line[0] == '#' {
|
|
if line[0] == '#' {
|
|
|
break
|
|
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" {
|
|
if string(line) == "#document-fragment\n" {
|
|
|
line, err = r.ReadSlice('\n')
|
|
line, err = r.ReadSlice('\n')
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
- context = strings.TrimSpace(string(line))
|
|
|
|
|
|
|
+ ta.context = strings.TrimSpace(string(line))
|
|
|
line, err = r.ReadSlice('\n')
|
|
line, err = r.ReadSlice('\n')
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// Read the dump of what the parse tree should be.
|
|
// Read the dump of what the parse tree should be.
|
|
|
if string(line) != "#document\n" {
|
|
if string(line) != "#document\n" {
|
|
|
- return "", "", "", fmt.Errorf(`got %q want "#document\n"`, line)
|
|
|
|
|
|
|
+ return nil, fmt.Errorf(`got %q want "#document\n"`, line)
|
|
|
}
|
|
}
|
|
|
inQuote := false
|
|
inQuote := false
|
|
|
for {
|
|
for {
|
|
|
line, err = r.ReadSlice('\n')
|
|
line, err = r.ReadSlice('\n')
|
|
|
if err != nil && err != io.EOF {
|
|
if err != nil && err != io.EOF {
|
|
|
- return "", "", "", err
|
|
|
|
|
|
|
+ return nil, err
|
|
|
}
|
|
}
|
|
|
trimmed := bytes.Trim(line, "| \n")
|
|
trimmed := bytes.Trim(line, "| \n")
|
|
|
if len(trimmed) > 0 {
|
|
if len(trimmed) > 0 {
|
|
@@ -96,7 +122,8 @@ func readParseTest(r *bufio.Reader) (text, want, context string, err error) {
|
|
|
}
|
|
}
|
|
|
b = append(b, line...)
|
|
b = append(b, line...)
|
|
|
}
|
|
}
|
|
|
- return text, string(b), context, nil
|
|
|
|
|
|
|
+ ta.want = string(b)
|
|
|
|
|
+ return ta, nil
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func dumpIndent(w io.Writer, level int) {
|
|
func dumpIndent(w io.Writer, level int) {
|
|
@@ -220,7 +247,7 @@ func TestParser(t *testing.T) {
|
|
|
r := bufio.NewReader(f)
|
|
r := bufio.NewReader(f)
|
|
|
|
|
|
|
|
for i := 0; ; i++ {
|
|
for i := 0; ; i++ {
|
|
|
- text, want, context, err := readParseTest(r)
|
|
|
|
|
|
|
+ ta, err := readParseTest(r)
|
|
|
if err == io.EOF {
|
|
if err == io.EOF {
|
|
|
break
|
|
break
|
|
|
}
|
|
}
|
|
@@ -228,10 +255,10 @@ func TestParser(t *testing.T) {
|
|
|
t.Fatal(err)
|
|
t.Fatal(err)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- err = testParseCase(text, want, context)
|
|
|
|
|
|
|
+ err = testParseCase(ta.text, ta.want, ta.context, ParseOptionEnableScripting(ta.scripting))
|
|
|
|
|
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
- t.Errorf("%s test #%d %q, %s", tf, i, text, err)
|
|
|
|
|
|
|
+ t.Errorf("%s test #%d %q, %s", tf, i, ta.text, err)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -319,7 +346,7 @@ func testParseCase(text, want, context string, opts ...ParseOption) (err error)
|
|
|
go func() {
|
|
go func() {
|
|
|
pw.CloseWithError(Render(pw, doc))
|
|
pw.CloseWithError(Render(pw, doc))
|
|
|
}()
|
|
}()
|
|
|
- doc1, err := Parse(pr)
|
|
|
|
|
|
|
+ doc1, err := ParseWithOptions(pr, opts...)
|
|
|
if err != nil {
|
|
if err != nil {
|
|
|
return err
|
|
return err
|
|
|
}
|
|
}
|