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  }