mirror of
https://github.com/golang/go
synced 2024-11-22 05:04:40 -07:00
html: handle breakout tags in foreign content.
Also recognize that, in the latest version of the HTML5 spec, foreign content is not an insertion mode, but a separate concern. Pass tests10.dat, test 13: <!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux | <!DOCTYPE html> | <html> | <head> | <body> | <table> | <caption> | <svg svg> | <svg g> | "foo" | <svg g> | "bar" | <p> | "baz" | <p> | "quux" Also pass tests through test 15: <!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux R=andybalholm CC=golang-dev https://golang.org/cl/5494078
This commit is contained in:
parent
b0eb68ad16
commit
fe28d1aacf
@ -319,10 +319,7 @@ func (p *parser) resetInsertionMode() {
|
|||||||
case "html":
|
case "html":
|
||||||
p.im = beforeHeadIM
|
p.im = beforeHeadIM
|
||||||
default:
|
default:
|
||||||
if p.top().Namespace == "" {
|
continue
|
||||||
continue
|
|
||||||
}
|
|
||||||
p.im = inForeignContentIM
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -814,7 +811,6 @@ func inBodyIM(p *parser) bool {
|
|||||||
// TODO: adjust foreign attributes.
|
// TODO: adjust foreign attributes.
|
||||||
p.addElement(p.tok.Data, p.tok.Attr)
|
p.addElement(p.tok.Data, p.tok.Attr)
|
||||||
p.top().Namespace = namespace
|
p.top().Namespace = namespace
|
||||||
p.im = inForeignContentIM
|
|
||||||
return true
|
return true
|
||||||
case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr":
|
case "caption", "col", "colgroup", "frame", "head", "tbody", "td", "tfoot", "th", "thead", "tr":
|
||||||
// Ignore the token.
|
// Ignore the token.
|
||||||
@ -1590,7 +1586,7 @@ func afterAfterFramesetIM(p *parser) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Section 12.2.5.5.
|
// Section 12.2.5.5.
|
||||||
func inForeignContentIM(p *parser) bool {
|
func parseForeignContent(p *parser) bool {
|
||||||
switch p.tok.Type {
|
switch p.tok.Type {
|
||||||
case TextToken:
|
case TextToken:
|
||||||
// TODO: HTML integration points.
|
// TODO: HTML integration points.
|
||||||
@ -1610,7 +1606,14 @@ func inForeignContentIM(p *parser) bool {
|
|||||||
})
|
})
|
||||||
case StartTagToken:
|
case StartTagToken:
|
||||||
if breakout[p.tok.Data] {
|
if breakout[p.tok.Data] {
|
||||||
// TODO.
|
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||||
|
// TODO: HTML, MathML integration points.
|
||||||
|
if p.oe[i].Namespace == "" {
|
||||||
|
p.oe = p.oe[:i+1]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
switch p.top().Namespace {
|
switch p.top().Namespace {
|
||||||
case "mathml":
|
case "mathml":
|
||||||
@ -1626,15 +1629,13 @@ func inForeignContentIM(p *parser) bool {
|
|||||||
case EndTagToken:
|
case EndTagToken:
|
||||||
for i := len(p.oe) - 1; i >= 0; i-- {
|
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||||
if p.oe[i].Namespace == "" {
|
if p.oe[i].Namespace == "" {
|
||||||
inBodyIM(p)
|
return p.im(p)
|
||||||
break
|
|
||||||
}
|
}
|
||||||
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
|
if strings.EqualFold(p.oe[i].Data, p.tok.Data) {
|
||||||
p.oe = p.oe[:i]
|
p.oe = p.oe[:i]
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.resetInsertionMode()
|
|
||||||
return true
|
return true
|
||||||
default:
|
default:
|
||||||
// Ignore the token.
|
// Ignore the token.
|
||||||
@ -1642,6 +1643,20 @@ func inForeignContentIM(p *parser) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Section 12.2.5.
|
||||||
|
func (p *parser) inForeignContent() bool {
|
||||||
|
if len(p.oe) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
n := p.oe[len(p.oe)-1]
|
||||||
|
if n.Namespace == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// TODO: MathML, HTML integration points.
|
||||||
|
// TODO: MathML's annotation-xml combining with SVG's svg.
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (p *parser) parse() error {
|
func (p *parser) parse() error {
|
||||||
// Iterate until EOF. Any other error will cause an early return.
|
// Iterate until EOF. Any other error will cause an early return.
|
||||||
consumed := true
|
consumed := true
|
||||||
@ -1654,7 +1669,11 @@ func (p *parser) parse() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
consumed = p.im(p)
|
if p.inForeignContent() {
|
||||||
|
consumed = parseForeignContent(p)
|
||||||
|
} else {
|
||||||
|
consumed = p.im(p)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Loop until the final token (the ErrorToken signifying EOF) is consumed.
|
// Loop until the final token (the ErrorToken signifying EOF) is consumed.
|
||||||
for {
|
for {
|
||||||
|
@ -173,7 +173,7 @@ func TestParser(t *testing.T) {
|
|||||||
{"tests4.dat", -1},
|
{"tests4.dat", -1},
|
||||||
{"tests5.dat", -1},
|
{"tests5.dat", -1},
|
||||||
{"tests6.dat", 45},
|
{"tests6.dat", 45},
|
||||||
{"tests10.dat", 13},
|
{"tests10.dat", 16},
|
||||||
}
|
}
|
||||||
for _, tf := range testFiles {
|
for _, tf := range testFiles {
|
||||||
f, err := os.Open("testdata/webkit/" + tf.filename)
|
f, err := os.Open("testdata/webkit/" + tf.filename)
|
||||||
|
Loading…
Reference in New Issue
Block a user