From c64e8e327ec706c4ac9ac767273e08a5175b5ec8 Mon Sep 17 00:00:00 2001 From: Andrew Balholm Date: Thu, 13 Oct 2011 12:40:48 +1100 Subject: [PATCH] html: insert implied

and

tags (test # 25 in tests1.dat) #data

X #document | | | |

| |

| | |

| "X" R=nigeltao CC=golang-dev https://golang.org/cl/5254060 --- src/pkg/html/parse.go | 60 +++++++++++++++++++++++--------------- src/pkg/html/parse_test.go | 2 +- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/pkg/html/parse.go b/src/pkg/html/parse.go index 519ebe587b..d476f4ac21 100644 --- a/src/pkg/html/parse.go +++ b/src/pkg/html/parse.go @@ -64,21 +64,37 @@ var ( // popUntil([]string{"html, "table"}, "table") would return true and leave: // ["html", "body", "font"] func (p *parser) popUntil(stopTags []string, matchTags ...string) bool { + if i := p.indexOfElementInScope(stopTags, 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 according to stopTags. +// If no matching element is in scope, it returns -1. +func (p *parser) indexOfElementInScope(stopTags []string, matchTags ...string) int { for i := len(p.oe) - 1; i >= 0; i-- { tag := p.oe[i].Data for _, t := range matchTags { if t == tag { - p.oe = p.oe[:i] - return true + return i } } for _, t := range stopTags { if t == tag { - return false + return -1 } } } - return false + return -1 +} + +// elementInScope is like popUntil, except that it doesn't modify the stack of +// open elements. +func (p *parser) elementInScope(stopTags []string, matchTags ...string) bool { + return p.indexOfElementInScope(stopTags, matchTags...) != -1 } // addChild adds a child node n to the top element, and pushes n onto the stack @@ -365,7 +381,6 @@ func afterHeadIM(p *parser) (insertionMode, bool) { // Section 11.2.5.4.7. func inBodyIM(p *parser) (insertionMode, bool) { - var endP bool switch p.tok.Type { case TextToken: p.reconstructActiveFormattingElements() @@ -374,15 +389,10 @@ func inBodyIM(p *parser) (insertionMode, bool) { case StartTagToken: switch p.tok.Data { case "address", "article", "aside", "blockquote", "center", "details", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "menu", "nav", "ol", "p", "section", "summary", "ul": - // TODO: Do the proper "does the stack of open elements has a p element in button scope" algorithm in section 11.2.3.2. - n := p.top() - if n.Type == ElementNode && n.Data == "p" { - endP = true - } else { - p.addElement(p.tok.Data, p.tok.Attr) - } + p.popUntil(buttonScopeStopTags, "p") + p.addElement(p.tok.Data, p.tok.Attr) case "h1", "h2", "h3", "h4", "h5", "h6": - // TODO: auto-insert

if necessary. + p.popUntil(buttonScopeStopTags, "p") switch n := p.top(); n.Data { case "h1", "h2", "h3", "h4", "h5", "h6": p.oe.pop() @@ -399,6 +409,11 @@ func inBodyIM(p *parser) (insertionMode, bool) { case "b", "big", "code", "em", "font", "i", "s", "small", "strike", "strong", "tt", "u": p.reconstructActiveFormattingElements() p.addFormattingElement(p.tok.Data, p.tok.Attr) + case "applet", "marquee", "object": + p.reconstructActiveFormattingElements() + p.addElement(p.tok.Data, p.tok.Attr) + p.afe = append(p.afe, &scopeMarker) + p.framesetOK = false case "area", "br", "embed", "img", "input", "keygen", "wbr": p.reconstructActiveFormattingElements() p.addElement(p.tok.Data, p.tok.Attr) @@ -406,12 +421,12 @@ func inBodyIM(p *parser) (insertionMode, bool) { p.acknowledgeSelfClosingTag() p.framesetOK = false case "table": - // TODO: auto-insert

if necessary, depending on quirks mode. + p.popUntil(buttonScopeStopTags, "p") // TODO: skip this step in quirks mode. p.addElement(p.tok.Data, p.tok.Attr) p.framesetOK = false return inTableIM, true case "hr": - // TODO: auto-insert

if necessary. + p.popUntil(buttonScopeStopTags, "p") p.addElement(p.tok.Data, p.tok.Attr) p.oe.pop() p.acknowledgeSelfClosingTag() @@ -425,6 +440,11 @@ func inBodyIM(p *parser) (insertionMode, bool) { case "body": // TODO: autoclose the stack of open elements. return afterBodyIM, true + case "p": + if !p.elementInScope(buttonScopeStopTags, "p") { + p.addElement("p", nil) + } + p.popUntil(buttonScopeStopTags, "p") case "a", "b", "big", "code", "em", "font", "i", "nobr", "s", "small", "strike", "strong", "tt", "u": p.inBodyEndTagFormatting(p.tok.Data) default: @@ -434,14 +454,8 @@ func inBodyIM(p *parser) (insertionMode, bool) { } } } - if endP { - // TODO: do the proper algorithm. - n := p.oe.pop() - if n.Type != ElementNode || n.Data != "p" { - panic("unreachable") - } - } - return inBodyIM, !endP + + return inBodyIM, true } func (p *parser) inBodyEndTagFormatting(tag string) { diff --git a/src/pkg/html/parse_test.go b/src/pkg/html/parse_test.go index 0c1b9f8937..c6fd37a10e 100644 --- a/src/pkg/html/parse_test.go +++ b/src/pkg/html/parse_test.go @@ -123,7 +123,7 @@ func TestParser(t *testing.T) { rc := make(chan io.Reader) go readDat(filename, rc) // TODO(nigeltao): Process all test cases, not just a subset. - for i := 0; i < 25; i++ { + for i := 0; i < 26; i++ { // Parse the #data section. b, err := ioutil.ReadAll(<-rc) if err != nil { -- 2.50.0