src/pkg/html/parse.go | 33 ++++++++++++++++++++++++++------- src/pkg/html/parse_test.go | 2 +- diff --git a/src/pkg/html/parse.go b/src/pkg/html/parse.go index d1d4e483c538e7a41867ec049e03fd768b987a40..292fbaf6be4be0039dad42c7ba885db547c96648 100644 --- a/src/pkg/html/parse.go +++ b/src/pkg/html/parse.go @@ -52,6 +52,11 @@ buttonScopeStopTags = []string{"applet", "caption", "html", "table", "td", "th", "marquee", "object", "button"} tableScopeStopTags = []string{"html", "table"} ) +// stopTags for use in clearStackToContext. +var ( + tableRowContextStopTags = []string{"tr", "html"} +) + // popUntil pops the stack of open elements at the highest element whose tag // is in matchTags, provided there is no higher element in stopTags. It returns // whether or not there was such an element. If there was not, popUntil leaves @@ -144,6 +149,11 @@ for i, child = range parent.Child { if child == table { break } + } + + if i > 0 && parent.Child[i-1].Type == TextNode && n.Type == TextNode { + parent.Child[i-1].Data += n.Data + return } if i == len(parent.Child) { @@ -749,11 +759,11 @@ // TODO. case StartTagToken: switch p.tok.Data { case "tbody", "tfoot", "thead": - p.clearStackToTableContext() + p.clearStackToContext(tableScopeStopTags) p.addElement(p.tok.Data, p.tok.Attr) return inTableBodyIM, true case "td", "th", "tr": - p.clearStackToTableContext() + p.clearStackToContext(tableScopeStopTags) p.addElement("tbody", nil) return inTableBodyIM, false case "table": @@ -794,11 +804,15 @@ return useTheRulesFor(p, inTableIM, inBodyIM) } -func (p *parser) clearStackToTableContext() { +// clearStackToContext pops elements off the stack of open elements +// until an element listed in stopTags is found. +func (p *parser) clearStackToContext(stopTags []string) { for i := len(p.oe) - 1; i >= 0; i-- { - if x := p.oe[i].Data; x == "table" || x == "html" { - p.oe = p.oe[:i+1] - return + for _, tag := range stopTags { + if p.oe[i].Data == tag { + p.oe = p.oe[:i+1] + return + } } } } @@ -877,7 +891,12 @@ } case EndTagToken: switch p.tok.Data { case "tr": - // TODO. + if !p.elementInScope(tableScopeStopTags, "tr") { + return inRowIM, true + } + p.clearStackToContext(tableRowContextStopTags) + p.oe.pop() + return inTableBodyIM, true case "table": if p.popUntil(tableScopeStopTags, "tr") { return inTableBodyIM, false diff --git a/src/pkg/html/parse_test.go b/src/pkg/html/parse_test.go index beba98d3ad2f5336d9f9d949e6bb77adfb5e5efc..865a47dea1d46d83d40e013057692e6022b068cb 100644 --- a/src/pkg/html/parse_test.go +++ b/src/pkg/html/parse_test.go @@ -132,7 +132,7 @@ for _, filename := range filenames { rc := make(chan io.Reader) go readDat(filename, rc) // TODO(nigeltao): Process all test cases, not just a subset. - for i := 0; i < 32; i++ { + for i := 0; i < 33; i++ { // Parse the #data section. b, err := ioutil.ReadAll(<-rc) if err != nil {