66
|
1 package blackfriday
|
|
2
|
|
3 import (
|
|
4 "html"
|
|
5 "io"
|
|
6 )
|
|
7
|
|
8 var htmlEscaper = [256][]byte{
|
|
9 '&': []byte("&"),
|
|
10 '<': []byte("<"),
|
|
11 '>': []byte(">"),
|
|
12 '"': []byte("""),
|
|
13 }
|
|
14
|
|
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) {
|
|
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
|
|
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
|
|
67 func escLink(w io.Writer, text []byte) {
|
|
68 unesc := html.UnescapeString(string(text))
|
|
69 escapeHTML(w, []byte(unesc))
|
|
70 }
|