2022-08-07 18:19:16 +02:00
package html
var (
singleQuoteEntityBytes = [ ] byte ( "'" )
doubleQuoteEntityBytes = [ ] byte ( """ )
)
// 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.
2024-02-19 08:23:08 +01:00
func EscapeAttrVal ( buf * [ ] byte , b [ ] byte , origQuote byte , mustQuote bool ) [ ] byte {
2022-08-07 18:19:16 +02:00
singles := 0
doubles := 0
unquoted := true
for _ , c := range b {
if charTable [ c ] {
unquoted = false
if c == '"' {
doubles ++
} else if c == '\'' {
singles ++
}
}
}
2024-02-19 08:23:08 +01:00
if unquoted && ( ! mustQuote || origQuote == 0 ) {
2022-08-07 18:19:16 +02:00
return b
2024-02-19 08:23:08 +01:00
} else if singles == 0 && origQuote == '\'' || doubles == 0 && origQuote == '"' {
2022-08-07 18:19:16 +02:00
if len ( b ) + 2 > cap ( * buf ) {
* buf = make ( [ ] byte , 0 , len ( b ) + 2 )
}
t := ( * buf ) [ : len ( b ) + 2 ]
t [ 0 ] = origQuote
copy ( t [ 1 : ] , b )
t [ 1 + len ( b ) ] = origQuote
return t
}
n := len ( b ) + 2
var quote byte
var escapedQuote [ ] byte
2024-02-19 08:23:08 +01:00
if singles > doubles || singles == doubles && origQuote != '\'' {
2022-08-07 18:19:16 +02:00
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
}
t := ( * buf ) [ : n ] // maximum size, not actual size
t [ 0 ] = quote
j := 1
start := 0
for i , c := range b {
if c == quote {
j += copy ( t [ j : ] , b [ start : i ] )
j += copy ( t [ j : ] , escapedQuote )
start = i + 1
}
}
j += copy ( t [ j : ] , b [ start : ] )
t [ j ] = quote
return t [ : j + 1 ]
}
var charTable = [ 256 ] bool {
// ASCII
false , false , false , false , false , false , false , false ,
false , true , true , false , true , true , false , false , // tab, line feed, form feed, carriage return
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
true , false , true , false , false , false , false , true , // space, "), '
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , true , true , true , false , // <, =, >
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
true , false , false , false , false , false , false , false , // `
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
// non-ASCII
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
false , false , false , false , false , false , false , false ,
}