esc.go 1.3 KB

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