| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- package html // import "github.com/tdewolff/parse/html"
- import "github.com/tdewolff/parse"
- var (
- singleQuoteEntityBytes = []byte("'")
- doubleQuoteEntityBytes = []byte(""")
- )
- var charTable = [256]bool{
- // ASCII
- false, false, false, false, false, false, false, false,
- false, true, true, true, true, true, false, false, // tab, new line, vertical tab, 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, true, 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,
- }
- // 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]
- }
|