// EscapeAttrVal returns the escape attribute value bytes without quotes. func EscapeAttrVal(buf *[]byte, b []byte) []byte { singles := 0 doubles := 0 for i, c := range b { if c == '&' { if quote, n := parse.QuoteEntity(b[i:]); n > 0 { if quote == '"' { doubles++ } else { singles++ } } } else if c == '"' { doubles++ } else if c == '\'' { singles++ } } n := len(b) + 2 var quote byte var escapedQuote []byte if doubles > singles { n += singles * 4 quote = '\'' escapedQuote = singleQuoteEntityBytes } else { n += doubles * 4 quote = '"' escapedQuote = doubleQuoteEntityBytes } 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 == '&' { if entityQuote, n := parse.QuoteEntity(b[i:]); n > 0 { j += copy(t[j:], b[start:i]) if entityQuote != quote { t[j] = entityQuote j++ } else { j += copy(t[j:], escapedQuote) } start = i + n } } else 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] }
// EscapeAttrVal returns the escaped attribute value bytes without quotes. func EscapeAttrVal(buf *[]byte, orig, b []byte) []byte { singles := 0 doubles := 0 unquoted := true entities := false for i, c := range b { if charTable[c] { if c == '&' { entities = true if quote, n := parse.QuoteEntity(b[i:]); n > 0 { if quote == '"' { unquoted = false doubles++ } else { unquoted = false singles++ } } } else { unquoted = false if c == '"' { doubles++ } else if c == '\'' { singles++ } } } } if unquoted { return b } else if !entities && len(orig) == len(b)+2 && (singles == 0 && orig[0] == '\'' || doubles == 0 && orig[0] == '"') { return orig } n := len(b) + 2 var quote byte var escapedQuote []byte if doubles > singles { n += singles * 4 quote = '\'' escapedQuote = singleQuoteEntityBytes } else { n += doubles * 4 quote = '"' escapedQuote = doubleQuoteEntityBytes } 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 == '&' { if entityQuote, n := parse.QuoteEntity(b[i:]); n > 0 { j += copy(t[j:], b[start:i]) if entityQuote != quote { t[j] = entityQuote j++ } else { j += copy(t[j:], escapedQuote) } start = i + n } } else 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] }