appview/pages/markup: move sanitizer to separate file #500

merged
opened by oppi.li targeting master from push-qwnqkqnmovyn
Changed files
+90 -83
appview
pages
-83
appview/pages/markup/markdown.go
··· 5 "bytes" 6 "fmt" 7 "io" 8 - "maps" 9 "net/url" 10 "path" 11 - "regexp" 12 - "slices" 13 "strings" 14 15 - "github.com/alecthomas/chroma/v2" 16 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 17 "github.com/alecthomas/chroma/v2/styles" 18 - "github.com/microcosm-cc/bluemonday" 19 "github.com/yuin/goldmark" 20 highlighting "github.com/yuin/goldmark-highlighting/v2" 21 "github.com/yuin/goldmark/ast" ··· 50 Sanitizer Sanitizer 51 } 52 53 - type Sanitizer struct { 54 - defaultPolicy *bluemonday.Policy 55 - } 56 - 57 func (rctx *RenderContext) RenderMarkdown(source string) string { 58 md := goldmark.New( 59 goldmark.WithExtensions( ··· 170 return rctx.Sanitizer.defaultPolicy.Sanitize(html) 171 } 172 173 - func NewSanitizer() Sanitizer { 174 - return Sanitizer{ 175 - defaultPolicy: defaultPolicy(), 176 - } 177 - } 178 - func defaultPolicy() *bluemonday.Policy { 179 - policy := bluemonday.UGCPolicy() 180 - 181 - // Allow generally safe attributes 182 - generalSafeAttrs := []string{ 183 - "abbr", "accept", "accept-charset", 184 - "accesskey", "action", "align", "alt", 185 - "aria-describedby", "aria-hidden", "aria-label", "aria-labelledby", 186 - "axis", "border", "cellpadding", "cellspacing", "char", 187 - "charoff", "charset", "checked", 188 - "clear", "cols", "colspan", "color", 189 - "compact", "coords", "datetime", "dir", 190 - "disabled", "enctype", "for", "frame", 191 - "headers", "height", "hreflang", 192 - "hspace", "ismap", "label", "lang", 193 - "maxlength", "media", "method", 194 - "multiple", "name", "nohref", "noshade", 195 - "nowrap", "open", "prompt", "readonly", "rel", "rev", 196 - "rows", "rowspan", "rules", "scope", 197 - "selected", "shape", "size", "span", 198 - "start", "summary", "tabindex", "target", 199 - "title", "type", "usemap", "valign", "value", 200 - "vspace", "width", "itemprop", 201 - } 202 - 203 - generalSafeElements := []string{ 204 - "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8", "br", "b", "i", "strong", "em", "a", "pre", "code", "img", "tt", 205 - "div", "ins", "del", "sup", "sub", "p", "ol", "ul", "table", "thead", "tbody", "tfoot", "blockquote", "label", 206 - "dl", "dt", "dd", "kbd", "q", "samp", "var", "hr", "ruby", "rt", "rp", "li", "tr", "td", "th", "s", "strike", "summary", 207 - "details", "caption", "figure", "figcaption", 208 - "abbr", "bdo", "cite", "dfn", "mark", "small", "span", "time", "video", "wbr", 209 - } 210 - 211 - policy.AllowAttrs(generalSafeAttrs...).OnElements(generalSafeElements...) 212 - 213 - // video 214 - policy.AllowAttrs("src", "autoplay", "controls").OnElements("video") 215 - 216 - // checkboxes 217 - policy.AllowAttrs("type").Matching(regexp.MustCompile(`^checkbox$`)).OnElements("input") 218 - policy.AllowAttrs("checked", "disabled", "data-source-position").OnElements("input") 219 - 220 - // for code blocks 221 - policy.AllowAttrs("class").Matching(regexp.MustCompile(`chroma`)).OnElements("pre") 222 - policy.AllowAttrs("class").Matching(regexp.MustCompile(strings.Join(slices.Collect(maps.Values(chroma.StandardTypes)), "|"))).OnElements("span") 223 - 224 - // centering content 225 - policy.AllowElements("center") 226 - 227 - policy.AllowAttrs("align", "style", "width", "height").Globally() 228 - policy.AllowStyles( 229 - "margin", 230 - "padding", 231 - "text-align", 232 - "font-weight", 233 - "text-decoration", 234 - "padding-left", 235 - "padding-right", 236 - "padding-top", 237 - "padding-bottom", 238 - "margin-left", 239 - "margin-right", 240 - "margin-top", 241 - "margin-bottom", 242 - ) 243 - 244 - return policy 245 - } 246 - 247 type MarkdownTransformer struct { 248 rctx *RenderContext 249 }
··· 5 "bytes" 6 "fmt" 7 "io" 8 "net/url" 9 "path" 10 "strings" 11 12 chromahtml "github.com/alecthomas/chroma/v2/formatters/html" 13 "github.com/alecthomas/chroma/v2/styles" 14 "github.com/yuin/goldmark" 15 highlighting "github.com/yuin/goldmark-highlighting/v2" 16 "github.com/yuin/goldmark/ast" ··· 45 Sanitizer Sanitizer 46 } 47 48 func (rctx *RenderContext) RenderMarkdown(source string) string { 49 md := goldmark.New( 50 goldmark.WithExtensions( ··· 161 return rctx.Sanitizer.defaultPolicy.Sanitize(html) 162 } 163 164 type MarkdownTransformer struct { 165 rctx *RenderContext 166 }
+90
appview/pages/markup/sanitizer.go
···
··· 1 + package markup 2 + 3 + import ( 4 + "maps" 5 + "regexp" 6 + "slices" 7 + "strings" 8 + 9 + "github.com/alecthomas/chroma/v2" 10 + "github.com/microcosm-cc/bluemonday" 11 + ) 12 + 13 + type Sanitizer struct { 14 + defaultPolicy *bluemonday.Policy 15 + } 16 + 17 + func NewSanitizer() Sanitizer { 18 + return Sanitizer{ 19 + defaultPolicy: defaultPolicy(), 20 + } 21 + } 22 + 23 + func 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(strings.Join(slices.Collect(maps.Values(chroma.StandardTypes)), "|"))).OnElements("span") 68 + 69 + // centering content 70 + policy.AllowElements("center") 71 + 72 + policy.AllowAttrs("align", "style", "width", "height").Globally() 73 + policy.AllowStyles( 74 + "margin", 75 + "padding", 76 + "text-align", 77 + "font-weight", 78 + "text-decoration", 79 + "padding-left", 80 + "padding-right", 81 + "padding-top", 82 + "padding-bottom", 83 + "margin-left", 84 + "margin-right", 85 + "margin-top", 86 + "margin-bottom", 87 + ) 88 + 89 + return policy 90 + }