github.com/evanw/esbuild@v0.21.4/internal/helpers/dataurl.go (about) 1 package helpers 2 3 import ( 4 "encoding/base64" 5 "fmt" 6 "strings" 7 "unicode/utf8" 8 ) 9 10 // Returns the shorter of either a base64-encoded or percent-escaped data URL 11 func EncodeStringAsShortestDataURL(mimeType string, text string) string { 12 encoded := base64.StdEncoding.EncodeToString([]byte(text)) 13 url := fmt.Sprintf("data:%s;base64,%s", mimeType, encoded) 14 if percentURL, ok := EncodeStringAsPercentEscapedDataURL(mimeType, text); ok && len(percentURL) < len(url) { 15 return percentURL 16 } 17 return url 18 } 19 20 // See "scripts/dataurl-escapes.html" for how this was derived 21 func EncodeStringAsPercentEscapedDataURL(mimeType string, text string) (string, bool) { 22 hex := "0123456789ABCDEF" 23 sb := strings.Builder{} 24 n := len(text) 25 i := 0 26 runStart := 0 27 sb.WriteString("data:") 28 sb.WriteString(mimeType) 29 sb.WriteByte(',') 30 31 // Scan for trailing characters that need to be escaped 32 trailingStart := n 33 for trailingStart > 0 { 34 if c := text[trailingStart-1]; c > 0x20 || c == '\t' || c == '\n' || c == '\r' { 35 break 36 } 37 trailingStart-- 38 } 39 40 for i < n { 41 c, width := utf8.DecodeRuneInString(text[i:]) 42 43 // We can't encode invalid UTF-8 data 44 if c == utf8.RuneError && width == 1 { 45 return "", false 46 } 47 48 // Escape this character if needed 49 if c == '\t' || c == '\n' || c == '\r' || c == '#' || i >= trailingStart || 50 (c == '%' && i+2 < n && isHex(text[i+1]) && isHex(text[i+2])) { 51 if runStart < i { 52 sb.WriteString(text[runStart:i]) 53 } 54 sb.WriteByte('%') 55 sb.WriteByte(hex[c>>4]) 56 sb.WriteByte(hex[c&15]) 57 runStart = i + width 58 } 59 60 i += width 61 } 62 63 if runStart < n { 64 sb.WriteString(text[runStart:]) 65 } 66 67 return sb.String(), true 68 } 69 70 func isHex(c byte) bool { 71 return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' 72 }