11 '>': []byte(">"), |
11 '>': []byte(">"), |
12 '"': []byte("""), |
12 '"': []byte("""), |
13 } |
13 } |
14 |
14 |
15 func escapeHTML(w io.Writer, s []byte) { |
15 func escapeHTML(w io.Writer, s []byte) { |
|
16 escapeEntities(w, s, false) |
|
17 } |
|
18 |
|
19 func escapeAllHTML(w io.Writer, s []byte) { |
|
20 escapeEntities(w, s, true) |
|
21 } |
|
22 |
|
23 func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) { |
16 var start, end int |
24 var start, end int |
17 for end < len(s) { |
25 for end < len(s) { |
18 escSeq := htmlEscaper[s[end]] |
26 escSeq := htmlEscaper[s[end]] |
19 if escSeq != nil { |
27 if escSeq != nil { |
20 w.Write(s[start:end]) |
28 isEntity, entityEnd := nodeIsEntity(s, end) |
21 w.Write(escSeq) |
29 if isEntity && !escapeValidEntities { |
22 start = end + 1 |
30 w.Write(s[start : entityEnd+1]) |
|
31 start = entityEnd + 1 |
|
32 } else { |
|
33 w.Write(s[start:end]) |
|
34 w.Write(escSeq) |
|
35 start = end + 1 |
|
36 } |
23 } |
37 } |
24 end++ |
38 end++ |
25 } |
39 } |
26 if start < len(s) && end <= len(s) { |
40 if start < len(s) && end <= len(s) { |
27 w.Write(s[start:end]) |
41 w.Write(s[start:end]) |
28 } |
42 } |
29 } |
43 } |
30 |
44 |
|
45 func nodeIsEntity(s []byte, end int) (isEntity bool, endEntityPos int) { |
|
46 isEntity = false |
|
47 endEntityPos = end + 1 |
|
48 |
|
49 if s[end] == '&' { |
|
50 for endEntityPos < len(s) { |
|
51 if s[endEntityPos] == ';' { |
|
52 if entities[string(s[end:endEntityPos+1])] { |
|
53 isEntity = true |
|
54 break |
|
55 } |
|
56 } |
|
57 if !isalnum(s[endEntityPos]) && s[endEntityPos] != '&' && s[endEntityPos] != '#' { |
|
58 break |
|
59 } |
|
60 endEntityPos++ |
|
61 } |
|
62 } |
|
63 |
|
64 return isEntity, endEntityPos |
|
65 } |
|
66 |
31 func escLink(w io.Writer, text []byte) { |
67 func escLink(w io.Writer, text []byte) { |
32 unesc := html.UnescapeString(string(text)) |
68 unesc := html.UnescapeString(string(text)) |
33 escapeHTML(w, []byte(unesc)) |
69 escapeHTML(w, []byte(unesc)) |
34 } |
70 } |