Skip to content

Commit

Permalink
Add XML option for EscapeAttrVal
Browse files Browse the repository at this point in the history
  • Loading branch information
tdewolff committed Mar 15, 2019
1 parent 13ebfff commit 83ccb3c
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 24 deletions.
14 changes: 7 additions & 7 deletions html/util.go
Expand Up @@ -52,7 +52,7 @@ var charTable = [256]bool{
}

// EscapeAttrVal returns the escaped attribute value bytes without quotes.
func EscapeAttrVal(buf *[]byte, orig, b []byte) []byte {
func EscapeAttrVal(buf *[]byte, orig, b []byte, isXML bool) []byte {
singles := 0
doubles := 0
unquoted := true
Expand Down Expand Up @@ -80,7 +80,7 @@ func EscapeAttrVal(buf *[]byte, orig, b []byte) []byte {
}
}
}
if unquoted {
if unquoted && !isXML {
return b
} else if !entities && len(orig) == len(b)+2 && (singles == 0 && orig[0] == '\'' || doubles == 0 && orig[0] == '"') {
return orig
Expand All @@ -89,14 +89,14 @@ func EscapeAttrVal(buf *[]byte, orig, b []byte) []byte {
n := len(b) + 2
var quote byte
var escapedQuote []byte
if doubles > singles {
n += singles * 4
quote = '\''
escapedQuote = singleQuoteEntityBytes
} else {
if singles >= doubles || isXML {
n += doubles * 4
quote = '"'
escapedQuote = doubleQuoteEntityBytes
} else {
n += singles * 4
quote = '\''
escapedQuote = singleQuoteEntityBytes
}
if n > cap(*buf) {
*buf = make([]byte, 0, n) // maximum size, not actual size
Expand Down
56 changes: 39 additions & 17 deletions html/util_test.go
Expand Up @@ -11,22 +11,22 @@ func TestEscapeAttrVal(t *testing.T) {
attrVal string
expected string
}{
{"xyz", "xyz"},
{"", ""},
{"x&z", "x&z"},
{"x/z", "x/z"},
{"x'z", "\"x'z\""},
{"x\"z", "'x\"z'"},
{"'x\"z'", "'x\"z'"},
{"'x'\"'z'", "\"x'"'z\""},
{"\"x"'"z\"", "'x\"'\"z'"},
{"\"x'z\"", "\"x'z\""},
{"'x"z'", "'x\"z'"},
{"'x\">'", "'x\">'"},
{"You're encouraged to log in; however, it's not mandatory. [o]", "\"You're encouraged to log in; however, it's not mandatory. [o]\""},
{"a'b=\"\"", "'a'b=\"\"'"},
{"x<z", "\"x<z\""},
{"'x\"&#39;\"z'", "'x\"&#39;\"z'"},
{`xyz`, `xyz`},
{``, ``},
{`x&amp;z`, `x&amp;z`},
{`x/z`, `x/z`},
{`x'z`, `"x'z"`},
{`x"z`, `'x"z'`},
{`'x"z'`, `'x"z'`},
{`'x&#39;"&#39;z'`, `"x'&#34;'z"`},
{`"x&#34;'&#34;z"`, `'x"&#39;"z'`},
{`"x&#x27;z"`, `"x'z"`},
{`'x&#x00022;z'`, `'x"z'`},
{`'x"&gt;'`, `'x"&gt;'`},
{`You&#039;re encouraged to log in; however, it&#039;s not mandatory. [o]`, `"You're encouraged to log in; however, it's not mandatory. [o]"`},
{`a'b=""`, `'a&#39;b=""'`},
{`x<z`, `"x<z"`},
{`'x"&#39;"z'`, `'x"&#39;"z'`},
}
var buf []byte
for _, tt := range escapeAttrValTests {
Expand All @@ -36,7 +36,29 @@ func TestEscapeAttrVal(t *testing.T) {
if len(b) > 1 && (b[0] == '"' || b[0] == '\'') && b[0] == b[len(b)-1] {
b = b[1 : len(b)-1]
}
val := EscapeAttrVal(&buf, orig, []byte(b))
val := EscapeAttrVal(&buf, orig, []byte(b), false)
test.String(t, string(val), tt.expected)
})
}
}

func TestEscapeAttrValXML(t *testing.T) {
var escapeAttrValTests = []struct {
attrVal string
expected string
}{
{`xyz`, `"xyz"`},
{``, `""`},
}
var buf []byte
for _, tt := range escapeAttrValTests {
t.Run(tt.attrVal, func(t *testing.T) {
b := []byte(tt.attrVal)
orig := b
if len(b) > 1 && (b[0] == '"' || b[0] == '\'') && b[0] == b[len(b)-1] {
b = b[1 : len(b)-1]
}
val := EscapeAttrVal(&buf, orig, []byte(b), true)
test.String(t, string(val), tt.expected)
})
}
Expand Down

0 comments on commit 83ccb3c

Please sign in to comment.