-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
dataurl.go
60 lines (50 loc) · 1.28 KB
/
dataurl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package helpers
import (
"strings"
"unicode/utf8"
)
// See "scripts/dataurl-escapes.html" for how this was derived
func EncodeStringAsPercentEscapedDataURL(mimeType string, text string) (string, bool) {
hex := "0123456789ABCDEF"
sb := strings.Builder{}
n := len(text)
i := 0
runStart := 0
sb.WriteString("data:")
sb.WriteString(mimeType)
sb.WriteByte(',')
// Scan for trailing characters that need to be escaped
trailingStart := n
for trailingStart > 0 {
if c := text[trailingStart-1]; c > 0x20 || c == '\t' || c == '\n' || c == '\r' {
break
}
trailingStart--
}
for i < n {
c, width := utf8.DecodeRuneInString(text[i:])
// We can't encode invalid UTF-8 data
if c == utf8.RuneError && width == 1 {
return "", false
}
// Escape this character if needed
if c == '\t' || c == '\n' || c == '\r' || c == '#' || i >= trailingStart ||
(c == '%' && i+2 < n && isHex(text[i+1]) && isHex(text[i+2])) {
if runStart < i {
sb.WriteString(text[runStart:i])
}
sb.WriteByte('%')
sb.WriteByte(hex[c>>4])
sb.WriteByte(hex[c&15])
runStart = i + width
}
i += width
}
if runStart < n {
sb.WriteString(text[runStart:])
}
return sb.String(), true
}
func isHex(c byte) bool {
return c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F'
}