this repo has no description
1package markup
2
3import (
4 "maps"
5 "regexp"
6 "slices"
7 "strings"
8
9 "github.com/alecthomas/chroma/v2"
10 "github.com/microcosm-cc/bluemonday"
11)
12
13type Sanitizer struct {
14 defaultPolicy *bluemonday.Policy
15}
16
17func NewSanitizer() Sanitizer {
18 return Sanitizer{
19 defaultPolicy: defaultPolicy(),
20 }
21}
22
23func defaultPolicy() *bluemonday.Policy {
24 policy := bluemonday.UGCPolicy()
25
26 // Allow generally safe attributes
27 generalSafeAttrs := []string{
28 "abbr", "accept", "accept-charset",
29 "accesskey", "action", "align", "alt",
30 "aria-describedby", "aria-hidden", "aria-label", "aria-labelledby",
31 "axis", "border", "cellpadding", "cellspacing", "char",
32 "charoff", "charset", "checked",
33 "clear", "cols", "colspan", "color",
34 "compact", "coords", "datetime", "dir",
35 "disabled", "enctype", "for", "frame",
36 "headers", "height", "hreflang",
37 "hspace", "ismap", "label", "lang",
38 "maxlength", "media", "method",
39 "multiple", "name", "nohref", "noshade",
40 "nowrap", "open", "prompt", "readonly", "rel", "rev",
41 "rows", "rowspan", "rules", "scope",
42 "selected", "shape", "size", "span",
43 "start", "summary", "tabindex", "target",
44 "title", "type", "usemap", "valign", "value",
45 "vspace", "width", "itemprop",
46 }
47
48 generalSafeElements := []string{
49 "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "br", "b", "i", "strong", "em", "a", "pre", "code", "img", "tt",
50 "div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", "label",
51 "dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary",
52 "details", "caption", "figure", "figcaption",
53 "abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr",
54 }
55
56 policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...)
57
58 // video
59 policy.AllowAttrs("src", "autoplay", "controls").OnElements("video")
60
61 // checkboxes
62 policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input")
63 policy.AllowAttrs("checked", "disabled", "data-source-position").OnElements("input")
64
65 // for code blocks
66 policy.AllowAttrs("class").Matching(regexp.MustCompile(`chroma`)).OnElements("pre")
67 policy.AllowAttrs("class").Matching(regexp.MustCompile(`anchor|footnote-ref|footnote-backref`)).OnElements("a")
68 policy.AllowAttrs("class").Matching(regexp.MustCompile(`heading`)).OnElements("h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8")
69 policy.AllowAttrs("class").Matching(regexp.MustCompile(strings.Join(slices.Collect(maps.Values(chroma.StandardTypes)), "|"))).OnElements("span")
70
71 // centering content
72 policy.AllowElements("center")
73
74 policy.AllowAttrs("align", "style", "width", "height").Globally()
75 policy.AllowStyles(
76 "margin",
77 "padding",
78 "text-align",
79 "font-weight",
80 "text-decoration",
81 "padding-left",
82 "padding-right",
83 "padding-top",
84 "padding-bottom",
85 "margin-left",
86 "margin-right",
87 "margin-top",
88 "margin-bottom",
89 )
90
91 return policy
92}