esc.go (view raw)
1package blackfriday
2
3import (
4 "html"
5 "io"
6)
7
8var htmlEscaper = [256][]byte{
9 '&': []byte("&"),
10 '<': []byte("<"),
11 '>': []byte(">"),
12 '"': []byte("""),
13}
14
15func escapeHTML(w io.Writer, s []byte) {
16 escapeEntities(w, s, false)
17}
18
19func escapeAllHTML(w io.Writer, s []byte) {
20 escapeEntities(w, s, true)
21}
22
23func escapeEntities(w io.Writer, s []byte, escapeValidEntities bool) {
24 var start, end int
25 for end < len(s) {
26 escSeq := htmlEscaper[s[end]]
27 if escSeq != nil {
28 isEntity, entityEnd := nodeIsEntity(s, end)
29 if isEntity && !escapeValidEntities {
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 }
37 }
38 end++
39 }
40 if start < len(s) && end <= len(s) {
41 w.Write(s[start:end])
42 }
43}
44
45func 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
67func escLink(w io.Writer, text []byte) {
68 unesc := html.UnescapeString(string(text))
69 escapeHTML(w, []byte(unesc))
70}