diff options
Diffstat (limited to 'libgo/go/html/parse.go')
-rw-r--r-- | libgo/go/html/parse.go | 94 |
1 files changed, 69 insertions, 25 deletions
diff --git a/libgo/go/html/parse.go b/libgo/go/html/parse.go index 519ebe587b9..582437f7673 100644 --- a/libgo/go/html/parse.go +++ b/libgo/go/html/parse.go @@ -29,6 +29,9 @@ type parser struct { head, form *Node // Other parsing state flags (section 11.2.3.5). scripting, framesetOK bool + // originalIM is the insertion mode to go back to after completing a text + // or inTableText insertion mode. + originalIM insertionMode } func (p *parser) top() *Node { @@ -64,21 +67,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 @@ -198,12 +217,23 @@ type insertionMode func(*parser) (insertionMode, bool) // Section 11.2.3.1, "using the rules for". func useTheRulesFor(p *parser, actual, delegate insertionMode) (insertionMode, bool) { im, consumed := delegate(p) + // TODO: do we need to update p.originalMode if it equals delegate? if im != delegate { return im, consumed } return actual, consumed } +// setOriginalIM sets the insertion mode to return to after completing a text or +// inTableText insertion mode. +// Section 11.2.3.1, "using the rules for". +func (p *parser) setOriginalIM(im insertionMode) { + if p.originalIM != nil { + panic("html: bad parser state: originalIM was set twice") + } + p.originalIM = im +} + // Section 11.2.5.4.1. func initialIM(p *parser) (insertionMode, bool) { if p.tok.Type == DoctypeToken { @@ -302,8 +332,10 @@ func inHeadIM(p *parser) (insertionMode, bool) { switch p.tok.Data { case "meta": // TODO. - case "script": - // TODO. + case "script", "title": + p.addElement(p.tok.Data, p.tok.Attr) + p.setOriginalIM(inHeadIM) + return textIM, true default: implied = true } @@ -365,7 +397,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 +405,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 </p> if necessary. + p.popUntil(buttonScopeStopTags, "p") switch n := p.top(); n.Data { case "h1", "h2", "h3", "h4", "h5", "h6": p.oe.pop() @@ -399,6 +425,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 +437,12 @@ func inBodyIM(p *parser) (insertionMode, bool) { p.acknowledgeSelfClosingTag() p.framesetOK = false case "table": - // TODO: auto-insert </p> 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 </p> if necessary. + p.popUntil(buttonScopeStopTags, "p") p.addElement(p.tok.Data, p.tok.Attr) p.oe.pop() p.acknowledgeSelfClosingTag() @@ -425,6 +456,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 +470,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) { @@ -560,6 +590,20 @@ func (p *parser) inBodyEndTagFormatting(tag string) { } } +// Section 11.2.5.4.8. +func textIM(p *parser) (insertionMode, bool) { + switch p.tok.Type { + case TextToken: + p.addText(p.tok.Data) + return textIM, true + case EndTagToken: + p.oe.pop() + } + o := p.originalIM + p.originalIM = nil + return o, p.tok.Type == EndTagToken +} + // Section 11.2.5.4.9. func inTableIM(p *parser) (insertionMode, bool) { var ( |