forked from tangled.org/core
Monorepo for Tangled — https://tangled.org
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 descriptionPolicy *bluemonday.Policy 16} 17 18func NewSanitizer() Sanitizer { 19 return Sanitizer{ 20 defaultPolicy: defaultPolicy(), 21 descriptionPolicy: descriptionPolicy(), 22 } 23} 24 25func (s *Sanitizer) SanitizeDefault(html string) string { 26 return s.defaultPolicy.Sanitize(html) 27} 28func (s *Sanitizer) SanitizeDescription(html string) string { 29 return s.descriptionPolicy.Sanitize(html) 30} 31 32func defaultPolicy() *bluemonday.Policy { 33 policy := bluemonday.UGCPolicy() 34 35 // Allow generally safe attributes 36 generalSafeAttrs := []string{ 37 "abbr", "accept", "accept-charset", 38 "accesskey", "action", "align", "alt", 39 "aria-describedby", "aria-hidden", "aria-label", "aria-labelledby", 40 "axis", "border", "cellpadding", "cellspacing", "char", 41 "charoff", "charset", "checked", 42 "clear", "cols", "colspan", "color", 43 "compact", "coords", "datetime", "dir", 44 "disabled", "enctype", "for", "frame", 45 "headers", "height", "hreflang", 46 "hspace", "ismap", "label", "lang", 47 "maxlength", "media", "method", 48 "multiple", "name", "nohref", "noshade", 49 "nowrap", "open", "prompt", "readonly", "rel", "rev", 50 "rows", "rowspan", "rules", "scope", 51 "selected", "shape", "size", "span", 52 "start", "summary", "tabindex", "target", 53 "title", "type", "usemap", "valign", "value", 54 "vspace", "width", "itemprop", 55 } 56 57 generalSafeElements := []string{ 58 "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "br", "b", "i", "strong", "em", "a", "pre", "code", "img", "tt", 59 "div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", "label", 60 "dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary", 61 "details", "caption", "figure", "figcaption", 62 "abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr", 63 } 64 65 policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...) 66 67 // video 68 policy.AllowAttrs("src", "autoplay", "controls").OnElements("video") 69 70 // checkboxes 71 policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input") 72 policy.AllowAttrs("checked", "disabled", "data-source-position").OnElements("input") 73 74 // for code blocks 75 policy.AllowAttrs("class").Matching(regexp.MustCompile(`chroma`)).OnElements("pre") 76 policy.AllowAttrs("class").Matching(regexp.MustCompile(`anchor|footnote-ref|footnote-backref`)).OnElements("a") 77 policy.AllowAttrs("class").Matching(regexp.MustCompile(`heading`)).OnElements("h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8") 78 policy.AllowAttrs("class").Matching(regexp.MustCompile(strings.Join(slices.Collect(maps.Values(chroma.StandardTypes)), "|"))).OnElements("span") 79 80 // at-mentions 81 policy.AllowAttrs("class").Matching(regexp.MustCompile(`mention`)).OnElements("a") 82 83 // centering content 84 policy.AllowElements("center") 85 86 policy.AllowAttrs("align", "style", "width", "height").Globally() 87 policy.AllowStyles( 88 "margin", 89 "padding", 90 "text-align", 91 "font-weight", 92 "text-decoration", 93 "padding-left", 94 "padding-right", 95 "padding-top", 96 "padding-bottom", 97 "margin-left", 98 "margin-right", 99 "margin-top", 100 "margin-bottom", 101 ) 102 103 // math 104 mathAttrs := []string{ 105 "accent", "columnalign", "columnlines", "columnspan", "dir", "display", 106 "displaystyle", "encoding", "fence", "form", "largeop", "linebreak", 107 "linethickness", "lspace", "mathcolor", "mathsize", "mathvariant", "minsize", 108 "movablelimits", "notation", "rowalign", "rspace", "rowspacing", "rowspan", 109 "scriptlevel", "stretchy", "symmetric", "title", "voffset", "width", 110 } 111 mathElements := []string{ 112 "annotation", "math", "menclose", "merror", "mfrac", "mi", "mmultiscripts", 113 "mn", "mo", "mover", "mpadded", "mprescripts", "mroot", "mrow", "mspace", 114 "msqrt", "mstyle", "msub", "msubsup", "msup", "mtable", "mtd", "mtext", 115 "mtr", "munder", "munderover", "semantics", 116 } 117 policy.AllowNoAttrs().OnElements(mathElements...) 118 policy.AllowAttrs(mathAttrs...).OnElements(mathElements...) 119 120 // goldmark-callout 121 policy.AllowAttrs("data-callout").OnElements("details") 122 123 return policy 124} 125 126func descriptionPolicy() *bluemonday.Policy { 127 policy := bluemonday.NewPolicy() 128 policy.AllowStandardURLs() 129 130 // allow italics and bold. 131 policy.AllowElements("i", "b", "em", "strong") 132 133 // allow code. 134 policy.AllowElements("code") 135 136 // allow links 137 policy.AllowAttrs("href", "target", "rel").OnElements("a") 138 139 return policy 140}