1
0
mirror of https://github.com/golang/go synced 2024-11-20 10:44:41 -07:00

html: parse <select> tags.

The additional test case in parse_test.go is:
<select><b><option><select><option></b></select>X

R=andybalholm
CC=golang-dev
https://golang.org/cl/5293051
This commit is contained in:
Nigel Tao 2011-10-22 20:18:12 +11:00
parent 696ced50fe
commit 2f352ae48a
2 changed files with 105 additions and 3 deletions

View File

@ -234,6 +234,41 @@ func (p *parser) setOriginalIM(im insertionMode) {
p.originalIM = im p.originalIM = im
} }
// Section 11.2.3.1, "reset the insertion mode".
func (p *parser) resetInsertionMode() insertionMode {
for i := len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i]
if i == 0 {
// TODO: set n to the context element, for HTML fragment parsing.
}
switch n.Data {
case "select":
return inSelectIM
case "td", "th":
return inCellIM
case "tr":
return inRowIM
case "tbody", "thead", "tfoot":
return inTableBodyIM
case "caption":
// TODO: return inCaptionIM
case "colgroup":
// TODO: return inColumnGroupIM
case "table":
return inTableIM
case "head":
return inBodyIM
case "body":
return inBodyIM
case "frameset":
// TODO: return inFramesetIM
case "html":
return beforeHeadIM
}
}
return inBodyIM
}
// Section 11.2.5.4.1. // Section 11.2.5.4.1.
func initialIM(p *parser) (insertionMode, bool) { func initialIM(p *parser) (insertionMode, bool) {
switch p.tok.Type { switch p.tok.Type {
@ -478,6 +513,12 @@ func inBodyIM(p *parser) (insertionMode, bool) {
p.oe.pop() p.oe.pop()
p.acknowledgeSelfClosingTag() p.acknowledgeSelfClosingTag()
p.framesetOK = false p.framesetOK = false
case "select":
p.reconstructActiveFormattingElements()
p.addElement(p.tok.Data, p.tok.Attr)
p.framesetOK = false
// TODO: detect <select> inside a table.
return inSelectIM, true
default: default:
// TODO. // TODO.
p.addElement(p.tok.Data, p.tok.Attr) p.addElement(p.tok.Data, p.tok.Attr)
@ -671,8 +712,7 @@ func inTableIM(p *parser) (insertionMode, bool) {
switch p.tok.Data { switch p.tok.Data {
case "table": case "table":
if p.popUntil(tableScopeStopTags, "table") { if p.popUntil(tableScopeStopTags, "table") {
// TODO: "reset the insertion mode appropriately" as per 11.2.3.1. return p.resetInsertionMode(), true
return inBodyIM, false
} }
// Ignore the token. // Ignore the token.
return inTableIM, true return inTableIM, true
@ -833,6 +873,68 @@ func inCellIM(p *parser) (insertionMode, bool) {
return useTheRulesFor(p, inCellIM, inBodyIM) return useTheRulesFor(p, inCellIM, inBodyIM)
} }
// Section 11.2.5.4.16.
func inSelectIM(p *parser) (insertionMode, bool) {
endSelect := false
switch p.tok.Type {
case ErrorToken:
// TODO.
case TextToken:
p.addText(p.tok.Data)
case StartTagToken:
switch p.tok.Data {
case "html":
// TODO.
case "option":
if p.top().Data == "option" {
p.oe.pop()
}
p.addElement(p.tok.Data, p.tok.Attr)
case "optgroup":
// TODO.
case "select":
endSelect = true
case "input", "keygen", "textarea":
// TODO.
case "script":
// TODO.
default:
// Ignore the token.
}
case EndTagToken:
switch p.tok.Data {
case "option":
// TODO.
case "optgroup":
// TODO.
case "select":
endSelect = true
default:
// Ignore the token.
}
case CommentToken:
p.doc.Add(&Node{
Type: CommentNode,
Data: p.tok.Data,
})
}
if endSelect {
for i := len(p.oe) - 1; i >= 0; i-- {
switch p.oe[i].Data {
case "select":
p.oe = p.oe[:i]
return p.resetInsertionMode(), true
case "option", "optgroup":
continue
default:
// Ignore the token.
return inSelectIM, true
}
}
}
return inSelectIM, true
}
// Section 11.2.5.4.18. // Section 11.2.5.4.18.
func afterBodyIM(p *parser) (insertionMode, bool) { func afterBodyIM(p *parser) (insertionMode, bool) {
switch p.tok.Type { switch p.tok.Type {

View File

@ -123,7 +123,7 @@ func TestParser(t *testing.T) {
rc := make(chan io.Reader) rc := make(chan io.Reader)
go readDat(filename, rc) go readDat(filename, rc)
// TODO(nigeltao): Process all test cases, not just a subset. // TODO(nigeltao): Process all test cases, not just a subset.
for i := 0; i < 29; i++ { for i := 0; i < 30; i++ {
// Parse the #data section. // Parse the #data section.
b, err := ioutil.ReadAll(<-rc) b, err := ioutil.ReadAll(<-rc)
if err != nil { if err != nil {