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:
parent
696ced50fe
commit
2f352ae48a
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user