mirror of
https://github.com/golang/go
synced 2024-11-22 04:24:39 -07:00
html: adjust foreign attributes.
Pass tests10.dat, test 22: <!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg> | <!DOCTYPE html> | <html> | <head> | <body> | xlink:href="foo" | <svg svg> | xlink href="foo" Also pass tests through test 29: <div><svg><path></svg><path> R=andybalholm CC=golang-dev https://golang.org/cl/5489117
This commit is contained in:
parent
b28f017537
commit
d5e45e3a8a
@ -4,6 +4,25 @@
|
|||||||
|
|
||||||
package html
|
package html
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func adjustForeignAttributes(aa []Attribute) {
|
||||||
|
for i, a := range aa {
|
||||||
|
if a.Key == "" || a.Key[0] != 'x' {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
switch a.Key {
|
||||||
|
case "xlink:actuate", "xlink:arcrole", "xlink:href", "xlink:role", "xlink:show",
|
||||||
|
"xlink:title", "xlink:type", "xml:base", "xml:lang", "xml:space", "xmlns:xlink":
|
||||||
|
j := strings.Index(a.Key, ":")
|
||||||
|
aa[i].Namespace = a.Key[:j]
|
||||||
|
aa[i].Key = a.Key[j+1:]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Section 12.2.5.5.
|
// Section 12.2.5.5.
|
||||||
var breakout = map[string]bool{
|
var breakout = map[string]bool{
|
||||||
"b": true,
|
"b": true,
|
||||||
|
@ -807,7 +807,7 @@ func inBodyIM(p *parser) bool {
|
|||||||
// TODO: adjust SVG attributes.
|
// TODO: adjust SVG attributes.
|
||||||
namespace = "svg"
|
namespace = "svg"
|
||||||
}
|
}
|
||||||
// TODO: adjust foreign attributes.
|
adjustForeignAttributes(p.tok.Attr)
|
||||||
p.addElement(p.tok.Data, p.tok.Attr)
|
p.addElement(p.tok.Data, p.tok.Attr)
|
||||||
p.top().Namespace = namespace
|
p.top().Namespace = namespace
|
||||||
return true
|
return true
|
||||||
@ -1678,7 +1678,7 @@ func parseForeignContent(p *parser) bool {
|
|||||||
default:
|
default:
|
||||||
panic("html: bad parser state: unexpected namespace")
|
panic("html: bad parser state: unexpected namespace")
|
||||||
}
|
}
|
||||||
// TODO: adjust foreign attributes.
|
adjustForeignAttributes(p.tok.Attr)
|
||||||
p.addElement(p.tok.Data, p.tok.Attr)
|
p.addElement(p.tok.Data, p.tok.Attr)
|
||||||
case EndTagToken:
|
case EndTagToken:
|
||||||
for i := len(p.oe) - 1; i >= 0; i-- {
|
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||||
|
@ -103,10 +103,21 @@ func dumpLevel(w io.Writer, n *Node, level int) error {
|
|||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(w, "<%s>", n.Data)
|
fmt.Fprintf(w, "<%s>", n.Data)
|
||||||
}
|
}
|
||||||
for _, a := range n.Attr {
|
attr := n.Attr
|
||||||
|
if len(attr) == 2 && attr[0].Namespace == "xml" && attr[1].Namespace == "xlink" {
|
||||||
|
// Some of the test cases in tests10.dat change the order of adjusted
|
||||||
|
// foreign attributes, but that behavior is not in the spec, and could
|
||||||
|
// simply be an implementation detail of html5lib's python map ordering.
|
||||||
|
attr[0], attr[1] = attr[1], attr[0]
|
||||||
|
}
|
||||||
|
for _, a := range attr {
|
||||||
io.WriteString(w, "\n")
|
io.WriteString(w, "\n")
|
||||||
dumpIndent(w, level+1)
|
dumpIndent(w, level+1)
|
||||||
fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
|
if a.Namespace != "" {
|
||||||
|
fmt.Fprintf(w, `%s %s="%s"`, a.Namespace, a.Key, a.Val)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, `%s="%s"`, a.Key, a.Val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
case TextNode:
|
case TextNode:
|
||||||
fmt.Fprintf(w, `"%s"`, n.Data)
|
fmt.Fprintf(w, `"%s"`, n.Data)
|
||||||
@ -173,7 +184,7 @@ func TestParser(t *testing.T) {
|
|||||||
{"tests4.dat", -1},
|
{"tests4.dat", -1},
|
||||||
{"tests5.dat", -1},
|
{"tests5.dat", -1},
|
||||||
{"tests6.dat", 47},
|
{"tests6.dat", 47},
|
||||||
{"tests10.dat", 22},
|
{"tests10.dat", 30},
|
||||||
}
|
}
|
||||||
for _, tf := range testFiles {
|
for _, tf := range testFiles {
|
||||||
f, err := os.Open("testdata/webkit/" + tf.filename)
|
f, err := os.Open("testdata/webkit/" + tf.filename)
|
||||||
|
@ -149,6 +149,14 @@ func render1(w writer, n *Node) error {
|
|||||||
if err := w.WriteByte(' '); err != nil {
|
if err := w.WriteByte(' '); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if a.Namespace != "" {
|
||||||
|
if _, err := w.WriteString(a.Namespace); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := w.WriteByte(':'); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if _, err := w.WriteString(a.Key); err != nil {
|
if _, err := w.WriteString(a.Key); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,14 @@ func (t TokenType) String() string {
|
|||||||
return "Invalid(" + strconv.Itoa(int(t)) + ")"
|
return "Invalid(" + strconv.Itoa(int(t)) + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
// An Attribute is an attribute key-value pair. Key is alphabetic (and hence
|
// An Attribute is an attribute namespace-key-value triple. Namespace is
|
||||||
|
// non-empty for foreign attributes like xlink, Key is alphabetic (and hence
|
||||||
// does not contain escapable characters like '&', '<' or '>'), and Val is
|
// does not contain escapable characters like '&', '<' or '>'), and Val is
|
||||||
// unescaped (it looks like "a<b" rather than "a<b").
|
// unescaped (it looks like "a<b" rather than "a<b").
|
||||||
|
//
|
||||||
|
// Namespace is only used by the parser, not the tokenizer.
|
||||||
type Attribute struct {
|
type Attribute struct {
|
||||||
Key, Val string
|
Namespace, Key, Val string
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Token consists of a TokenType and some Data (tag name for start and end
|
// A Token consists of a TokenType and some Data (tag name for start and end
|
||||||
@ -756,7 +759,7 @@ func (z *Tokenizer) Token() Token {
|
|||||||
for moreAttr {
|
for moreAttr {
|
||||||
var key, val []byte
|
var key, val []byte
|
||||||
key, val, moreAttr = z.TagAttr()
|
key, val, moreAttr = z.TagAttr()
|
||||||
attr = append(attr, Attribute{string(key), string(val)})
|
attr = append(attr, Attribute{"", string(key), string(val)})
|
||||||
}
|
}
|
||||||
t.Data = string(name)
|
t.Data = string(name)
|
||||||
t.Attr = attr
|
t.Attr = attr
|
||||||
|
Loading…
Reference in New Issue
Block a user