aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/html/parse.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/html/parse.go')
-rw-r--r--libgo/go/html/parse.go94
1 files changed, 69 insertions, 25 deletions
diff --git a/libgo/go/html/parse.go b/libgo/go/html/parse.go
index 519ebe5..582437f 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 (