1package html
2
3var (
4 singleQuoteEntityBytes = []byte("'")
5 doubleQuoteEntityBytes = []byte(""")
6)
7
8// EscapeAttrVal returns the escaped attribute value bytes with quotes. Either single or double quotes are used, whichever is shorter. If there are no quotes present in the value and the value is in HTML (not XML), it will return the value without quotes.
9func EscapeAttrVal(buf *[]byte, b []byte, origQuote byte, mustQuote, isXML bool) []byte {
10 singles := 0
11 doubles := 0
12 unquoted := true
13 for _, c := range b {
14 if charTable[c] {
15 unquoted = false
16 if c == '"' {
17 doubles++
18 } else if c == '\'' {
19 singles++
20 }
21 }
22 }
23 if unquoted && (!mustQuote || origQuote == 0) && !isXML {
24 return b
25 } else if singles == 0 && origQuote == '\'' && !isXML || doubles == 0 && origQuote == '"' {
26 if len(b)+2 > cap(*buf) {
27 *buf = make([]byte, 0, len(b)+2)
28 }
29 t := (*buf)[:len(b)+2]
30 t[0] = origQuote
31 copy(t[1:], b)
32 t[1+len(b)] = origQuote
33 return t
34 }
35
36 n := len(b) + 2
37 var quote byte
38 var escapedQuote []byte
39 if singles >= doubles || isXML {
40 n += doubles * 4
41 quote = '"'
42 escapedQuote = doubleQuoteEntityBytes
43 if singles == doubles && origQuote == '\'' && !isXML {
44 quote = '\''
45 escapedQuote = singleQuoteEntityBytes
46 }
47 } else {
48 n += singles * 4
49 quote = '\''
50 escapedQuote = singleQuoteEntityBytes
51 }
52 if n > cap(*buf) {
53 *buf = make([]byte, 0, n) // maximum size, not actual size
54 }
55 t := (*buf)[:n] // maximum size, not actual size
56 t[0] = quote
57 j := 1
58 start := 0
59 for i, c := range b {
60 if c == quote {
61 j += copy(t[j:], b[start:i])
62 j += copy(t[j:], escapedQuote)
63 start = i + 1
64 }
65 }
66 j += copy(t[j:], b[start:])
67 t[j] = quote
68 return t[:j+1]
69}
70
71var charTable = [256]bool{
72 // ASCII
73 false, false, false, false, false, false, false, false,
74 false, true, true, false, true, true, false, false, // tab, line feed, form feed, carriage return
75 false, false, false, false, false, false, false, false,
76 false, false, false, false, false, false, false, false,
77
78 true, false, true, false, false, false, false, true, // space, "), '
79 false, false, false, false, false, false, false, false,
80 false, false, false, false, false, false, false, false,
81 false, false, false, false, true, true, true, false, // <, =, >
82
83 false, false, false, false, false, false, false, false,
84 false, false, false, false, false, false, false, false,
85 false, false, false, false, false, false, false, false,
86 false, false, false, false, false, false, false, false,
87
88 true, false, false, false, false, false, false, false, // `
89 false, false, false, false, false, false, false, false,
90 false, false, false, false, false, false, false, false,
91 false, false, false, false, false, false, false, false,
92
93 // non-ASCII
94 false, false, false, false, false, false, false, false,
95 false, false, false, false, false, false, false, false,
96 false, false, false, false, false, false, false, false,
97 false, false, false, false, false, false, false, false,
98
99 false, false, false, false, false, false, false, false,
100 false, false, false, false, false, false, false, false,
101 false, false, false, false, false, false, false, false,
102 false, false, false, false, false, false, false, false,
103
104 false, false, false, false, false, false, false, false,
105 false, false, false, false, false, false, false, false,
106 false, false, false, false, false, false, false, false,
107 false, false, false, false, false, false, false, false,
108
109 false, false, false, false, false, false, false, false,
110 false, false, false, false, false, false, false, false,
111 false, false, false, false, false, false, false, false,
112 false, false, false, false, false, false, false, false,
113}